00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "mesh.h"
00011 #include "rendcontext.h"
00012 #include "gl.h"
00013 #include "glext.h"
00014 #include <cassert>
00015 #include <iostream>
00016 using namespace std;
00017
00018
00019 static size_t VertexAttributeFormatSizes[Mesh::FormatMax] =
00020 {
00021 4,
00022 8,
00023 12,
00024 16,
00025 4,
00026 };
00027
00028
00029
00030
00031
00032 static const unsigned int MinVBOSize = 4096;
00033 static bool VBOSupportTested = false;
00034 static bool VBOSupported = false;
00035
00036 static bool isVBOSupported()
00037 {
00038 if (!VBOSupportTested)
00039 {
00040 VBOSupportTested = true;
00041 VBOSupported = ExtensionSupported("GL_ARB_vertex_buffer_object");
00042 }
00043
00044 return VBOSupported;
00045 }
00046
00047
00048 Mesh::Material::Material() :
00049 diffuse(0.0f, 0.0f, 0.0f),
00050 emissive(0.0f, 0.0f, 0.0f),
00051 specular(0.0f, 0.0f, 0.0f),
00052 specularPower(1.0f),
00053 opacity(1.0f)
00054 {
00055 for (int i = 0; i < TextureSemanticMax; i++)
00056 maps[i] = InvalidResource;
00057
00058 }
00059
00060
00061 Mesh::VertexDescription::VertexDescription(uint32 _stride,
00062 uint32 _nAttributes,
00063 VertexAttribute* _attributes) :
00064 stride(_stride),
00065 nAttributes(_nAttributes),
00066 attributes(NULL)
00067 {
00068 if (nAttributes != 0)
00069 {
00070 attributes = new VertexAttribute[nAttributes];
00071 for (uint32 i = 0; i < nAttributes; i++)
00072 attributes[i] = _attributes[i];
00073 buildSemanticMap();
00074 }
00075 }
00076
00077
00078 Mesh::VertexDescription::VertexDescription(const VertexDescription& desc) :
00079 stride(desc.stride),
00080 nAttributes(desc.nAttributes),
00081 attributes(NULL)
00082 {
00083 if (nAttributes != 0)
00084 {
00085 attributes = new VertexAttribute[nAttributes];
00086 for (uint32 i = 0; i < nAttributes; i++)
00087 attributes[i] = desc.attributes[i];
00088 buildSemanticMap();
00089 }
00090 }
00091
00092
00093 Mesh::VertexDescription&
00094 Mesh::VertexDescription::operator=(const Mesh::VertexDescription& desc)
00095 {
00096 if (nAttributes < desc.nAttributes)
00097 {
00098 if (attributes != NULL)
00099 delete[] attributes;
00100 attributes = new VertexAttribute[desc.nAttributes];
00101 }
00102
00103 nAttributes = desc.nAttributes;
00104 stride = desc.stride;
00105 for (uint32 i = 0; i < nAttributes; i++)
00106 attributes[i] = desc.attributes[i];
00107 clearSemanticMap();
00108 buildSemanticMap();
00109
00110 return *this;
00111 }
00112
00113
00114
00115
00116 bool
00117 Mesh::VertexDescription::validate() const
00118 {
00119 for (uint32 i = 0; i < nAttributes; i++)
00120 {
00121 VertexAttribute& attr = attributes[i];
00122
00123
00124 if (attr.semantic >= SemanticMax || attr.format >= FormatMax)
00125 return false;
00126 if (attr.offset % 4 != 0)
00127 return false;
00128 if (attr.offset + VertexAttributeFormatSizes[attr.format] > stride)
00129 return false;
00130
00131
00132
00133 }
00134
00135 return true;
00136 }
00137
00138
00139 Mesh::VertexDescription::~VertexDescription()
00140 {
00141 delete[] attributes;
00142 }
00143
00144
00145 void
00146 Mesh::VertexDescription::buildSemanticMap()
00147 {
00148 for (uint32 i = 0; i < nAttributes; i++)
00149 semanticMap[attributes[i].semantic] = attributes[i];
00150 }
00151
00152
00153 void
00154 Mesh::VertexDescription::clearSemanticMap()
00155 {
00156 for (uint32 i = 0; i < SemanticMax; i++)
00157 semanticMap[i] = VertexAttribute();
00158 }
00159
00160
00161 Mesh::PrimitiveGroup::PrimitiveGroup()
00162 {
00163 }
00164
00165
00166 Mesh::PrimitiveGroup::~PrimitiveGroup()
00167 {
00168
00169
00170 }
00171
00172
00173 Mesh::Mesh() :
00174 vertexDesc(0, 0, NULL),
00175 nVertices(0),
00176 vertices(NULL),
00177 vbObject(0),
00178 vbInitialized(false)
00179 {
00180 }
00181
00182
00183 Mesh::~Mesh()
00184 {
00185 for (vector<PrimitiveGroup*>::iterator iter = groups.begin();
00186 iter != groups.end(); iter++)
00187 {
00188 delete *iter;
00189 }
00190
00191 if (vertices != NULL)
00192 delete vertices;
00193
00194 if (vbObject != 0)
00195 {
00196 glx::glDeleteBuffersARB(1, &vbObject);
00197 }
00198 }
00199
00200
00201 void
00202 Mesh::setVertices(uint32 _nVertices, void* vertexData)
00203 {
00204 nVertices = _nVertices;
00205 vertices = vertexData;
00206 }
00207
00208
00209 bool
00210 Mesh::setVertexDescription(const VertexDescription& desc)
00211 {
00212 if (!desc.validate())
00213 return false;
00214
00215 vertexDesc = desc;
00216
00217 return true;
00218 }
00219
00220
00221 const Mesh::VertexDescription& Mesh::getVertexDescription() const
00222 {
00223 return vertexDesc;
00224 }
00225
00226
00227 const Mesh::PrimitiveGroup*
00228 Mesh::getGroup(uint32 index) const
00229 {
00230 if (index >= groups.size())
00231 return NULL;
00232 else
00233 return groups[index];
00234 }
00235
00236
00237 uint32
00238 Mesh::addGroup(PrimitiveGroup* group)
00239 {
00240 groups.push_back(group);
00241 return groups.size();
00242 }
00243
00244
00245 uint32
00246 Mesh::addGroup(PrimitiveGroupType prim,
00247 uint32 materialIndex,
00248 uint32 nIndices,
00249 uint32* indices)
00250 {
00251 PrimitiveGroup* g = new PrimitiveGroup();
00252 g->prim = prim;
00253 g->materialIndex = materialIndex;
00254 g->nIndices = nIndices;
00255 g->indices = indices;
00256
00257 return addGroup(g);
00258 }
00259
00260
00261 void
00262 Mesh::clearGroups()
00263 {
00264 for (vector<PrimitiveGroup*>::iterator iter = groups.begin();
00265 iter != groups.end(); iter++)
00266 {
00267 delete *iter;
00268 }
00269
00270 groups.clear();
00271 }
00272
00273
00274 const string&
00275 Mesh::getName() const
00276 {
00277 return name;
00278 }
00279
00280
00281 void
00282 Mesh::setName(const string& _name)
00283 {
00284 name = _name;
00285 }
00286
00287
00288 void
00289 Mesh::remapIndices(const vector<uint32>& indexMap)
00290 {
00291 for (vector<PrimitiveGroup*>::iterator iter = groups.begin();
00292 iter != groups.end(); iter++)
00293 {
00294 PrimitiveGroup* group = *iter;
00295 for (uint32 i = 0; i < group->nIndices; i++)
00296 {
00297 group->indices[i] = indexMap[group->indices[i]];
00298 }
00299 }
00300 }
00301
00302
00303 bool
00304 Mesh::pick(const Ray3d& ray, double& distance) const
00305 {
00306 double maxDistance = 1.0e30;
00307 double closest = maxDistance;
00308
00309
00310
00311 if (vertexDesc.getAttribute(Position).semantic != Position ||
00312 vertexDesc.getAttribute(Position).format != Float3)
00313 {
00314 return false;
00315 }
00316
00317 uint posOffset = vertexDesc.getAttribute(Position).offset;
00318 char* vdata = reinterpret_cast<char*>(vertices);
00319
00320
00321 for (vector<PrimitiveGroup*>::const_iterator iter = groups.begin();
00322 iter != groups.end(); iter++)
00323 {
00324 Mesh::PrimitiveGroupType primType = (*iter)->prim;
00325 uint32 nIndices = (*iter)->nIndices;
00326
00327
00328
00329 if ((primType == TriList || primType == TriStrip || primType == TriFan) &&
00330 (nIndices >= 3) &&
00331 !(primType == TriList && nIndices % 3 != 0))
00332 {
00333 uint32 index = 0;
00334 uint32 i0 = (*iter)->indices[0];
00335 uint32 i1 = (*iter)->indices[1];
00336 uint32 i2 = (*iter)->indices[2];
00337
00338
00339 do
00340 {
00341
00342 float* f0 = reinterpret_cast<float*>(vdata + i0 * vertexDesc.stride + posOffset);
00343 float* f1 = reinterpret_cast<float*>(vdata + i1 * vertexDesc.stride + posOffset);
00344 float* f2 = reinterpret_cast<float*>(vdata + i2 * vertexDesc.stride + posOffset);
00345 Point3d v0(f0[0], f0[1], f0[2]);
00346 Point3d v1(f1[0], f1[1], f1[2]);
00347 Point3d v2(f2[0], f2[1], f2[2]);
00348
00349
00350 Vec3d e0 = v1 - v0;
00351 Vec3d e1 = v2 - v0;
00352 Vec3d n = e0 ^ e1;
00353
00354
00355 double c = n * ray.direction;
00356
00357
00358
00359
00360 if (c != 0.0)
00361 {
00362 double t = (n * (v0 - ray.origin)) / c;
00363 if (t < closest && t > 0.0)
00364 {
00365 double m00 = e0 * e0;
00366 double m01 = e0 * e1;
00367 double m10 = e1 * e0;
00368 double m11 = e1 * e1;
00369 double det = m00 * m11 - m01 * m10;
00370 if (det != 0.0)
00371 {
00372 Point3d p = ray.point(t);
00373 Vec3d q = p - v0;
00374 double q0 = e0 * q;
00375 double q1 = e1 * q;
00376 double d = 1.0 / det;
00377 double s0 = (m11 * q0 - m01 * q1) * d;
00378 double s1 = (m00 * q1 - m10 * q0) * d;
00379 if (s0 >= 0.0 && s1 >= 0.0 && s0 + s1 <= 1.0)
00380 closest = t;
00381 }
00382 }
00383 }
00384
00385
00386 if (primType == TriList)
00387 {
00388 index += 3;
00389 if (index < nIndices)
00390 {
00391 i0 = (*iter)->indices[index + 0];
00392 i1 = (*iter)->indices[index + 1];
00393 i2 = (*iter)->indices[index + 2];
00394 }
00395 }
00396 else if (primType == TriStrip)
00397 {
00398 index += 1;
00399 if (index < nIndices)
00400 {
00401 i0 = i1;
00402 i1 = i2;
00403 i2 = (*iter)->indices[index];
00404
00405 }
00406 }
00407 else
00408 {
00409 index += 1;
00410 if (index < nIndices)
00411 {
00412 index += 1;
00413 i1 = i2;
00414 i2 = (*iter)->indices[index];
00415 }
00416 }
00417
00418 } while (index < nIndices);
00419 }
00420 }
00421
00422 if (closest != maxDistance)
00423 {
00424 distance = closest;
00425 return true;
00426 }
00427 else
00428 {
00429 return false;
00430 }
00431 }
00432
00433
00434 void
00435 Mesh::render(const std::vector<const Material*>& materials,
00436 RenderContext& rc) const
00437 {
00438
00439
00440
00441
00442
00443
00444
00445 if (!vbInitialized && isVBOSupported())
00446 {
00447 vbInitialized = true;
00448
00449 if (nVertices * vertexDesc.stride > MinVBOSize)
00450 {
00451 glx::glGenBuffersARB(1, &vbObject);
00452 if (vbObject != 0)
00453 {
00454 glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbObject);
00455 glx::glBufferDataARB(GL_ARRAY_BUFFER_ARB,
00456 nVertices * vertexDesc.stride,
00457 vertices,
00458 GL_STATIC_DRAW_ARB);
00459 }
00460 }
00461 }
00462
00463 if (vbObject != 0)
00464 {
00465 glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbObject);
00466 rc.setVertexArrays(vertexDesc, NULL);
00467 }
00468 else
00469 {
00470 rc.setVertexArrays(vertexDesc, vertices);
00471 }
00472
00473 uint32 lastMaterial = ~0;
00474
00475
00476 for (vector<PrimitiveGroup*>::const_iterator iter = groups.begin();
00477 iter != groups.end(); iter++)
00478 {
00479
00480 const Material* mat = NULL;
00481 uint32 materialIndex = (*iter)->materialIndex;
00482 if (materialIndex != lastMaterial && materialIndex < materials.size())
00483 mat = materials[materialIndex];
00484
00485 rc.setMaterial(mat);
00486 rc.drawGroup(**iter);
00487 }
00488
00489 if (vbObject != 0)
00490 glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
00491 }
00492
00493
00494 AxisAlignedBox
00495 Mesh::getBoundingBox() const
00496 {
00497 AxisAlignedBox bbox;
00498
00499
00500 if (vertexDesc.getAttribute(Position).format != Float3)
00501 return bbox;
00502
00503 char* vdata = reinterpret_cast<char*>(vertices) + vertexDesc.getAttribute(Position).offset;
00504
00505 for (uint32 i = 0; i < nVertices; i++, vdata += vertexDesc.stride)
00506 bbox.include(Point3f(reinterpret_cast<float*>(vdata)));
00507
00508 return bbox;
00509 }
00510
00511
00512 void
00513 Mesh::transform(Vec3f translation, float scale)
00514 {
00515 if (vertexDesc.getAttribute(Position).format != Float3)
00516 return;
00517
00518 char* vdata = reinterpret_cast<char*>(vertices) + vertexDesc.getAttribute(Position).offset;
00519 for (uint32 i = 0; i < nVertices; i++, vdata += vertexDesc.stride)
00520 {
00521 Vec3f tv = (Vec3f(reinterpret_cast<float*>(vdata)) + translation) * scale;
00522 reinterpret_cast<float*>(vdata)[0] = tv.x;
00523 reinterpret_cast<float*>(vdata)[1] = tv.y;
00524 reinterpret_cast<float*>(vdata)[2] = tv.z;
00525 }
00526 }
00527
00528
00529 Mesh::PrimitiveGroupType
00530 Mesh::parsePrimitiveGroupType(const string& name)
00531 {
00532 if (name == "trilist")
00533 return TriList;
00534 else if (name == "tristrip")
00535 return TriStrip;
00536 else if (name == "trifan")
00537 return TriFan;
00538 else if (name == "linelist")
00539 return LineList;
00540 else if (name == "linestrip")
00541 return LineStrip;
00542 else if (name == "points")
00543 return PointList;
00544 else
00545 return InvalidPrimitiveGroupType;
00546 }
00547
00548
00549 Mesh::VertexAttributeSemantic
00550 Mesh::parseVertexAttributeSemantic(const string& name)
00551 {
00552 if (name == "position")
00553 return Position;
00554 else if (name == "normal")
00555 return Normal;
00556 else if (name == "color0")
00557 return Color0;
00558 else if (name == "color1")
00559 return Color1;
00560 else if (name == "tangent")
00561 return Tangent;
00562 else if (name == "texcoord0")
00563 return Texture0;
00564 else if (name == "texcoord1")
00565 return Texture1;
00566 else if (name == "texcoord2")
00567 return Texture2;
00568 else if (name == "texcoord3")
00569 return Texture3;
00570 else
00571 return InvalidSemantic;
00572 }
00573
00574
00575 Mesh::VertexAttributeFormat
00576 Mesh::parseVertexAttributeFormat(const string& name)
00577 {
00578 if (name == "f1")
00579 return Float1;
00580 else if (name == "f2")
00581 return Float2;
00582 else if (name == "f3")
00583 return Float3;
00584 else if (name == "f4")
00585 return Float4;
00586 else if (name == "ub4")
00587 return UByte4;
00588 else
00589 return InvalidFormat;
00590 }
00591
00592
00593 Mesh::TextureSemantic
00594 Mesh::parseTextureSemantic(const string& name)
00595 {
00596 if (name == "texture0")
00597 return DiffuseMap;
00598 else if (name == "normalmap")
00599 return NormalMap;
00600 else if (name == "specularmap")
00601 return SpecularMap;
00602 else if (name == "emissivemap")
00603 return EmissiveMap;
00604 else
00605 return InvalidTextureSemantic;
00606 }
00607
00608
00609 uint32
00610 Mesh::getVertexAttributeSize(VertexAttributeFormat fmt)
00611 {
00612 switch (fmt)
00613 {
00614 case Float1:
00615 case UByte4:
00616 return 4;
00617 case Float2:
00618 return 8;
00619 case Float3:
00620 return 12;
00621 case Float4:
00622 return 16;
00623 default:
00624 return 0;
00625 }
00626 }