Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
00075 gluTessNormal( tobj, tessNormal().x(), tessNormal().y(), tessNormal().z() );
00076
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
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
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
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
00174
00175 void CALLBACK Tessellator::tessBeginData( GLenum type, Tessellator* tessellator )
00176 {
00177 tessellator->mPrimitiveType = type;
00178 if(type == GL_TRIANGLES)
00179 {
00180
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