Thread: 3D spheres

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    3D spheres

    Trying to write a small class that will draw a 3D sphere primitive.

    What I'm doing now is working, however, I cannot get the sphere to rotate around itself unless it is very close to the origin of my world.

    This code is not in a speed-critical section - all spheres are generated in the constructor - all objects are created prior to rendering the world. This will be called once for every sphere (planet) in the world (universe) during the load process.

    Here is the code to create the base circle:

    Code:
    class Vector
    {
      public:
        double x;
        double y;
        double z;
      ....
      ....
    };
     
    struct Vertex
    {
      Vector Local;
      Vector World;
      Vector Aligned;
    };
    
    void Sphere::Sphere(Vector center,double lx,double ly,double lz,short NumFacets,short radius)
    {
      double lx=center.x;
      double ly=center.y;
      double lz=center.z;
      SphereCenter.Local=center;    //SphereCenter is type vertex in  
                                                      //class
    
      double anginc=6.28f/(double)NumFacets;
      short NumXCircles=(short)(6.28f/angleinc);
      short NumYCircles=NumXCircles;
      short TotalVertexes=(NumXCircles*NumYCircles)<<1;
      
      Vtxs=new Vertex[TotalVertexes];
      Vertex *BaseCircle=new Vertex[NumFacets];
       for (int i=0;i<NumFacets;i++)
      {
        double localx=(double)radius*cos(curangle);
        double localy=(double)radius*sin(curangle);
        double localz=0;
        Vector temp(localx,localy,localz);
    
        BaseCircle[i].Local=temp;  //operator handled by vector class
        curangle+=anginc;
      }
      //Now translate lx,ly,lz on x,y,z 
      //rotate this circle ax,ay, az radians 
      //Transform using local space to get world space
      //Append result to vertexes for sphere
      ....
      ....
      //Too lengthy to post here
    }
    If you find errors in the code, I posted wrong. There are no warnings or errors when I compile the project.

    The translation to world coords causes them to rotate around lx-origin, ly-origin, lz-origin, not around their actual centers.

    I think the problem is that my sphere is not centered around the x,y,z axes. This would cause the sphere to rotate around that point, rather than it's center. However, I've also tried to create a sphere using x,z and y,z, but the same thing happens.

    How do I rotate these spheres around their central point, rather than around a point in space? I don't want them to orbit, they need to rotate.

    An algorithm to create the approx of a sphere around point lx,ly,lz at radius r and facets f is what I'm looking for.

  2. #2
    Registered User Coder's Avatar
    Join Date
    Aug 2001
    Location
    Cairo, Egypt
    Posts
    128

    Unhappy trying to help

    If your spheres are orbiting, that means their coordinates are defined relative to the point they're rotating around (origin).

    To make their coordinates local (i.e relative to their geometrical center) you should get their geometrical center :
    vGeometricalCenter = vSumOfVertices/wNumVertices;

    Then (PSEUDO):
    for each vertex
    local vertex = vertex - vGeometricalCenter;

    when rotating, you mutliply your local vertex by the rotation matrix (or rotate directly) ---> This gives you a rotated vertex in the sphere space (object space, i.e rotated about the sphere's geometrical center).

    After that you add the vGeometricalCenter to the rotated vertices which gives you the world vertices.

    Multiply by the view matrix to get your aligned coordinates, then by the projection matrix and I suppose you're done.

    However, this approach is dumb because it depends on modifying the vertices after creating them (which is slow and stupid).
    You should re-write it so it creates the vertices in local coordinates directly.

    I can't help you do that currently because :
    (1) I'm having a headache (I've just got out of a mechanics exam )

    (2) THe code contains mistakes and things I don't know why they're here (typos, definitely) :

    void Sphere::Sphere(Vector center,double lx,double ly,double lz,short NumFacets,short radius)
    {
    double lx=center.x;
    double ly=center.y;
    double lz=center.z;
    lx,ly & lz are parameters, yet they're re-declared inside the constructor. What are lx,ly & lz (the parameters)?

    Sorry if I've been useless and wasted your time.
    Last edited by Coder; 11-14-2001 at 08:12 AM.

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Well, the actual code does not have lx, ly, and lz in the constructor as this would be redundant since center takes care of those coords.

    It was late when I posted this, so I know there are probably a lot of typos. But, I do understand what you are saying about the relative coordinates. My problem is that I think my local coords are correct since I'm creating a base circle and using my rotation matrices to get the other circles. The spheres look perfect, but will not rotate around their center. What you said has been helpful and at least given me a point of reference. If you continue to help me or would like to help me get this class working, PM me and I'll show you the source to the class. There are a lot of references to matrix, vector, and vertex functions/classes but since you are familiar with 3D, you should be able to get the jist of what I'm doing.

    Sorry for the typos in the code. DJGPP won't let me paste to the board (since it does not use the Windows clipboard).

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I thought geometrical center was this:

    (minx+maxx)/2
    (miny+maxy)/2
    (minz+maxz)/2

    If I were to search for mins and maxes on all three axes and then rotated relative to that point, would this be the correct geometrical center?

    These spheres (planets) will be rotating around their center and at the same time will be orbiting their sun, or another planet if it is part of a pair that rotates around each other.

    This rotation will also be somewhat based on gravitational attraction between the two objects:

    I think the formula is F=M1*M2*6.67^-11/d^2

    ^ stands for an exponential expression.
    Constant for gravitational attraction between two objects at 1m is 6.67 * 10^-11 NM^2. So if I give a specific mass to my objects and convert all the units to usable ones by my system, I could simulate or approximate a small solar system of planets (I could just arbitrarily assign orbital ranges - we'll see what works)

  5. #5
    Unregistered
    Guest
    Stayed up late (early) last night and got it to work. I was doing it right, but for some reason my operator was not working correctly for my Vector class. So, it was not translating correctly.

    To rotate around a point in space, I translate during the creation phase. If that is 0,0,0 then the sphere will rotate around itself. If it is not, then the sphere will rotate around the point in space, and around its center.

  6. #6
    Registered User Coder's Avatar
    Join Date
    Aug 2001
    Location
    Cairo, Egypt
    Posts
    128
    I thought geometrical center was this:

    (minx+maxx)/2
    (miny+maxy)/2
    (minz+maxz)/2
    It can be calculated in both ways, I prefer the 1st because it's brute-forcish and requires less coding on my side (3 - 4 lines less), and the speed difference isn't that large.


    Anyway, I'll PM you right now.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Found another way to generate 3D spheres. The problem with the above method was that the vertexes of the spheres did not meet at the correct points on the sphere and the function was rather large and clunky. This sphere looked quite odd on screen and my source was large and clunky.

    So, I did some research and tried an algorithm from a math website. It did not work. Looked at another website and found that the first website had a typo in the formula. aaarrrgghhh!!

    To generate a 3D sphere:

    -90<=theta<=90
    0<phi<360

    x=cos(theta)*cos(phi)
    y=cos(theta)*sin(phi)
    z=sin(theta)

    These need to be multiplied by radius r. You need at least 14 to 16 facets in the sphere to get rid of the flat poles - caused by the change in size of the sections near the poles. You can alternate these coords to fit your coordinate system. I have switched y and z around to better suit my needs.

    To draw the sphere you can either draw multiple polies based on the coords of the sphere

    Code:
    int vert1=num;
    int vert2=num+(numfacets+1);
    int vert3=(num+1)+(numfacets+1);   //coord2+1
    int vert4=num+1;
    These are counterclockwise so backface culling comes out perfect when you use vertices 1,2,3. Backface culling is not accurate if you use vertex 0 in the mix (0,1,2). Have not figured out why.
    The entire sphere should be transformed to world space and to aligned space (whatever you call it). Then use the vertex data with the above numbers to get the vertices to draw lines between.

    My setup is like this:

    Code:
    class Vector
    {
       double x;
       double y;
       double z;
    
    
       //Constructors, operator overloading, etc
    ...
    ...
    ..
    }
    
    
    struct point2D
    {
      double x;
      double y;
    };
    
    struct Vertex
    {
       Vector Local;
       Vector World;
       Vector Aligned;
       point2D ScreenCoords;
    };

    So after all transformations and projection are done:

    Vertices is within the sphere class of type Vertex

    int x1=Vertices[vert1].ScreenCoords.x;
    int y1=Vertices[vert1].ScreenCoords.y;
    int x2=Vertices[vert2].ScreenCoords.x;
    int y2=Vertices[vert2].ScreenCoords.y;

    Line (x1,y1,x2,y2,color);

    This will draw a line at the correct point on the sphere from vert1 to vert2. How you set up your data/3D engine is not a big deal just as long as you draw lines between the correct points.

    Of course, based on the above info, you could just generate a large list of polygons that represent the sphere and then draw the sphere by iterating through the list.


    Looked at some code in DirectX - would be much easier using that and doing shading, texturing, etc.

    Coder, will get the new sphere source to you soon. Still working on correctly scan converting the polygons so I can shade, texture, etc. Eventually though I should have a fully functional 3D planet class to use in my system.

    There is another way to generate by a recursive subdivide of a base shape, finding the normal vector of the shape, and translating along that normal by radius r effectively pushing the shape into the right spot on the sphere - but have not coded it yet.

  8. #8
    Registered User Coder's Avatar
    Join Date
    Aug 2001
    Location
    Cairo, Egypt
    Posts
    128

    Smile

    Great!

    Just a question, why don't you use Direct3D/OGL instead?!
    It'll make things look a lot better (although you won't do any rasterization).

    Good luck, and keep up the good work.
    Muhammad Haggag

  9. #9
    "The Oldest Member Here" Xterria's Avatar
    Join Date
    Sep 2001
    Location
    Buffalo, NY
    Posts
    1,039
    iche...get DirectX. Atleast Opengl. Doing that garbage takes too much triginometry...it takes less in DirectX or opengl.

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I'm not using DirectX because I do not have a compiler that can work with it. I'm waiting to get a new compiler - probably MSVC - so that I can use DirectX.

    The trig is not that complicated and neither is the rasterization part. In fact, polygon scan converting is so easy I cannot believe I've overlooked the simplicity in it.

    The light source shading code, gauroud (however you spell it) shading, phong shading, and texture mapping trig/calculus is much harder than any of these sphere equations.

    There is one problem, though. For some odd reason the system thinks that one of the poles of my sphere is on the other side. So, when I light source shade it, everything looks ok except for that one pole which is only as bright as the ambient light. Have not figured out why this little quirk is happening.

  11. #11
    Registered User Coder's Avatar
    Join Date
    Aug 2001
    Location
    Cairo, Egypt
    Posts
    128
    Originally posted by Xterria
    Doing that garbage takes too much triginometry...it takes less in DirectX or opengl.
    Generating a sphere in DirectX/OGL takes the same time. It's the same math (unless you use 3rd party/helper libraries)

    Additionally, I don't think it's good to be coding 3D with D3D/OGL without knowing how to do rasterization and shading yourself.

    Originally posted by Bubba
    I'm waiting to get a new compiler - probably MSVC - so that I can use DirectX.
    I believe there's a free version of MSVC - the standard version. It's limited (Debug builds only, as far as I know) but it can get you rolling.

    Also, you can try Borland's C++ 5.5 compiler (although working without an IDE isn't nice)

    Originally posted by Bubba
    So, when I light source shade it, everything looks ok except for that one pole which is only as bright as the ambient light. Have not figured out why this little quirk is happening.
    Depends on how you do your lighting, do you use the vertex normals? (I believe you said you use gouraud shading?)
    You might have your vertex normal inverted (check it's creation, maybe you've got an inverted cross product)
    Muhammad Haggag

  12. #12
    Registered User Coder's Avatar
    Join Date
    Aug 2001
    Location
    Cairo, Egypt
    Posts
    128
    These are counterclockwise so backface culling comes out perfect when you use vertices 1,2,3. Backface culling is not accurate if you use vertex 0 in the mix (0,1,2). Have not figured out why.
    The entire sphere should be transformed to world space and to aligned space (whatever you call it). Then use the vertex data with the above numbers to get the vertices to draw lines between.
    The text quoted above appears in my Opera 5 browser in Verdana font! I noticed that any text written after a code tag appears in verdana (it should be in Times new roman, or Arial. I can't determine)

    The point is, text after code tags is different from text before them - on my browser.

    Is this a problem in Opera, or you have the same problem?
    Muhammad Haggag

  13. #13
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Yes, I'm using the vertex normals. Still, cannot figure out why the bottom facets are drawn correctly, but do not produce the correct numbers during backface culling, or during shading. This only happens when the angle is -90<x<~-80.

    Since angle step size depends on the number of facets, the variation of when this happens can be greater than or less than 80. But it is only on the very first row of facets - the sphere is drawn bottom to top.

    Maybe this is why some have used the recursive splitting method to produce the sphere and not the mathematical method.

    I guess I could just reverse the vertex order on the first "ring" of the sphere but this seems more like a workaround than a fix and may introduce more problems later in the render.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. 3d graphics without API
    By h3ro in forum Game Programming
    Replies: 6
    Last Post: 05-31-2008, 11:51 AM
  2. 3D Network Analysis Tool
    By durban in forum Projects and Job Recruitment
    Replies: 1
    Last Post: 11-08-2005, 06:33 PM
  3. 3D starfield
    By VirtualAce in forum Game Programming
    Replies: 6
    Last Post: 06-26-2003, 12:40 PM
  4. 3D SDK for C++ programmers
    By chand in forum Game Programming
    Replies: 2
    Last Post: 05-20-2003, 07:38 AM
  5. 3d engines
    By Unregistered in forum Game Programming
    Replies: 7
    Last Post: 12-17-2001, 11:19 AM