Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #include <vlGraphics/Tessellator.hpp> 00033 00034 using namespace vl; 00035 00036 //----------------------------------------------------------------------------- 00037 Tessellator::Tessellator() 00038 { 00039 VL_DEBUG_SET_OBJECT_NAME() 00040 mTessNormal = fvec3(0,0,0); 00041 mBoundaryOnly = false; 00042 mTolerance = 0.0; 00043 mWindingRule = TW_TESS_WINDING_ODD; 00044 mTessellateIntoSinglePolygon = true; 00045 } 00046 //----------------------------------------------------------------------------- 00047 Tessellator::~Tessellator() 00048 { 00049 freeCombinedVertices(); 00050 } 00051 //----------------------------------------------------------------------------- 00052 bool Tessellator::tessellate(bool append_tessellated_tris) 00053 { 00054 if (!append_tessellated_tris) 00055 mTessellatedTris.clear(); 00056 mFans.clear(); 00057 mTriStrips.clear(); 00058 mLineLoops.clear(); 00059 mPrimitiveType = 0; 00060 freeCombinedVertices(); 00061 if (mContours.empty() || mContourVerts.empty()) 00062 { 00063 vl::Log::error("Tessellator::tessellate(): no contours specified.\n"); 00064 return false; 00065 } 00066 00067 GLUtesselator* tobj = gluNewTess(); 00068 // callbacks 00069 gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (callback_type)tessBeginData); 00070 gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (callback_type)tessVertexData); 00071 gluTessCallback(tobj, GLU_TESS_COMBINE_DATA, (callback_type)tessCombineData); 00072 gluTessCallback(tobj, GLU_TESS_END, (callback_type)tessEnd); 00073 gluTessCallback(tobj, GLU_TESS_ERROR, (callback_type)tessError); 00074 // normal 00075 gluTessNormal( tobj, tessNormal().x(), tessNormal().y(), tessNormal().z() ); 00076 // properties 00077 gluTessProperty(tobj, GLU_TESS_BOUNDARY_ONLY, boundaryOnly() ? GL_TRUE : GL_FALSE); 00078 gluTessProperty(tobj, GLU_TESS_TOLERANCE, tolerance()); 00079 gluTessProperty(tobj, GLU_TESS_WINDING_RULE, windingRule()); 00080 // tessellation 00081 if (tessellateIntoSinglePolygon()) 00082 { 00083 gluTessBeginPolygon(tobj, this); 00084 for(unsigned cont=0, idx=0; cont<mContours.size(); ++cont) 00085 { 00086 gluTessBeginContour(tobj); 00087 for(int i=0; i<mContours[cont]; ++i, ++idx) 00088 gluTessVertex(tobj, mContourVerts[idx].ptr(), mContourVerts[idx].ptr()); 00089 gluTessEndContour(tobj); 00090 } 00091 gluTessEndPolygon(tobj); 00092 } 00093 else 00094 { 00095 for(unsigned cont=0, idx=0; cont<mContours.size(); ++cont) 00096 { 00097 gluTessBeginPolygon(tobj, this); 00098 gluTessBeginContour(tobj); 00099 for(int i=0; i<mContours[cont]; ++i, ++idx) 00100 gluTessVertex(tobj, mContourVerts[idx].ptr(), mContourVerts[idx].ptr()); 00101 gluTessEndContour(tobj); 00102 gluTessEndPolygon(tobj); 00103 } 00104 } 00105 gluDeleteTess(tobj); 00106 00107 // triangulate fans 00108 for(unsigned fan=0; fan<mFans.size(); ++fan) 00109 for(unsigned iv =1; iv<mFans[fan].size()-1; ++iv) 00110 { 00111 mTessellatedTris.push_back(mFans[fan][0]); 00112 mTessellatedTris.push_back(mFans[fan][iv]); 00113 mTessellatedTris.push_back(mFans[fan][iv+1]); 00114 } 00115 00116 // triangulate strips 00117 for(unsigned strip=0; strip<mTriStrips.size(); ++strip) 00118 for(unsigned iv=0; iv<mTriStrips[strip].size()-2; ++iv) 00119 { 00120 if (iv % 2) 00121 { 00122 mTessellatedTris.push_back(mTriStrips[strip][iv+0]); 00123 mTessellatedTris.push_back(mTriStrips[strip][iv+2]); 00124 mTessellatedTris.push_back(mTriStrips[strip][iv+1]); 00125 } 00126 else 00127 { 00128 mTessellatedTris.push_back(mTriStrips[strip][iv+0]); 00129 mTessellatedTris.push_back(mTriStrips[strip][iv+1]); 00130 mTessellatedTris.push_back(mTriStrips[strip][iv+2]); 00131 } 00132 } 00133 00134 mContours.clear(); 00135 mContourVerts.clear(); 00136 00137 #if 0 00138 if (tessellatedTris().empty()) 00139 { 00140 vl::Log::warning("Tessellator::tessellate(): no triangles generated.\n"); 00141 return false; 00142 } 00143 #endif 00144 00145 return true; 00146 } 00147 //----------------------------------------------------------------------------- 00148 void Tessellator::freeCombinedVertices() 00149 { 00150 for(unsigned i=0; i<mCombinedVertices.size(); ++i) 00151 delete mCombinedVertices[i]; 00152 mCombinedVertices.clear(); 00153 } 00154 //----------------------------------------------------------------------------- 00155 ref<Geometry> Tessellator::tessellateGeometry(bool append_tessellated_tris) 00156 { 00157 tessellate(append_tessellated_tris); 00158 00159 if (mTessellatedTris.empty()) 00160 return NULL; 00161 00162 ref<Geometry> geom = new Geometry; 00163 ref<ArrayFloat3> vert_array = new ArrayFloat3; 00164 00165 vert_array->initFrom(mTessellatedTris); 00166 00167 geom->setVertexArray(vert_array.get()); 00168 geom->drawCalls()->push_back( new vl::DrawArrays(PT_TRIANGLES, 0, vert_array->size()) ); 00169 geom->computeNormals(); 00170 return geom; 00171 } 00172 //----------------------------------------------------------------------------- 00173 // Tessellation callbacks 00174 //----------------------------------------------------------------------------- 00175 void CALLBACK Tessellator::tessBeginData( GLenum type, Tessellator* tessellator ) 00176 { 00177 tessellator->mPrimitiveType = type; 00178 if(type == GL_TRIANGLES) 00179 { 00180 // do nothing 00181 } 00182 else 00183 if(type == GL_TRIANGLE_FAN) 00184 tessellator->mFans.resize( tessellator->mFans.size() + 1 ); 00185 else 00186 if(type == GL_TRIANGLE_STRIP) 00187 tessellator->mTriStrips.resize( tessellator->mTriStrips.size() + 1 ); 00188 else 00189 if(type == GL_LINE_LOOP) 00190 tessellator->mLineLoops.resize( tessellator->mLineLoops.size() + 1 ); 00191 else 00192 { 00193 Log::error("Tessellator::beginData() unknown primitive.\n"); 00194 } 00195 } 00196 //----------------------------------------------------------------------------- 00197 void CALLBACK Tessellator::tessVertexData( dvec3* vec, Tessellator* tessellator ) 00198 { 00199 if(tessellator->mPrimitiveType == GL_TRIANGLES) 00200 tessellator->mTessellatedTris.push_back( (fvec3)(*vec) ); 00201 else 00202 if(tessellator->mPrimitiveType == GL_TRIANGLE_FAN) 00203 tessellator->mFans.back().push_back( (fvec3)(*vec) ); 00204 else 00205 if(tessellator->mPrimitiveType == GL_TRIANGLE_STRIP) 00206 tessellator->mTriStrips.back().push_back( (fvec3)(*vec) ); 00207 else 00208 if(tessellator->mPrimitiveType == GL_LINE_LOOP) 00209 tessellator->mLineLoops.back().push_back( (fvec3)(*vec) ); 00210 else 00211 { 00212 Log::error("Tessellator::vertexData() unknown primitive.\n"); 00213 } 00214 } 00215 //----------------------------------------------------------------------------- 00216 void CALLBACK Tessellator::tessCombineData( GLdouble coords[3], dvec3*[4], GLfloat[4], dvec3 **dataOut, Tessellator* tessellator ) 00217 { 00218 dvec3 *vec = new dvec3; 00219 vec->x() = coords[0]; 00220 vec->y() = coords[1]; 00221 vec->z() = coords[2]; 00222 *dataOut = vec; 00223 tessellator->mCombinedVertices.push_back( vec ); 00224 } 00225 //----------------------------------------------------------------------------- 00226 void CALLBACK Tessellator::tessEnd(void) 00227 { 00228 } 00229 //----------------------------------------------------------------------------- 00230 void CALLBACK Tessellator::tessError( GLenum errno ) 00231 { 00232 const GLubyte* estring = gluErrorString(errno); 00233 Log::error( Say("Tessellator error: %s.\n") << estring ); 00234 } 00235 //-----------------------------------------------------------------------------