diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/llcylinder.cpp |
Print done when done.
Diffstat (limited to 'indra/newview/llcylinder.cpp')
-rw-r--r-- | indra/newview/llcylinder.cpp | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/indra/newview/llcylinder.cpp b/indra/newview/llcylinder.cpp new file mode 100644 index 0000000000..1774ff4ccf --- /dev/null +++ b/indra/newview/llcylinder.cpp @@ -0,0 +1,308 @@ +/** + * @file llcylinder.cpp + * @brief Draws a cylinder using display lists for speed. + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcylinder.h" + +#include "llerror.h" +#include "math.h" +#include "llmath.h" +#include "noise.h" +#include "v3math.h" + +#include "llgl.h" +#include "llglheaders.h" + +LLCylinder gCylinder; +LLCone gCone; + +GLUquadricObj* gQuadObj = NULL; + +// draws a cylinder or cone +// returns approximate number of triangles required +U32 draw_cylinder_side(GLint slices, GLint stacks, GLfloat base_radius, GLfloat top_radius) +{ + U32 triangles = 0; + GLfloat height = 1.0f; + + if (!gQuadObj) + { + gQuadObj = gluNewQuadric(); + if (!gQuadObj) llerror("draw_cylindrical_body couldn't allocated quadric", 0); + } + + gluQuadricDrawStyle(gQuadObj, GLU_FILL); + gluQuadricNormals(gQuadObj, GLU_SMOOTH); + gluQuadricOrientation(gQuadObj, GLU_OUTSIDE); + gluQuadricTexture(gQuadObj, GL_TRUE); + gluCylinder(gQuadObj, base_radius, top_radius, height, slices, stacks); + triangles += stacks * (slices * 2); + + + return triangles; +} + + +// Returns number of triangles required to draw +// Need to know if top or not to set lighting normals +const BOOL TOP = TRUE; +const BOOL BOTTOM = FALSE; +U32 draw_cylinder_cap(GLint slices, GLfloat base_radius, BOOL is_top) +{ + U32 triangles = 0; + + if (!gQuadObj) + { + gQuadObj = gluNewQuadric(); + if (!gQuadObj) llerror("draw_cylinder_base couldn't allocated quadric", 0); + } + + gluQuadricDrawStyle(gQuadObj, GLU_FILL); + gluQuadricNormals(gQuadObj, GLU_SMOOTH); + gluQuadricOrientation(gQuadObj, GLU_OUTSIDE); + gluQuadricTexture(gQuadObj, GL_TRUE); + + // no hole in the middle of the disk, and just one ring + GLdouble inner_radius = 0.0; + GLint rings = 1; + + // normals point in +z for top, -z for base + if (is_top) + { + gluQuadricOrientation(gQuadObj, GLU_OUTSIDE); + } + else + { + gluQuadricOrientation(gQuadObj, GLU_INSIDE); + } + gluDisk(gQuadObj, inner_radius, base_radius, slices, rings); + triangles += slices; + + return triangles; +} + + +void LLCylinder::prerender() +{ + GLint stacks = 2; + GLfloat radius = 0.5f; + GLint slices[CYLINDER_LEVELS_OF_DETAIL] = { 30, 20, 12, 6 }; // same as sphere slices + + for (S32 detail = 0; detail < CYLINDER_LEVELS_OF_DETAIL; detail++) + { + mTriangleCount[detail] = 0; + + mDisplayListSide[detail] = glGenLists(1); + glNewList(mDisplayListSide[detail], GL_COMPILE); + mTriangleCount[detail] += draw_cylinder_side( slices[detail], stacks, radius, radius ); + glEndList(); + + mDisplayListTop[detail] = glGenLists(1); + glNewList( mDisplayListTop[detail], GL_COMPILE); + mTriangleCount[detail] += draw_cylinder_cap( slices[detail], radius, TOP ); + glEndList(); + + mDisplayListBottom[detail] = glGenLists(1); + glNewList( mDisplayListBottom[detail], GL_COMPILE); + mTriangleCount[detail] += draw_cylinder_cap( slices[detail], radius, BOTTOM ); + glEndList(); + } +} + +void LLCylinder::cleanupGL() +{ + for (S32 detail = 0; detail < CYLINDER_LEVELS_OF_DETAIL; detail++) + { + glDeleteLists(mDisplayListSide[detail], 1); + mDisplayListSide[detail] = 0; + glDeleteLists(mDisplayListTop[detail], 1); + mDisplayListTop[detail] = 0; + glDeleteLists(mDisplayListBottom[detail], 1); + mDisplayListBottom[detail] = 0; + } + + if (gQuadObj) + { + gluDeleteQuadric(gQuadObj); + gQuadObj = NULL; + } +} + +void LLCylinder::render(F32 pixel_area) +{ + renderface(pixel_area, 0); + renderface(pixel_area, 1); + renderface(pixel_area, 2); +} + + +void LLCylinder::renderface(F32 pixel_area, S32 face) +{ + if (face < 0 || face > 2) + { + llerror("LLCylinder::renderface() invalid face number", face); + return; + } + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + S32 level_of_detail; + + if (pixel_area > 20000.f) + { + level_of_detail = 0; + } + else if (pixel_area > 1600.f) + { + level_of_detail = 1; + } + else if (pixel_area > 200.f) + { + level_of_detail = 2; + } + else + { + level_of_detail = 3; + } + + if (level_of_detail < 0 || CYLINDER_LEVELS_OF_DETAIL <= level_of_detail) + { + llerror("LLCylinder::renderface() invalid level of detail", level_of_detail); + return; + } + + switch(face) + { + case 0: + glTranslatef(0.f, 0.f, -0.5f); + glCallList(mDisplayListSide[level_of_detail]); + break; + case 1: + glTranslatef(0.0f, 0.f, 0.5f); + glCallList(mDisplayListTop[level_of_detail]); + break; + case 2: + glTranslatef(0.0f, 0.f, -0.5f); + glCallList(mDisplayListBottom[level_of_detail]); + break; + default: + llerror("LLCylinder::renderface() fell out of switch", 0); + break; + } + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + + +// +// Cones +// + +void LLCone::prerender() +{ + GLint stacks = 2; + GLfloat radius = 0.5f; + GLint slices[CONE_LEVELS_OF_DETAIL] = { 32, 18, 12, 6 }; + + for (S32 detail = 0; detail < CONE_LEVELS_OF_DETAIL; detail++) + { + mTriangleCount[detail] = 0; + + mDisplayListSide[detail] = glGenLists(1); + glNewList(mDisplayListSide[detail], GL_COMPILE); + mTriangleCount[detail] += draw_cylinder_side( slices[detail], stacks, radius, 0.f ); + glEndList(); + + mDisplayListBottom[detail] = glGenLists(1); + glNewList( mDisplayListBottom[detail], GL_COMPILE); + mTriangleCount[detail] += draw_cylinder_cap( slices[detail], radius, BOTTOM ); + glEndList(); + } +} + +void LLCone::cleanupGL() +{ + for (S32 detail = 0; detail < CYLINDER_LEVELS_OF_DETAIL; detail++) + { + glDeleteLists(mDisplayListSide[detail], 1); + mDisplayListSide[detail] = 0; + + glDeleteLists(mDisplayListBottom[detail], 1); + mDisplayListBottom[detail] = 0; + } + + if (gQuadObj) + { + gluDeleteQuadric(gQuadObj); + gQuadObj = NULL; + } +} + + +void LLCone::render(S32 level_of_detail) +{ + GLfloat height = 1.0f; + + if (level_of_detail < 0 || CONE_LEVELS_OF_DETAIL <= level_of_detail) + { + llerror("LLCone::render() invalid level of detail", level_of_detail); + return; + } + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + // center object at 0 + glTranslatef(0.f, 0.f, - height / 2.0f); + + glCallList(mDisplayListSide[level_of_detail]); + glCallList(mDisplayListBottom[level_of_detail]); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + + +void LLCone::renderface(S32 level_of_detail, S32 face) +{ + if (face < 0 || face > 1) + { + llerror("LLCone::renderface() invalid face number", face); + return; + } + + if (level_of_detail < 0 || CONE_LEVELS_OF_DETAIL <= level_of_detail) + { + llerror("LLCone::renderface() invalid level of detail", level_of_detail); + return; + } + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + switch(face) + { + case 0: + glTranslatef(0.f, 0.f, -0.5f); + glCallList(mDisplayListSide[level_of_detail]); + break; + case 1: + glTranslatef(0.f, 0.f, -0.5f); + glCallList(mDisplayListBottom[level_of_detail]); + break; + default: + llerror("LLCylinder::renderface() fell out of switch", 0); + break; + } + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} |