mesh.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:18k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // mesh.cpp
  2. //
  3. // Copyright (C) 2004-2006, Chris Laurel <claurel@shatters.net>
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. #include "mesh.h"
  10. #include "rendcontext.h"
  11. #include "gl.h"
  12. #include "glext.h"
  13. #include <cassert>
  14. #include <iostream>
  15. #include <algorithm>
  16. using namespace std;
  17. static size_t VertexAttributeFormatSizes[Mesh::FormatMax] =
  18. {
  19.      4,  // Float1
  20.      8,  // Float2
  21.      12, // Float3
  22.      16, // Float4,
  23.      4,  // UByte4
  24. };
  25. // Vertex buffer object support
  26. // VBO optimization is only worthwhile for large enough vertex lists
  27. static const unsigned int MinVBOSize = 4096;
  28. static bool VBOSupportTested = false;
  29. static bool VBOSupported = false;
  30. static bool isVBOSupported()
  31. {
  32.     if (!VBOSupportTested)
  33.     {
  34.         VBOSupportTested = true;
  35.         VBOSupported = ExtensionSupported("GL_ARB_vertex_buffer_object");
  36.     }
  37.     return VBOSupported;
  38. }
  39. Mesh::Material::Material() :
  40.     diffuse(0.0f, 0.0f, 0.0f),
  41.     emissive(0.0f, 0.0f, 0.0f),
  42.     specular(0.0f, 0.0f, 0.0f),
  43.     specularPower(1.0f),
  44.     opacity(1.0f),
  45.     blend(NormalBlend)
  46. {
  47.     for (int i = 0; i < TextureSemanticMax; i++)
  48.         maps[i] = InvalidResource;
  49. }
  50. Mesh::VertexDescription::VertexDescription(uint32 _stride,
  51.                                            uint32 _nAttributes,
  52.                                            VertexAttribute* _attributes) :
  53.             stride(_stride),
  54.             nAttributes(_nAttributes),
  55.             attributes(NULL)
  56. {
  57.     if (nAttributes != 0)
  58.     {
  59.         attributes = new VertexAttribute[nAttributes];
  60.         for (uint32 i = 0; i < nAttributes; i++)
  61.             attributes[i] = _attributes[i];
  62.         buildSemanticMap();
  63.     }
  64. }
  65. Mesh::VertexDescription::VertexDescription(const VertexDescription& desc) :
  66.     stride(desc.stride),
  67.     nAttributes(desc.nAttributes),
  68.     attributes(NULL)
  69. {
  70.     if (nAttributes != 0)
  71.     {
  72.         attributes = new VertexAttribute[nAttributes];
  73.         for (uint32 i = 0; i < nAttributes; i++)
  74.             attributes[i] = desc.attributes[i];
  75.         buildSemanticMap();
  76.     }
  77. }
  78. Mesh::VertexDescription&
  79. Mesh::VertexDescription::operator=(const Mesh::VertexDescription& desc)
  80. {
  81.     if (nAttributes < desc.nAttributes)
  82.     {
  83.         if (attributes != NULL)
  84.             delete[] attributes;
  85.         attributes = new VertexAttribute[desc.nAttributes];
  86.     }
  87.     nAttributes = desc.nAttributes;
  88.     stride = desc.stride;
  89.     for (uint32 i = 0; i < nAttributes; i++)
  90.         attributes[i] = desc.attributes[i];
  91.     clearSemanticMap();
  92.     buildSemanticMap();
  93.     return *this;
  94. }
  95. // TODO: This should be called in the constructor; we should start using
  96. // exceptions in Celestia.
  97. bool
  98. Mesh::VertexDescription::validate() const
  99. {
  100.     for (uint32 i = 0; i < nAttributes; i++)
  101.     {
  102.         VertexAttribute& attr = attributes[i];
  103.         // Validate the attribute
  104.         if (attr.semantic >= SemanticMax || attr.format >= FormatMax)
  105.             return false;
  106.         if (attr.offset % 4 != 0)
  107.             return false;
  108.         if (attr.offset + VertexAttributeFormatSizes[attr.format] > stride)
  109.             return false;
  110.         // TODO: check for repetition of attributes
  111.         // if (vertexAttributeMap[attr->semantic].format != InvalidFormat)
  112.         //   return false;
  113.     }
  114.     return true;
  115. }
  116. Mesh::VertexDescription::~VertexDescription()
  117. {
  118.     delete[] attributes;
  119. }
  120. void
  121. Mesh::VertexDescription::buildSemanticMap()
  122. {
  123.     for (uint32 i = 0; i < nAttributes; i++)
  124.         semanticMap[attributes[i].semantic] = attributes[i];
  125. }
  126. void
  127. Mesh::VertexDescription::clearSemanticMap()
  128. {
  129.     for (uint32 i = 0; i < SemanticMax; i++)
  130.         semanticMap[i] = VertexAttribute();
  131. }
  132. Mesh::PrimitiveGroup::PrimitiveGroup()
  133. {
  134. }
  135. Mesh::PrimitiveGroup::~PrimitiveGroup()
  136. {
  137.     // TODO: probably should free index list; need to sort out
  138.     // ownership issues.
  139. }
  140. uint32
  141. Mesh::PrimitiveGroup::getPrimitiveCount() const
  142. {
  143.     switch (prim)
  144.     {
  145.     case TriList:
  146.         return nIndices / 3;
  147.     case TriStrip:
  148.     case TriFan:
  149.         return nIndices - 2;
  150.     case LineList:
  151.         return nIndices / 2;
  152.     case LineStrip:
  153.         return nIndices - 2;
  154.     case PointList:
  155.     case SpriteList:
  156.         return nIndices;
  157.     default:
  158.         // Invalid value
  159.         return 0;
  160.     }
  161. }
  162. Mesh::Mesh() :
  163.     vertexDesc(0, 0, NULL),
  164.     nVertices(0),
  165.     vertices(NULL),
  166.     vbObject(0),
  167.     vbInitialized(false)
  168. {
  169. }
  170. Mesh::~Mesh()
  171. {
  172.     for (vector<PrimitiveGroup*>::iterator iter = groups.begin();
  173.          iter != groups.end(); iter++)
  174.     {
  175.         delete *iter;
  176.     }
  177.     // TODO: this is just to cast away void* and shut up GCC warnings;
  178.     // should probably be static_cast<VertexList::VertexPart*>
  179.     if (vertices != NULL)
  180.         delete[] static_cast<char*>(vertices);
  181.     if (vbObject != 0)
  182.     {
  183.         glx::glDeleteBuffersARB(1, &vbObject);
  184.     }
  185. }
  186. void
  187. Mesh::setVertices(uint32 _nVertices, void* vertexData)
  188. {
  189.     nVertices = _nVertices;
  190.     vertices = vertexData;
  191. }
  192. bool
  193. Mesh::setVertexDescription(const VertexDescription& desc)
  194. {
  195.     if (!desc.validate())
  196.         return false;
  197.     vertexDesc = desc;
  198.     return true;
  199. }
  200. const Mesh::VertexDescription& Mesh::getVertexDescription() const
  201. {
  202.     return vertexDesc;
  203. }
  204. const Mesh::PrimitiveGroup*
  205. Mesh::getGroup(uint32 index) const
  206. {
  207.     if (index >= groups.size())
  208.         return NULL;
  209.     else
  210.         return groups[index];
  211. }
  212. uint32
  213. Mesh::addGroup(PrimitiveGroup* group)
  214. {
  215.     groups.push_back(group);
  216.     return groups.size();
  217. }
  218. uint32
  219. Mesh::addGroup(PrimitiveGroupType prim,
  220.                uint32 materialIndex,
  221.                uint32 nIndices,
  222.                uint32* indices)
  223. {
  224.     PrimitiveGroup* g = new PrimitiveGroup();
  225.     g->prim = prim;
  226.     g->materialIndex = materialIndex;
  227.     g->nIndices = nIndices;
  228.     g->indices = indices;
  229.     return addGroup(g);
  230. }
  231. uint32
  232. Mesh::getGroupCount() const
  233. {
  234.     return groups.size();
  235. }
  236. void
  237. Mesh::clearGroups()
  238. {
  239.     for (vector<PrimitiveGroup*>::iterator iter = groups.begin();
  240.          iter != groups.end(); iter++)
  241.     {
  242.         delete *iter;
  243.     }
  244.     groups.clear();
  245. }
  246. const string&
  247. Mesh::getName() const
  248. {
  249.     return name;
  250. }
  251. void
  252. Mesh::setName(const string& _name)
  253. {
  254.     name = _name;
  255. }
  256. void
  257. Mesh::remapIndices(const vector<uint32>& indexMap)
  258. {
  259.     for (vector<PrimitiveGroup*>::iterator iter = groups.begin();
  260.          iter != groups.end(); iter++)
  261.     {
  262.         PrimitiveGroup* group = *iter;
  263.         for (uint32 i = 0; i < group->nIndices; i++)
  264.         {
  265.             group->indices[i] = indexMap[group->indices[i]];
  266.         }
  267.     }
  268. }
  269. void
  270. Mesh::remapMaterials(const vector<uint32>& materialMap)
  271. {
  272.     for (vector<PrimitiveGroup*>::iterator iter = groups.begin();
  273.          iter != groups.end(); iter++)
  274.     {
  275.         (*iter)->materialIndex = materialMap[(*iter)->materialIndex];
  276.     }
  277. }
  278. class PrimitiveGroupComparator : public std::binary_function<const Mesh::PrimitiveGroup*, const Mesh::PrimitiveGroup*, bool>
  279. {
  280. public:
  281.     bool operator()(const Mesh::PrimitiveGroup* g0, const Mesh::PrimitiveGroup* g1) const
  282.     {
  283.         return g0->materialIndex < g1->materialIndex;
  284.     }
  285. private:
  286.     int unused;
  287. };
  288. void
  289. Mesh::aggregateByMaterial()
  290. {
  291.     sort(groups.begin(), groups.end(), PrimitiveGroupComparator());
  292. }
  293. bool
  294. Mesh::pick(const Ray3d& ray, double& distance) const
  295. {
  296.     double maxDistance = 1.0e30;
  297.     double closest = maxDistance;
  298.     // Pick will automatically fail without vertex positions--no reasonable
  299.     // mesh should lack these.
  300.     if (vertexDesc.getAttribute(Position).semantic != Position ||
  301.         vertexDesc.getAttribute(Position).format != Float3)
  302.     {
  303.         return false;
  304.     }
  305.     uint posOffset = vertexDesc.getAttribute(Position).offset;
  306.     char* vdata = reinterpret_cast<char*>(vertices);
  307.     // Iterate over all primitive groups in the mesh
  308.     for (vector<PrimitiveGroup*>::const_iterator iter = groups.begin();
  309.          iter != groups.end(); iter++)
  310.     {
  311.         Mesh::PrimitiveGroupType primType = (*iter)->prim;
  312.         uint32 nIndices = (*iter)->nIndices;
  313.         // Only attempt to compute the intersection of the ray with triangle
  314.         // groups.
  315.         if ((primType == TriList || primType == TriStrip || primType == TriFan) &&
  316.             (nIndices >= 3) &&
  317.             !(primType == TriList && nIndices % 3 != 0))
  318.         {
  319.             uint32 index = 0;
  320.             uint32 i0 = (*iter)->indices[0];
  321.             uint32 i1 = (*iter)->indices[1];
  322.             uint32 i2 = (*iter)->indices[2];
  323.             // Iterate over the triangles in the primitive group
  324.             do
  325.             {
  326.                 // Get the triangle vertices v0, v1, and v2
  327.                 float* f0 = reinterpret_cast<float*>(vdata + i0 * vertexDesc.stride + posOffset);
  328.                 float* f1 = reinterpret_cast<float*>(vdata + i1 * vertexDesc.stride + posOffset);
  329.                 float* f2 = reinterpret_cast<float*>(vdata + i2 * vertexDesc.stride + posOffset);
  330.                 Point3d v0(f0[0], f0[1], f0[2]);
  331.                 Point3d v1(f1[0], f1[1], f1[2]);
  332.                 Point3d v2(f2[0], f2[1], f2[2]);
  333.                 // Compute the edge vectors e0 and e1, and the normal n
  334.                 Vec3d e0 = v1 - v0;
  335.                 Vec3d e1 = v2 - v0;
  336.                 Vec3d n = e0 ^ e1;
  337.                 // c is the cosine of the angle between the ray and triangle normal
  338.                 double c = n * ray.direction;
  339.                 // If the ray is parallel to the triangle, it either misses the
  340.                 // triangle completely, or is contained in the triangle's plane.
  341.                 // If it's contained in the plane, we'll still call it a miss.
  342.                 if (c != 0.0)
  343.                 {
  344.                     double t = (n * (v0 - ray.origin)) / c;
  345.                     if (t < closest && t > 0.0)
  346.                     {
  347.                         double m00 = e0 * e0;
  348.                         double m01 = e0 * e1;
  349.                         double m10 = e1 * e0;
  350.                         double m11 = e1 * e1;
  351.                         double det = m00 * m11 - m01 * m10;
  352.                         if (det != 0.0)
  353.                         {
  354.                             Point3d p = ray.point(t);
  355.                             Vec3d q = p - v0;
  356.                             double q0 = e0 * q;
  357.                             double q1 = e1 * q;
  358.                             double d = 1.0 / det;
  359.                             double s0 = (m11 * q0 - m01 * q1) * d;
  360.                             double s1 = (m00 * q1 - m10 * q0) * d;
  361.                             if (s0 >= 0.0 && s1 >= 0.0 && s0 + s1 <= 1.0)
  362.                                 closest = t;
  363.                         }
  364.                     }
  365.                 }
  366.                 // Get the indices for the next triangle
  367.                 if (primType == TriList)
  368.                 {
  369.                     index += 3;
  370.                     if (index < nIndices)
  371.                     {
  372.                         i0 = (*iter)->indices[index + 0];
  373.                         i1 = (*iter)->indices[index + 1];
  374.                         i2 = (*iter)->indices[index + 2];
  375.                     }
  376.                 }
  377.                 else if (primType == TriStrip)
  378.                 {
  379.                     index += 1;
  380.                     if (index < nIndices)
  381.                     {
  382.                         i0 = i1;
  383.                         i1 = i2;
  384.                         i2 = (*iter)->indices[index];
  385.                         // TODO: alternate orientation of triangles in a strip
  386.                     }
  387.                 }
  388.                 else // primType == TriFan
  389.                 {
  390.                     index += 1;
  391.                     if (index < nIndices)
  392.                     {
  393.                         index += 1;
  394.                         i1 = i2;
  395.                         i2 = (*iter)->indices[index];
  396.                     }
  397.                 }
  398.             } while (index < nIndices);
  399.         }
  400.     }
  401.     if (closest != maxDistance)
  402.     {
  403.         distance = closest;
  404.         return true;
  405.     }
  406.     else
  407.     {
  408.         return false;
  409.     }
  410. }
  411. void
  412. Mesh::render(const std::vector<const Material*>& materials,
  413.              RenderContext& rc) const
  414. {
  415.     // The first time the mesh is rendered, we will try and place the
  416.     // vertex data in a vertex buffer object and potentially get a huge
  417.     // rendering performance boost.  This can consume a great deal of
  418.     // memory, since we're duplicating the vertex data.  TODO: investigate
  419.     // the possibility of deleting the original data.  We can always map
  420.     // read-only later on for things like picking, but this could be a low
  421.     // performance path.
  422.     if (!vbInitialized && isVBOSupported())
  423.     {
  424.         vbInitialized = true;
  425.         if (nVertices * vertexDesc.stride > MinVBOSize)
  426.         {
  427.             glx::glGenBuffersARB(1, &vbObject);
  428.             if (vbObject != 0)
  429.             {
  430.                 glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbObject);
  431.                 glx::glBufferDataARB(GL_ARRAY_BUFFER_ARB,
  432.                                      nVertices * vertexDesc.stride,
  433.                                      vertices,
  434.                                      GL_STATIC_DRAW_ARB);
  435.             }
  436.         }
  437.     }
  438.     if (vbObject != 0)
  439.     {
  440.         glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbObject);
  441.         rc.setVertexArrays(vertexDesc, NULL);
  442.     }
  443.     else
  444.     {
  445.         rc.setVertexArrays(vertexDesc, vertices);
  446.     }
  447.     uint32 lastMaterial = ~0u;
  448.     // Iterate over all primitive groups in the mesh
  449.     for (vector<PrimitiveGroup*>::const_iterator iter = groups.begin();
  450.          iter != groups.end(); iter++)
  451.     {
  452.         // Set up the material
  453.         const Material* mat = NULL;
  454.         uint32 materialIndex = (*iter)->materialIndex;
  455.         if (materialIndex != lastMaterial && materialIndex < materials.size())
  456.             mat = materials[materialIndex];
  457.         rc.setMaterial(mat);
  458.         rc.drawGroup(**iter);
  459.     }
  460.     if (vbObject != 0)
  461.         glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
  462. }
  463. AxisAlignedBox
  464. Mesh::getBoundingBox() const
  465. {
  466.     AxisAlignedBox bbox;
  467.     // Return an empty box if there's no position info
  468.     if (vertexDesc.getAttribute(Position).format != Float3)
  469.         return bbox;
  470.     char* vdata = reinterpret_cast<char*>(vertices) + vertexDesc.getAttribute(Position).offset;
  471.     if (vertexDesc.getAttribute(PointSize).format == Float1)
  472.     {
  473.         // Handle bounding box calculation for point sprites. Unlike other
  474.         // primitives, point sprite vertices have a non-zero size.
  475.         int pointSizeOffset = (int) vertexDesc.getAttribute(PointSize).offset -
  476.             (int) vertexDesc.getAttribute(Position).offset;
  477.         
  478.         for (uint32 i = 0; i < nVertices; i++, vdata += vertexDesc.stride)
  479.         {
  480.             Point3f center = Point3f(reinterpret_cast<float*>(vdata));
  481.             float pointSize = (reinterpret_cast<float*>(vdata + pointSizeOffset))[0];
  482.             Vec3f offsetVec(pointSize, pointSize, pointSize);
  483.             AxisAlignedBox pointbox(center - offsetVec, center + offsetVec);
  484.             bbox.include(pointbox);
  485.         }
  486.     }
  487.     else
  488.     {
  489.         for (uint32 i = 0; i < nVertices; i++, vdata += vertexDesc.stride)
  490.             bbox.include(Point3f(reinterpret_cast<float*>(vdata)));
  491.     }
  492.     return bbox;
  493. }
  494. void
  495. Mesh::transform(Vec3f translation, float scale)
  496. {
  497.     if (vertexDesc.getAttribute(Position).format != Float3)
  498.         return;
  499.     char* vdata = reinterpret_cast<char*>(vertices) + vertexDesc.getAttribute(Position).offset;
  500.     uint32 i;
  501.     // Scale and translate the vertex positions
  502.     for (i = 0; i < nVertices; i++, vdata += vertexDesc.stride)
  503.     {
  504.         Vec3f tv = (Vec3f(reinterpret_cast<float*>(vdata)) + translation) * scale;
  505.         reinterpret_cast<float*>(vdata)[0] = tv.x;
  506.         reinterpret_cast<float*>(vdata)[1] = tv.y;
  507.         reinterpret_cast<float*>(vdata)[2] = tv.z;
  508.     }
  509.     // Point sizes need to be scaled as well
  510.     if (vertexDesc.getAttribute(PointSize).format == Float1)
  511.     {
  512.         vdata = reinterpret_cast<char*>(vertices) + vertexDesc.getAttribute(PointSize).offset;
  513.         for (i = 0; i < nVertices; i++, vdata += vertexDesc.stride)
  514.             reinterpret_cast<float*>(vdata)[0] *= scale;
  515.     }
  516. }
  517. uint32
  518. Mesh::getPrimitiveCount() const
  519. {
  520.     uint32 count = 0;
  521.     for (vector<PrimitiveGroup*>::const_iterator iter = groups.begin();
  522.          iter != groups.end(); iter++)
  523.     {
  524.         count += (*iter)->getPrimitiveCount();
  525.     }
  526.     return count;
  527. }
  528. Mesh::PrimitiveGroupType
  529. Mesh::parsePrimitiveGroupType(const string& name)
  530. {
  531.     if (name == "trilist")
  532.         return TriList;
  533.     else if (name == "tristrip")
  534.         return TriStrip;
  535.     else if (name == "trifan")
  536.         return TriFan;
  537.     else if (name == "linelist")
  538.         return LineList;
  539.     else if (name == "linestrip")
  540.         return LineStrip;
  541.     else if (name == "points")
  542.         return PointList;
  543.     else if (name == "sprites")
  544.         return SpriteList;
  545.     else
  546.         return InvalidPrimitiveGroupType;
  547. }
  548. Mesh::VertexAttributeSemantic
  549. Mesh::parseVertexAttributeSemantic(const string& name)
  550. {
  551.     if (name == "position")
  552.         return Position;
  553.     else if (name == "normal")
  554.         return Normal;
  555.     else if (name == "color0")
  556.         return Color0;
  557.     else if (name == "color1")
  558.         return Color1;
  559.     else if (name == "tangent")
  560.         return Tangent;
  561.     else if (name == "texcoord0")
  562.         return Texture0;
  563.     else if (name == "texcoord1")
  564.         return Texture1;
  565.     else if (name == "texcoord2")
  566.         return Texture2;
  567.     else if (name == "texcoord3")
  568.         return Texture3;
  569.     else if (name == "pointsize")
  570.         return PointSize;
  571.     else
  572.         return InvalidSemantic;
  573. }
  574. Mesh::VertexAttributeFormat
  575. Mesh::parseVertexAttributeFormat(const string& name)
  576. {
  577.     if (name == "f1")
  578.         return Float1;
  579.     else if (name == "f2")
  580.         return Float2;
  581.     else if (name == "f3")
  582.         return Float3;
  583.     else if (name == "f4")
  584.         return Float4;
  585.     else if (name == "ub4")
  586.         return UByte4;
  587.     else
  588.         return InvalidFormat;
  589. }
  590. Mesh::TextureSemantic
  591. Mesh::parseTextureSemantic(const string& name)
  592. {
  593.     if (name == "texture0")
  594.         return DiffuseMap;
  595.     else if (name == "normalmap")
  596.         return NormalMap;
  597.     else if (name == "specularmap")
  598.         return SpecularMap;
  599.     else if (name == "emissivemap")
  600.         return EmissiveMap;
  601.     else
  602.         return InvalidTextureSemantic;
  603. }
  604. uint32
  605. Mesh::getVertexAttributeSize(VertexAttributeFormat fmt)
  606. {
  607.     switch (fmt)
  608.     {
  609.     case Float1:
  610.     case UByte4:
  611.         return 4;
  612.     case Float2:
  613.         return 8;
  614.     case Float3:
  615.         return 12;
  616.     case Float4:
  617.         return 16;
  618.     default:
  619.         return 0;
  620.     }
  621. }