00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include <GL/gl.h>
00027
00028 #include <archon/x3d/server/field_type.H>
00029 #include <archon/x3d/server/field.H>
00030 #include <archon/x3d/server/geometry.H>
00031
00032 namespace Archon
00033 {
00034 namespace X3D
00035 {
00036 const NodeType *GeometryNode::type = 0;
00037 const NodeType *Geometry3DNode::type = 0;
00038
00039 const NodeType *Box::type = 0;
00040 const NodeType *Cone::type = 0;
00041 const NodeType *Cylinder::type = 0;
00042 const NodeType *IndexedLineSet::type = 0;
00043 const NodeType *PointSet::type = 0;
00044 const NodeType *Sphere::type = 0;
00045
00046 const NodeType *ComposedGeometryNode::type = 0;
00047 const NodeType *ElevationGrid::type = 0;
00048 const NodeType *IndexedFaceSet::type = 0;
00049
00050 const NodeType *ShapeNode::type = 0;
00051 const NodeType *Shape::type = 0;
00052
00053 void initializeGeometryComponent()
00054 {
00055 vector<const FieldBase *> fields;
00056
00057
00058
00059
00060 GeometryNode::type =
00061 NodeType::newAbstract("GeometryNode", false, 0,
00062 Node::type);
00063
00064
00065
00066
00067 Geometry3DNode::type =
00068 NodeType::newAbstract("Geometry3DNode", false, 0,
00069 GeometryNode::type);
00070
00071
00072
00073
00074 fields.push_back(newPrivateField("size", SFVec3f::type,
00075 &Box::size));
00076 Box::type =
00077 NodeType::newConcrete("Box", "geometry",
00078 Box::instantiate, &fields,
00079 Geometry3DNode::type);
00080 fields.clear();
00081
00082
00083
00084
00085 fields.push_back(newPrivateField("bottomRadius", SFFloat::type,
00086 &Cone::bottomRadius));
00087 fields.push_back(newPrivateField("height", SFFloat::type,
00088 &Cone::height));
00089 fields.push_back(newPrivateField("side", SFBool::type,
00090 &Cone::side));
00091 fields.push_back(newPrivateField("bottom", SFBool::type,
00092 &Cone::bottom));
00093 Cone::type =
00094 NodeType::newConcrete("Cone", "geometry",
00095 Cone::instantiate, &fields,
00096 Geometry3DNode::type);
00097 fields.clear();
00098
00099
00100
00101
00102 fields.push_back(newPrivateField("bottom", SFBool::type,
00103 &Cylinder::bottom));
00104 fields.push_back(newPrivateField("radius", SFFloat::type,
00105 &Cylinder::radius));
00106 fields.push_back(newPrivateField("height", SFFloat::type,
00107 &Cylinder::height));
00108 fields.push_back(newPrivateField("side", SFBool::type,
00109 &Cylinder::side));
00110 fields.push_back(newPrivateField("top", SFBool::type,
00111 &Cylinder::top));
00112 Cylinder::type =
00113 NodeType::newConcrete("Cylinder", "geometry",
00114 Cylinder::instantiate, &fields,
00115 Geometry3DNode::type);
00116 fields.clear();
00117
00118
00119
00120
00121 fields.push_back(newExposedField("color",
00122 &IndexedLineSet::color,
00123 &IndexedLineSet::colorChanged,
00124 &IndexedLineSet::colorStamp));
00125 fields.push_back(newExposedField("coord",
00126 &IndexedLineSet::coord,
00127 &IndexedLineSet::coordChanged,
00128 &IndexedLineSet::coordStamp));
00129 fields.push_back(newPrivateField("colorIndex", MFInt32::type,
00130 &IndexedLineSet::colorIndex));
00131 fields.push_back(newEventIn("set_colorIndex", MFInt32::type,
00132 &IndexedLineSet::colorIndex,
00133 &IndexedLineSet::colorIndexStamp));
00134 fields.push_back(newPrivateField("colorPerVertex", SFBool::type,
00135 &IndexedLineSet::colorPerVertex));
00136 fields.push_back(newPrivateField("coordIndex", MFInt32::type,
00137 &IndexedLineSet::coordIndex));
00138 fields.push_back(newEventIn("set_coordIndex", MFInt32::type,
00139 &IndexedLineSet::coordIndex,
00140 &IndexedLineSet::coordIndexStamp));
00141 fields.push_back(newPrivateField("lineWidth", SFFloat::type,
00142 &IndexedLineSet::lineWidth));
00143 IndexedLineSet::type =
00144 NodeType::newConcrete("IndexedLineSet", "geometry",
00145 IndexedLineSet::instantiate, &fields,
00146 Geometry3DNode::type);
00147 fields.clear();
00148
00149
00150
00151
00152
00153 fields.push_back(newExposedField("color",
00154 &PointSet::color,
00155 &PointSet::colorChanged,
00156 &PointSet::colorStamp));
00157 fields.push_back(newExposedField("coord",
00158 &PointSet::coord,
00159 &PointSet::coordChanged,
00160 &PointSet::coordStamp));
00161 PointSet::type =
00162 NodeType::newConcrete("PointSet", "geometry",
00163 PointSet::instantiate, &fields,
00164 Geometry3DNode::type);
00165 fields.clear();
00166
00167
00168
00169
00170 fields.push_back(newPrivateField("radius", SFFloat::type,
00171 &Sphere::radius));
00172 Sphere::type =
00173 NodeType::newConcrete("Sphere", "geometry",
00174 Sphere::instantiate, &fields,
00175 Geometry3DNode::type);
00176 fields.clear();
00177
00178
00179
00180
00181 fields.push_back(newExposedField("color",
00182 &ComposedGeometryNode::color,
00183 &ComposedGeometryNode::colorAssign,
00184 &ComposedGeometryNode::colorChanged,
00185 &ComposedGeometryNode::colorStamp));
00186 fields.push_back(newExposedField("coord",
00187 &ComposedGeometryNode::coord,
00188 &ComposedGeometryNode::coordAssign,
00189 &ComposedGeometryNode::coordChanged,
00190 &ComposedGeometryNode::coordStamp));
00191 fields.push_back(newExposedField("normal",
00192 &ComposedGeometryNode::normal,
00193 &ComposedGeometryNode::normalAssign,
00194 &ComposedGeometryNode::normalChanged,
00195 &ComposedGeometryNode::normalStamp));
00196 fields.push_back(newExposedField("texCoord",
00197 &ComposedGeometryNode::texCoord,
00198 &ComposedGeometryNode::texCoordAssign,
00199 &ComposedGeometryNode::texCoordChanged,
00200 &ComposedGeometryNode::texCoordStamp));
00201 fields.push_back(newPrivateField("ccw", SFBool::type,
00202 &ComposedGeometryNode::ccw));
00203 fields.push_back(newPrivateField("colorPerVertex", SFBool::type,
00204 &ComposedGeometryNode::colorPerVertex));
00205 fields.push_back(newPrivateField("normalPerVertex", SFBool::type,
00206 &ComposedGeometryNode::normalPerVertex));
00207 fields.push_back(newPrivateField("solid", SFBool::type,
00208 &ComposedGeometryNode::solid));
00209 ComposedGeometryNode::type =
00210 NodeType::newAbstract("ComposedGeometryNode", false, &fields,
00211 Geometry3DNode::type);
00212 fields.clear();
00213
00214
00215
00216
00217 fields.push_back(newPrivateField("convex", SFBool::type,
00218 &IndexedFaceSet::convex));
00219 fields.push_back(newPrivateField("colorIndex", MFInt32::type,
00220 &IndexedFaceSet::colorIndex));
00221 fields.push_back(newEventIn("set_colorIndex", MFInt32::type,
00222 &IndexedFaceSet::colorIndexAssign,
00223 &IndexedFaceSet::colorIndexStamp));
00224 fields.push_back(newPrivateField("coordIndex", MFInt32::type,
00225 &IndexedFaceSet::coordIndex));
00226 fields.push_back(newEventIn("set_coordIndex", MFInt32::type,
00227 &IndexedFaceSet::coordIndexAssign,
00228 &IndexedFaceSet::coordIndexStamp));
00229 fields.push_back(newPrivateField("creaseAngle", SFFloat::type,
00230 &IndexedFaceSet::creaseAngle));
00231 fields.push_back(newPrivateField("normalIndex", MFInt32::type,
00232 &IndexedFaceSet::normalIndex));
00233 fields.push_back(newEventIn("set_normalIndex", MFInt32::type,
00234 &IndexedFaceSet::normalIndexAssign,
00235 &IndexedFaceSet::normalIndexStamp));
00236 fields.push_back(newPrivateField("texCoordIndex", MFInt32::type,
00237 &IndexedFaceSet::texCoordIndex));
00238 fields.push_back(newEventIn("set_texCoordIndex", MFInt32::type,
00239 &IndexedFaceSet::texCoordIndexAssign,
00240 &IndexedFaceSet::texCoordIndexStamp));
00241 IndexedFaceSet::type =
00242 NodeType::newConcrete("IndexedFaceSet", "geometry",
00243 IndexedFaceSet::instantiate, &fields,
00244 ComposedGeometryNode::type);
00245 fields.clear();
00246
00247
00248
00249
00250 fields.push_back(newPrivateField("creaseAngle", SFFloat::type,
00251 &ElevationGrid::creaseAngle));
00252 fields.push_back(newPrivateField("height", MFFloat::type,
00253 &ElevationGrid::height));
00254 fields.push_back(newEventIn("set_height", MFFloat::type,
00255 &ElevationGrid::height,
00256 &ElevationGrid::heightStamp));
00257 fields.push_back(newPrivateField("xDimension", SFInt32::type,
00258 &ElevationGrid::xDimension));
00259 fields.push_back(newPrivateField("xSpacing", SFFloat::type,
00260 &ElevationGrid::xSpacing));
00261 fields.push_back(newPrivateField("zDimension", SFInt32::type,
00262 &ElevationGrid::zDimension));
00263 fields.push_back(newPrivateField("zSpacing", SFFloat::type,
00264 &ElevationGrid::zSpacing));
00265 ElevationGrid::type =
00266 NodeType::newConcrete("ElevationGrid", "geometry",
00267 ElevationGrid::instantiate, &fields,
00268 ComposedGeometryNode::type);
00269 fields.clear();
00270
00271
00272
00273
00274 ShapeNode::type =
00275 NodeType::newAbstract("ShapeNode", false, 0,
00276 ChildNode::type);
00277
00278
00279
00280
00281 fields.push_back(newExposedField("appearance",
00282 &Shape::appearance,
00283 &Shape::appearanceChanged,
00284 &Shape::appearanceStamp));
00285 fields.push_back(newExposedField("geometry",
00286 &Shape::geometry,
00287 &Shape::geometryChanged,
00288 &Shape::geometryStamp));
00289 Shape::type =
00290 NodeType::newConcrete("Shape", "children",
00291 Shape::instantiate, &fields,
00292 ShapeNode::type, BoundedObject::type);
00293 fields.clear();
00294 }
00295
00296
00297 bool ComposedGeometryNode::coordAssign(const Ref<CoordinateNode> &v, const Time &t)
00298 {
00299 coord = v;
00300 coordStamp = t;
00301 reprocess();
00302 return true;
00303 }
00304
00305 bool ComposedGeometryNode::colorAssign(const Ref<ColorNode> &v, const Time &t)
00306 {
00307 color = v;
00308 colorStamp = t;
00309 reprocess();
00310 return true;
00311 }
00312
00313 bool ComposedGeometryNode::normalAssign(const Ref<NormalNode> &v, const Time &t)
00314 {
00315 normal = v;
00316 normalStamp = t;
00317 reprocess();
00318 return true;
00319 }
00320
00321 bool ComposedGeometryNode::texCoordAssign(const Ref<TextureCoordinateNode> &v, const Time &t)
00322 {
00323 texCoord = v;
00324 texCoordStamp = t;
00325 reprocess();
00326 return true;
00327 }
00328
00329 bool IndexedFaceSet::coordIndexAssign(const vector<int> &v, const Time &t)
00330 {
00331 coordIndex = v;
00332 coordIndexStamp = t;
00333 reprocess();
00334 return true;
00335 }
00336
00337 bool IndexedFaceSet::colorIndexAssign(const vector<int> &v, const Time &t)
00338 {
00339 colorIndex = v;
00340 colorIndexStamp = t;
00341 reprocess();
00342 return true;
00343 }
00344
00345 bool IndexedFaceSet::normalIndexAssign(const vector<int> &v, const Time &t)
00346 {
00347 normalIndex = v;
00348 normalIndexStamp = t;
00349 reprocess();
00350 return true;
00351 }
00352
00353 bool IndexedFaceSet::texCoordIndexAssign(const vector<int> &v, const Time &t)
00354 {
00355 texCoordIndex = v;
00356 texCoordIndexStamp = t;
00357 reprocess();
00358 return true;
00359 }
00360
00361
00362 void renderNormals(const vector<Vector3> &n, const RenderConfig *c)
00363 {
00364 glDisable(GL_LIGHTING);
00365 glDisable(GL_TEXTURE_2D);
00366 glLineWidth(1);
00367 glColor3f(c->normalColor[0], c->normalColor[1], c->normalColor[2]);
00368 glBegin(GL_LINES);
00369 unsigned i = 0;
00370 while(i<n.size())
00371 {
00372 Vector3 v = n[i++];
00373 glVertex3d(v[0], v[1], v[2]);
00374 v += n[i++] * c->normalLength;
00375 glVertex3d(v[0], v[1], v[2]);
00376 }
00377 glEnd();
00378 }
00379
00380
00381
00382
00383 int Box::intersect(const Math::Ray3 &ray, double &dist) const
00384 {
00385 Math::Box3 box(size);
00386 return Math::intersect(ray, box, dist);
00387 }
00388
00389 void Box::getNormalAndTexCoord(Vector3 hitPoint, int where,
00390 const Shape *,
00391 Vector3 *hitNormal,
00392 Vector2 *hitTexCoord) const
00393 {
00394 switch(where)
00395 {
00396 case 1:
00397 if(hitNormal) hitNormal->set(-1, 0, 0);
00398 if(hitTexCoord) hitTexCoord->set(0.5+hitPoint[2]/size[2], 0.5+hitPoint[1]/size[1]);
00399 break;
00400 case 2:
00401 if(hitNormal) hitNormal->set(1, 0, 0);
00402 if(hitTexCoord) hitTexCoord->set(0.5-hitPoint[2]/size[2], 0.5+hitPoint[1]/size[1]);
00403 break;
00404 case 3:
00405 if(hitNormal) hitNormal->set(0, -1, 0);
00406 if(hitTexCoord) hitTexCoord->set(0.5+hitPoint[0]/size[0], 0.5+hitPoint[2]/size[2]);
00407 break;
00408 case 4:
00409 if(hitNormal) hitNormal->set(0, 1, 0);
00410 if(hitTexCoord) hitTexCoord->set(0.5+hitPoint[0]/size[0], 0.5-hitPoint[2]/size[2]);
00411 break;
00412 case 5:
00413 if(hitNormal) hitNormal->set(0, 0, -1);
00414 if(hitTexCoord) hitTexCoord->set(0.5-hitPoint[0]/size[0], 0.5+hitPoint[1]/size[1]);
00415 break;
00416 case 6:
00417 if(hitNormal) hitNormal->set(0, 0, 1);
00418 if(hitTexCoord) hitTexCoord->set(0.5+hitPoint[0]/size[0], 0.5+hitPoint[1]/size[1]);
00419 break;
00420 }
00421 }
00422
00423
00424
00425
00426 int Cone::intersect(const Math::Ray3 &ray, double &dist) const
00427 {
00428 bool enterOnly = side & bottom;
00429 return Math::intersectCone(ray, height, bottomRadius, dist, side,
00430 bottom, enterOnly);
00431 }
00432
00433 void Cone::getNormalAndTexCoord(Vector3 hitPoint, int where,
00434 const Shape *,
00435 Vector3 *hitNormal,
00436 Vector2 *hitTexCoord) const
00437 {
00438 switch(where)
00439 {
00440 case 1:
00441 if(hitNormal)
00442 {
00443 double h = bottomRadius/height;
00444 double f = bottomRadius * (0.5 - hitPoint[1]/height);
00445 if(f==0) hitNormal->set(0, h, 1);
00446 else hitNormal->set(hitPoint[0]/f, h, hitPoint[2]/f);
00447 }
00448
00449 if(hitTexCoord)
00450 {
00451 (*hitTexCoord)[0] = hitPoint[0] == 0 ? hitPoint[2] < 0 ? 0 : 0.5 :
00452 (hitPoint[0] < 0 ? 0.25 : 0.75) - atan(hitPoint[2]/hitPoint[0]) / (2 * M_PI);
00453
00454 (*hitTexCoord)[1] = 0.5 + hitPoint[1]/height;
00455 }
00456 break;
00457
00458 case 2:
00459 if(hitNormal) hitNormal->set(0, -1, 0);
00460 if(hitTexCoord) hitTexCoord->set(0.5+hitPoint[0]/bottomRadius/2, 0.5+hitPoint[2]/bottomRadius/2);
00461 break;
00462 }
00463 }
00464
00465
00466
00467
00474 int Cylinder::intersect(const Math::Ray3 &ray, double &dist) const
00475 {
00476 bool enterOnly = side & top & bottom;
00477 return Math::intersectCylinder(ray, height, radius, dist, side,
00478 top, bottom, enterOnly);
00479 }
00480
00481 void Cylinder::getNormalAndTexCoord(Vector3 hitPoint, int where,
00482 const Shape *,
00483 Vector3 *hitNormal,
00484 Vector2 *hitTexCoord) const
00485 {
00486 switch(where)
00487 {
00488 case 1:
00489 if(hitNormal)
00490 {
00491 hitNormal->set(hitPoint[0], 0, hitPoint[2]);
00492 }
00493
00494 if(hitTexCoord)
00495 {
00496 (*hitTexCoord)[0] = hitPoint[0] == 0 ? hitPoint[2] < 0 ? 0 : 0.5 :
00497 (hitPoint[0] < 0 ? 0.25 : 0.75) - atan(hitPoint[2]/hitPoint[0]) / (2 * M_PI);
00498
00499 (*hitTexCoord)[1] = 0.5 + hitPoint[1]/height;
00500 }
00501 break;
00502
00503 case 2:
00504 if(hitNormal) hitNormal->set(0, -1, 0);
00505 if(hitTexCoord) hitTexCoord->set(0.5+hitPoint[0]/radius/2, 0.5+hitPoint[2]/radius/2);
00506 break;
00507
00508 case 3:
00509 if(hitNormal) hitNormal->set(0, 1, 0);
00510 if(hitTexCoord) hitTexCoord->set(0.5+hitPoint[0]/radius/2, 0.5-hitPoint[2]/radius/2);
00511 break;
00512 }
00513 }
00514
00515
00516
00517
00518 int Sphere::intersect(const Math::Ray3 &ray, double &dist) const
00519 {
00520 Math::Sphere3 sphere(radius);
00521 return Math::intersect(ray, sphere, dist) ? 1 : 0;
00522 }
00523
00524 void Sphere::getNormalAndTexCoord(Vector3 hitPoint, int where,
00525 const Shape *,
00526 Vector3 *hitNormal,
00527 Vector2 *hitTexCoord) const
00528 {
00529 if(hitNormal) *hitNormal = hitPoint;
00530
00531 if(!hitTexCoord) return;
00532
00533
00534
00535
00536
00537
00538
00539
00540 (*hitTexCoord)[0] = hitPoint[0] == 0 ? hitPoint[2] < 0 ? 0 : 0.5 :
00541 (hitPoint[0] < 0 ? 0.25 : 0.75) - atan(hitPoint[2]/hitPoint[0]) / (2 * M_PI);
00542
00543
00544
00545
00546
00547
00548
00549
00550 (*hitTexCoord)[1] = acos(-hitPoint[1]/radius) / M_PI;
00551 }
00552
00553
00554
00555
00559 int ElevationGrid::intersect(const Math::Ray3 &, double &dist) const
00560 {
00561 return false;
00562 }
00563
00567 void ElevationGrid::getNormalAndTexCoord(Vector3 hitPoint, int where,
00568 const Shape *,
00569 Vector3 *hitNormal,
00570 Vector2 *hitTexCoord) const
00571 {
00572 if(hitNormal) *hitNormal = Vector3::zero();
00573 if(hitTexCoord) *hitTexCoord = Vector2::zero();
00574 }
00575
00576
00577
00578
00587 int IndexedFaceSet::intersect(const Math::Ray3 &ray, double &dist) const
00588 {
00589 if(!coords) return 0;
00590
00591 int f = 0;
00592 for(unsigned i=0; i<preprocessedCoordIndex.size(); ++i, ++f)
00593 {
00594 Vector3 n = preprocessedNormal[f];
00595 double c = dot(n, ray.direction);
00596 if(c >= 0)
00597 {
00598
00599 while(preprocessedCoordIndex[++i] >= 0);
00600 continue;
00601 }
00602
00603 int i0, i1, i2;
00604 Math::sort3(abs(n[0]), abs(n[1]), abs(n[2]), i2, i0, i1);
00605
00606 Vector3 p0 = (*coords)[preprocessedCoordIndex[i]];
00607 Vector3 p1 = (*coords)[preprocessedCoordIndex[++i]];
00608 Vector3 p2 = (*coords)[preprocessedCoordIndex[++i]];
00609
00610 double d = dot(n, p0-ray.origin) / c;
00611
00612 double v00 = ray.origin[i0] + d*ray.direction[i0] - p0[i0];
00613 double v01 = ray.origin[i1] + d*ray.direction[i1] - p0[i1];
00614
00615 double v10 = p1[i0] - p0[i0];
00616 double v11 = p1[i1] - p0[i1];
00617
00618 double v20, v21;
00619 for(;;)
00620 {
00621 v20 = p2[i0] - p0[i0];
00622 v21 = p2[i1] - p0[i1];
00623
00624 double a, b;
00625 bool hit = false;
00626 if(v10)
00627 {
00628 b = (v01*v10 - v00*v11)/(v21*v10 - v20*v11);
00629 if(b >= 0 && b <= 1)
00630 {
00631 a = (v00 - b*v20)/v10;
00632 if(a >= 0 && a+b <= 1) hit = true;
00633 }
00634 }
00635 else
00636 {
00637 b = v00/v20;
00638 if(b >= 0 && b <= 1)
00639 {
00640 a = (v01 - b*v21)/v11;
00641 if(a >= 0 && a+b <= 1) hit = true;
00642 }
00643 }
00644
00645 if(hit)
00646 {
00647
00648
00649
00650 dist = d;
00651 return i-1;
00652 }
00653
00654 int j = preprocessedCoordIndex[++i];
00655 if(j<0) break;
00656
00657 p2 = (*coords)[j];
00658 v10=v20;
00659 v11=v21;
00660 }
00661 }
00662
00663 return 0;
00664 }
00665
00666 void IndexedFaceSet::getNormalAndTexCoord(Vector3 hitPoint, int where,
00667 const Shape *shape,
00668 Vector3 *hitNormal,
00669 Vector2 *hitTexCoord) const
00670 {
00671 if(!coords) return;
00672
00673
00674 int i = where-1;
00675 while(i>0)
00676 {
00677 int j = preprocessedCoordIndex[--i];
00678 if(j<0)
00679 {
00680 ++i;
00681 break;
00682 }
00683 }
00684
00685 int j0 = preprocessedCoordIndex[i];
00686 int j1 = preprocessedCoordIndex[where];
00687 int j2 = preprocessedCoordIndex[where+1];
00688
00689
00690
00691 int f=0;
00692 {
00693 int j=i;
00694 while(j>0) if(preprocessedCoordIndex[--j]<0) ++f;
00695 }
00696
00697 Vector3 n = preprocessedNormal[f];
00698
00699 int i0, i1, i2;
00700 Math::sort3(abs(n[0]), abs(n[1]), abs(n[2]), i2, i0, i1);
00701
00702 Vector3 p0 = (*coords)[j0];
00703 Vector3 p1 = (*coords)[j1];
00704 Vector3 p2 = (*coords)[j2];
00705
00706 double v00 = hitPoint[i0] - p0[i0];
00707 double v01 = hitPoint[i1] - p0[i1];
00708
00709 double v10 = p1[i0] - p0[i0];
00710 double v11 = p1[i1] - p0[i1];
00711
00712 double v20 = p2[i0] - p0[i0];
00713 double v21 = p2[i1] - p0[i1];
00714
00715 double a, b;
00716 if(v10)
00717 {
00718 b = (v01*v10 - v00*v11)/(v21*v10 - v20*v11);
00719 a = (v00 - b*v20)/v10;
00720 }
00721 else
00722 {
00723 b = v00/v20;
00724 a = (v01 - b*v21)/v11;
00725 }
00726
00727
00728 if(hitNormal)
00729 {
00730 Vector3 n0, n1, n2;
00731 if(preprocessedNormalIndex.empty())
00732 {
00733 n0 = (*normals)[j0];
00734 n1 = (*normals)[j1];
00735 n2 = (*normals)[j2];
00736 }
00737 else
00738 {
00739 n0 = (*normals)[preprocessedNormalIndex[i]];
00740 n1 = (*normals)[preprocessedNormalIndex[where]];
00741 n2 = (*normals)[preprocessedNormalIndex[where+1]];
00742 }
00743
00744 n0 *= 1-(a+b);
00745 n1 *= a;
00746 n2 *= b;
00747 n0 += n1;
00748 n0 += n2;
00749 *hitNormal = n0;
00750 }
00751
00752
00753 if(hitTexCoord)
00754 {
00755 if(texCoords)
00756 {
00757 Vector2 t0, t1, t2;
00758 if(preprocessedTexCoordIndex.empty())
00759 {
00760 t0 = (*texCoords)[j0];
00761 t1 = (*texCoords)[j1];
00762 t2 = (*texCoords)[j2];
00763 }
00764 else
00765 {
00766 t0 = (*texCoords)[preprocessedTexCoordIndex[i]];
00767 t1 = (*texCoords)[preprocessedTexCoordIndex[where]];
00768 t2 = (*texCoords)[preprocessedTexCoordIndex[where+1]];
00769 }
00770
00771 t0 *= 1-(a+b);
00772 t1 *= a;
00773 t2 *= b;
00774 t0 += t1;
00775 t0 += t2;
00776 *hitTexCoord = t0;
00777 }
00778 else
00779 {
00780 Vector3 bboxCenter;
00781 Vector3 bboxSize = shape->getBboxSize();
00782 if(bboxSize[0] == -1)
00783 {
00784 bboxCenter = preprocessedBboxCenter;
00785 bboxSize = preprocessedBboxSize;
00786 }
00787 else bboxCenter = shape->getBboxCenter();
00788
00789
00790
00791 int i0, i1, i2;
00792 Math::sort3(bboxSize[0], bboxSize[1], bboxSize[2], i0, i1, i2);
00793
00794 hitTexCoord->set(0.5 + (hitPoint[i0] - bboxCenter[i0]) / bboxSize[i0],
00795 (bboxSize[i1]/2 + hitPoint[i1] - bboxCenter[i1]) / bboxSize[i0]);
00796 }
00797 }
00798 }
00799
00800 void Box::render(bool texture,
00801 const Shape *shape,
00802 const RenderConfig *config)
00803 {
00804 glFrontFace(GL_CCW);
00805 glDisable(GL_COLOR_MATERIAL);
00806 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
00807 glEnable(GL_CULL_FACE);
00808
00809 const double x = size[0]/2;
00810 const double y = size[1]/2;
00811 const double z = size[2]/2;
00812
00813 glBegin(GL_QUADS);
00814
00815
00816 glNormal3d(-1, 0, 0);
00817 if(texture) glTexCoord2d(0, 0);
00818 glVertex3d(-x, -y, -z);
00819 if(texture) glTexCoord2d(1, 0);
00820 glVertex3d(-x, -y, z);
00821 if(texture) glTexCoord2d(1, 1);
00822 glVertex3d(-x, y, z);
00823 if(texture) glTexCoord2d(0, 1);
00824 glVertex3d(-x, y, -z);
00825
00826
00827 glNormal3d( 1, 0, 0);
00828 if(texture) glTexCoord2d(0, 0);
00829 glVertex3d( x, -y, z);
00830 if(texture) glTexCoord2d(1, 0);
00831 glVertex3d( x, -y, -z);
00832 if(texture) glTexCoord2d(1, 1);
00833 glVertex3d( x, y, -z);
00834 if(texture) glTexCoord2d(0, 1);
00835 glVertex3d( x, y, z);
00836
00837
00838 glNormal3d( 0, -1, 0);
00839 if(texture) glTexCoord2d(0, 0);
00840 glVertex3d(-x, -y, -z);
00841 if(texture) glTexCoord2d(1, 0);
00842 glVertex3d( x, -y, -z);
00843 if(texture) glTexCoord2d(1, 1);
00844 glVertex3d( x, -y, z);
00845 if(texture) glTexCoord2d(0, 1);
00846 glVertex3d(-x, -y, z);
00847
00848
00849 glNormal3d( 0, 1, 0);
00850 if(texture) glTexCoord2d(0, 0);
00851 glVertex3d(-x, y, z);
00852 if(texture) glTexCoord2d(1, 0);
00853 glVertex3d( x, y, z);
00854 if(texture) glTexCoord2d(1, 1);
00855 glVertex3d( x, y, -z);
00856 if(texture) glTexCoord2d(0, 1);
00857 glVertex3d(-x, y, -z);
00858
00859
00860 glNormal3d( 0, 0, -1);
00861 if(texture) glTexCoord2d(0, 0);
00862 glVertex3d( x, -y, -z);
00863 if(texture) glTexCoord2d(1, 0);
00864 glVertex3d(-x, -y, -z);
00865 if(texture) glTexCoord2d(1, 1);
00866 glVertex3d(-x, y, -z);
00867 if(texture) glTexCoord2d(0, 1);
00868 glVertex3d( x, y, -z);
00869
00870
00871 glNormal3d( 0, 0, 1);
00872 if(texture) glTexCoord2d(0, 0);
00873 glVertex3d(-x, -y, z);
00874 if(texture) glTexCoord2d(1, 0);
00875 glVertex3d( x, -y, z);
00876 if(texture) glTexCoord2d(1, 1);
00877 glVertex3d( x, y, z);
00878 if(texture) glTexCoord2d(0, 1);
00879 glVertex3d(-x, y, z);
00880
00881 glEnd();
00882
00883 if(config->showNormals)
00884 {
00885 vector<Vector3> normals;
00886
00887
00888 normals.push_back(Vector3(-x, -y, -z));
00889 normals.push_back(Vector3(-1, 0, 0));
00890 normals.push_back(Vector3(-x, -y, z));
00891 normals.push_back(Vector3(-1, 0, 0));
00892 normals.push_back(Vector3(-x, y, z));
00893 normals.push_back(Vector3(-1, 0, 0));
00894 normals.push_back(Vector3(-x, y, -z));
00895 normals.push_back(Vector3(-1, 0, 0));
00896
00897
00898 normals.push_back(Vector3( x, -y, z));
00899 normals.push_back(Vector3( 1, 0, 0));
00900 normals.push_back(Vector3( x, -y, -z));
00901 normals.push_back(Vector3( 1, 0, 0));
00902 normals.push_back(Vector3( x, y, -z));
00903 normals.push_back(Vector3( 1, 0, 0));
00904 normals.push_back(Vector3( x, y, z));
00905 normals.push_back(Vector3( 1, 0, 0));
00906
00907
00908 normals.push_back(Vector3(-x, -y, -z));
00909 normals.push_back(Vector3( 0, -1, 0));
00910 normals.push_back(Vector3( x, -y, -z));
00911 normals.push_back(Vector3( 0, -1, 0));
00912 normals.push_back(Vector3( x, -y, z));
00913 normals.push_back(Vector3( 0, -1, 0));
00914 normals.push_back(Vector3(-x, -y, z));
00915 normals.push_back(Vector3( 0, -1, 0));
00916
00917
00918 normals.push_back(Vector3(-x, y, z));
00919 normals.push_back(Vector3( 0, 1, 0));
00920 normals.push_back(Vector3( x, y, z));
00921 normals.push_back(Vector3( 0, 1, 0));
00922 normals.push_back(Vector3( x, y, -z));
00923 normals.push_back(Vector3( 0, 1, 0));
00924 normals.push_back(Vector3(-x, y, -z));
00925 normals.push_back(Vector3( 0, 1, 0));
00926
00927
00928 normals.push_back(Vector3( x, -y, -z));
00929 normals.push_back(Vector3( 0, 0, -1));
00930 normals.push_back(Vector3(-x, -y, -z));
00931 normals.push_back(Vector3( 0, 0, -1));
00932 normals.push_back(Vector3(-x, y, -z));
00933 normals.push_back(Vector3( 0, 0, -1));
00934 normals.push_back(Vector3( x, y, -z));
00935 normals.push_back(Vector3( 0, 0, -1));
00936
00937
00938 normals.push_back(Vector3(-x, -y, z));
00939 normals.push_back(Vector3( 0, 0, 1));
00940 normals.push_back(Vector3( x, -y, z));
00941 normals.push_back(Vector3( 0, 0, 1));
00942 normals.push_back(Vector3( x, y, z));
00943 normals.push_back(Vector3( 0, 0, 1));
00944 normals.push_back(Vector3(-x, y, z));
00945 normals.push_back(Vector3( 0, 0, 1));
00946
00947 renderNormals(normals, config);
00948 }
00949 }
00950
00951 void Cone::render(bool texture,
00952 const Shape *shape,
00953 const RenderConfig *config)
00954 {
00955 glFrontFace(GL_CW);
00956 glDisable(GL_COLOR_MATERIAL);
00957 if(side&bottom)
00958 {
00959 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
00960 glEnable(GL_CULL_FACE);
00961 }
00962 else
00963 {
00964 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
00965 glDisable(GL_CULL_FACE);
00966 }
00967
00968 const int heightSteps = config->subdivision2;
00969 const int thetaSteps = config->subdivision1;
00970
00971 const double r = bottomRadius;
00972 const double h = height;
00973
00974 vector<Vector2> vl(thetaSteps);
00975
00976 vector<Vector3> normals;
00977 const bool showNormals = config->showNormals;
00978
00979
00980 if(bottom)
00981 {
00982 glBegin(GL_POLYGON);
00983 glNormal3d(0, -1, 0);
00984 const double y = h/-2;
00985 for(int i=0; i<thetaSteps; ++i)
00986 {
00987 const double theta = 2 * M_PI / thetaSteps * i;
00988
00989 Vector2 v(-sin(theta), -cos(theta));
00990 if(texture) glTexCoord2d(v[0]/2+0.5, v[1]/2+0.5);
00991 vl[i] = v *= r;
00992 glVertex3d(v[0], y, v[1]);
00993 }
00994 glEnd();
00995 if(showNormals) for(int i=0; i<thetaSteps; ++i)
00996 {
00997 normals.push_back(Vector3(vl[i][0], y, vl[i][1]));
00998 normals.push_back(Vector3(0, -1, 0));
00999 }
01000 }
01001 else
01002 {
01003 for(int i=0; i<thetaSteps; ++i)
01004 {
01005 const double theta = 2 * M_PI / thetaSteps * i;
01006 vl[i] = Vector2(-sin(theta)*r, -cos(theta)*r);
01007 }
01008 }
01009
01010 if(side)
01011 {
01012 Vector2 n(h, r);
01013 n.normalize();
01014
01015 double prevTexT = 0;
01016 double prevY = h/-2;
01017
01018 Vector2 v;
01019
01020
01021 for(int i=1; i<=heightSteps; ++i)
01022 {
01023 glBegin(GL_QUAD_STRIP);
01024
01025 const Vector2 w = vl[0];
01026
01027 const double texT = 1.0 / heightSteps * i;
01028 const double y = h * (texT - 0.5);
01029
01030 for(int j=0; j<thetaSteps; ++j)
01031 {
01032 const double texS = 1.0 / thetaSteps * j;
01033 const double theta = 2 * M_PI * texS;
01034
01035 double x = -sin(theta);
01036 double z = -cos(theta);
01037
01038 glNormal3d(x*n[0], n[1], z*n[0]);
01039
01040 if(texture) glTexCoord2d(texS, prevTexT);
01041 v = vl[j];
01042 glVertex3d(v[0], prevY, v[1]);
01043 if(showNormals)
01044 {
01045 normals.push_back(Vector3(v[0], prevY, v[1]));
01046 normals.push_back(Vector3(x*n[0], n[1], z*n[0]));
01047 }
01048
01049 if(texture) glTexCoord2d(texS, texT);
01050 v = Vector2(x, z);
01051 v *= r * (1 - texT);
01052 glVertex3d(v[0], y, v[1]);
01053 vl[j] = v;
01054 }
01055
01056 glNormal3d(0, n[1], -n[0]);
01057
01058 if(texture) glTexCoord2d(1, prevTexT);
01059 glVertex3d(w[0], prevY, w[1]);
01060
01061 if(texture) glTexCoord2d(1, texT);
01062 v = vl[0];
01063 glVertex3d(v[0], y, v[1]);
01064
01065 prevTexT = texT;
01066 prevY = y;
01067
01068 glEnd();
01069 }
01070
01071 if(showNormals) for(int i=0; i<thetaSteps; ++i)
01072 {
01073 const double texS = 1.0 / thetaSteps * i;
01074 const double theta = 2 * M_PI * texS;
01075
01076 double x = -sin(theta);
01077 double z = -cos(theta);
01078
01079 normals.push_back(Vector3(vl[i][0], prevY, vl[i][1]));
01080 normals.push_back(Vector3(x*n[0], n[1], z*n[0]));
01081 }
01082 }
01083
01084 if(showNormals) renderNormals(normals, config);
01085 }
01086
01087 void Cylinder::render(bool texture,
01088 const Shape *shape,
01089 const RenderConfig *config)
01090 {
01091 glFrontFace(GL_CCW);
01092 glDisable(GL_COLOR_MATERIAL);
01093 if(side&top&bottom)
01094 {
01095 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
01096 glEnable(GL_CULL_FACE);
01097 }
01098 else
01099 {
01100 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
01101 glDisable(GL_CULL_FACE);
01102 }
01103
01104 const int thetaSteps = config->subdivision1;
01105
01106 const double r = radius;
01107 const double y = height / 2;
01108
01109 vector<Vector2> vl(thetaSteps);
01110 vector<Vector2> tl(texture ? thetaSteps : 0);
01111
01112 vector<Vector3> normals;
01113 const bool showNormals = config->showNormals;
01114
01115
01116 if(side)
01117 {
01118 glBegin(GL_QUAD_STRIP);
01119
01120 for(int i=0; i<thetaSteps; ++i)
01121 {
01122 const double texS = 1.0 / thetaSteps * i;
01123 const double theta = 2 * M_PI * texS;
01124
01125 double x = -sin(theta);
01126 double z = -cos(theta);
01127
01128 if(texture) tl[i] = Vector2(x/2+0.5, z/-2+0.5);
01129
01130 glNormal3d(x, 0, z);
01131 if(showNormals)
01132 {
01133 normals.push_back(Vector3(x*r, y, z*r));
01134 normals.push_back(Vector3(x, 0, z));
01135 normals.push_back(Vector3(x*r, -y, z*r));
01136 normals.push_back(Vector3(x, 0, z));
01137 }
01138 x *= r;
01139 z *= r;
01140 if(texture) glTexCoord2d(texS, 1);
01141 glVertex3d(x, y, z);
01142 if(texture) glTexCoord2d(texS, 0);
01143 glVertex3d(x, -y, z);
01144
01145 vl[i] = Vector2(x, z);
01146 }
01147
01148 glNormal3d(0, 0, -1);
01149 if(texture) glTexCoord2d(1, 1);
01150 glVertex3d(0, y, -r);
01151 if(texture) glTexCoord2d(1, 0);
01152 glVertex3d(0, -y, -r);
01153
01154 glEnd();
01155 }
01156 else
01157 {
01158 for(int i=0; i<thetaSteps; ++i)
01159 {
01160 const double theta = 2 * M_PI / thetaSteps * i;
01161
01162 double x = -sin(theta);
01163 double z = -cos(theta);
01164 if(texture) tl[i] = Vector2(x/2+0.5, z/-2+0.5);
01165 vl[i] = Vector2(x*r, z*r);
01166 }
01167 }
01168
01169
01170 if(top)
01171 {
01172 glNormal3d(0, 1, 0);
01173 glBegin(GL_POLYGON);
01174 for(int i=0; i<thetaSteps; ++i)
01175 {
01176 if(texture) glTexCoord2d(tl[i][0], tl[i][1]);
01177 glVertex3d(vl[i][0], y, vl[i][1]);
01178 }
01179 glEnd();
01180 if(showNormals) for(int i=0; i<thetaSteps; ++i)
01181 {
01182 normals.push_back(Vector3(vl[i][0], y, vl[i][1]));
01183 normals.push_back(Vector3(0, 1, 0));
01184 }
01185 }
01186
01187
01188 if(bottom)
01189 {
01190 glNormal3d(0, -1, 0);
01191 glBegin(GL_POLYGON);
01192 for(int i=thetaSteps-1; i>=0; --i)
01193 {
01194 if(texture) glTexCoord2d(tl[i][0], -tl[i][1]);
01195 glVertex3d(vl[i][0], -y, vl[i][1]);
01196 }
01197 glEnd();
01198 if(showNormals) for(int i=0; i<thetaSteps; ++i)
01199 {
01200 normals.push_back(Vector3(vl[i][0], -y, vl[i][1]));
01201 normals.push_back(Vector3(0, -1, 0));
01202 }
01203 }
01204
01205 if(showNormals) renderNormals(normals, config);
01206 }
01207
01208
01209 void IndexedLineSet::render(bool texture,
01210 const Shape *shape,
01211 const RenderConfig *config)
01212 {
01213 if(!coord) return;
01214
01215 const Coordinate *_coord =
01216 dynamic_cast<const Coordinate *>(coord.get());
01217 const Color *rgb =
01218 dynamic_cast<const Color *>(color.get());
01219 const ColorRGBA *rgba =
01220 dynamic_cast<const ColorRGBA *>(color.get());
01221
01222 if(!_coord)
01223 ARCHON_THROW1(InternalException,
01224 "'" + coord->getType()->getName() +
01225 "' is not supported yet");
01226 if(!rgb && !rgba && color)
01227 ARCHON_THROW1(InternalException,
01228 "'" + color->getType()->getName() +
01229 "' is not supported yet");
01230
01231 const vector<Vector3> &v = _coord->getPoint();
01232 const vector<Vector3> *rgb_v = rgb ? &rgb->getColor() : 0;
01233 const vector<Vector4> *rgba_v = rgba ? &rgba->getColor() : 0;
01234
01235 bool hasColorIndex = !colorIndex.empty();
01236 bool rgbPerVertex = rgb && colorPerVertex;
01237 bool rgbPerFace = rgb && !rgbPerVertex;
01238 bool rgbaPerVertex = rgba && colorPerVertex;
01239 bool rgbaPerFace = rgba && !rgbaPerVertex;
01240
01241 vector<int>::const_iterator ci = colorIndex.begin();
01242 vector<int>::const_iterator vi = coordIndex.begin();
01243
01244 glLineWidth(lineWidth);
01245
01246 glDisable(GL_LIGHTING);
01247 glDisable(GL_TEXTURE_2D);
01248
01249 if(!rgb && !rgba)
01250 {
01251 const Appearance *a =
01252 dynamic_cast<const Appearance *>(shape->getAppearance().get());
01253 if(a)
01254 {
01255 const Material *m =
01256 dynamic_cast<const Material *>(a->getMaterial().get());
01257 if(m)
01258 {
01259 Vector3 c = m->getEmissiveColor();
01260 glColor3d(c[0], c[1], c[2]);
01261 }
01262 }
01263 }
01264
01265 int i = 0;
01266 while(vi != coordIndex.end())
01267 {
01268 if(rgbPerFace)
01269 {
01270 const Vector3 &c = (*rgb_v)[hasColorIndex ? *(ci++) : i];
01271 glColor3d(c[0], c[1], c[2]);
01272 }
01273
01274 if(rgbaPerFace)
01275 {
01276 const Vector4 &c = (*rgba_v)[hasColorIndex ? *(ci++) : i];
01277 glColor4d(c[0], c[1], c[2], c[3]);
01278 }
01279
01280 glBegin(GL_LINE_STRIP);
01281 for(;;)
01282 {
01283 if(rgbPerVertex)
01284 {
01285 const Vector3 &c = (*rgb_v)[hasColorIndex ? *(ci++) : *vi];
01286 glColor3d(c[0], c[1], c[2]);
01287 }
01288
01289 if(rgbaPerVertex)
01290 {
01291 const Vector4 &c = (*rgba_v)[hasColorIndex ? *(ci++) : *vi];
01292 glColor4d(c[0], c[1], c[2], c[3]);
01293 }
01294
01295 const Vector3 &w = v[*(vi++)];
01296 glVertex3d(w[0], w[1], w[2]);
01297
01298 if(vi == coordIndex.end()) break;
01299 if(*vi == -1)
01300 {
01301 ++vi;
01302 if(rgbPerVertex || rgbaPerVertex) ++ci;
01303 break;
01304 }
01305 }
01306 glEnd();
01307
01308 ++i;
01309 }
01310 }
01311
01312
01313 void PointSet::render(bool texture,
01314 const Shape *shape,
01315 const RenderConfig *config)
01316 {
01317 if(!coord) return;
01318
01319 const Coordinate *_coord =
01320 dynamic_cast<const Coordinate *>(coord.get());
01321 const Color *rgb =
01322 dynamic_cast<const Color *>(color.get());
01323 const ColorRGBA *rgba =
01324 dynamic_cast<const ColorRGBA *>(color.get());
01325
01326 if(!_coord)
01327 ARCHON_THROW1(InternalException,
01328 "'" + coord->getType()->getName() +
01329 "' is not supported yet");
01330 if(!rgb && !rgba && color)
01331 ARCHON_THROW1(InternalException,
01332 "'" + color->getType()->getName() +
01333 "' is not supported yet");
01334
01335 const vector<Vector3> &v = _coord->getPoint();
01336 const unsigned n = v.size();
01337 if(!n) return;
01338
01339 if(rgb && rgb->getColor().size() < n ||
01340 rgba && rgba->getColor().size() < n)
01341 {
01342 rgb = 0;
01343 rgba = 0;
01344 }
01345
01346 glPointSize(2);
01347
01348 glDisable(GL_LIGHTING);
01349 glDisable(GL_TEXTURE_2D);
01350
01351 if(!rgb && !rgba)
01352 {
01353 const Appearance *a =
01354 dynamic_cast<const Appearance *>(shape->getAppearance().get());
01355 if(a)
01356 {
01357 const Material *m =
01358 dynamic_cast<const Material *>(a->getMaterial().get());
01359 if(m)
01360 {
01361 Vector3 c = m->getEmissiveColor();
01362 glColor3d(c[0], c[1], c[2]);
01363 }
01364 }
01365 }
01366
01367 glBegin(GL_POINTS);
01368 for(unsigned i=0; i<n; ++i)
01369 {
01370 if(rgb)
01371 {
01372 Vector3 c = rgb->getColor()[i];
01373 glColor3d(c[0], c[1], c[2]);
01374 }
01375 else if(rgba)
01376 {
01377 Vector4 c = rgba->getColor()[i];
01378 glColor4d(c[0], c[1], c[2], c[3]);
01379 }
01380 Vector3 w = v[i];
01381 glVertex3d(w[0], w[1], w[2]);
01382 }
01383 glEnd();
01384 }
01385
01386
01387 void Sphere::render(bool texture,
01388 const Shape *shape,
01389 const RenderConfig *config)
01390 {
01391 glFrontFace(GL_CW);
01392 glDisable(GL_COLOR_MATERIAL);
01393 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
01394 glEnable(GL_CULL_FACE);
01395
01396 const int phiSteps = config->subdivision2;
01397 const int thetaSteps = config->subdivision1;
01398
01399 vector<Vector3> normals;
01400 const bool showNormals = config->showNormals;
01401
01402 vector<Vector3> vl(thetaSteps);
01403
01404 glBegin(GL_QUAD_STRIP);
01405
01406 Vector3 v;
01407
01408
01409 if(showNormals)
01410 {
01411 normals.push_back(Vector3(0, -radius, 0));
01412 normals.push_back(Vector3(0, -1, 0));
01413 }
01414 double texT = 1.0 / phiSteps;
01415 double phi = M_PI * (texT - 0.5);
01416 double sin_phi = sin(phi);
01417 double cos_phi = cos(phi);
01418 for(int i=0; i<thetaSteps; ++i)
01419 {
01420 double texS = 1.0 / thetaSteps * i;
01421 double theta = 2 * M_PI * texS;
01422
01423 if(texture) glTexCoord2d(texS, 0);
01424 glNormal3d(0, -1, 0);
01425 glVertex3d(0, -radius, 0);
01426
01427 if(texture) glTexCoord2d(texS, texT);
01428 v = vl[i] = Vector3(cos_phi*-sin(theta), sin_phi, cos_phi*-cos(theta));
01429 glNormal3d(v[0], v[1], v[2]);
01430 v *= radius;
01431 glVertex3d(v[0], v[1], v[2]);
01432 if(showNormals)
01433 {
01434 normals.push_back(v);
01435 normals.push_back(vl[i]);
01436 }
01437 }
01438
01439 if(texture) glTexCoord2d(1, 0);
01440 glNormal3d(0, -1, 0);
01441 glVertex3d(0, -radius, 0);
01442
01443 if(texture) glTexCoord2d(1, texT);
01444 v = vl[0];
01445 glNormal3d(v[0], v[1], v[2]);
01446 v *= radius;
01447 glVertex3d(v[0], v[1], v[2]);
01448
01449 double prevTexT = texT;
01450
01451 glEnd();
01452
01453
01454 for(int i=2; i<phiSteps; ++i)
01455 {
01456 glBegin(GL_QUAD_STRIP);
01457
01458 Vector3 w = vl[0];
01459
01460 texT = 1.0 / phiSteps * i;
01461 phi = M_PI * (texT - 0.5);
01462 sin_phi = sin(phi);
01463 cos_phi = cos(phi);
01464 for(int j=0; j<thetaSteps; ++j)
01465 {
01466 double texS = 1.0 / thetaSteps * j;
01467 double theta = 2 * M_PI * texS;
01468
01469 if(texture) glTexCoord2d(texS, prevTexT);
01470 v = vl[j];
01471 glNormal3d(v[0], v[1], v[2]);
01472 v *= radius;
01473 glVertex3d(v[0], v[1], v[2]);
01474
01475 if(texture) glTexCoord2d(texS, texT);
01476 v = vl[j] = Vector3(cos_phi*-sin(theta), sin_phi, cos_phi*-cos(theta));
01477 glNormal3d(v[0], v[1], v[2]);
01478 v *= radius;
01479 glVertex3d(v[0], v[1], v[2]);
01480 if(showNormals)
01481 {
01482 normals.push_back(v);
01483 normals.push_back(vl[j]);
01484 }
01485 }
01486
01487 if(texture) glTexCoord2d(1, prevTexT);
01488 glNormal3d(w[0], w[1], w[2]);
01489 w *= radius;
01490 glVertex3d(w[0], w[1], w[2]);
01491
01492 if(texture) glTexCoord2d(1, texT);
01493 v = vl[0];
01494 glNormal3d(v[0], v[1], v[2]);
01495 v *= radius;
01496 glVertex3d(v[0], v[1], v[2]);
01497
01498 prevTexT = texT;
01499
01500 glEnd();
01501 }
01502
01503
01504 glBegin(GL_QUAD_STRIP);
01505
01506 for(int i=0; i<thetaSteps; ++i)
01507 {
01508 double texS = 1.0 / thetaSteps * i;
01509
01510 if(texture) glTexCoord2d(texS, prevTexT);
01511 v = vl[i];
01512 glNormal3d(v[0], v[1], v[2]);
01513 v *= radius;
01514 glVertex3d(v[0], v[1], v[2]);
01515
01516 if(texture) glTexCoord2d(texS, 1);
01517 glNormal3d(0, 1, 0);
01518 glVertex3d(0, radius, 0);
01519 }
01520
01521 if(texture) glTexCoord2d(1, prevTexT);
01522 v = vl[0];
01523 glNormal3d(v[0], v[1], v[2]);
01524 v *= radius;
01525 glVertex3d(v[0], v[1], v[2]);
01526
01527 if(texture) glTexCoord2d(1, 1);
01528 glNormal3d(0, 1, 0);
01529 glVertex3d(0, radius, 0);
01530
01531 if(showNormals)
01532 {
01533 normals.push_back(Vector3(0, radius, 0));
01534 normals.push_back(Vector3(0, 1, 0));
01535 }
01536
01537 glEnd();
01538
01539 if(showNormals) renderNormals(normals, config);
01540 }
01541
01542 void IndexedFaceSet::reprocess()
01543 {
01544 preprocessed = false;
01545 }
01546
01626 void IndexedFaceSet::preprocess()
01627 {
01628 Logger *logger = Logger::get();
01629
01630 coords = 0;
01631 rgbColors = 0;
01632 rgbaColors = 0;
01633 normals = 0;
01634 texCoords = 0;
01635
01636 preprocessedCoordIndex.clear();
01637 preprocessedColorIndex.clear();
01638 preprocessedNormalIndex.clear();
01639 preprocessedTexCoordIndex.clear();
01640 preprocessedNormal.clear();
01641
01642
01643 if(coordIndex.empty())
01644 {
01645 preprocessed = true;
01646 return;
01647 }
01648 if(!coord)
01649 {
01650 logger->log("IndexedFaceSet::preprocess: Lacking CoordinateNode");
01651 preprocessed = true;
01652 return;
01653 }
01654 const Coordinate *_coord =
01655 dynamic_cast<const Coordinate *>(coord.get());
01656 if(!_coord)
01657 ARCHON_THROW1(InternalException,
01658 "'" + coord->getType()->getName() +
01659 "' is not supported yet");
01660 coords = &_coord->getPoint();
01661 int nv = coords->size();
01662 if(!nv)
01663 {
01664 logger->log("IndexedFaceSet::preprocess: Empty CoordinateNode");
01665 preprocessed = true;
01666 return;
01667 }
01668
01669
01670 const Color *_rgbColor = 0;
01671 const ColorRGBA *_rgbaColor = 0;
01672 int nc = 0;
01673 if(color)
01674 {
01675 if((_rgbColor = dynamic_cast<const Color *>(color.get())))
01676 nc = _rgbColor->getColor().size();
01677 else if((_rgbaColor = dynamic_cast<const ColorRGBA *>(color.get())))
01678 nc = _rgbaColor->getColor().size();
01679 else ARCHON_THROW1(InternalException,
01680 "'" + color->getType()->getName() +
01681 "' is not supported yet");
01682 if(!nc) logger->log("IndexedFaceSet::preprocess: Empty ColorNode");
01683 }
01684 else if(!colorIndex.empty()) logger->log("IndexedFaceSet::preprocess: Lacking ColorNode");
01685
01686
01687 const Normal *_normal = 0;
01688 int nn = 0;
01689 if(normal)
01690 {
01691 if((_normal = dynamic_cast<const Normal *>(normal.get())))
01692 nn = _normal->getNormal().size();
01693 else ARCHON_THROW1(InternalException,
01694 "'" + normal->getType()->getName() +
01695 "' is not supported yet");
01696 if(!nn) logger->log("IndexedFaceSet::preprocess: Empty NormalNode");
01697 }
01698 else if(!normalIndex.empty()) logger->log("IndexedFaceSet::preprocess: WARN: Lacking NormalNode");
01699
01700
01701 const TextureCoordinate *_texCoord = 0;
01702 int nt = 0;
01703 if(texCoord)
01704 {
01705 if((_texCoord = dynamic_cast<const TextureCoordinate *>(texCoord.get())))
01706 nt = _texCoord->getPoint().size();
01707 else ARCHON_THROW1(InternalException,
01708 "'" + texCoord->getType()->getName() +
01709 "' is not supported yet");
01710 if(!nt) logger->log("IndexedFaceSet::preprocess: Empty TextureCoordinateNode");
01711 }
01712 else if(!texCoordIndex.empty()) logger->log("IndexedFaceSet::preprocess: Lacking TextureCoordinateNode");
01713
01714
01715 if(nc && colorIndex.empty() && colorPerVertex && nc<nv) nv = nc;
01716 if(nn && normalIndex.empty() && normalPerVertex && nn<nv) nv = nn;
01717 if(nt && texCoordIndex.empty() && nt<nv) nv = nt;
01718
01719
01720 int n = coordIndex.size()+1;
01721 preprocessedCoordIndex.reserve(n);
01722 if(nc && (!colorPerVertex || !colorIndex.empty()))
01723 preprocessedColorIndex.reserve(n);
01724 if(nn && (!normalPerVertex || !normalIndex.empty()))
01725 preprocessedNormalIndex.reserve(n);
01726 if(nt && !texCoordIndex.empty())
01727 preprocessedTexCoordIndex.reserve(n);
01728
01729 bool wc = false;
01730 bool wn = false;
01731 bool wt = false;
01732
01733 int jv = 0;
01734 int jc = 0;
01735 int jn = 0;
01736 int jt = 0;
01737
01738 int f=0;
01739 int i0=0;
01740 for(int i=0; static_cast<unsigned>(i0)<coordIndex.size(); ++i)
01741 {
01742 int j = static_cast<unsigned>(i)<coordIndex.size() ? coordIndex[i] : -1;
01743 if(j < 0)
01744 {
01745 if(j != -1) logger->log("IndexedFaceSet::preprocess: Bad end-of-face marker (coordIndex[i]=j)");
01746 if(i-i0 < 3)
01747 {
01748 logger->log("IndexedFaceSet::preprocess: Too few vertices in polygon (i-i0)");
01749 i0 = i+1;
01750 ++f;
01751 continue;
01752 }
01753
01754
01755 vector<int> poly;
01756 poly.reserve(i-i0);
01757 if(ccw) for(int k=i0; k<i; ++k)
01758 {
01759 j = coordIndex[k];
01760 if(j<nv) jv = j;
01761 else logger->log("IndexedFaceSet::preprocess: Index out of range (coordIndex[k]==j)");
01762 poly.push_back(jv);
01763 }
01764 else for(int k=i-1; k>=i0; --k)
01765 {
01766 j = coordIndex[k];
01767 if(j<nv) jv = j;
01768 else logger->log("IndexedFaceSet::preprocess: Index out of range (coordIndex[k]==j)");
01769 poly.push_back(jv);
01770 }
01771
01772
01773 {
01774 int j0 = poly[0];
01775 int j1 = poly[1];
01776 int j2 = poly[2];
01777 Vector3 normal = (*coords)[j1];
01778 normal -= (*coords)[j0];
01779 Vector3 v = (*coords)[j2];
01780 v -= (*coords)[j0];
01781 normal *= v;
01782 if(normal == Vector3::zero())
01783 {
01784 logger->log("IndexedFaceSet::preprocess: Polygon was not both simple and convex");
01785 i0 = i+1;
01786 ++f;
01787 continue;
01788 }
01789 normal.normalize();
01790 preprocessedNormal.push_back(normal);
01791 }
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805 preprocessedCoordIndex.insert(preprocessedCoordIndex.end(), poly.begin(), poly.end());
01806 preprocessedCoordIndex.push_back(-1);
01807
01808
01809 if(nc)
01810 {
01811 if(!colorPerVertex)
01812 {
01813 if(colorIndex.empty())
01814 {
01815 if(f<nc) jc = f;
01816 else logger->log("IndexedFaceSet::preprocess: Too few elements in ColorNode");
01817 }
01818 else if(static_cast<unsigned>(f)<colorIndex.size())
01819 {
01820 j = colorIndex[f];
01821 if(j>=0 && j<nc) jc = j;
01822 else logger->log("IndexedFaceSet::preprocess: Index out of range (colorIndex[f]==j)");
01823 }
01824 else logger->log("IndexedFaceSet::preprocess: Too few indices in colorIndex");
01825 for(int k=i0; k<i; ++k) preprocessedColorIndex.push_back(jc);
01826 preprocessedColorIndex.push_back(-1);
01827 }
01828 else if(!colorIndex.empty())
01829 {
01830 j = static_cast<unsigned>(i)<colorIndex.size() ? colorIndex[i] : -1;
01831 if(j != -1) logger->log("IndexedFaceSet::preprocess: Bad end-of-face marker (colorIndex[i]==j)");
01832 if(ccw) for(int k=i0; k<i; ++k)
01833 {
01834 if(static_cast<unsigned>(k)<colorIndex.size())
01835 {
01836 j = colorIndex[k];
01837 if(j>=0 && j<nc) jc = j;
01838 else logger->log("IndexedFaceSet::preprocess: Index out of range (colorIndex[k]==j)");
01839 }
01840 else if(!wc)
01841 {
01842 logger->log("IndexedFaceSet::preprocess: Too few indices in colorIndex");
01843 wc = true;
01844 }
01845 preprocessedColorIndex.push_back(jc);
01846 }
01847 else for(int k=i-1; k>=i0; --k)
01848 {
01849 if(static_cast<unsigned>(k)<colorIndex.size())
01850 {
01851 j = colorIndex[k];
01852 if(j>=0 && j<nc) jc = j;
01853 else logger->log("IndexedFaceSet::preprocess: Index out of range (colorIndex[k]==j)");
01854 }
01855 else if(!wc)
01856 {
01857 logger->log("IndexedFaceSet::preprocess: Too few indices in colorIndex");
01858 wc = true;
01859 }
01860 preprocessedColorIndex.push_back(jc);
01861 }
01862 preprocessedColorIndex.push_back(-1);
01863 }
01864 }
01865
01866
01867 if(nn)
01868 {
01869 if(!normalPerVertex)
01870 {
01871 if(normalIndex.empty())
01872 {
01873 if(f<nn) jn = f;
01874 else logger->log("IndexedFaceSet::preprocess: Too few elements in NormalNode");
01875 }
01876 else if(static_cast<unsigned>(f)<normalIndex.size())
01877 {
01878 j = normalIndex[f];
01879 if(j>=0 && j<nn) jn = j;
01880 else logger->log("IndexedFaceSet::preprocess: Index out of range (normalIndex[f]==j)");
01881 }
01882 else logger->log("IndexedFaceSet::preprocess: Too few indices in normalIndex");
01883 for(int k=i0; k<i; ++k) preprocessedNormalIndex.push_back(jn);
01884 preprocessedNormalIndex.push_back(-1);
01885 }
01886 else if(!normalIndex.empty())
01887 {
01888 j = static_cast<unsigned>(i)<normalIndex.size() ? normalIndex[i] : -1;
01889 if(j != -1) logger->log("IndexedFaceSet::preprocess: Bad end-of-face marker (normalIndex[i]==j)");
01890 if(ccw) for(int k=i0; k<i; ++k)
01891 {
01892 if(static_cast<unsigned>(k)<normalIndex.size())
01893 {
01894 j = normalIndex[k];
01895 if(j>=0 && j<nn) jn = j;
01896 else logger->log("IndexedFaceSet::preprocess: Index out of range (normalIndex[k]==j)");
01897 }
01898 else if(!wn)
01899 {
01900 logger->log("IndexedFaceSet::preprocess: Too few indices in normalIndex");
01901 wn = true;
01902 }
01903 preprocessedNormalIndex.push_back(jn);
01904 }
01905 else for(int k=i-1; k>=i0; --k)
01906 {
01907 if(static_cast<unsigned>(k)<normalIndex.size())
01908 {
01909 j = normalIndex[k];
01910 if(j>=0 && j<nn) jn = j;
01911 else logger->log("IndexedFaceSet::preprocess: Index out of range (normalIndex[k]==j)");
01912 }
01913 else if(!wn)
01914 {
01915 logger->log("IndexedFaceSet::preprocess: Too few indices in normalIndex");
01916 wn = true;
01917 }
01918 preprocessedNormalIndex.push_back(jn);
01919 }
01920 preprocessedNormalIndex.push_back(-1);
01921 }
01922 }
01923
01924
01925 if(nt && !texCoordIndex.empty())
01926 {
01927 j = static_cast<unsigned>(i)<texCoordIndex.size() ? texCoordIndex[i] : -1;
01928 if(j != -1) logger->log("IndexedFaceSet::preprocess: Bad end-of-face marker (texCoordIndex[i]==j)");
01929 if(ccw) for(int k=i0; k<i; ++k)
01930 {
01931 if(static_cast<unsigned>(k)<texCoordIndex.size())
01932 {
01933 j = texCoordIndex[k];
01934 if(j>=0 && j<nt) jt = j;
01935 else logger->log("IndexedFaceSet::preprocess: Index out of range (texCoordIndex[k]==j)");
01936 }
01937 else if(!wt)
01938 {
01939 logger->log("IndexedFaceSet::preprocess: Too few indices in texCoordIndex");
01940 wt = true;
01941 }
01942 preprocessedTexCoordIndex.push_back(jt);
01943 }
01944 else for(int k=i-1; k>=i0; --k)
01945 {
01946 if(static_cast<unsigned>(k)<texCoordIndex.size())
01947 {
01948 j = texCoordIndex[k];
01949 if(j>=0 && j<nt) jt = j;
01950 else logger->log("IndexedFaceSet::preprocess: Index out of range (texCoordIndex[k]==j)");
01951 }
01952 else if(!wt)
01953 {
01954 logger->log("IndexedFaceSet::preprocess: Too few indices in texCoordIndex");
01955 wt = true;
01956 }
01957 preprocessedTexCoordIndex.push_back(jt);
01958 }
01959 preprocessedTexCoordIndex.push_back(-1);
01960 }
01961
01962 i0 = i+1;
01963 ++f;
01964 }
01965 }
01966
01967
01968 if(preprocessedCoordIndex.empty())
01969 {
01970 coords = 0;
01971 preprocessed = true;
01972 return;
01973 }
01974
01975 if(nc)
01976 if(_rgbColor) rgbColors = &_rgbColor->getColor();
01977 else rgbaColors = &_rgbaColor->getColor();
01978 if(nn) normals = &_normal->getNormal();
01979 if(nt) texCoords = &_texCoord->getPoint();
01980
01981
01982 if(!nn)
01983 {
01984
01985 vector<vector<int> > vertexFaces;
01986 vertexFaces.resize(coords->size());
01987 int f=0;
01988 for(unsigned i=0; i<preprocessedCoordIndex.size(); ++i)
01989 {
01990 int j = preprocessedCoordIndex[i];
01991 if(j < 0) { ++f; continue; }
01992 vertexFaces[j].push_back(f);
01993 }
01994
01995 double creaseDotLimit = creaseAngle >= M_PI ? -1 : cos(creaseAngle);
01996
01997 f=0;
01998 for(unsigned i=0; i<preprocessedCoordIndex.size(); ++i)
01999 {
02000 int j = preprocessedCoordIndex[i];
02001 if(j < 0)
02002 {
02003 preprocessedNormalIndex.push_back(-1);
02004 ++f;
02005 continue;
02006 }
02007
02008 vector<int> &fv = vertexFaces[j];
02009 vector<int>::iterator fi = fv.begin();
02010 Vector3 n0 = preprocessedNormal[f];
02011 Vector3 n = n0;
02012 bool c = false;
02013 while(fi != fv.end())
02014 {
02015 if(*fi != f)
02016 {
02017 Vector3 n1 = preprocessedNormal[*fi];
02018 if(dot(n0, n1) > creaseDotLimit)
02019 {
02020 n += n1;
02021 c = true;
02022 }
02023 }
02024
02025 ++fi;
02026 }
02027
02028 int k = f;
02029 if(c)
02030 {
02031
02032
02033 n.normalize();
02034 k = preprocessedNormal.size();
02035 preprocessedNormal.push_back(n);
02036 }
02037 preprocessedNormalIndex.push_back(k);
02038 }
02039
02040 normals = &preprocessedNormal;
02041 }
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051 if(!nt)
02052 {
02053 Box3 b(Vector3::zero());
02054 for(unsigned i=0; i<coords->size(); ++i)
02055 {
02056 Vector3 v = (*coords)[i];
02057 if(v[0] < b.lowerCorner[0]) b.lowerCorner[0] = v[0];
02058 if(v[0] > b.upperCorner[0]) b.upperCorner[0] = v[0];
02059 if(v[1] < b.lowerCorner[1]) b.lowerCorner[1] = v[1];
02060 if(v[1] > b.upperCorner[1]) b.upperCorner[1] = v[1];
02061 if(v[2] < b.lowerCorner[2]) b.lowerCorner[2] = v[2];
02062 if(v[2] > b.upperCorner[2]) b.upperCorner[2] = v[2];
02063 }
02064 preprocessedBboxCenter = b.getCenter();
02065 preprocessedBboxSize = b.getSize();
02066 }
02067
02068 preprocessed = true;
02069 }
02070
02071 void IndexedFaceSet::render(bool texture,
02072 const Shape *shape,
02073 const RenderConfig *config)
02074 {
02075 if(!preprocessed) preprocess();
02076 if(!coords) return;
02077
02078 glFrontFace(GL_CCW);
02079
02080 if(solid)
02081 {
02082 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
02083 glEnable(GL_CULL_FACE);
02084 }
02085 else
02086 {
02087 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
02088 glDisable(GL_CULL_FACE);
02089 }
02090
02091 if(rgbColors || rgbaColors) glEnable(GL_COLOR_MATERIAL);
02092 else glDisable(GL_COLOR_MATERIAL);
02093
02094
02095 if(texture && !texCoords)
02096 {
02097 Vector3 bboxCenter;
02098 Vector3 bboxSize = shape->getBboxSize();
02099 if(bboxSize[0] == -1)
02100 {
02101 bboxCenter = preprocessedBboxCenter;
02102 bboxSize = preprocessedBboxSize;
02103 }
02104 else bboxCenter = shape->getBboxCenter();
02105
02106
02107
02108 int i0, i1, i2;
02109 Math::sort3(bboxSize[0], bboxSize[1], bboxSize[2], i0, i1, i2);
02110
02111
02112 {
02113 double c = 1/bboxSize[i0];
02114 GLdouble v[4] = { 0, 0, 0, (bboxSize[i0]/2-bboxCenter[i0])*c };
02115 v[i0] = c;
02116 glTexGendv(GL_S, GL_OBJECT_PLANE, v);
02117 }
02118
02119
02120 {
02121 double c = 1/bboxSize[i0];
02122 GLdouble v[4] = { 0, 0, 0, (bboxSize[i1]/2-bboxCenter[i1])*c };
02123 v[i1] = c;
02124 glTexGendv(GL_T, GL_OBJECT_PLANE, v);
02125 }
02126
02127 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
02128 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
02129
02130 glEnable(GL_TEXTURE_GEN_S);
02131 glEnable(GL_TEXTURE_GEN_T);
02132 }
02133
02134 bool emptyColorIndex = preprocessedColorIndex.empty();
02135 bool emptyNormalIndex = preprocessedNormalIndex.empty();
02136 bool emptyTexCoordIndex = preprocessedTexCoordIndex.empty();
02137
02138 for(unsigned i=0; i<preprocessedCoordIndex.size(); ++i)
02139 {
02140 glBegin(GL_POLYGON);
02141
02142 for(;; ++i)
02143 {
02144 int j = preprocessedCoordIndex[i];
02145 if(j<0) break;
02146
02147
02148 if(rgbColors)
02149 {
02150 Vector3 c = (*rgbColors)[emptyColorIndex ? j : preprocessedColorIndex[i]];
02151 glColor3d(c[0], c[1], c[2]);
02152 }
02153 else if(rgbaColors)
02154 {
02155 Vector4 c = (*rgbaColors)[emptyColorIndex ? j : preprocessedColorIndex[i]];
02156 glColor4d(c[0], c[1], c[2], c[3]);
02157 }
02158
02159
02160 {
02161 Vector3 n = (*normals)[emptyNormalIndex ? j : preprocessedNormalIndex[i]];
02162 glNormal3d(n[0], n[1], n[2]);
02163 }
02164
02165
02166 if(texCoords)
02167 {
02168 Vector2 t = (*texCoords)[emptyTexCoordIndex ? j : preprocessedTexCoordIndex[i]];
02169 glTexCoord2d(t[0], t[1]);
02170 }
02171
02172
02173 {
02174 Vector3 v = (*coords)[j];
02175 glVertex3d(v[0], v[1], v[2]);
02176 }
02177 }
02178
02179 glEnd();
02180 }
02181
02182
02183 if(texture && !texCoords)
02184 {
02185 glDisable(GL_TEXTURE_GEN_S);
02186 glDisable(GL_TEXTURE_GEN_T);
02187 }
02188
02189 if(config->showNormals)
02190 {
02191 vector<Vector3> n;
02192 for(unsigned i=0; i<preprocessedCoordIndex.size(); ++i)
02193 {
02194 int j = preprocessedCoordIndex[i];
02195 if(j<0) continue;
02196 n.push_back((*coords)[j]);
02197 n.push_back((*normals)[emptyNormalIndex ? j : preprocessedNormalIndex[i]]);
02198 }
02199 renderNormals(n, config);
02200 }
02201 }
02202
02207 void ElevationGrid::render(bool texture,
02208 const Shape *shape,
02209 const RenderConfig *config)
02210 {
02211 const unsigned n = xDimension * zDimension;
02212 if(height.size() < n) return;
02213
02214 const int iMax = xDimension - 1;
02215 const int jMax = zDimension - 1;
02216 const unsigned m = iMax * jMax;
02217
02218 const Color *rgb =
02219 dynamic_cast<const Color *>(color.get());
02220 const ColorRGBA *rgba =
02221 dynamic_cast<const ColorRGBA *>(color.get());
02222 const TextureCoordinate *_texCoord =
02223 dynamic_cast<const TextureCoordinate *>(texCoord.get());
02224 const Normal *_normal =
02225 dynamic_cast<const Normal *>(normal.get());
02226
02227 if(!rgb && !rgba && color)
02228 ARCHON_THROW1(InternalException,
02229 "'" + color->getType()->getName() +
02230 "' is not supported yet");
02231 if(!_texCoord && texCoord)
02232 ARCHON_THROW1(InternalException,
02233 "'" + texCoord->getType()->getName() +
02234 "' is not supported yet");
02235 if(!_normal && normal)
02236 ARCHON_THROW1(InternalException,
02237 "'" + normal->getType()->getName() +
02238 "' is not supported yet");
02239
02240 if(rgb && rgb->getColor().size() < (colorPerVertex ? n : m) ||
02241 rgba && rgba->getColor().size() < (colorPerVertex ? n : m))
02242 {
02243 rgb = 0;
02244 rgba = 0;
02245 }
02246
02247 if(_texCoord && _texCoord->getPoint().size() < n) _texCoord = 0;
02248 if(_normal && _normal->getNormal().size() < (normalPerVertex ? n : m)) _normal = 0;
02249
02250 glFrontFace(ccw ? GL_CCW : GL_CW);
02251
02252 if(solid)
02253 {
02254 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
02255 glEnable(GL_CULL_FACE);
02256 }
02257 else
02258 {
02259 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
02260 glDisable(GL_CULL_FACE);
02261 }
02262
02263 if(rgb || rgba) glEnable(GL_COLOR_MATERIAL);
02264 else glDisable(GL_COLOR_MATERIAL);
02265
02266
02267
02268
02269
02270 double creaseDotLimit;
02271 vector<Vector3> autoNormals(m);
02272 double prevZ = 0;
02273 if(!_normal)
02274 {
02275 creaseDotLimit = creaseAngle >= M_PI ? -1 : cos(creaseAngle);
02276 const bool cw = !ccw;
02277 for(int j=1; j<zDimension; ++j)
02278 {
02279 const double z = zSpacing * j;
02280
02281 double prevX = 0;
02282 for(int i=1; i<xDimension; ++i)
02283 {
02284 const double x = xSpacing * i;
02285
02286 Vector3 n(prevX, height[(i-1) + (j-1) * xDimension], prevZ);
02287 n -= Vector3(x, height[i + j * xDimension], z);
02288 Vector3 v(prevX, height[(i-1) + j * xDimension], z);
02289 v -= Vector3(x, height[i + (j-1) * xDimension], prevZ);
02290 n *= v;
02291 if(cw) n.negate();
02292 n.normalize();
02293 autoNormals[(i-1) + (j-1) * iMax] = n;
02294
02295 prevX = x;
02296 }
02297
02298 prevZ = z;
02299 }
02300
02301 prevZ = 0;
02302 }
02303
02304 double prevT = 0;
02305
02306 vector<Vector3> normals;
02307 const bool showNormals = config->showNormals;
02308
02309 glBegin(GL_QUADS);
02310
02311 for(int j=1; j<zDimension; ++j)
02312 {
02313 const double z = zSpacing * j;
02314 const double t = j/double(jMax);
02315
02316 double prevX = 0;
02317 double prevS = 0;
02318
02319 for(int i=1; i<xDimension; ++i)
02320 {
02321 const double x = xSpacing * i;
02322 const double s = i/double(iMax);
02323
02324 int faseIndex = (i-1) + (j-1) * iMax;
02325
02326 Vector3 n;
02327
02328 if(rgb && !colorPerVertex)
02329 {
02330 const Vector3 &c = rgb->getColor()[faseIndex];
02331 glColor3d(c[0], c[1], c[2]);
02332 }
02333 if(rgba && !colorPerVertex)
02334 {
02335 const Vector4 &c = rgba->getColor()[faseIndex];
02336 glColor4d(c[0], c[1], c[2], c[3]);
02337 }
02338 if(_normal && !normalPerVertex)
02339 {
02340 n = _normal->getNormal()[faseIndex];
02341 glNormal3d(n[0], n[1], n[2]);
02342 }
02343
02344
02345
02346 {
02347 int vertexIndex = i + (j-1) * xDimension;
02348
02349 if(rgb && colorPerVertex)
02350 {
02351 const Vector3 &c = rgb->getColor()[vertexIndex];
02352 glColor3d(c[0], c[1], c[2]);
02353 }
02354 if(rgba && colorPerVertex)
02355 {
02356 const Vector4 &c = rgba->getColor()[vertexIndex];
02357 glColor4d(c[0], c[1], c[2], c[3]);
02358 }
02359 if(_normal && normalPerVertex)
02360 {
02361 n = _normal->getNormal()[vertexIndex];
02362 glNormal3d(n[0], n[1], n[2]);
02363 }
02364 else if(!_normal)
02365 {
02366
02367
02368 Vector3 n0 = autoNormals[faseIndex];
02369 n = n0;
02370 int m = 1;
02371 if(i<iMax)
02372 {
02373 Vector3 n1 = autoNormals[faseIndex + 1];
02374 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02375 }
02376 if(j>1)
02377 {
02378 Vector3 n1 = autoNormals[faseIndex - iMax];
02379 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02380 }
02381 if(i<iMax && j>1)
02382 {
02383 Vector3 n1 = autoNormals[faseIndex - iMax + 1];
02384 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02385 }
02386 n /= m;
02387
02388 glNormal3d(n[0], n[1], n[2]);
02389 }
02390
02391 if(texture)
02392 {
02393 if(texCoord)
02394 {
02395 const Vector2 &v = _texCoord->getPoint()[vertexIndex];
02396 glTexCoord2d(v[0], v[1]);
02397 }
02398 else glTexCoord2d(s, prevT);
02399 }
02400
02401 glVertex3d(x, height[vertexIndex], prevZ);
02402 if(showNormals)
02403 {
02404 normals.push_back(Vector3(x, height[vertexIndex], prevZ));
02405 normals.push_back(n);
02406 }
02407 }
02408
02409
02410 {
02411 int vertexIndex = (i-1) + (j-1) * xDimension;
02412
02413 if(rgb && colorPerVertex)
02414 {
02415 const Vector3 &c = rgb->getColor()[vertexIndex];
02416 glColor3d(c[0], c[1], c[2]);
02417 }
02418 if(rgba && colorPerVertex)
02419 {
02420 const Vector4 &c = rgba->getColor()[vertexIndex];
02421 glColor4d(c[0], c[1], c[2], c[3]);
02422 }
02423 if(_normal && normalPerVertex)
02424 {
02425 n = _normal->getNormal()[vertexIndex];
02426 glNormal3d(n[0], n[1], n[2]);
02427 }
02428 else if(!_normal)
02429 {
02430
02431
02432 Vector3 n0 = autoNormals[faseIndex];
02433 n = n0;
02434 int m = 1;
02435 if(i>1)
02436 {
02437 Vector3 n1 = autoNormals[faseIndex - 1];
02438 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02439 }
02440 if(j>1)
02441 {
02442 Vector3 n1 = autoNormals[faseIndex - iMax];
02443 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02444 }
02445 if(i>1 && j>1)
02446 {
02447 Vector3 n1 = autoNormals[faseIndex - iMax - 1];
02448 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02449 }
02450 n /= m;
02451
02452 glNormal3d(n[0], n[1], n[2]);
02453 }
02454
02455 if(texture)
02456 {
02457 if(texCoord)
02458 {
02459 const Vector2 &v = _texCoord->getPoint()[vertexIndex];
02460 glTexCoord2d(v[0], v[1]);
02461 }
02462 else glTexCoord2d(prevS, prevT);
02463 }
02464
02465 glVertex3d(prevX, height[vertexIndex], prevZ);
02466 if(showNormals)
02467 {
02468 normals.push_back(Vector3(prevX, height[vertexIndex], prevZ));
02469 normals.push_back(n);
02470 }
02471 }
02472
02473
02474 {
02475 int vertexIndex = (i-1) + j * xDimension;
02476
02477 if(rgb && colorPerVertex)
02478 {
02479 const Vector3 &c = rgb->getColor()[vertexIndex];
02480 glColor3d(c[0], c[1], c[2]);
02481 }
02482 if(rgba && colorPerVertex)
02483 {
02484 const Vector4 &c = rgba->getColor()[vertexIndex];
02485 glColor4d(c[0], c[1], c[2], c[3]);
02486 }
02487 if(_normal && normalPerVertex)
02488 {
02489 n = _normal->getNormal()[vertexIndex];
02490 glNormal3d(n[0], n[1], n[2]);
02491 }
02492 else if(!_normal)
02493 {
02494
02495
02496 Vector3 n0 = autoNormals[faseIndex];
02497 n = n0;
02498 int m = 1;
02499 if(i>1)
02500 {
02501 Vector3 n1 = autoNormals[faseIndex - 1];
02502 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02503 }
02504 if(j<jMax)
02505 {
02506 Vector3 n1 = autoNormals[faseIndex + iMax];
02507 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02508 }
02509 if(i>1 && j<jMax)
02510 {
02511 Vector3 n1 = autoNormals[faseIndex + iMax - 1];
02512 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02513 }
02514 n /= m;
02515
02516 glNormal3d(n[0], n[1], n[2]);
02517 }
02518
02519 if(texture)
02520 {
02521 if(texCoord)
02522 {
02523 const Vector2 &v = _texCoord->getPoint()[vertexIndex];
02524 glTexCoord2d(v[0], v[1]);
02525 }
02526 else glTexCoord2d(prevS, t);
02527 }
02528
02529 glVertex3d(prevX, height[vertexIndex], z);
02530 if(showNormals)
02531 {
02532 normals.push_back(Vector3(prevX, height[vertexIndex], z));
02533 normals.push_back(n);
02534 }
02535 }
02536
02537
02538 {
02539 int vertexIndex = i + j * xDimension;
02540
02541 if(rgb && colorPerVertex)
02542 {
02543 const Vector3 &c = rgb->getColor()[vertexIndex];
02544 glColor3d(c[0], c[1], c[2]);
02545 }
02546 if(rgba && colorPerVertex)
02547 {
02548 const Vector4 &c = rgba->getColor()[vertexIndex];
02549 glColor4d(c[0], c[1], c[2], c[3]);
02550 }
02551 if(_normal && normalPerVertex)
02552 {
02553 n = _normal->getNormal()[vertexIndex];
02554 glNormal3d(n[0], n[1], n[2]);
02555 }
02556 else if(!_normal)
02557 {
02558
02559
02560 Vector3 n0 = autoNormals[faseIndex];
02561 n = n0;
02562 int m = 1;
02563 if(i<iMax)
02564 {
02565 Vector3 n1 = autoNormals[faseIndex + 1];
02566 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02567 }
02568 if(j<jMax)
02569 {
02570 Vector3 n1 = autoNormals[faseIndex + iMax];
02571 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02572 }
02573 if(i<iMax && j<jMax)
02574 {
02575 Vector3 n1 = autoNormals[faseIndex + iMax + 1];
02576 if(dot(n0, n1) > creaseDotLimit) { n += n1; ++m; }
02577 }
02578 n /= m;
02579
02580 glNormal3d(n[0], n[1], n[2]);
02581 }
02582
02583 if(texture)
02584 {
02585 if(texCoord)
02586 {
02587 const Vector2 &v = _texCoord->getPoint()[vertexIndex];
02588 glTexCoord2d(v[0], v[1]);
02589 }
02590 else glTexCoord2d(s, t);
02591 }
02592
02593 glVertex3d(x, height[vertexIndex], z);
02594 if(showNormals)
02595 {
02596 normals.push_back(Vector3(x, height[vertexIndex], z));
02597 normals.push_back(n);
02598 }
02599 }
02600
02601 prevX = x;
02602 prevS = s;
02603 }
02604
02605 prevZ = z;
02606 prevT = t;
02607 }
02608
02609 glEnd();
02610
02611 if(showNormals) renderNormals(normals, config);
02612 }
02613 }
02614 }