00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <algorithm>
00011 #include <iostream>
00012 #include "gl.h"
00013 #ifndef MACOSX
00014 #include "glext.h"
00015 #endif
00016 #include "vertexprog.h"
00017 #include "texmanager.h"
00018 #include "3dsmesh.h"
00019
00020 using namespace std;
00021
00022
00023 static VertexList* convertToVertexList(M3DTriangleMesh& mesh,
00024 const M3DScene& scene,
00025 const string& texturePath);
00026
00027
00028
00029
00030 static int compareVertexLists(VertexList* vl0, VertexList* vl1)
00031 {
00032 float a0 = vl0->getDiffuseColor().alpha();
00033 float a1 = vl1->getDiffuseColor().alpha();
00034
00035 #if _MSC_VER <= 1200
00036
00037
00038
00039
00040
00041 if (a0 == -50.0f)
00042 cout << "Stupid MSVC compiler bug workaround! (This line will never be printed)\n";
00043 #endif
00044
00045 if (a0 == a1)
00046 {
00047 return vl0->getTexture() < vl1->getTexture();
00048 }
00049 else
00050 {
00051 return (a0 > a1);
00052 }
00053 }
00054
00055 Mesh3DS::Mesh3DS(const M3DScene& scene, const string& texturePath)
00056 {
00057 for (unsigned int i = 0; i < scene.getModelCount(); i++)
00058 {
00059 M3DModel* model = scene.getModel(i);
00060 if (model != NULL)
00061 {
00062 for (unsigned int j = 0; j < model->getTriMeshCount(); j++)
00063 {
00064 M3DTriangleMesh* mesh = model->getTriMesh(j);
00065 if (mesh != NULL)
00066 {
00067 vertexLists.insert(vertexLists.end(),
00068 convertToVertexList(*mesh, scene, texturePath));
00069 }
00070 }
00071 }
00072 }
00073
00074
00075
00076 sort(vertexLists.begin(), vertexLists.end(), compareVertexLists);
00077 }
00078
00079
00080 Mesh3DS::~Mesh3DS()
00081 {
00082 for (VertexListVec::iterator i = vertexLists.begin(); i != vertexLists.end(); i++)
00083 if (*i != NULL)
00084 delete *i;
00085 }
00086
00087
00088 void Mesh3DS::render(float lod)
00089 {
00090 render(Normals | Colors, lod);
00091 }
00092
00093
00094 void Mesh3DS::render(unsigned int attributes, float)
00095 {
00096 TextureManager* textureManager = GetTextureManager();
00097 ResourceHandle currentTexture = InvalidResource;
00098 bool specularOn = false;
00099 bool blendOn = false;
00100 Color black(0.0f, 0.0f, 0.0f);
00101
00102 int count = 0;
00103 for (VertexListVec::iterator i = vertexLists.begin(); i != vertexLists.end(); i++)
00104 {
00105
00106
00107
00108
00109 if ((attributes & Multipass) == 0)
00110 {
00111
00112
00113 if (attributes & VertexProgParams)
00114 vp::parameter(20, (*i)->getDiffuseColor());
00115
00116
00117
00118
00119
00120 if (!blendOn && (*i)->getDiffuseColor().alpha() <= 254.0f / 255.0f)
00121 {
00122 glEnable(GL_BLEND);
00123 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00124 }
00125
00126 Color specular = (*i)->getSpecularColor();
00127 float shininess = (*i)->getShininess();
00128 ResourceHandle texture = (*i)->getTexture();
00129 bool useSpecular = (specular != black);
00130
00131 if (specularOn && !useSpecular)
00132 {
00133 float matSpecular[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
00134 float zero = 0.0f;
00135 glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
00136 glMaterialfv(GL_FRONT, GL_SHININESS, &zero);
00137 }
00138 if (useSpecular)
00139 {
00140 float matSpecular[4] = { specular.red(), specular.green(),
00141 specular.blue(), 1.0f };
00142 glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
00143 glMaterialfv(GL_FRONT, GL_SHININESS, &shininess);
00144 }
00145 specularOn = useSpecular;
00146
00147 if (currentTexture != texture)
00148 {
00149 if (texture == InvalidResource)
00150 {
00151 glDisable(GL_TEXTURE_2D);
00152 }
00153 else
00154 {
00155 if (currentTexture == InvalidResource)
00156 glEnable(GL_TEXTURE_2D);
00157 Texture* t = textureManager->find(texture);
00158 if (t != NULL)
00159 t->bind();
00160 }
00161 currentTexture = texture;
00162 }
00163 }
00164
00165 (*i)->render();
00166 }
00167
00168 if (specularOn)
00169 {
00170 float matSpecular[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
00171 float zero = 0.0f;
00172 glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
00173 glMaterialfv(GL_FRONT, GL_SHININESS, &zero);
00174 }
00175
00176 if (blendOn)
00177 {
00178 glDisable(GL_BLEND);
00179 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00180 }
00181 }
00182
00183 void Mesh3DS::render(unsigned int attributes, const Frustum&, float lod)
00184 {
00185 render(attributes, lod);
00186 }
00187
00188
00189 bool Mesh3DS::pick(const Ray3d& r, double& distance)
00190 {
00191 double maxDistance = 1.0e30;
00192 double closest = maxDistance;
00193
00194 for (VertexListVec::const_iterator iter = vertexLists.begin();
00195 iter != vertexLists.end(); iter++)
00196 {
00197 double d = maxDistance;
00198 if ((*iter)->pick(r, d) && d < closest)
00199 closest = d;
00200 }
00201
00202 if (closest != maxDistance)
00203 {
00204 distance = closest;
00205 return true;
00206 }
00207 else
00208 {
00209 return false;
00210 }
00211 }
00212
00213
00214
00215
00216 void Mesh3DS::normalize(const Vec3f& centerOffset)
00217 {
00218 AxisAlignedBox bbox;
00219
00220 VertexListVec::iterator i;
00221 for (i = vertexLists.begin(); i != vertexLists.end(); i++)
00222 bbox.include((*i)->getBoundingBox());
00223
00224 Point3f center = bbox.getCenter() + centerOffset;
00225 Vec3f extents = bbox.getExtents();
00226 float maxExtent = extents.x;
00227 if (extents.y > maxExtent)
00228 maxExtent = extents.y;
00229 if (extents.z > maxExtent)
00230 maxExtent = extents.z;
00231
00232 for (i = vertexLists.begin(); i != vertexLists.end(); i++)
00233 (*i)->transform(Point3f(0, 0, 0) - center, 2.0f / maxExtent);
00234 }
00235
00236
00237 static VertexList* convertToVertexList(M3DTriangleMesh& mesh,
00238 const M3DScene& scene,
00239 const string& texturePath)
00240 {
00241 int nFaces = mesh.getFaceCount();
00242 int nVertices = mesh.getVertexCount();
00243 int nTexCoords = mesh.getTexCoordCount();
00244 bool smooth = (mesh.getSmoothingGroupCount() == nFaces);
00245 int i;
00246
00247 uint32 parts = VertexList::VertexNormal;
00248 if (nTexCoords == nVertices)
00249 parts |= VertexList::TexCoord0;
00250 VertexList* vl = new VertexList(parts);
00251
00252 Vec3f* faceNormals = new Vec3f[nFaces];
00253 Vec3f* vertexNormals = new Vec3f[nFaces * 3];
00254 int* faceCounts = new int[nVertices];
00255 int** vertexFaces = new int*[nVertices];
00256
00257 for (i = 0; i < nVertices; i++)
00258 {
00259 faceCounts[i] = 0;
00260 vertexFaces[i] = NULL;
00261 }
00262
00263
00264 for (i = 0; i < nFaces; i++)
00265 {
00266 uint16 v0, v1, v2;
00267 mesh.getFace(i, v0, v1, v2);
00268
00269 faceCounts[v0]++;
00270 faceCounts[v1]++;
00271 faceCounts[v2]++;
00272
00273 Point3f p0 = mesh.getVertex(v0);
00274 Point3f p1 = mesh.getVertex(v1);
00275 Point3f p2 = mesh.getVertex(v2);
00276 faceNormals[i] = cross(p1 - p0, p2 - p1);
00277 faceNormals[i].normalize();
00278 }
00279
00280 if (!smooth && 0)
00281 {
00282 for (i = 0; i < nFaces; i++)
00283 {
00284 vertexNormals[i * 3] = faceNormals[i];
00285 vertexNormals[i * 3 + 1] = faceNormals[i];
00286 vertexNormals[i * 3 + 2] = faceNormals[i];
00287 }
00288 }
00289 else
00290 {
00291
00292 for (i = 0; i < nVertices; i++)
00293 {
00294 vertexFaces[i] = new int[faceCounts[i] + 1];
00295 vertexFaces[i][0] = faceCounts[i];
00296 }
00297
00298 for (i = 0; i < nFaces; i++)
00299 {
00300 uint16 v0, v1, v2;
00301 mesh.getFace(i, v0, v1, v2);
00302 vertexFaces[v0][faceCounts[v0]--] = i;
00303 vertexFaces[v1][faceCounts[v1]--] = i;
00304 vertexFaces[v2][faceCounts[v2]--] = i;
00305 }
00306
00307
00308 for (i = 0; i < nFaces; i++)
00309 {
00310 uint16 v0, v1, v2;
00311 mesh.getFace(i, v0, v1, v2);
00312
00313
00314 int j;
00315 Vec3f v = Vec3f(0, 0, 0);
00316 for (j = 1; j <= vertexFaces[v0][0]; j++)
00317 {
00318 int k = vertexFaces[v0][j];
00319
00320 if (faceNormals[i] * faceNormals[k] > 0.5f)
00321 v += faceNormals[k];
00322 }
00323 v.normalize();
00324 vertexNormals[i * 3] = v;
00325
00326 v = Vec3f(0, 0, 0);
00327 for (j = 1; j <= vertexFaces[v1][0]; j++)
00328 {
00329 int k = vertexFaces[v1][j];
00330
00331 if (faceNormals[i] * faceNormals[k] > 0.5f)
00332 v += faceNormals[k];
00333 }
00334 v.normalize();
00335 vertexNormals[i * 3 + 1] = v;
00336
00337 v = Vec3f(0, 0, 0);
00338 for (j = 1; j <= vertexFaces[v2][0]; j++)
00339 {
00340 int k = vertexFaces[v2][j];
00341
00342 if (faceNormals[i] * faceNormals[k] > 0.5f)
00343 v += faceNormals[k];
00344 }
00345 v.normalize();
00346 vertexNormals[i * 3 + 2] = v;
00347 }
00348 }
00349
00350
00351 for (i = 0; i < nFaces; i++)
00352 {
00353 uint16 triVert[3];
00354 mesh.getFace(i, triVert[0], triVert[1], triVert[2]);
00355
00356 for (int j = 0; j < 3; j++)
00357 {
00358 VertexList::Vertex v;
00359 v.point = mesh.getVertex(triVert[j]);
00360 v.normal = vertexNormals[i * 3 + j];
00361 if ((parts & VertexList::TexCoord0) != 0)
00362 v.texCoords[0] = mesh.getTexCoord(triVert[j]);
00363 vl->addVertex(v);
00364 }
00365 }
00366
00367
00368 {
00369 string materialName = mesh.getMaterialName();
00370 if (materialName.length() > 0)
00371 {
00372 int nMaterials = scene.getMaterialCount();
00373 for (i = 0; i < nMaterials; i++)
00374 {
00375 M3DMaterial* material = scene.getMaterial(i);
00376 if (materialName == material->getName())
00377 {
00378 M3DColor diffuse = material->getDiffuseColor();
00379 vl->setDiffuseColor(Color(diffuse.red, diffuse.green, diffuse.blue, material->getOpacity()));
00380 M3DColor specular = material->getSpecularColor();
00381 vl->setSpecularColor(Color(specular.red, specular.green, specular.blue));
00382 float shininess = material->getShininess();
00383
00384
00385
00386 shininess = (float) pow(2, 10.0 * shininess);
00387 if (shininess > 128.0f)
00388 shininess = 128.0f;
00389 vl->setShininess(128.0f);
00390
00391 if (material->getTextureMap() != "")
00392 {
00393 ResourceHandle tex = GetTextureManager()->getHandle(TextureInfo(material->getTextureMap(), texturePath, TextureInfo::WrapTexture));
00394 vl->setTexture(tex);
00395 }
00396
00397 break;
00398 }
00399 }
00400 }
00401 }
00402
00403
00404 if (faceNormals != NULL)
00405 delete[] faceNormals;
00406 if (vertexNormals != NULL)
00407 delete[] vertexNormals;
00408 if (faceCounts != NULL)
00409 delete[] faceCounts;
00410 if (vertexFaces != NULL)
00411 {
00412 for (i = 0; i < nVertices; i++)
00413 {
00414 if (vertexFaces[i] != NULL)
00415 delete[] vertexFaces[i];
00416 }
00417 delete[] vertexFaces;
00418 }
00419
00420 return vl;
00421 }