## 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 { }```
Sage
Posts: 1,234
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.
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.
Sage
Posts: 1,066
Joined: 2004.07
Post: #4
Thanks for the advice.
Sage
Posts: 1,487
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.
Sage
Posts: 1,234
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.
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
Sage
Posts: 1,234
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.
Sage
Posts: 1,487
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.

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