#include <windows.h> // Header File For Windows
#include <math.h> // Math Library Header File
#include <stdio.h> // Header File For Standard Input/Output
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library
#include <gl\glaux.h> // Header File For The GLu32 Library
#pragma comment( lib, "opengl32.lib" ) // Search For OpenGL32.lib While Linking
#pragma comment( lib, "glu32.lib" ) // Search For GLu32.lib While Linking
#pragma comment( lib, "winmm.lib" ) // Search For WinMM Library While Linking
#define IDT_TIMER1 0x12345
BOOL bDone = FALSE;
LONG WINAPI WndProc(HWND,UINT,WPARAM,LPARAM);//Window procedure
HGLRC SetUpOpenGL(HWND hwnd);//Initialize OpenGL
void DrawOpenGLScene(HWND hWnd);//Actual Drawing code
static LRESULT OnLButtonDown(HWND hWnd, UINT nFlags, POINT point);
//////////////////////////////////////////////////////////////////////////
GLuint texture;
GLfloat xtrans;
GLfloat ztrans;
GLfloat ytrans;
GLfloat sceneroty;
GLfloat sceneroty_look;
//////////////////////////////////////////////////////////////////////////
BOOL bLoadBitmaps = TRUE;
BOOL keys[256]; // Array Used For The Keyboard Routine.
GLuint narcissus = 0;
GLsizei m_glnWidth = 0, m_glnHeight = 0;
GLdouble m_gldAspect = 0.0f;
static HGLRC m_hRC; // Note this is STATIC!
const float piover180 = 0.0174532925f;
float heading;
float xpos;
float zpos = 1.6f; // Eigenlijk 10.0f
float ypos = 0.0f;
GLfloat yrot; // Y Rotation
GLfloat walkbias = 0;
GLfloat walkbiasangle = 0;
GLfloat lookupdown = 45.0f;
GLfloat z = 0.0f; // Depth Into The Screen
HDC m_hDC;
GLUquadricObj *coronaObj;
GLUquadricObj *stemObj;
void Update(HWND hWnd)
{
if(!bDone)
{
if(keys[VK_ESCAPE])
{
SendMessage(hWnd, WM_DESTROY, 0, 0); // Close the app.
}
if (keys[VK_PRIOR])
{
z-=0.02f;
}
if (keys[VK_NEXT])
{
z+=0.02f;
}
if (keys[VK_UP])
{
xpos -= (float)sin(heading*piover180) * 0.05f;
zpos -= (float)cos(heading*piover180) * 0.05f;
if (walkbiasangle >= 359.0f)
{
walkbiasangle = 0.0f;
}
else
{
walkbiasangle+= 10;
}
walkbias = (float)sin(walkbiasangle * piover180)/20.0f;
}
if (keys[VK_DOWN])
{
xpos += (float)sin(heading*piover180) * 0.05f;
zpos += (float)cos(heading*piover180) * 0.05f;
if (walkbiasangle <= 1.0f)
{
walkbiasangle = 359.0f;
}
else
{
walkbiasangle-= 10;
}
walkbias = (float)sin(walkbiasangle * piover180)/20.0f;
}
if (keys[VK_RIGHT])
{
heading -= 1.0f;
yrot = heading;
}
if (keys[VK_LEFT])
{
heading += 1.0f;
yrot = heading;
}
if (keys[VK_PRIOR])
{
lookupdown-= 1.0f;
}
if (keys[VK_NEXT])
{
lookupdown+= 1.0f;
}
if(keys['D'])
{
ypos = 0.75f;
}
else
{
ypos = 0.0f;
}
SwapBuffers(m_hDC);
DrawOpenGLScene(hWnd);
ReleaseDC(hWnd, m_hDC);
}
}
// WinMain - the main window entry point.
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
static char szAppName[] = "OpenGL";
static char szTitle[] = "Getting Started With OpenGL";
WNDCLASS wc; // Windows class struct.
MSG msg; // Message struct .
HWND hWnd; // Main window handle..
// Fill in window class structure with parameters that
// describe the main window.
wc.style = CS_HREDRAW | CS_VREDRAW; // Class style(s).
wc.lpfnWndProc = (WNDPROC)WndProc; // Window Procedure
wc.cbClsExtra = 0; // No per-class extra data.
wc.cbWndExtra = 0; // No per-window extra data.
wc.hInstance = hInstance; // Owner of this class.
wc.hIcon = NULL; // Icon name.
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Cursor.
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // Default color.
wc.lpszMenuName = NULL; // Menu from .RC.
wc.lpszClassName = szAppName; // Name to register as.
// Register the window class
RegisterClass(&wc);
// Create a main window for this application instance.
hWnd = CreateWindow(
szAppName, // App name.
szTitle, // Text for window title bar.
WS_OVERLAPPEDWINDOW // Window style.
// NEED THESE for OpenGL calls to work!
| WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, 1280, (1024 - 30),
NULL, // No parent window.
NULL, // Use the window class menu.
hInstance, // This instance owns this window.
NULL // We don't use any extra data.
);
// If window could not be created, return zero.
if(!hWnd)
{
return(0);
}
// Make the window visible & update its client area.
ShowWindow(hWnd, 1); // Show the window.
UpdateWindow(hWnd); // Sends WM_PAINT message.
SetTimer(hWnd, // handle to main window
IDT_TIMER1, // timer identifier
10, // 10-second interval
(TIMERPROC) NULL); // no timer callback
// Enter the Windows message loop.
// Get and dispatch messages until WM_QUIT.
while(GetMessage(&msg, // Message structure.
NULL, // Handle of window receiving the message.
0, // Lowest message id to examine.
0)) // Highest message id to examine.
{
if(msg.message == WM_TIMER)
{
Update(hWnd);
}
TranslateMessage(&msg); // Translates messages
DispatchMessage(&msg); // then dispatches
}
return (int) msg.wParam;
}
GLfloat vdx = 0.0f, vdy = 0.0f;
void DoMouseMotion(int x, int y)
{
vdx = (GLfloat)x;
vdy = (GLfloat)y;
lookupdown = GLfloat((90.0f / m_glnHeight) * vdy)-45.0f; // -45.0f; for looking streight ahead.
sceneroty_look = GLfloat((180.0f / m_glnWidth) * vdx)-90.0f; // -45.0f to 'look' left under 0 degrees.
}
//WndProc.
LONG WINAPI WndProc(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
m_hDC = GetDC(hWnd);
PAINTSTRUCT *ps = new PAINTSTRUCT;
POINT *point = new POINT;
switch(msg)
{
case WM_CREATE: // Select a pixel format and then
// create a rendering context from it.
m_hRC = SetUpOpenGL(hWnd);
return 0;
case WM_SIZE: // Redefine the viewing volume and viewport
// when the window size changes.
// Make the RC current since we're going to
// make an OpenGL call here...
wglMakeCurrent(m_hDC, m_hRC);
// Get the new size of the client window.
// Note that we size according to the height,
// not the smaller of the height or width.
m_glnWidth = (GLsizei) LOWORD(lParam);
m_glnHeight = (GLsizei) HIWORD(lParam);
m_gldAspect = (GLdouble)m_glnWidth/(GLdouble)m_glnHeight;
// Set up a projection matrix to fill the
// client window.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// a perspective-view matrix...
gluPerspective(
45.0f, // Field-of-view angle.
m_gldAspect, // Aspect ratio of view volume.
0.1f, // Distance to near clipping plane.
100.0f); // Distance to far clipping plane.
glViewport(0, 0, m_glnWidth, m_glnHeight);
wglMakeCurrent(NULL, NULL);
SwapBuffers(m_hDC);
return 0;
case WM_PAINT: // Draw the scene.
// Get a DC, then make the RC current and
// associate with this DC.
m_hDC = BeginPaint(hWnd, ps);
wglMakeCurrent(m_hDC, m_hRC);
EndPaint(hWnd, ps);
ReleaseDC(hWnd, m_hDC);
return 0;
case WM_KEYDOWN: // Is A Key Being Held Down?
keys[wParam] = TRUE; // If So, Mark It As TRUE.
return 0; // Jump Back.
case WM_KEYUP: // Has A Key Been Released?
keys[wParam] = FALSE; // If So, Mark It As FALSE.
return 0; // Jump Back.
case WM_MOUSEMOVE:
point->x = LOWORD(lParam);
point->y = HIWORD(lParam);
DoMouseMotion(point->x, point->y);
return 0;
case WM_DESTROY: // Clean up and terminate.
KillTimer(hWnd, IDT_TIMER1);
gluDeleteQuadric(coronaObj); // Delete coronaObj - Free Resources
gluDeleteQuadric(stemObj); // Delete stemObj - Free Resources
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, m_hDC);
wglDeleteContext(m_hRC);
PostQuitMessage(0);
bDone = TRUE;
return 0;
}
delete ps;
delete point;
ps = NULL;
point = NULL;
// This function handles any messages that we didn't.
// (Which is most messages) It belongs to the OS.
return (long) DefWindowProc(hWnd, msg, wParam, lParam);
}
//////////////////////////////////////////////////////////////////////////
#define TEXTURE_AMOUNT 4
GLuint texture2[TEXTURE_AMOUNT]; // Storage For One Texture ( NEW )
AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
{
FILE *File=NULL; // File Handle
if (!Filename) // Make Sure A Filename Was Given
{
return NULL; // If Not Return NULL
}
File=fopen(Filename,"r"); // Check To See If The File Exists
if (File) // Does The File Exist?
{
fclose(File); // Close The Handle
return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer
}
return NULL; // If Load Failed Return NULL
}
int LoadGLTextures() // Load Bitmaps And Convert To Textures
{
int Status=FALSE; // Status Indicator
GLint nLoop = 0;
AUX_RGBImageRec *TextureImage[TEXTURE_AMOUNT]; // Create Storage Space For The Texture
memset(TextureImage,0,sizeof(void *)*TEXTURE_AMOUNT); // Set The Pointer To NULL
// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
if((TextureImage[0]=LoadBMP("Data/NeHe.bmp")) &&
(TextureImage[1]=LoadBMP("Data/NeHeMask.bmp")) &&
(TextureImage[2]=LoadBMP("Data/grass.bmp")) &&
(TextureImage[3]=LoadBMP("Data/petal.bmp")))
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(TEXTURE_AMOUNT, &texture2[0]); // Create The Texture
for(nLoop = 0; nLoop < TEXTURE_AMOUNT; nLoop++)
{
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texture2[nLoop]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[nLoop]->sizeX, TextureImage[nLoop]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[nLoop]->data);
}
}
for(nLoop = 0; nLoop < TEXTURE_AMOUNT; nLoop++)
{
if (TextureImage[nLoop]) // If Texture Exists
{
if (TextureImage[nLoop]->data) // If Texture Image Exists
{
free(TextureImage[nLoop]->data); // Free The Texture Image Memory
}
free(TextureImage[nLoop]); // Free The Image Structure
}
}
return Status; // Return The Status
}
/////////////////////////////////////////////////////////
// SetUpOpenGL sets the pixel format and a rendering
// context then returns the RC.
/////////////////////////////////////////////////////////
HGLRC SetUpOpenGL(HWND hWnd)
{
static PIXELFORMATDESCRIPTOR pfd = {
sizeof (PIXELFORMATDESCRIPTOR), // Struct size.
1, // Version number.
PFD_DRAW_TO_WINDOW | // Flags, draw to a window,
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER, // use OpenGL
PFD_TYPE_RGBA, // RGBA pixel values
24, // 24-bit color
0, 0, 0, // RGB bits & shift sizes.
0, 0, 0, // Don't care about them
0, 0, // No alpha buffer info
0, 0, 0, 0, 0, // No accumulation buffer
32, // 32-bit depth buffer
0, // No stencil buffer
0, // No auxiliary buffers
PFD_MAIN_PLANE, // Layer type
0, // Reserved (must be 0)
0, // No layer mask
0, // No visible mask
0 // No damage mask
};
int nMyPixelFormatID;
HDC hDC;
HGLRC hRC;
hDC = GetDC(hWnd);
nMyPixelFormatID = ChoosePixelFormat(hDC, &pfd);
// Catch errors here.
// If nMyPixelFormat is zero, then there's
// something wrong... most likely the window's
// style bits are incorrect (in CreateWindow() )
// or OpenGl isn't installed on this machine.
SetPixelFormat(hDC, nMyPixelFormatID, &pfd);
hRC = wglCreateContext(hDC);
ReleaseDC(hWnd, hDC);
return hRC;
}
void Narcissus()
{
// First Patal triangle.
glBegin(GL_TRIANGLES);
glColor3f(1.0, 1.0, 0.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.1,-0.5, 1.0);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.1,-0.5, 1.0);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.0,-0.65, 1.0);
glEnd();
// Second petal triangle.
glBegin(GL_TRIANGLES);
glColor3f(1.0, 1.0, 0.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.1,-0.6, 1.0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.1,-0.6, 1.0);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.0,-0.45, 1.0);
glEnd();
// Leafs.
glBegin(GL_TRIANGLES);
glColor3f(0.0f, 0.6f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.01,-1.0, 0.995);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.02, -0.6, 0.95);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.01,-1.0, 0.995);
glEnd();
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
glTranslatef(-1.0f, 0.0f, -1.0f);
glBegin(GL_TRIANGLES);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.01,-1.0, 0.995);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.02, -0.7, 0.95);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.01,-1.0, 0.995);
glEnd();
glTranslatef(1.0f, 0.0f, 1.0f);
glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
// Corona.
glColor3f(0.85, 0.85, 0.0); // Yellow color for the corona.
coronaObj = gluNewQuadric();
gluQuadricDrawStyle(coronaObj, GLU_FILL);
gluQuadricNormals(coronaObj, GLU_SMOOTH);
gluQuadricTexture(coronaObj, GL_TRUE); // Texture use on.
glTranslatef(0.0f,-0.55f, 1.0f);
gluCylinder(coronaObj, 0.015, 0.025, 0.05, 32, 32);
glTranslatef(0.0f, 0.55f,-1.0f);
// Stem.
glColor3f(0.0, 0.5, 0.0); // Green color for the stem.
stemObj = gluNewQuadric();
gluQuadricDrawStyle(stemObj, GLU_FILL);
gluQuadricNormals(stemObj, GLU_SMOOTH);
gluQuadricTexture(stemObj, GL_TRUE); // Texture use on.
glTranslatef(0.0f,-1.0f, 1.0f);
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
gluCylinder(stemObj, 0.01, 0.005, 0.4, 32, 32);
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
glTranslatef(0.0f, 1.0f,-1.0f);
}
void DrawNarcissus()
{
glBindTexture(GL_TEXTURE_2D, texture2[2]);
glEnable( GL_TEXTURE_2D );
// Square.
glBegin(GL_QUADS);
glColor3f(1.0, 1.0, 1.0); // All bright colors for the texture display.
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, -1.0f, 0.0f); // Top Right Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5f, -1.0f, 0.0f); // Top Left Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glEnd();
glBindTexture(GL_TEXTURE_2D, texture2[3]);
glRotatef(270.0f, 0.0f, 1.0f, 0.0f);
glTranslatef(0.25f,0.0f,-0.75f);
Narcissus();
glTranslatef(-0.25f, 0.0f,0.75f);
glRotatef(-270.0f, 0.0f, 1.0f, 0.0f);
glDisable(GL_TEXTURE_2D);
}
void BuildNarcissus()
{
narcissus = glGenLists(1); // Build one list.
glNewList(narcissus, GL_COMPILE); // New compiled narcissus display list.
glLoadName(33);
DrawNarcissus();
glEndList(); // Done building the narcissus list.
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// DrawScene uses OpenGL commands to draw a triangle.
// This is where the OpenGL drawing commands live.
//////////////////////////////////////////////////////////
void DrawOpenGLScene(HWND hWnd)
{
ReleaseDC(hWnd, m_hDC);
if(bLoadBitmaps)
{
bLoadBitmaps = FALSE;
LoadGLTextures();
BuildNarcissus();
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Define the modelview transformation.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
xtrans = -xpos;
ztrans = -zpos;
ytrans = -walkbias-0.25f + ypos;
sceneroty = 360.0f - yrot;
glRotatef(lookupdown, 1.0f, 0.0f, 0.0f);
glRotatef(sceneroty_look, 0.0f, 1.0f, 0.0f);
glRotatef(sceneroty, 0.0f, 1.0f, 0.0f);
glTranslatef(xtrans, ytrans, ztrans);
glCallList(narcissus); // Draw the narcissus
ReleaseDC(hWnd, m_hDC);
}
🔒 Locked
Performance and update
Advertisement
Original Post
Hi, for some time now i am trying to make some kind of a 3D world. I have made a little program based on the NeHe tutorials but I have some questons: In my code I make 1 daffodil on a square and this goes well: I can look and walk around without any problem. But when I loop 360 times and draw the daffodil as many times as I loop there is a major performance hit although I create the 360 daffodills in the methode DrawNarcissus() in a list. Here is my code, can somebody please help me get this to a acceptable speed? Thank you!
it's mostly because you keep switching textures all the time(and this is BTW bad, really bad), so to fix it first create all the geometry that uses the first texture then create all geometry that uses the second and so on.
Thanks for your reaction!
I do not loop the DrawNarcissus() methode 360 times but within this methode I loop the code section
360 times (with each loop counter being the amount of rotating-degrees), so I don't switch textures at all...
Is there maybe some other explanation why this performance hit is occuring?
Thanks in advance...
I do not loop the DrawNarcissus() methode 360 times but within this methode I loop the code section
glRotatef(270.0f, 0.0f, 1.0f, 0.0f);glTranslatef(0.25f,0.0f,-0.75f);Narcissus();glTranslatef(-0.25f, 0.0f,0.75f);glRotatef(-270.0f, 0.0f, 1.0f, 0.0f);360 times (with each loop counter being the amount of rotating-degrees), so I don't switch textures at all...
Is there maybe some other explanation why this performance hit is occuring?
Thanks in advance...
The performance hit is that the CPU is going up from 02 to 99 and the graphics become very very slow.
I can decrease the amount of glBegin/glEnd's but don't I have to glEnd before a glRotatef or glTranslatef?
I pre-build it only once at the beginning of DrawOpenGLScene().
Can you please give me an example of the "rendering in different places by pushing on translation/rotation matrices."?
That would help me very much..
Thanks for your time.
I can decrease the amount of glBegin/glEnd's but don't I have to glEnd before a glRotatef or glTranslatef?
I pre-build it only once at the beginning of DrawOpenGLScene().
Can you please give me an example of the "rendering in different places by pushing on translation/rotation matrices."?
That would help me very much..
Thanks for your time.
well. in a fullscreen app the CPU should always be around 100%. To gauge performance you need to implement a FPS(frames per second) counter. Otherwise you're just dealing with subjectivity.
Basically I mean this:
at level start:
create a narcissus model (list of vertices, and their draw order). Your flowers are the same every single time you draw them so it's wasteful to recalculate where each vertex is. you'll just have to implement non-opengl functions that do the same thing as the glQuadricXXX functions.
each update cycle:
-me
Basically I mean this:
at level start:
create a narcissus model (list of vertices, and their draw order). Your flowers are the same every single time you draw them so it's wasteful to recalculate where each vertex is. you'll just have to implement non-opengl functions that do the same thing as the glQuadricXXX functions.
each update cycle:
for each narcissus{ glPushMatrix(); glTranslatef( the narcissus instance position ); glRotatef( the narcissus instance rotation ); //render the narcissus vertices that you've already calculated //don't remember the syntax but something like this glVertexList( myNarcissusVertices, numVertices ); glIndexList( myNarcissusIndices, numIndices ); //these are indexes into the vertex list i.e. draw vertex 1,2,3 then 3,4,5 or whatever glPopMatrix();}-me
Actually, might just be easier to use a display list. you can just fill the body of the display list with your Narcissus() function body... i think (didn't really read your code that closely)
http://fly.cc.fer.hr/~unreal/theredbook/chapter04.html
http://fly.cc.fer.hr/~unreal/theredbook/chapter04.html
Rather than building one large display list for all 360 loops, as you're doing now, try one small list for one loop, then draw that list 360 times, because there is a performance hit when using large lists. Whether that is the reason for your troubles, I'm not sure of. Your list may not be large enough to qualify for that problem.
So as a first suggestion for what to try:
So as a first suggestion for what to try:
for( int i = 0; i < 360; i++ ) { glTranslatef(1.0f, 0.0f, 0.0f); drawNarcissusList();}
Wait, youre looping on the narcissus() function 360 times per render?
Inside narcissus() I see two calls to gluNewQuadric() This is Bad. Most likely a major slowdown. Allocate the quadrics Once, outside the rendering loop; then reuse them. Do Not re-allocate them for every flower in the 360 interation loop.
On top of that it contains a few unecesarry glBeing/glEnds that could be combined. but I'm guessing the quadrics are the major factor here.
Inside narcissus() I see two calls to gluNewQuadric() This is Bad. Most likely a major slowdown. Allocate the quadrics Once, outside the rendering loop; then reuse them. Do Not re-allocate them for every flower in the 360 interation loop.
On top of that it contains a few unecesarry glBeing/glEnds that could be combined. but I'm guessing the quadrics are the major factor here.
Tank you all for your replies and suggestions...
I will use them adn post my findings.
I will use them adn post my findings.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement