Opinions Of My Personal OpenGL Math/Quick Drawing Functions

Sage
Posts: 1,066
Joined: 2004.07
Post: #1
I just got done adding a couple functions to my math/quick drawing functions and I figured I'd get an opinion on these. I was wondering what other developers thought of my laziness, ease of making functions, etc. There are a few I haven't done because they all involve circles or rounded objects and I need more knowledge before I can tackle that. It's all pretty well commented.

Code:
#include "MyMath.h"

int RoundUp(float x)
{
    int y;
    y = int(x) + 1;
    return y;
}

int RoundDown(float x)
{
    int y;
    y = int(x);
    return y;
}

int RoundNearest(float x)
{
    int y,u;
    float c,v;
    y = int(x);
    u = y + 1;
    c = y - x;
    v = u - x;
    if ( c < v ) { return y; }
    if ( c > v ) { return u; }
    return u;
}

float Distance2D(float x, float y, float xx, float yy)
{
    float d;
    d = sqrt( ((xx-x)*(xx-x)) + ((yy-y)*(yy-y)) );
    return d;
}

float Distance3D(float x, float y, float z, float xx, float yy, float zz)
{
    float d;
    d = sqrt( ((xx-x)*(xx-x)) + ((yy-y)*(yy-y)) + ((zz-z)*(zz-z)) );
    return d;
}

////////////////////
//DRAWING FUNCTIONS/
////////////////////

void DrawTriangle(float x, float y, float z,
                  float w, float h,
                  int r, int g, int b) //2D triangle
{
    glBegin(GL_TRIANGLES);
    glColor3ub(r,g,b);
    
    glVertex3f(x+w,y-h,z); //right point
    glVertex3f(x,y+h,z); //top point
    glVertex3f(x-w,y-h,z); //left point
    
    glEnd();
}

void DrawCone(float x, float y, float z,
              float rx, float rz, float h,
              int r, int g, int b) //3D triangle with circular base
{
}

void DrawPyramid3(float x, float y, float z,
                  float w, float h, float d,
                  int r, int g, int b) //3D triangle with triangular base
{
    glBegin(GL_TRIANGLES);
    glColor3ub(r,g,b);
    
    //sides
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x,y-h,z-d);
    
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x+w,y-h,z+d);
    
    glVertex3f(x,y+h,z);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x,y-h,z-d);
    
    //bottom
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x,y-h,z-d);
    glVertex3f(x-w,y-h,z+d);
    
    glEnd();
}

void DrawPyramid3WithEdges(float x, float y, float z,
                           float w, float h, float d,
                           int r, int g, int b) //3D triangle with triangular base and edges
{
    glBegin(GL_TRIANGLES);
    glColor3ub(r,g,b);
    
    //sides
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x,y-h,z-d);
    
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x+w,y-h,z+d);
    
    glVertex3f(x,y+h,z);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x,y-h,z-d);
    
    //bottom
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x,y-h,z-d);
    glVertex3f(x-w,y-h,z+d);
    
    glEnd();
    
    w+=.07; //smallest addition to make line visible
    h+=.07;
    d+=.07;
    
    glBegin(GL_LINES);
    glColor3ub(0,0,0);
    
    //side edges
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z+d);
    
    glVertex3f(x,y+h,z);
    glVertex3f(x+w,y-h,z+d);
    
    glVertex3f(x,y+h,z);
    glVertex3f(x,y-h,z-d);
    
    //bottom edges
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x+w,y-h,z+d);
    
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x,y-h,z-d);
    
    glVertex3f(x,y-h,z-d);
    glVertex3f(x-w,y-h,z+d);
    
    glEnd();
}

void DrawPyramid4(float x, float y, float z,
                  float w, float h, float d,
                  int r, int g, int b) //3D triangle with rectangular base
{
    glBegin(GL_TRIANGLES);
    glColor3ub(r,g,b);
    
    //"left" face
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x-w,y-h,z-d);
    
    //"back" face
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z-d);
    glVertex3f(x+w,y-h,z-d);
    
    //"right" face
    glVertex3f(x,y+h,z);
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x+w,y-h,z+d);
    
    //"front" face
    glVertex3f(x,y+h,z);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x-w,y-h,z+d);
    
    glEnd();
    
    glBegin(GL_QUADS);
    glColor3ub(r,g,b);
    
    //base
    glVertex3f(x-w,y-h,z-d);
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x-w,y-h,z+d);
    
    glEnd();
}

void DrawPyramid4WithEdges(float x, float y, float z,
                           float w, float h, float d,
                           int r, int g, int b) //3D triangle with rectangular base and edges
{
    glBegin(GL_TRIANGLES);
    glColor3ub(r,g,b);
    
    //"left" face
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x-w,y-h,z-d);
    
    //"back" face
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z-d);
    glVertex3f(x+w,y-h,z-d);
    
    //"right" face
    glVertex3f(x,y+h,z);
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x+w,y-h,z+d);
    
    //"front" face
    glVertex3f(x,y+h,z);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x-w,y-h,z+d);
    
    glEnd();
    
    glBegin(GL_QUADS);
    glColor3ub(r,g,b);
    
    //base
    glVertex3f(x-w,y-h,z-d);
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x-w,y-h,z+d);
    
    glEnd();
    
    w+=.07; //smallest addition to make line visible
    h+=.07;
    d+=.07;
    
    glBegin(GL_LINES);
    glColor3ub(0,0,0);
    
    //side edges
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z+d);
    
    glVertex3f(x,y+h,z);
    glVertex3f(x+w,y-h,z+d);
    
    glVertex3f(x,y+h,z);
    glVertex3f(x+w,y-h,z-d);
    
    glVertex3f(x,y+h,z);
    glVertex3f(x-w,y-h,z-d);
    
    //bottom edges
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x+w,y-h,z+d);
    
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x+w,y-h,z-d);
    
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x-w,y-h,z-d);
    
    glVertex3f(x-w,y-h,z-d);
    glVertex3f(x-w,y-h,z+d);
    
    glEnd();
}

void DrawRectangle(float x, float y, float z,
                   float w, float h,
                   int r, int g, int b) //2D rectangle
{
    glBegin(GL_QUADS);
    glColor3ub(r,g,b);
    
    glVertex3f(x-w,y-h,z); //bottom left
    glVertex3f(x+w,y-h,z); //bottom right
    glVertex3f(x+w,y+h,z); //top right
    glVertex3f(x-w,y+h,z); //top left
    
    glEnd();
}

void DrawPrism(float x, float y, float z,
               float w, float h, float d,
               int r, int g, int b) //3D rectangle
{
    glBegin(GL_QUADS);
    glColor3ub(r,g,b);
    
    //top
    glVertex3f(x-w,y+h,z-d);
    glVertex3f(x+w,y+h,z-d);
    glVertex3f(x+w,y+h,z+d);
    glVertex3f(x-w,y+h,z+d);
    
    //bottom
    glVertex3f(x-w,y-h,z-d);
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x-w,y-h,z+d);
    
    //left
    glVertex3f(x-w,y+h,z-d);
    glVertex3f(x-w,y+h,z+d);
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x-w,y-h,z-d);
    
    //right
    glVertex3f(x+w,y+h,z-d);
    glVertex3f(x+w,y+h,z+d);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x+w,y-h,z-d);
    
    //front
    glVertex3f(x-w,y+h,z+d);
    glVertex3f(x+w,y+h,z+d);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x-w,y-h,z+d);
    
    //back
    glVertex3f(x-w,y+h,z-d);
    glVertex3f(x+w,y+h,z-d);
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x-w,y-h,z-d);
    
    glEnd();
}

void DrawPrismWithEdges(float x, float y, float z,
                        float w, float h, float d,
                        int r, int g, int b) //3D rectangle with edges
{
    glBegin(GL_QUADS);
    glColor3ub(r,g,b);
    
    //top
    glVertex3f(x-w,y+h,z-d);
    glVertex3f(x+w,y+h,z-d);
    glVertex3f(x+w,y+h,z+d);
    glVertex3f(x-w,y+h,z+d);
    
    //bottom
    glVertex3f(x-w,y-h,z-d);
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x-w,y-h,z+d);
    
    //left
    glVertex3f(x-w,y+h,z-d);
    glVertex3f(x-w,y+h,z+d);
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x-w,y-h,z-d);
    
    //right
    glVertex3f(x+w,y+h,z-d);
    glVertex3f(x+w,y+h,z+d);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x+w,y-h,z-d);
    
    //front
    glVertex3f(x-w,y+h,z+d);
    glVertex3f(x+w,y+h,z+d);
    glVertex3f(x+w,y-h,z+d);
    glVertex3f(x-w,y-h,z+d);
    
    //back
    glVertex3f(x-w,y+h,z-d);
    glVertex3f(x+w,y+h,z-d);
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x-w,y-h,z-d);
    
    glEnd();
    
    w+=.07; //smallest addition to make line visible
    h+=.07;
    d+=.07;
    
    glBegin(GL_LINES);
    glColor3ub(0,0,0);
    
    /*
     Commenting in here gets hard to understand. The first side descriptor names a face. The second side descriptor describes
     the edge as if that face was a 2D rectangle facing the screen. Like below
     */
    
    //front top & top bottom
    glVertex3f(x-w,y+h,z+d);
    glVertex3f(x+w,y+h,z+d);
    
    //front bottom & bottom top
    glVertex3f(x-w,y-h,z+d);
    glVertex3f(x+w,y-h,z+d);
    
    //front left & left right
    glVertex3f(x-w,y+h,z+d);
    glVertex3f(x-w,y-h,z+d);
    
    //front right & right left
    glVertex3f(x+w,y+h,z+d);
    glVertex3f(x+w,y-h,z+d);
    
    //right top & top right
    glVertex3f(x+w,y+h,z+d);
    glVertex3f(x+w,y+h,z-d);
    
    //right right & back right
    glVertex3f(x+w,y+h,z-d);
    glVertex3f(x+w,y-h,z-d);
    
    //right bottom & bottom right
    glVertex3f(x+w,y-h,z-d);
    glVertex3f(x+w,y-h,z+d);
    
    //top left & left top
    glVertex3f(x-w,y+h,z+d);
    glVertex3f(x-w,y+h,z-d);
    
    //left left & back left
    glVertex3f(x-w,y+h,z-d);
    glVertex3f(x-w,y-h,z-d);
    
    //left bottom & bottom left
    glVertex3f(x-w,y-h,z-d);
    glVertex3f(x-w,y-h,z+d);
    
    //back bottom & bottom bottom
    glVertex3f(x-w,y-h,z-d);
    glVertex3f(x+w,y-h,z-d);
    
    //back top & top top
    glVertex3f(x-w,y+h,z-d);
    glVertex3f(x+w,y+h,z-d);
    
    glEnd();
}

void DrawCircle(float x, float y, float z,
                float rr,
                int r, int g, int b) //2D circle
{
}

void DrawSphere(float x, float y, float z,
                float rr,
                int r, int g, int b) //3D circle
{
}

void DrawOval(float x, float y, float z,
              float rx, float ry,
              int r, int g, int b) //2D oval
{
}

void DrawEgg(float x, float y, float z,
             float rx, float ry, float rz,
             int r, int g, int b) //3D oval
{
}
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #2
1) Things to avoid on PPC include int<->float conversion and sqrt(). If you care about speed, it's better to stick with floats and use floorf(), ceilf(), roundf(). If approximations are OK, use __frsqrtes, with a round or two of Newton-Raphson refinement.

2) Your shapes are all drawn in immediate mode, which is the slowest possible path. Since they all look like static objects, you could compile them into display lists (the fastest possible path on OS X) and let the current state (color, modelview matrix) determine the parameters you're passing in.
Quote this message in a reply
Member
Posts: 184
Joined: 2004.07
Post: #3
A much easier trick for doing RoundNearest is RoundNearest(x) = int(x+0.5). Also, I think your roundup will add 1 to a round float?

Code style is a matter of taste- I think the best rule to try to fit with (though it's not always possible) is 'never write anything twice'- if you see the same fragment of code or same idea repeated more than once, try to fit it into a function or macro- then if the code changes you don't need to copy and paste it.
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #4
Thanks for the advice.
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #5
So how exactly do you use the square root estimation? I could look up the newton estimation method from my calc notes, but I've never seen the code to do it.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #6
From the glAArg code:
Code:
#include <ppc_intrinsics.h>
// ---------------------------------------------------------------------
// fast reciprocal square root estimate with Newton-Raphson refinement
// ---------------------------------------------------------------------
static inline float frsqrtes_nr(float x) {
    float e = __frsqrtes(x);
    e *= (1.5f - (0.5f * x * e * e));
    return e;
}
You must compile with -force_cpusubtype_ALL to get ppc_intrinsics.h to work (because __frsqrtes isn't available on the PPC 601. But no 601 machines can run OS X, so it doesn't matter.)

The section of Help for Shark that shows the example of optimizing the Flurry screensaver shows in detail how to make this sort of optimization. Of course, you shouldn't just jump in and do this. You should profile first to see if sqrt() is a bottleneck, which in the case above, depends entirely on how often those Distance functions are being called.

Apple's performance documentation is pretty good.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #7
be aware that the accuracy of frsqrte dramatically reduces from G3 to G4, and G4 to G5. Test your code on G5 before assuming it's good enough Wink
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #8
Yep. The G5 has a full precision sqrt intrinsic to make up for it. But that means making CPU-specific code paths (no inline functions.)

For reference though, at screen resolutions (~2k by 2k) one round of Newton-Raphson is adequate for glAArg's perpendicular vector projections, with subpixel precision, on a G5. You could use more (or no) rounds depending what your needs are.
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #9
Yeah, sqrt() can be a bottle neck in SPK if lots of particles are used with drag, but considering the headache that this could be for someone of my level of experience, I think I'll just hold off for now.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  opengl text/font drawing from CGContext fretmunky 11 12,937 Dec 7, 2008 11:29 AM
Last Post: fretmunky
  OpenGL ES - Drawing a simple cube help. MattCairns 7 12,496 Oct 10, 2008 05:26 PM
Last Post: Frogblast
  Drawing bitmaps in OpenGL MacGoober 21 21,831 Sep 22, 2007 05:50 PM
Last Post: MikeC
  quick opengl 2d quad question dave05 2 3,642 Jun 9, 2005 06:09 PM
Last Post: arekkusu
  2D Drawing in OpenGL LongJumper 2 2,862 Nov 21, 2003 06:04 PM
Last Post: johnMG