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/Extrusion.hpp>
00033 #include <vlGraphics/Tessellator.hpp>
00034 #include <vlCore/glsl_math.hpp>
00035
00036 using namespace vl;
00037
00038 ref<Geometry> Extrusion::extrude(bool compatibilityProfile)
00039 {
00040 if (silhouette().empty())
00041 {
00042 Log::error("Extrusion::extrude(): no silhouette defined.\n");
00043 return NULL;
00044 }
00045 if (positionPath().empty())
00046 {
00047 Log::error("Extrusion::extrude() needs at least a non empty positionPath().\n");
00048 return NULL;
00049 }
00050 if (!scalingPath().empty() && scalingPath().size() != positionPath().size()-2)
00051 {
00052 Log::error("Extrusion::extrude(): scalingPath() must have the same number of control points as positionPath().\n");
00053 return NULL;
00054 }
00055 if (!rotationPath().empty() && rotationPath().size() != positionPath().size()-2)
00056 {
00057 Log::error("Extrusion::extrude(): rotationPath() must have the same number of control points as positionPath().\n");
00058 return NULL;
00059 }
00060 if (!colorPath().empty() && colorPath().size() != positionPath().size()-2)
00061 {
00062 Log::error("Extrusion::extrude(): colorPath() must have the same number of control points as positionPath().\n");
00063 return NULL;
00064 }
00065
00066 ref<Geometry> geom = new Geometry;
00067
00068 size_t segments = positionPath().size()-2;
00069
00070 std::vector<fvec3> verts;
00071 verts.resize( silhouette().size() * segments );
00072
00073 vl::fmat4 m = fmat4::getRotation(fvec3(0,1,0),positionPath()[1]-positionPath()[0]);
00074
00075
00076 std::vector<vl::fvec3> projected_sil;
00077 projected_sil.resize(silhouette().size());
00078 for(unsigned i=0; i<silhouette().size(); ++i)
00079 {
00080 projected_sil[i] = m * vl::fvec3(silhouette()[i].x(),0,silhouette()[i].y()) + positionPath()[0];
00081 }
00082
00083
00084 std::vector<fvec3> plane_normals;
00085 plane_normals.resize(positionPath().size());
00086 for(unsigned i=1; i<plane_normals.size()-1; ++i)
00087 {
00088 fvec3 p0 = positionPath()[i-1] - positionPath()[i];
00089 fvec3 p1 = positionPath()[i+1] - positionPath()[i];
00090 p0.normalize();
00091 p1.normalize();
00092 plane_normals[i] = (p1-p0).normalize();
00093 }
00094
00095 for(unsigned i=1; i<positionPath().size()-1; ++i)
00096 {
00097 for(int j=0; j<(int)silhouette().size(); ++j)
00098 {
00099 fvec3 V = (positionPath()[i] - positionPath()[i-1]).normalize();
00100 const fvec3& P = projected_sil[j];
00101 const fvec3& orig = positionPath()[i];
00102 const fvec3& N = plane_normals [i];
00103 float d = dot(N,orig);
00104 float t = dot(V,N) ? (d-dot(P,N))/dot(V,N) : 0 ;
00105
00106 verts.at(j+silhouette().size()*(i-1)) = projected_sil[j] = P + V*t;
00107 }
00108 }
00109
00110
00111 if(!rotationPath().empty())
00112 {
00113 for(unsigned i=1; i<positionPath().size()-1; ++i)
00114 {
00115 fvec3 r = (positionPath()[i+1] - positionPath()[i]).normalize();
00116 fmat4 mat = vl::fmat4::getRotation(rotationPath()[i-1],r);
00117 fvec3 c;
00118 for(int j=0; j<(int)silhouette().size(); ++j)
00119 c += verts.at(j+silhouette().size()*(i-1));
00120 c /= (float)silhouette().size();
00121 for(int j=0; j<(int)silhouette().size(); ++j)
00122 verts.at(j+silhouette().size()*(i-1)) = (mat*(verts.at(j+silhouette().size()*(i-1))-c))+c;
00123 }
00124 }
00125
00126
00127 if(!scalingPath().empty())
00128 {
00129 for(unsigned i=1; i<positionPath().size()-1; ++i)
00130 {
00131 float s = scalingPath()[i-1];
00132 fvec3 c;
00133 for(int j=0; j<(int)silhouette().size(); ++j)
00134 c += verts.at(j+silhouette().size()*(i-1));
00135 c /= (float)silhouette().size();
00136 for(int j=0; j<(int)silhouette().size(); ++j)
00137 verts.at(j+silhouette().size()*(i-1)) = (s*(verts.at(j+silhouette().size()*(i-1))-c))+c;
00138 }
00139 }
00140
00141 int prof_count = silhouetteMode() == SilhouetteClosed ? (int)silhouette().size() : (int)silhouette().size()-1;
00142 ref<DrawElementsUInt> de = new DrawElementsUInt(PT_QUADS);
00143 geom->drawCalls()->push_back(de.get());
00144 de->indexBuffer()->resize(4 * prof_count * (segments-1));
00145 for(size_t iseg=0; iseg<segments-1; ++iseg)
00146 {
00147 for(int iquad=0; iquad<prof_count; ++iquad)
00148 {
00149 de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 3) = (iseg + 0) * (GLuint)silhouette().size() + iquad;
00150 de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 2) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
00151 de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 1) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
00152 de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 0) = (iseg + 1) * (GLuint)silhouette().size() + iquad;
00153 }
00154 }
00155
00156
00157
00158 size_t tess_bottom_count = 0;
00159 size_t tess_top_count = 0;
00160
00161 if(fillBottom())
00162 {
00163 size_t start = verts.size();
00164 Tessellator tessellator;
00165 tessellator.contours().push_back((int)silhouette().size());
00166 for(unsigned i=0; i<silhouette().size(); ++i)
00167 tessellator.contourVerts().push_back((dvec3)verts[i]);
00168 tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
00169 tessellator.tessellate();
00170 for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
00171 verts.push_back(tessellator.tessellatedTris()[i]);
00172 if (tessellator.tessellatedTris().size())
00173 geom->drawCalls()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
00174 tess_bottom_count = tessellator.tessellatedTris().size();
00175 }
00176 if(fillTop())
00177 {
00178 size_t start = verts.size();
00179 Tessellator tessellator;
00180 tessellator.contours().push_back(silhouette().size());
00181 for(unsigned i=0; i<silhouette().size(); ++i)
00182 tessellator.contourVerts().push_back((dvec3)verts[verts.size()-i-1-tess_bottom_count]);
00183 tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
00184 tessellator.tessellate();
00185 for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
00186 verts.push_back(tessellator.tessellatedTris()[i]);
00187 if (tessellator.tessellatedTris().size())
00188 geom->drawCalls()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
00189 tess_top_count = tessellator.tessellatedTris().size();
00190 }
00191
00192 ref<ArrayFloat3> vert_array = new ArrayFloat3;
00193 if(compatibilityProfile)
00194 geom->setVertexArray( vert_array.get() );
00195 else
00196 geom->setVertexAttribArray(VA_Position, vert_array.get());
00197 vert_array->initFrom(verts);
00198
00199 if (!colorPath().empty())
00200 {
00201 ref<ArrayFloat4> col_array = new ArrayFloat4;
00202 if(compatibilityProfile)
00203 geom->setColorArray(col_array.get());
00204 else
00205 geom->setVertexAttribArray(VA_Color, col_array.get());
00206 col_array->resize(geom->vertexArray()->size());
00207 int offs = 0;
00208 for(size_t iseg=0; iseg<segments; ++iseg)
00209 {
00210 for(unsigned j=0; j<silhouette().size(); ++j, ++offs)
00211 col_array->at(offs) = colorPath()[iseg];
00212 }
00213 if (fillBottom())
00214 {
00215 for(unsigned j=0; j<tess_bottom_count; ++j, ++offs)
00216 col_array->at(offs) = colorPath()[0];
00217 }
00218 if (fillTop())
00219 {
00220 for(unsigned j=0; j<tess_top_count; ++j, ++offs)
00221 col_array->at(offs) = colorPath().back();
00222 }
00223 }
00224
00225 if (!smooth())
00226 geom->convertDrawCallToDrawArrays();
00227
00228 geom->computeNormals();
00229
00230 return geom;
00231 }