newbie in Java 3d, HELP!!

I want to create a complex shape, a polyhedron. How could i manage it?

Thanks in advance

Assuming you’re using Java3D, I’d strongly recommend you go through Sun’s tutorial. It can be found online at http://java.sun.com/products/java-media/3D/collateral/

Yep, i have allready read the first 2 chapters, Geometry is what i am concerning with most. But there is no a simple program that explains the implementation.

Sun provides some simple primitives in their utility package: Sphere, Cone, Box, and Cylinder.

If you want to make anything more complicated than that, you either have to do the math and create the polygons yourself, or create the shape in a 3D tool like Maya, 3DS, AC3D, Blender, etc. Then you can load it into Java3D using a Loader.

There’s a whole bunch of Loaders available at http://www.j3d.org for different tools.

If you want to make the shape yourself using math, then you can. You don’t need to concern yourself too much with the different kinds of geometries right now. You can just make a QuadArray or TriangleArray from individual 3D points, and then use the Stripifier and NormalGenerator (more Sun utilities) to turn the geometry into a more optimized representation for faster rendering, if you want.

Any good book on 3D graphics programming should provide some sample code to create the individual 3D points for various types of polyhedrons .

Reading the Java3d Tutorial i notice that there is a recipe.

Now, i am trying to create a cube with the following coordinators

A {0,0,0}
B {0,0,1}
C {1,0,1}
D {1,0,0}
E {0,1,1}
F {1,1,1}
G {1,1,0}
H {0,1,0}

Here is my attempt


-----------------
import java.awt.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;


public class TheCube extends javax.media.j3d.Shape3D {


 public TheCube() {

 ViewingPlatform ourView;

 setLayout(new BorderLayout());

         GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();


  Canvas3D c = new Canvas3D(config);

  add("Center", c);
         SimpleUniverse u = new SimpleUniverse(c);


         BranchGroup scene = createSceneGraph();
  u.addBranchGraph(scene);

  ourView = u.getViewingPlatform();
         ourView.setNominalViewingTransform();

  BranchGroup objRoot = new BranchGroup();
  Appearance app = new Appearance();

  Point3d A=new Point3d(0,0,0);
  Point3d B=new Point3d(0,0,1);
  Point3d C=new Point3d(1,0,1);
  Point3d D=new Point3d(1,0,0);
  Point3d E=new Point3d(0,1,1);
  Point3d F=new Point3d(1,1,1);
  Point3d G=new Point3d(1,1,0);
  Point3d H=new Point3d(0,1,0);

  Point3d[] points =new Point3d[8];

  int[] stripCounts= new int[4];
        stripCounts[0]=4;
        stripCounts[1]=4;
        stripCounts[2]=4;
        stripCounts[3]=4;

        int[] contourCount=new int[4];
        contourCount[0]=1;
        contourCount[1]=1;
        contourCount[2]=1;
        contourCount[3]=1;




  GeometryInfo gInf = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);

  gInf.setCoordinates(points);
  gInf.setStripCounts(stripCounts);
     gInf.setContourCounts(contourCount);


  NormalGenerator ng= new NormalGenerator();

  ng.generateNormals(gInf);

  this.setGeometry(gInf.getGeometryArray());





  }




  public static void main(String[] args) {



   new MainFrame(new TheCube(), 700, 700);}



  }
---------------------

The Errors


--------------------Configuration: j2sdk1.4.0 <Default>--------------------
D:\java\TheCube.java:16: cannot resolve symbol
symbol  : method setLayout  (java.awt.BorderLayout)
location: class TheCube
 setLayout(new BorderLayout());
        ^
D:\java\TheCube.java:23: cannot resolve symbol
symbol  : method add  (java.lang.String,javax.media.j3d.Canvas3D)
location: class TheCube
  add("Center", c);
                ^
D:\java\TheCube.java:27: cannot resolve symbol
symbol  : method createSceneGraph  ()
location: class TheCube
         BranchGroup scene = createSceneGraph();
                             ^
D:\java\TheCube.java:88: cannot resolve symbol
symbol  : constructor MainFrame  (TheCube,int,int)
location: class com.sun.j3d.utils.applet.MainFrame
   new MainFrame(new TheCube(), 700, 700);}
                ^
4 errors


You’ve got a kind of cut and paste from one of the applet examples there, but you’ve put everything in one class.

Create another class that contains all the layout stuff and extends Applet, or whatever it is they usually extend and then use a “createSceneGraph” method in that to instanciate your TheCube object and go from there.

I put together a basic tutorial on J3D a while ago which begins with how to create polygons - that may be useful to you as well.

Here is the TheLayout class


import java.awt.*;
import java.awt.event.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.universe.*;
import java.applet.Applet;

 public class TheLayout extends Applet {

   public static void main(String args[]) {

     new TheLayout();
   }
 

   public TheLayout() {


     setSize(500,500); 
     
     GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
     
    Canvas3D myCanvas3D = new Canvas3D(config);
     add("Center",myCanvas3D);
 

     setVisible(true);


     View myView = constructView(myCanvas3D);
     Locale myLocale = constructViewBranch(myView);
     
   }



  private View constructView(Canvas3D myCanvas3D) {
     View myView = new View();
     myView.addCanvas3D(myCanvas3D);
     myView.setPhysicalBody(new PhysicalBody());
     myView.setPhysicalEnvironment(new PhysicalEnvironment());
     return(myView);
   }



   private Locale constructViewBranch(View myView) {

     VirtualUniverse myUniverse = new VirtualUniverse();
     Locale myLocale = new Locale(myUniverse);
     BranchGroup myBranchGroup = new BranchGroup();
     TransformGroup myTransformGroup = new TransformGroup();
     ViewPlatform myViewPlatform = new ViewPlatform();
 

     myTransformGroup.addChild(myViewPlatform);
     myBranchGroup.addChild(myTransformGroup);
     myLocale.addBranchGraph(myBranchGroup);
 

     myView.attachViewPlatform(myViewPlatform);
     return(myLocale);
   }
 

   
}


I suppose that is correct, Your suggestions

You’re using those two together, I take it? The problems are exactly what I described. To make it easier when you are getting started it is worth using SimpleUniverse. Make sure you take out all the applet stuff from TheCube.

I strongly recommend you check out the tutorial I linked because it does explain how to do this. There are also some good tutorials on this site: http://www.newdawnsoftware.com/tutorials/tutorials.html

Having read some tutorials, i decided to create a polyhedron and that is my code

But the shape that generates isn;t as good as i expected.


 
---------------------------------
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.BranchGroup;
import com.sun.j3d.utils.applet.MainFrame;
import javax.media.j3d.*;
import java.awt.*;
import javax.vecmath.*;
import java.awt.BorderLayout;
import javax.media.j3d.GeometryArray;
 
public class ThePolyhedron extends javax.media.j3d.Shape3D {
 
private Point3d a1= new Point3d(0.333333, 0.942809, 0.57735);
private Point3d a2= new Point3d(-1., 0, 0.57735);
private Point3d a3= new Point3d(-0.333333, -0.942809, 0.57735);
private Point3d a4= new Point3d(1., 0, -0.57735);
private Point3d a5= new Point3d(0.666667, -0.942809, 0);
private Point3d a6= new Point3d(-0.666667, 0.942809, 0);
private Point3d a7= new Point3d(0.333333, 0.942809, -0.57735);
private Point3d a8= new Point3d(-1., 0, -0.57735);
private Point3d a9= new Point3d(-0.333333, -0.942809, -0.57735);
private Point3d a10= new Point3d(0, 0, -1.1547);
private Point3d a11= new Point3d(0, 0, 1.1547);
private Point3d a12= new Point3d(1., 0, 0.57735);
 
public ThePolyhedron()
 
{ 
 
 
 Point3d[] points=new Point3d[12];
 
 points[0]=a1;
 points[1]=a2;
 points[2]=a3;
 points[3]=a4;
 points[4]=a5;
 points[5]=a6;
 points[6]=a7;
 points[7]=a8;
 points[8]=a9;
 points[9]=a10;
 points[10]=a11;
 points[11]=a12;
 
 
 int[] stripCounts=new int[1];
 stripCounts[0]=12;
 
 
 int[] contourCount=new int[1];
 contourCount[0]=1;
 
 
 
 GeometryInfo gInf = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
 
 gInf.setCoordinates(points);
 gInf.setStripCounts(stripCounts);
 gInf.setContourCounts(contourCount);
 
 NormalGenerator ng= new NormalGenerator();
 ng.setCreaseAngle ((float) Math.toRadians(30));
 ng.generateNormals(gInf);
 
 
 this.setGeometry(gInf.getGeometryArray());
 
 
 
 
   SimpleUniverse universe = new SimpleUniverse();
   
   GraphicsConfiguration config = universe.getPreferredConfiguration();
 

  Canvas3D c = new Canvas3D(config);
  
  
  
  
 
   BranchGroup group = new BranchGroup();
   
   group.addChild(this);
 
    
    
    
    
    
    
 
   
   
   Color3f light1Color = new Color3f(0.0f, 1.0f, 0.0f);
   
    Vector3f light1Direction = new Vector3f(4.0f, -7.0f, 12.0f);
   
   
   DirectionalLight dl = new DirectionalLight(light1Color,light1Direction);
   BoundingSphere bounds = new BoundingSphere();
   bounds.setRadius(Double.POSITIVE_INFINITY);
   dl.setInfluencingBounds(bounds);
   group.addChild(dl);
 
 
 
   
   universe.getViewingPlatform().setNominalViewingTransform();
 
   universe.addBranchGraph(group); 
 
}
 
 
 
 
 
} // end of class
 
-------------------------
 

Does this work for you?

Any help?

No, remember that you are in a class that extends Shape3D here - once you have created the geometry your shape is created. All the other stuff there is telling Java3D how to display the shape.

Take everything after “this.setGeometry()” out and move it to the class that displays the object. Look at any class that shows a Shape3D ( HelloWorld3D is a good example ) and you should see how this works - as TheCube is a shape3D you will be able to do it in the same way. It should probably look a bit like this (mostly your code, a few bits from me) :



public class TheLayout extends Applet { 
 
   public static void main(String args[]) { 
 
     new TheLayout(); 
   } 
  
 
public TheLayout() 
{ 
   setSize(500,500);  
   GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); 
   Canvas3D myCanvas3D = new Canvas3D(config); 
     add("Center",myCanvas3D); 
  
    SimpleUniverse u = new SimpleUniverse(c);
    BranchGroup scene = createSceneGraph(); 
    u.addBranchGraph(scene);
    u.getViewingPlatform().setNominalViewingTransform(); 
    setVisible(true); 
} 

private BranchGroup createSceneGraph()
{

   BranchGroup group = new BranchGroup(); 
    
   TheCube ourCube = new TheCube();

// The next few lines where we add an appearance and a material allow 
// J3d to know how the shape interacts with the light source - a shape
// that does not have a material will not be affected by the light.

    Appearance app = new Appearance();
    Color3f objColor = new Color3f(0.2f, 0.7f, 0.8f);
    Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
    app.setMaterial(new Material(objColor, black, objColor, black, 80.0f));
    ourCube.setAppearance(app);

   group.addChild(ourCube); 
    
   Color3f light1Color = new Color3f(0.0f, 1.0f, 0.0f); 
   Vector3f light1Direction = new Vector3f(4.0f, -7.0f, 12.0f); 
    
   DirectionalLight dl = new DirectionalLight(light1Color,light1Direction); 
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
   dl.setInfluencingBounds(bounds); 
   group.addChild(dl); 

   return group;
}

What about my polyhedron attempt? Is what disappointing me most :frowning:

Sorry, I wasn’t paying attention. The same applies- take out everything after the “this.setGeometry()” and run the rest exactly the same except that you use ThePolyhedron instead of TheCube. As they are both Shape3D objects it will treat them identically.

Aint inheritance great?

I have changed a little my code. To be more strict, i used the TriangleFanArray instead of GeometryInfo

Here it is


import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.BranchGroup;
import com.sun.j3d.utils.applet.MainFrame;
import javax.media.j3d.*;
import java.awt.*;
import javax.vecmath.*;
import java.awt.BorderLayout;
import javax.media.j3d.GeometryArray;

public class ThePolyhedron extends javax.media.j3d.Shape3D {

private Point3d a1= new Point3d(0.333333, 0.942809, 0.57735);
private      Point3d a2= new Point3d(-1., 0, 0.57735);
private      Point3d a3= new Point3d(-0.333333, -0.942809, 0.57735);
private      Point3d a4= new Point3d(1., 0, -0.57735);
private      Point3d a5= new Point3d(0.666667, -0.942809, 0);
private      Point3d a6= new Point3d(-0.666667, 0.942809, 0);
private      Point3d a7= new Point3d(0.333333, 0.942809, -0.57735);
private      Point3d a8= new Point3d(-1., 0, -0.57735);
private      Point3d a9= new Point3d(-0.333333, -0.942809, -0.57735);
private      Point3d a10= new Point3d(0, 0, -1.1547);
private      Point3d a11= new Point3d(0, 0, 1.1547);
private      Point3d a12= new Point3d(1., 0, 0.57735);

public ThePolyhedron()

{      
      
       
      
      Point3d[] pts=new Point3d[12];
      
      pts[0]=a1;
      pts[1]=a2;
      pts[2]=a3;
      pts[3]=a4;
      pts[4]=a5;
      pts[5]=a6;
      pts[6]=a7;
      pts[7]=a8;
      pts[8]=a9;
      pts[9]=a10;
      pts[10]=a11;
      pts[11]=a12;
      
      
      int[] indices={3,1,0,2,4,5,
      9,7,6,8,10,11};

      int[] stripCounts={6,6};


      
      
      TriangleFanArray myPolyhedron = new TriangleFanArray(12,
    TriangleFanArray.COORDINATES|TriangleFanArray.NORMALS,stripCounts);
      myPolyhedron.setCoordinates(0,pts);
      
      TransformGroup tg=new TransformGroup();
      tg.addChild(myPolyhedron); 


   SimpleUniverse universe = new SimpleUniverse();
   
   GraphicsConfiguration config = universe.getPreferredConfiguration();


            Canvas3D c = new Canvas3D(config);            
            

   BranchGroup group = new BranchGroup();
   
   group.addChild(tg);
   
   
   Color3f light1Color = new Color3f(0.0f, 1.0f, 0.0f);
   
    Vector3f light1Direction = new Vector3f(4.0f, -7.0f, 12.0f);
   
   
   DirectionalLight dl = new DirectionalLight(light1Color,light1Direction);
   BoundingSphere bounds = new BoundingSphere();
   bounds.setRadius(Double.POSITIVE_INFINITY);
   dl.setInfluencingBounds(bounds);
   group.addChild(dl);



   
   universe.getViewingPlatform().setNominalViewingTransform();

   universe.addBranchGraph(group); 

}





} // end of class


and that’s the problem


D:\java\Java3d Project\Project\ThePolyhedron.java:61: addChild(javax.media.j3d.Node) in javax.media.j3d.Group cannot be applied to (javax.media.j3d.TriangleFanArray)
      tg.addChild(myPolyhedron); 
          ^
1 error

Why i cannot add the TransformGroup?

You are still mixing up the Geometry and shape definition the “Shape3D” part and the Branchgroup creation and scene definition , the “scene” part, in one class.

Let your Polyhedron be a shape, and let your main applet class do all the work of creating the scene and displaying the scenegraph, exactly as I described earlier.

You cannot create a canvas3d or a light source or a universe inside a Shape3D class. Take all of it out and move it elsewhere.

Think of it in terms of object oriented programming (if you need some reminders about how that works take a look at these excellent tutorials - they are pretty good even if you do know how it all works ) and try to keep your objects doing only what they need to do. Don’t try and jam everything in one class.

Ok, i separated the code into 2 classes

ThePolyhedron.java


import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.BranchGroup;
import com.sun.j3d.utils.applet.MainFrame;
import javax.media.j3d.*;
import java.awt.*;
import javax.vecmath.*;
import java.awt.BorderLayout;
import javax.media.j3d.GeometryArray;

public class ThePolyhedron extends javax.media.j3d.Shape3D {

private Point3d a1= new Point3d(0.333333, 0.942809, 0.57735);
private      Point3d a2= new Point3d(-1., 0, 0.57735);
private      Point3d a3= new Point3d(-0.333333, -0.942809, 0.57735);
private      Point3d a4= new Point3d(1., 0, -0.57735);
private      Point3d a5= new Point3d(0.666667, -0.942809, 0);
private      Point3d a6= new Point3d(-0.666667, 0.942809, 0);
private      Point3d a7= new Point3d(0.333333, 0.942809, -0.57735);
private      Point3d a8= new Point3d(-1., 0, -0.57735);
private      Point3d a9= new Point3d(-0.333333, -0.942809, -0.57735);
private      Point3d a10= new Point3d(0, 0, -1.1547);
private      Point3d a11= new Point3d(0, 0, 1.1547);
private      Point3d a12= new Point3d(1., 0, 0.57735);

public ThePolyhedron()

{      
      
       
      
      Point3d[] pts=new Point3d[12];
      
      pts[0]=a1;
      pts[1]=a2;
      pts[2]=a3;
      pts[3]=a4;
      pts[4]=a5;
      pts[5]=a6;
      pts[6]=a7;
      pts[7]=a8;
      pts[8]=a9;
      pts[9]=a10;
      pts[10]=a11;
      pts[11]=a12;
      
      
      int[] indices={3,1,0,2,4,5,
      9,7,6,8,10,11};

      int[] stripCounts={6,6};


      
      
      TriangleFanArray myPolyhedron = new TriangleFanArray(12,
    TriangleFanArray.COORDINATES|TriangleFanArray.NORMALS,stripCounts);
      myPolyhedron.setCoordinates(0,pts);
      
      TransformGroup tg=new TransformGroup();
      tg.addChild(myPolyhedron); 

   
   
   Color3f light1Color = new Color3f(0.0f, 1.0f, 0.0f);
   
    Vector3f light1Direction = new Vector3f(4.0f, -7.0f, 12.0f);
   
   
   DirectionalLight dl = new DirectionalLight(light1Color,light1Direction);
   BoundingSphere bounds = new BoundingSphere();
   bounds.setRadius(Double.POSITIVE_INFINITY);
   dl.setInfluencingBounds(bounds);


 
   

}





} // end of class

and the CallClasses.java

I am not sure about that class


import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.BranchGroup;
import com.sun.j3d.utils.applet.MainFrame;
import javax.media.j3d.*;
import java.awt.*;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;

public class CallClass extends  java.applet.Applet{
      
      
      public CallClass () {
            
            
      SimpleUniverse universe = new SimpleUniverse();
   
   GraphicsConfiguration config = universe.getPreferredConfiguration();


            Canvas3D c = new Canvas3D(config);            
            

   BranchGroup group = new BranchGroup();
   
    
   universe.getViewingPlatform().setNominalViewingTransform();

   universe.addBranchGraph(group);       
            
            
      }
      
      public static void main(String[] args) {
            
            
      new CallClass();
            
            
            
      }
}//end class CallClass

Any idea?

"If you want to make anything more complicated than that, you either have to do the math and create the polygons yourself, or create the shape in a 3D tool like Maya, 3DS, AC3D, Blender, etc. Then you can load it into Java3D using a Loader.

There’s a whole bunch of Loaders available at http://www.j3d.org for different tools."

Hi,
I am new on this also. I read the Java3D tutorial and I´ve also tried to use a loader. I tried several of them from j3d.org but I couldn´t make them work…can you recommend me one for 3ds or vrml ?

I tried this example (I also tried others with 3ds) and I can only see a black window :frowning:

Any hint will be highly appreciated

import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.loaders.Scene;
import com.sun.j3d.loaders.Loader;

import javax.media.j3d.BranchGroup;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Canvas3D;
import javax.vecmath.Point3d;
import java.awt.*;
import java.io.FileNotFoundException;
import java.applet.Applet;

import org.web3d.j3d.loaders.VRML97Loader;

public class vrmlLoader extends Applet {

public vrmlLoader (String filename) {
    setLayout(new BorderLayout());
    Canvas3D canvas3D = new Canvas3D(null);
    add("Center", canvas3D);

    BranchGroup scene = createSceneGraph(filename);
    scene.compile();

    // SimpleUniverse is a Convenience Utility class
    SimpleUniverse simpleU = new SimpleUniverse(canvas3D);

  // This will move the ViewPlatform back a bit so the
  // objects in the scene can be viewed.
    simpleU.getViewingPlatform().setNominalViewingTransform();
    simpleU.addBranchGraph(scene);
}

//  The following allows this to be run as an application
//  as well as an applet

public static void main(String[] args) {
    int x = 1024;
    int y = 768;

    if (args.length > 2) {
        x = Integer.parseInt(args[1]);
        y = Integer.parseInt(args[2]);
    }

    Frame frame = new MainFrame(new vrmlLoader(args[0]), x, y);
}

public BranchGroup createSceneGraph(String filename) {
    BranchGroup objRoot = new BranchGroup();

    Loader loader = null;
    Scene theScene = null;

    try {
       loader = new VRML97Loader();
       theScene = loader.load(filename);
       System.out.println("Scene description : " +theScene.getDescription());
       objRoot.addChild(theScene.getSceneGroup());
    }
    catch(FileNotFoundException fnf) {
        System.out.println("exception " + fnf);
    }

    return objRoot;

 }

}