00001 #include <esg/Definitions.h>
00002 #include <esg/mesh/PolygonalMesh.h>
00003 #include <assert.h>
00004 #include <iostream>
00005
00006 using namespace esg;
00007
00008 #ifndef LONGBITS
00009 #define LONGBITS (sizeof(long int) * 8)
00010 #endif
00011
00012 const unsigned PolygonalMesh::MAX_LOOP = 50;
00013
00014 Mesh::Vert* PolygonalMesh::_find_vertex(int index)
00015 {
00016 return _vertices[index];
00017 }
00018
00019 void PolygonalMesh::_store_vertex(Vert* v)
00020 {
00021 if (v) _vertices[v->jmeno_vrcholu] = v;
00022 }
00023
00024
00025 Vector3 PolygonalMesh::_plane_normal(const unsigned vIndices[],
00026 unsigned i1,
00027 unsigned i2,
00028 unsigned i3)
00029 {
00030 Vector3 normal;
00031 Mesh::Vert *v;
00032 Vector3 v1, v2, v3;
00033
00034 v = _find_vertex(vIndices[i1]);
00035 assert(v);
00036 v1.set(v->x, v->y, v->z);
00037 v = _find_vertex(vIndices[i2]);
00038 assert(v);
00039 v2.set(v->x, v->y, v->z);
00040 v = _find_vertex(vIndices[i3]);
00041 assert(v);
00042 v3.set(v->x, v->y, v->z);
00043 normal.cross(v2 - v1, v3 - v1);
00044 normal.normalize();
00045
00046 return normal;
00047 }
00048
00049 long int PolygonalMesh::_multiplex(unsigned i1, unsigned i2)
00050 {
00051 if (i1 < i2)
00052 return (i1<<(LONGBITS/2))|i2;
00053 else
00054 return (i2<<(LONGBITS/2))|i1;
00055 }
00056
00057 Mesh::Edge* PolygonalMesh::_find_edge(unsigned i1, unsigned i2)
00058 {
00059 return _edges[_multiplex(i1,i2)];
00060 }
00061
00062 void PolygonalMesh::_store_edge(Edge* e)
00063 {
00064 _edges[_multiplex(e->V1->jmeno_vrcholu, e->V2->jmeno_vrcholu)] = e;
00065 }
00066
00067 void PolygonalMesh::_erase_edge(unsigned i1, unsigned i2)
00068 {
00069 _edges.erase(_edges.find(_multiplex(i1,i2)));
00070 }
00071
00072 Mesh::Edge* PolygonalMesh::_append_new_edge(Mesh::Vert* V1p,
00073 Mesh::Vert* V2p,
00074 Mesh::Plane* F)
00075 {
00076 Mesh::Edge *E = new Edge;
00077
00078 E->V1=V1p; E->V2=V2p; E->jmeno_hrany=++pocet_hran;
00079 E->LeftLoop=F; E->RightLoop=F;
00080 E->LeftIn = E; E->LeftOut = E;
00081 E->RightIn = E; E->RightOut = E;
00082 E->druh_hrany = TELESOVA;
00083
00084 _connect_edge(E,F);
00085
00086 AppendEdge(pSolid,E);
00087 _store_edge(E);
00088 return E;
00089 }
00090
00091 bool PolygonalMesh::_connect_edge(Mesh::Edge* E, Mesh::Plane* F)
00092 {
00093 if (F->any_edge == NULL) {
00094 F->any_edge = E;
00095 return true;
00096 }
00097
00098 Mesh::Vert *Vin, *Vout;
00099 Mesh::Vert *EVin, *EVout;
00100 Mesh::Edge *CE = F->any_edge;
00101 Mesh::Vert *VNin;
00102 Mesh::Vert *VNout;
00103 Mesh::Edge *CEN;
00104
00105 Orient_Edge(E,F,&EVin,&EVout);
00106 Orient_Edge(CE,F,&Vin,&Vout);
00107
00108
00109 register unsigned loops = 0;
00110 while (Vout != EVin) {
00111 if (loops++ > MAX_LOOP) {
00112 std::cerr << "PolygonalMesh::_connect_edge(): Infinite loop detected" << std::endl;
00113 return false;
00114 }
00115 CE = Next_Edge_in_loop(CE,&Vin,&Vout);
00116 }
00117
00118
00119 VNin = Vin;
00120 VNout = Vout;
00121 CEN = Next_Edge_in_loop(CE,&VNin,&VNout);
00122
00123
00124 if (CE->LeftLoop == F) CE->LeftOut = E;
00125 else CE->RightOut = E;
00126 if (E->LeftLoop == F) { E->LeftIn = CE; E->LeftOut = CEN; }
00127 else { E->RightIn = CE; E->RightOut = CEN; }
00128 if (CEN->LeftLoop == F) CEN->LeftIn = E;
00129 else CEN->RightIn = E;
00130
00131 return true;
00132 }
00133
00134 Mesh::Edge* PolygonalMesh::_split_edge(Mesh::Edge * E, Mesh::Vert * V)
00135 {
00136 Mesh::Edge *NE = new Edge;
00137
00138 NE = new Edge;
00139 NE->V1=E->V1; NE->V2=V; NE->jmeno_hrany=++pocet_hran;
00140 NE->LeftLoop=E->LeftLoop; NE->RightLoop=E->RightLoop;
00141 NE->druh_hrany = VNITRNI;
00142
00143 NE->LeftIn = E->LeftIn;
00144 NE->RightOut = E->RightOut;
00145 if (NE->LeftIn->V2 == NE->V1) {
00146 NE->LeftIn->LeftOut = NE;
00147 if (NE->LeftIn->RightIn == E) NE->LeftIn->RightIn = NE;
00148 } else {
00149 NE->LeftIn->RightOut = NE;
00150 if (NE->LeftIn->LeftIn == E) NE->LeftIn->LeftIn = NE;
00151 }
00152 if (NE->RightOut->V2 == NE->V1) NE->RightOut->RightIn = NE;
00153 else NE->RightOut->LeftIn = NE;
00154 NE->LeftOut = (NE->RightIn = E);
00155 E->LeftIn = (E->RightOut = NE);
00156
00157 _erase_edge(E->V1->jmeno_vrcholu, E->V2->jmeno_vrcholu);
00158 E->V1 = V;
00159 AppendEdge(pSolid,NE);
00160 _store_edge(E);
00161 _store_edge(NE);
00162
00163 return NE;
00164 }
00165
00166 Mesh::Plane* PolygonalMesh::_split_plane(Mesh::Plane * F,
00167 Mesh::Vert * V1,
00168 Mesh::Vert * V2)
00169 {
00170 if (_find_edge(V1->jmeno_vrcholu, V2->jmeno_vrcholu)) return NULL;
00171
00172 Mesh::Plane* NF = NewPlane(pSolid, F->a, F->b, F->c, F->d);
00173 Mesh::Edge* E = new Edge;
00174
00175 E->V1=V1; E->V2=V2; E->jmeno_hrany=++pocet_hran;
00176 E->LeftLoop=F; E->RightLoop=NF;
00177 E->druh_hrany = VNITRNI;
00178
00179 AppendEdge(pSolid,E);
00180 _store_edge(E);
00181
00182
00183 Mesh::Vert *Vin, *Vout;
00184 Mesh::Edge *CE = F->any_edge;
00185 Mesh::Edge *CEN;
00186
00187
00188 Orient_Edge(CE,F,&Vin,&Vout);
00189 while (Vout != V1) CE = Next_Edge_in_loop(CE,&Vin,&Vout);
00190 CEN = Next_Edge_in_loop(CE,&Vin,&Vout);
00191
00192
00193 if (CE->LeftLoop == F) CE->LeftOut = E;
00194 else CE->RightOut = E;
00195 if (CEN->LeftLoop == F) CEN->LeftIn = E;
00196 else CEN->RightIn = E;
00197 E->LeftIn = CE;
00198 E->RightOut = CEN;
00199
00200
00201
00202
00203 CE = CEN;
00204 while (Vout != V2) {
00205 if (CE->LeftLoop == F) CE->LeftLoop = NF;
00206 if (CE->RightLoop == F) CE->RightLoop = NF;
00207 CE = Next_Edge_in_loop(CE,&Vin,&Vout);
00208 }
00209 if (CE->LeftLoop == F) CE->LeftLoop = NF;
00210 if (CE->RightLoop == F) CE->RightLoop = NF;
00211 CEN = Next_Edge_in_loop(CE,&Vin,&Vout);
00212
00213
00214 if (CE->LeftLoop == NF) CE->LeftOut = E;
00215 else CE->RightOut = E;
00216 if (CEN->LeftLoop == F) CEN->LeftIn = E;
00217 else CEN->RightIn = E;
00218 E->LeftOut = CEN;
00219 E->RightIn = CE;
00220
00221 F->any_edge = (NF->any_edge = E);
00222
00223 return NF;
00224 }
00225
00226 bool PolygonalMesh::_get_facet_topology(Vert* vertices[],
00227 Edge* edges[],
00228 unsigned num,
00229 const unsigned vIndices[],
00230 const Vector3 normals[])
00231 {
00232 bool duplicate = false;
00233
00234 for (register unsigned i = 0; i < num; i++) {
00235 vertices[i] = _find_vertex(vIndices[i]);
00236 if (!vertices[i]) {
00237 fprintf(stderr,"PolygonalMesh Error: Index of vertex out of range\n");
00238 return false;
00239 }
00240
00241
00242 if (normals) {
00243 if (vertices[i]->hasValidNormal() &&
00244 !vertices[i]->normal.equals(normals[i]))
00245 duplicate = true;
00246 else
00247 vertices[i]->normal.set(normals[i]);
00248 }
00249 }
00250
00251
00252 for (register unsigned i = 0; i < num && !duplicate; i++) {
00253 edges[i] = _find_edge(vertices[i]->jmeno_vrcholu,
00254 vertices[(i+1)%num]->jmeno_vrcholu);
00255 if (edges[i] && edges[i]->LeftLoop != edges[i]->RightLoop)
00256 duplicate = true;
00257 }
00258
00259 if (duplicate) {
00260 for (register unsigned i = 0; i < num; i++) {
00261
00262
00263 if (vertices[i]->hasValidNormal() ||
00264 (edges[i] && edges[i]->LeftLoop != edges[i]->RightLoop)) {
00265 Vert* v = NewVertex(pSolid,
00266 vertices[i]->x,
00267 vertices[i]->y,
00268 vertices[i]->z);
00269 if (normals) v->normal.set(normals[i]);
00270 else v->normal.set(vertices[i]->normal);
00271 vertices[i] = v;
00272 _store_vertex(vertices[i]);
00273 }
00274 edges[i] = NULL;
00275 }
00276 }
00277
00278 return true;
00279 }
00280
00281
00282
00283
00284 PolygonalMesh::PolygonalMesh(const Vector3 vertices[],
00285 unsigned nvi,
00286 const unsigned vIndices[])
00287 {
00288 if (! vertices || nvi == 0) {
00289 fprintf(stderr,"PolygonalMesh Error: Surface without vertices\n");
00290 return;
00291 }
00292
00293
00294 pSolid = new Solid;
00295 pSolid->solid_name = 0;
00296 pSolid->first_vertex = NULL;
00297 pSolid->first_edge = NULL;
00298 pSolid->first_plane = NULL;
00299 pSolid->next_solid = pSolid;
00300 pSolid->previous_solid = pSolid;
00301
00302
00303 for (register unsigned i = 0; i < nvi; i++) {
00304
00305 if (vIndices) {
00306 Vert* v = NewVertex(pSolid,
00307 vertices[vIndices[i]].x,
00308 vertices[vIndices[i]].y,
00309 vertices[vIndices[i]].z);
00310 _store_vertex(v);
00311 } else {
00312 Vert* v = NewVertex(pSolid,
00313 vertices[i].x,
00314 vertices[i].y,
00315 vertices[i].z);
00316 _store_vertex(v);
00317 }
00318 }
00319
00320 pActSolid = pSolid;
00321 pActVert = pSolid->first_vertex;
00322 }
00323
00324 #define __NEW_FACET_FAILED(r) { \
00325 cerr << "PolygonalMesh::addFacet(): Can't append facet - " << (r) << ":" << endl; \
00326 for (unsigned i = 0; i < nVert; i++) { \
00327 cerr << " v" << i << ": "; \
00328 cerr << _find_vertex(vIndices[i])->x << " " ; \
00329 cerr << _find_vertex(vIndices[i])->y << " " ; \
00330 cerr << _find_vertex(vIndices[i])->z << endl; \
00331 } \
00332 delete [] fVertices; \
00333 delete [] fEdges; \
00334 return false; \
00335 }
00336
00337 bool PolygonalMesh::addFacet(const unsigned vIndices[],
00338 const Vector3 normals[],
00339 unsigned nVert,
00340 const Vector3& normal)
00341 {
00342 Vert** fVertices = new Vert* [nVert];
00343 Edge** fEdges = new Edge* [nVert];
00344
00345 for (register unsigned i = 0; i < nVert; i++) {
00346 fVertices[i] = NULL;
00347 fEdges[i] = NULL;
00348 }
00349
00350 if (!_get_facet_topology(fVertices, fEdges, nVert, vIndices, normals))
00351 __NEW_FACET_FAILED("Bad topology");
00352
00353
00354 Mesh::Plane* p = NewPlane(pSolid,
00355 normal.x,normal.y,normal.z,
00356 -normal.dot(Vector3(fVertices[0]->x,
00357 fVertices[0]->y,
00358 fVertices[0]->z)));
00359
00360
00361 for (unsigned i = 0; i < nVert; i++) {
00362 if (!fEdges[i]) {
00363 fEdges[i]=_append_new_edge(fVertices[i],fVertices[(i+1)%nVert],p);
00364 if (!fEdges[i]) __NEW_FACET_FAILED("Appending new edge");
00365 } else {
00366 fEdges[i]->RightLoop = p;
00367 fEdges[i]->druh_hrany = VNITRNI;
00368 if (!_connect_edge(fEdges[i], p))
00369 __NEW_FACET_FAILED("Connecting new edge");
00370 }
00371 }
00372
00373 delete [] fVertices;
00374 delete [] fEdges;
00375
00376 return true;
00377 }
00378
00379 #undef __NEW_FACET_FAILED
00380
00381 bool PolygonalMesh::addFacet(const unsigned vIndices[],
00382 const Vector3 normals[],
00383 unsigned nVert)
00384 {
00385 return addFacet(vIndices,
00386 normals,
00387 nVert,
00388 _plane_normal(vIndices, 0, 1, nVert-1));
00389 }