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/Extrusions.hpp>
00033 #include <vlGraphics/Tessellator.hpp>
00034 #include <vlCore/glsl_math.hpp>
00035
00036 using namespace vl;
00037
00038 ref<Geometry> Extrusions::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;
00074
00075
00076
00077
00078
00079
00080 m = fmat4::getRotation(fvec3(0,1,0),positionPath()[1]-positionPath()[0]);
00081
00082
00083 vl::defLogger()->error("positionPath()[1]-positionPath()[0] : " + vl::String::fromDouble((positionPath()[1]-positionPath()[0]).x()) + ";" +
00084 vl::String::fromDouble((positionPath()[1]-positionPath()[0]).y()) + ";" +
00085 vl::String::fromDouble((positionPath()[1]-positionPath()[0]).z()) + "\n");
00086
00087
00088 std::vector<vl::fvec3> projected_sil;
00089 projected_sil.resize(silhouette().size());
00090 for(unsigned i=0; i<silhouette().size(); ++i)
00091 {
00092 projected_sil[i] = m * vl::fvec3(silhouette()[i].x(),0,silhouette()[i].y()) + positionPath()[0];
00093 }
00094
00095
00096 std::vector<fvec3> plane_normals;
00097 plane_normals.resize(positionPath().size());
00098 for(unsigned i=1; i<plane_normals.size()-1; ++i)
00099 {
00100 fvec3 p0 = positionPath()[i-1] - positionPath()[i];
00101 fvec3 p1 = positionPath()[i+1] - positionPath()[i];
00102 p0.normalize();
00103 p1.normalize();
00104 plane_normals[i] = (p1-p0).normalize();
00105 }
00106
00107 for(unsigned i=1; i<positionPath().size()-1; ++i)
00108 {
00109 for(int j=0; j<(int)silhouette().size(); ++j)
00110 {
00111 fvec3 V = (positionPath()[i] - positionPath()[i-1]).normalize();
00112 const fvec3& P = projected_sil[j];
00113 const fvec3& orig = positionPath()[i];
00114 const fvec3& N = plane_normals [i];
00115 float d = dot(N,orig);
00116 float t = dot(V,N) ? (d-dot(P,N))/dot(V,N) : 0 ;
00117
00118 verts.at(j+silhouette().size()*(i-1)) = projected_sil[j] = P + V*t;
00119 }
00120 }
00121
00122
00123 if(!rotationPath().empty())
00124 {
00125 for(unsigned i=1; i<positionPath().size()-1; ++i)
00126 {
00127 fvec3 r = (positionPath()[i+1] - positionPath()[i]).normalize();
00128 fmat4 mat = vl::fmat4::getRotation(rotationPath()[i-1],r);
00129 fvec3 c;
00130 for(int j=0; j<(int)silhouette().size(); ++j)
00131 c += verts.at(j+silhouette().size()*(i-1));
00132 c /= (float)silhouette().size();
00133 for(int j=0; j<(int)silhouette().size(); ++j)
00134 verts.at(j+silhouette().size()*(i-1)) = (mat*(verts.at(j+silhouette().size()*(i-1))-c))+c;
00135 }
00136 }
00137
00138
00139 if(!scalingPath().empty())
00140 {
00141 for(unsigned i=1; i<positionPath().size()-1; ++i)
00142 {
00143 float s = scalingPath()[i-1];
00144 fvec3 c;
00145 for(int j=0; j<(int)silhouette().size(); ++j)
00146 c += verts.at(j+silhouette().size()*(i-1));
00147 c /= (float)silhouette().size();
00148 for(int j=0; j<(int)silhouette().size(); ++j)
00149 verts.at(j+silhouette().size()*(i-1)) = (s*(verts.at(j+silhouette().size()*(i-1))-c))+c;
00150 }
00151 }
00152
00153 for(unsigned int i = 0; i < silhouettes().size(); ++i)
00154 {
00155 int previousSilhouetteSize = (i == 0) ? 0 : silhouettes().at(i - 1);
00156 int prof_count = silhouetteMode() == SilhouetteClosed ? (int)silhouettes().at(i) : (int)silhouettes().at(i) - 1;
00157 ref<DrawElementsUInt> de = new DrawElementsUInt(PT_QUADS);
00158 geom->drawCalls()->push_back(de.get());
00159 de->indexBuffer()->resize(4 * prof_count * (segments-1));
00160 for(size_t iseg=0; iseg<segments-1; ++iseg)
00161 {
00162 for(int iquad=0; iquad<prof_count; ++iquad)
00163 {
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 3) = (iseg + 0) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize;
00174 de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 2) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize;
00175 de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 1) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize;
00176 de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 0) = (iseg + 1) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize;
00177
00178 }
00179 }
00180 }
00181
00182
00183
00184 size_t tess_bottom_count = 0;
00185 size_t tess_top_count = 0;
00186
00187 if(fillBottom())
00188 {
00189 size_t start = verts.size();
00190 Tessellator tessellator;
00191 for(unsigned i=0; i < silhouettes().size(); ++i)
00192 tessellator.contours().push_back(silhouettes().at(i));
00193 for(unsigned i=0; i<silhouette().size(); ++i)
00194 tessellator.contourVerts().push_back((dvec3)verts[i]);
00195 tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
00196 tessellator.tessellate();
00197 for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
00198 verts.push_back(tessellator.tessellatedTris()[i]);
00199 if (tessellator.tessellatedTris().size())
00200 geom->drawCalls()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
00201 tess_bottom_count = tessellator.tessellatedTris().size();
00202 }
00203 if(fillTop())
00204 {
00205 size_t start = verts.size();
00206 Tessellator tessellator;
00207 for(int i=silhouettes().size() - 1; i >= 0; --i)
00208 tessellator.contours().push_back(silhouettes().at(i));
00209 for(unsigned i=0; i < silhouette().size(); ++i)
00210 tessellator.contourVerts().push_back((dvec3)verts[verts.size()-i-1-tess_bottom_count]);
00211 tessellator.setWindingRule(vl::TW_TESS_WINDING_ODD);
00212 tessellator.tessellate();
00213 for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
00214 verts.push_back(tessellator.tessellatedTris()[i]);
00215 if (tessellator.tessellatedTris().size())
00216 geom->drawCalls()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
00217 tess_top_count = tessellator.tessellatedTris().size();
00218 }
00219
00220 ref<ArrayFloat3> vert_array = new ArrayFloat3;
00221 if(compatibilityProfile)
00222 geom->setVertexArray( vert_array.get() );
00223 else
00224 geom->setVertexAttribArray(VA_Position, vert_array.get());
00225 vert_array->initFrom(verts);
00226
00227 if (!colorPath().empty())
00228 {
00229 ref<ArrayFloat4> col_array = new ArrayFloat4;
00230 if(compatibilityProfile)
00231 geom->setColorArray(col_array.get());
00232 else
00233 geom->setVertexAttribArray(VA_Color, col_array.get());
00234 col_array->resize(geom->vertexArray()->size());
00235 int offs = 0;
00236 for(size_t iseg=0; iseg<segments; ++iseg)
00237 {
00238 for(unsigned j=0; j<silhouette().size(); ++j, ++offs)
00239 col_array->at(offs) = colorPath()[iseg];
00240 }
00241 if (fillBottom())
00242 {
00243 for(unsigned j=0; j<tess_bottom_count; ++j, ++offs)
00244 col_array->at(offs) = colorPath()[0];
00245 }
00246 if (fillTop())
00247 {
00248 for(unsigned j=0; j<tess_top_count; ++j, ++offs)
00249 col_array->at(offs) = colorPath().back();
00250 }
00251 }
00252
00253 if (!smooth())
00254 geom->convertDrawCallToDrawArrays();
00255
00256 geom->computeNormals();
00257
00258 return geom;
00259 }