00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <algorithm>
00011 #include "gl.h"
00012 #include "glext.h"
00013 #include "vecgl.h"
00014 #include "vertexlist.h"
00015
00016 using namespace std;
00017
00018
00019 VertexList::VertexList(uint32 _parts, uint32 initialVertexPoolSize) :
00020 parts(_parts),
00021 nVertices(0),
00022 maxVertices(0),
00023 vertices(NULL),
00024 diffuseColor(1.0f, 1.0f, 1.0f),
00025 specularColor(0.0f, 0.0f, 0.0f),
00026 shininess(0.0f),
00027 texture(InvalidResource),
00028 bbox()
00029 {
00030 if (initialVertexPoolSize > 0)
00031 {
00032 maxVertices = initialVertexPoolSize;
00033 vertices = new VertexPart[vertexSize * maxVertices];
00034 }
00035
00036 vertexSize = 3;
00037 if ((parts & VertexNormal) != 0)
00038 vertexSize += 3;
00039 if ((parts & VertexColor0) != 0)
00040 vertexSize += 1;
00041 if ((parts & TexCoord0) != 0)
00042 vertexSize += 2;
00043 if ((parts & TexCoord1) != 0)
00044 vertexSize += 2;
00045 }
00046
00047
00048 VertexList::~VertexList()
00049 {
00050
00051
00052
00053 #if 0
00054 if (vertices != NULL)
00055 delete[] vertices;
00056 #endif
00057 }
00058
00059
00060 void VertexList::render()
00061 {
00062 GLsizei stride = sizeof(VertexPart) * vertexSize;
00063 uint32 start = 3;
00064
00065
00066 glEnableClientState(GL_VERTEX_ARRAY);
00067 glVertexPointer(3, GL_FLOAT, stride, static_cast<void*>(vertices));
00068
00069
00070 if ((parts & VertexNormal) != 0)
00071 {
00072 glEnableClientState(GL_NORMAL_ARRAY);
00073 glNormalPointer(GL_FLOAT, stride, static_cast<void*>(&vertices[start]));
00074 start += 3;
00075 }
00076 else
00077 {
00078 glDisableClientState(GL_NORMAL_ARRAY);
00079 }
00080
00081
00082 if ((parts & VertexColor0) != 0)
00083 {
00084 glEnableClientState(GL_COLOR_ARRAY);
00085 glColorPointer(4, GL_UNSIGNED_BYTE, stride,
00086 static_cast<void*>(&vertices[start]));
00087 start += 1;
00088 }
00089 else
00090 {
00091 glDisableClientState(GL_COLOR_ARRAY);
00092 glColor(diffuseColor);
00093 }
00094
00095
00096 if ((parts & TexCoord0) != 0)
00097 {
00098 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00099 glTexCoordPointer(2, GL_FLOAT, stride,
00100 static_cast<void*>(&vertices[start]));
00101 start += 2;
00102 }
00103 else
00104 {
00105 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00106 }
00107
00108 if ((parts & TexCoord1) != 0)
00109 {
00110
00111 glTexCoordPointer(2, GL_FLOAT, stride,
00112 static_cast<void*>(&vertices[start]));
00113 start += 2;
00114 }
00115
00116 glDrawArrays(GL_TRIANGLES, 0, nVertices);
00117 }
00118
00119
00120 void VertexList::addVertex(const Vertex& v)
00121 {
00122 if (nVertices == maxVertices)
00123 {
00124 if (maxVertices == 0)
00125 {
00126 vertices = new VertexPart[16 * vertexSize];
00127 maxVertices = 16;
00128 }
00129 else
00130 {
00131 VertexPart* newVertices = new VertexPart[maxVertices * 2 * vertexSize];
00132 copy(vertices, vertices + nVertices * vertexSize, newVertices);
00133 delete[] vertices;
00134 vertices = newVertices;
00135 maxVertices *= 2;
00136 }
00137 }
00138
00139 uint32 n = nVertices * vertexSize;
00140 vertices[n++].f = v.point.x;
00141 vertices[n++].f = v.point.y;
00142 vertices[n++].f = v.point.z;
00143 if ((parts & VertexNormal) != 0)
00144 {
00145 vertices[n++].f = v.normal.x;
00146 vertices[n++].f = v.normal.y;
00147 vertices[n++].f = v.normal.z;
00148 }
00149 if ((parts & VertexColor0) != 0)
00150 {
00151 vertices[n].c[0] = (int) (v.color.red() * 255.99f);
00152 vertices[n].c[1] = (int) (v.color.green() * 255.99f);
00153 vertices[n].c[2] = (int) (v.color.blue() * 255.99f);
00154 vertices[n].c[3] = (int) (v.color.alpha() * 255.99f);
00155 n++;
00156 }
00157 if ((parts & TexCoord0) != 0)
00158 {
00159 vertices[n++].f = v.texCoords[0].x;
00160 vertices[n++].f = v.texCoords[0].y;
00161 }
00162 if ((parts & TexCoord1) != 0)
00163 {
00164 vertices[n++].f = v.texCoords[1].x;
00165 vertices[n++].f = v.texCoords[1].y;
00166 }
00167
00168 bbox.include(v.point);
00169
00170 nVertices++;
00171 }
00172
00173
00174 AxisAlignedBox VertexList::getBoundingBox() const
00175 {
00176 return bbox;
00177 }
00178
00179
00180 Color VertexList::getDiffuseColor() const
00181 {
00182 return diffuseColor;
00183 }
00184
00185 void VertexList::setDiffuseColor(Color color)
00186 {
00187 diffuseColor = color;
00188 }
00189
00190 Color VertexList::getSpecularColor() const
00191 {
00192 return specularColor;
00193 }
00194
00195 void VertexList::setSpecularColor(Color color)
00196 {
00197 specularColor = color;
00198 }
00199
00200 float VertexList::getShininess() const
00201 {
00202 return shininess;
00203 }
00204
00205 void VertexList::setShininess(float _shininess)
00206 {
00207 shininess = _shininess;
00208 }
00209
00210 ResourceHandle VertexList::getTexture() const
00211 {
00212 return texture;
00213 }
00214
00215 void VertexList::setTexture(ResourceHandle _texture)
00216 {
00217 texture = _texture;
00218 }
00219
00220
00221
00222 void VertexList::transform(Vec3f translation, float scale)
00223 {
00224 for (uint32 i = 0; i < nVertices; i++)
00225 {
00226 uint32 n = i * vertexSize;
00227 Vec3f tv = (Vec3f(vertices[n].f, vertices[n + 1].f, vertices[n + 2].f) + translation) * scale;
00228 vertices[n ].f = tv.x;
00229 vertices[n + 1].f = tv.y;
00230 vertices[n + 2].f = tv.z;
00231 }
00232
00233
00234 Point3f mn = bbox.getMinimum();
00235 Point3f mx = bbox.getMaximum();
00236 Point3f tr(-translation.x, -translation.y, -translation.z);
00237 bbox = AxisAlignedBox(Point3f(0, 0, 0) + ((mn - tr) * scale),
00238 Point3f(0, 0, 0) + ((mx - tr) * scale));
00239 }
00240
00241
00242 bool VertexList::pick(const Ray3d& ray, double& distance)
00243 {
00244 double maxDistance = 1.0e30;
00245 double closest = maxDistance;
00246
00247 uint32 k = 0;
00248 for (uint32 i = 0; i < nVertices; i += 3)
00249 {
00250
00251 Point3d v0(vertices[k + 0].f, vertices[k + 1].f, vertices[k + 2].f);
00252 k += vertexSize;
00253 Point3d v1(vertices[k + 0].f, vertices[k + 1].f, vertices[k + 2].f);
00254 k += vertexSize;
00255 Point3d v2(vertices[k + 0].f, vertices[k + 1].f, vertices[k + 2].f);
00256 k += vertexSize;
00257
00258
00259 Vec3d e0 = v1 - v0;
00260 Vec3d e1 = v2 - v0;
00261 Vec3d n = e0 ^ e1;
00262
00263
00264 double c = n * ray.direction;
00265
00266
00267
00268
00269 if (c != 0.0)
00270 {
00271 double t = (n * (v0 - ray.origin)) / c;
00272 if (t < closest && t > 0.0)
00273 {
00274 double m00 = e0 * e0;
00275 double m01 = e0 * e1;
00276 double m10 = e1 * e0;
00277 double m11 = e1 * e1;
00278 double det = m00 * m11 - m01 * m10;
00279 if (det != 0.0)
00280 {
00281 Point3d p = ray.point(t);
00282 Vec3d q = p - v0;
00283 double q0 = e0 * q;
00284 double q1 = e1 * q;
00285 double d = 1.0 / det;
00286 double s0 = (m11 * q0 - m01 * q1) * d;
00287 double s1 = (m00 * q1 - m10 * q0) * d;
00288 if (s0 >= 0.0 && s1 >= 0.0 && s0 + s1 <= 1.0)
00289 closest = t;
00290 }
00291 }
00292 }
00293 }
00294
00295 if (closest != maxDistance)
00296 {
00297 distance = closest;
00298 return true;
00299 }
00300 else
00301 {
00302 return false;
00303 }
00304 }
00305
00306
00307 uint32 VertexList::getVertexParts() const
00308 {
00309 return parts;
00310 }
00311
00312
00313 void* VertexList::getVertexData() const
00314 {
00315 return reinterpret_cast<void*>(vertices);
00316 }
00317
00318
00319 uint32 VertexList::getVertexCount() const
00320 {
00321 return nVertices;
00322 }