summaryrefslogtreecommitdiff
path: root/indra/newview/llcylinder.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/llcylinder.cpp
Print done when done.
Diffstat (limited to 'indra/newview/llcylinder.cpp')
-rw-r--r--indra/newview/llcylinder.cpp308
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();
+}