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

OpenGL

开发平台:

Visual C++

  1. // vertexlist.cpp
  2. //
  3. // Copyright (C) 2001, Chris Laurel
  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 <algorithm>
  10. #include "gl.h"
  11. #include "glext.h"
  12. #include "vecgl.h"
  13. #include "vertexlist.h"
  14. using namespace std;
  15. VertexList::VertexList(uint32 _parts, uint32 initialVertexPoolSize) :
  16.     parts(_parts),
  17.     nVertices(0),
  18.     maxVertices(0),
  19.     vertices(NULL),
  20.     diffuseColor(1.0f, 1.0f, 1.0f),
  21.     specularColor(0.0f, 0.0f, 0.0f),
  22.     shininess(0.0f),
  23.     texture(InvalidResource),
  24.     bbox()
  25. {
  26.     if (initialVertexPoolSize > 0)
  27.     {
  28.         maxVertices = initialVertexPoolSize;
  29.         vertices = new VertexPart[vertexSize * maxVertices];
  30.     }
  31.     vertexSize = 3;
  32.     if ((parts & VertexNormal) != 0)
  33.         vertexSize += 3;
  34.     if ((parts & VertexColor0) != 0)
  35.         vertexSize += 1;
  36.     if ((parts & TexCoord0) != 0)
  37.         vertexSize += 2;
  38.     if ((parts & TexCoord1) != 0)
  39.         vertexSize += 2;
  40. }
  41. VertexList::~VertexList()
  42. {
  43.     // HACK: Don't delete the vertex data; the VertexList class as an intermediate
  44.     // step in converting from 3DS models to Celestia models, and after the
  45.     // conversion, the Celestia model will own the vertex data pointer.
  46. #if 0
  47.     if (vertices != NULL)
  48.         delete[] vertices;
  49. #endif
  50. }
  51. void VertexList::render()
  52. {
  53.     GLsizei stride = sizeof(VertexPart) * vertexSize;
  54.     uint32 start = 3;
  55.     // Vertex points
  56.     glEnableClientState(GL_VERTEX_ARRAY);
  57.     glVertexPointer(3, GL_FLOAT, stride, static_cast<void*>(vertices));
  58.     
  59.     // Vertex normals
  60.     if ((parts & VertexNormal) != 0)
  61.     {
  62.         glEnableClientState(GL_NORMAL_ARRAY);
  63.         glNormalPointer(GL_FLOAT, stride, static_cast<void*>(&vertices[start]));
  64.         start += 3;
  65.     }
  66.     else
  67.     {
  68.         glDisableClientState(GL_NORMAL_ARRAY);
  69.     }
  70.     // Vertex color
  71.     if ((parts & VertexColor0) != 0)
  72.     {
  73.         glEnableClientState(GL_COLOR_ARRAY);
  74.         glColorPointer(4, GL_UNSIGNED_BYTE, stride,
  75.                        static_cast<void*>(&vertices[start]));
  76.         start += 1;
  77.     }
  78.     else
  79.     {
  80.         glDisableClientState(GL_COLOR_ARRAY);
  81.         glColor(diffuseColor);
  82.     }
  83.     // Texture coordinates
  84.     if ((parts & TexCoord0) != 0)
  85.     {
  86.         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  87.         glTexCoordPointer(2, GL_FLOAT, stride,
  88.                           static_cast<void*>(&vertices[start]));
  89.         start += 2;
  90.     }
  91.     else
  92.     {
  93.         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  94.     }
  95.     if ((parts & TexCoord1) != 0)
  96.     {
  97.         // glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  98.         glTexCoordPointer(2, GL_FLOAT, stride,
  99.                           static_cast<void*>(&vertices[start]));
  100.         start += 2;
  101.     }
  102.     glDrawArrays(GL_TRIANGLES, 0, nVertices);
  103. }
  104. void VertexList::addVertex(const Vertex& v)
  105. {
  106.     if (nVertices == maxVertices)
  107.     {
  108.         if (maxVertices == 0)
  109.         {
  110.             vertices = new VertexPart[16 * vertexSize];
  111.             maxVertices = 16;
  112.         }
  113.         else
  114.         {
  115.             VertexPart* newVertices = new VertexPart[maxVertices * 2 * vertexSize];
  116.             copy(vertices, vertices + nVertices * vertexSize, newVertices);
  117.             delete[] vertices;
  118.             vertices = newVertices;
  119.             maxVertices *= 2;
  120.         }
  121.     }
  122.     uint32 n = nVertices * vertexSize;
  123.     vertices[n++].f = v.point.x;
  124.     vertices[n++].f = v.point.y;
  125.     vertices[n++].f = v.point.z;
  126.     if ((parts & VertexNormal) != 0)
  127.     {
  128.         vertices[n++].f = v.normal.x;
  129.         vertices[n++].f = v.normal.y;
  130.         vertices[n++].f = v.normal.z;
  131.     }
  132.     if ((parts & VertexColor0) != 0)
  133.     {
  134.         vertices[n].c[0] = (int) (v.color.red() * 255.99f);
  135.         vertices[n].c[1] = (int) (v.color.green() * 255.99f);
  136.         vertices[n].c[2] = (int) (v.color.blue() * 255.99f);
  137.         vertices[n].c[3] = (int) (v.color.alpha() * 255.99f);
  138.         n++;
  139.     }
  140.     if ((parts & TexCoord0) != 0)
  141.     {
  142.         vertices[n++].f = v.texCoords[0].x;
  143.         vertices[n++].f = v.texCoords[0].y;
  144.     }
  145.     if ((parts & TexCoord1) != 0)
  146.     {
  147.         vertices[n++].f = v.texCoords[1].x;
  148.         vertices[n++].f = v.texCoords[1].y;
  149.     }
  150.     bbox.include(v.point);
  151.     nVertices++;
  152. }
  153. AxisAlignedBox VertexList::getBoundingBox() const
  154. {
  155.     return bbox;
  156. }
  157. Color VertexList::getDiffuseColor() const
  158. {
  159.     return diffuseColor;
  160. }
  161. void VertexList::setDiffuseColor(Color color)
  162. {
  163.     diffuseColor = color;
  164. }
  165. Color VertexList::getSpecularColor() const
  166. {
  167.     return specularColor;
  168. }
  169. void VertexList::setSpecularColor(Color color)
  170. {
  171.     specularColor = color;
  172. }
  173. float VertexList::getShininess() const
  174. {
  175.     return shininess;
  176. }
  177. void VertexList::setShininess(float _shininess)
  178. {
  179.     shininess = _shininess;
  180. }
  181. ResourceHandle VertexList::getTexture() const
  182. {
  183.     return texture;
  184. }
  185. void VertexList::setTexture(ResourceHandle _texture)
  186. {
  187.     texture = _texture;
  188. }
  189. // Apply a translation and uniform scale to the vertices
  190. void VertexList::transform(Vec3f translation, float scale)
  191. {
  192.     for (uint32 i = 0; i < nVertices; i++)
  193.     {
  194.         uint32 n = i * vertexSize;
  195.         Vec3f tv = (Vec3f(vertices[n].f, vertices[n + 1].f, vertices[n + 2].f) + translation) * scale;
  196.         vertices[n    ].f = tv.x;
  197.         vertices[n + 1].f = tv.y;
  198.         vertices[n + 2].f = tv.z;
  199.     }
  200.     // Transform the bounding box
  201.     Point3f mn = bbox.getMinimum();
  202.     Point3f mx = bbox.getMaximum();
  203.     Point3f tr(-translation.x, -translation.y, -translation.z);
  204.     bbox = AxisAlignedBox(Point3f(0, 0, 0) + ((mn - tr) * scale),
  205.                           Point3f(0, 0, 0) + ((mx - tr) * scale));
  206. }
  207. bool VertexList::pick(const Ray3d& ray, double& distance)
  208. {
  209.     double maxDistance = 1.0e30;
  210.     double closest = maxDistance;
  211.     uint32 k = 0;
  212.     for (uint32 i = 0; i < nVertices; i += 3)
  213.     {
  214.         // Get the triangle vertices v0, v1, and v2
  215.         Point3d v0(vertices[k + 0].f, vertices[k + 1].f, vertices[k + 2].f);
  216.         k += vertexSize;
  217.         Point3d v1(vertices[k + 0].f, vertices[k + 1].f, vertices[k + 2].f);
  218.         k += vertexSize;
  219.         Point3d v2(vertices[k + 0].f, vertices[k + 1].f, vertices[k + 2].f);
  220.         k += vertexSize;
  221.         // Compute the edge vectors e0 and e1, and the normal n
  222.         Vec3d e0 = v1 - v0;
  223.         Vec3d e1 = v2 - v0;
  224.         Vec3d n = e0 ^ e1;
  225.         // c is the cosine of the angle between the ray and triangle normal
  226.         double c = n * ray.direction;
  227.         // If the ray is parallel to the triangle, it either misses the
  228.         // triangle completely, or is contained in the triangle's plane.
  229.         // If it's contained in the plane, we'll still call it a miss.
  230.         if (c != 0.0)
  231.         {
  232.             double t = (n * (v0 - ray.origin)) / c;
  233.             if (t < closest && t > 0.0)
  234.             {
  235.                 double m00 = e0 * e0;
  236.                 double m01 = e0 * e1;
  237.                 double m10 = e1 * e0;
  238.                 double m11 = e1 * e1;
  239.                 double det = m00 * m11 - m01 * m10;
  240.                 if (det != 0.0)
  241.                 {
  242.                     Point3d p = ray.point(t);
  243.                     Vec3d q = p - v0;
  244.                     double q0 = e0 * q;
  245.                     double q1 = e1 * q;
  246.                     double d = 1.0 / det;
  247.                     double s0 = (m11 * q0 - m01 * q1) * d;
  248.                     double s1 = (m00 * q1 - m10 * q0) * d;
  249.                     if (s0 >= 0.0 && s1 >= 0.0 && s0 + s1 <= 1.0)
  250.                         closest = t;
  251.                 }
  252.             }
  253.         }
  254.     }
  255.     if (closest != maxDistance)
  256.     {
  257.         distance = closest;
  258.         return true;
  259.     }
  260.     else
  261.     {
  262.         return false;
  263.     }
  264. }
  265. uint32 VertexList::getVertexParts() const
  266. {
  267.     return parts;
  268. }
  269. void* VertexList::getVertexData() const
  270. {
  271.     return reinterpret_cast<void*>(vertices);
  272. }
  273. uint32 VertexList::getVertexCount() const
  274. {
  275.     return nVertices;
  276. }