Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

model.cpp

Go to the documentation of this file.
00001 // model.cpp
00002 //
00003 // Copyright (C) 2004, Chris Laurel <claurel@shatters.net>
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 #include "model.h"
00011 #include "rendcontext.h"
00012 #include <cassert>
00013 #include <functional>
00014 #include <algorithm>
00015 
00016 using namespace std;
00017 
00018 
00019 #if 0
00020 static GLenum GLPrimitiveModes[MaxPrimitiveType] = 
00021 {
00022     GL_TRIANGLES,
00023     GL_TRIANGLE_STRIP,
00024     GL_TRIANGLE_FAN,
00025     GL_LINES,
00026     GL_LINE_STRIP,
00027     GL_POINTS
00028 };
00029 #endif
00030 
00031 static size_t VertexAttributeFormatSizes[Mesh::FormatMax] = 
00032 {
00033      4,  // Float1
00034      8,  // Float2
00035      12, // Float3
00036      16, // Float4,
00037      4,  // UByte4
00038 };
00039 
00040 
00041 Model::Model()
00042 {
00043     for (int i = 0; i < Mesh::TextureSemanticMax; i++)
00044         textureUsage[i] = false;
00045 }
00046 
00047 
00048 Model::~Model()
00049 {
00050     {
00051         for (vector<Mesh*>::iterator iter = meshes.begin();
00052              iter != meshes.end(); iter++)
00053             delete *iter;
00054     }
00055 
00056 #if 0
00057     {
00058         for (vector<const Mesh::Material*>::iterator iter = materials.begin();
00059              iter != materials.end(); iter++)
00060             delete *iter;
00061     }
00062 #endif
00063 }
00064 
00065 
00066 const Mesh::Material*
00067 Model::getMaterial(uint32 index) const
00068 {
00069     if (index < materials.size())
00070         return materials[index];
00071     else
00072         return NULL;
00073 }
00074 
00075 
00076 uint32
00077 Model::addMaterial(const Mesh::Material* m)
00078 {
00079     // Update the texture map usage information for the model.  Since
00080     // the material being added isn't necessarily used by a mesh within
00081     // the model, we could potentially end up with false positives--this
00082     // won't cause any rendering troubles, but could hurt performance
00083     // if it forces multipass rendering when it's not required.
00084     for (int i = 0; i < Mesh::TextureSemanticMax; i++)
00085     {
00086         if (m->maps[i] != InvalidResource)
00087             textureUsage[i] = true;
00088     }
00089 
00090     materials.push_back(m);
00091     return materials.size();
00092 }
00093 
00094 
00095 Mesh*
00096 Model::getMesh(uint32 index) const
00097 {
00098     if (index < meshes.size())
00099         return meshes[index];
00100     else
00101         return NULL;
00102 }
00103 
00104 
00105 uint32
00106 Model::addMesh(Mesh* m)
00107 {
00108     meshes.push_back(m);
00109     return meshes.size();
00110 }
00111 
00112 
00113 bool
00114 Model::pick(const Ray3d& r, double& distance) const
00115 {
00116     double maxDistance = 1.0e30;
00117     double closest = maxDistance;
00118 
00119     for (vector<Mesh*>::const_iterator iter = meshes.begin();
00120          iter != meshes.end(); iter++)
00121     {
00122         double d = maxDistance;
00123         if ((*iter)->pick(r, d) && d < closest)
00124             closest = d;
00125     }    
00126 
00127     if (closest != maxDistance)
00128     {
00129         distance = closest;
00130         return true;
00131     }
00132     else
00133     {
00134         return false;
00135     }
00136 }
00137 
00138 
00139 void
00140 Model::render(RenderContext& rc)
00141 {
00142     for (vector<Mesh*>::const_iterator iter = meshes.begin();
00143          iter != meshes.end(); iter++)
00144     {
00145         (*iter)->render(materials, rc);
00146     }
00147 }
00148 
00149 
00150 void
00151 Model::normalize(const Vec3f& centerOffset)
00152 {
00153     AxisAlignedBox bbox;
00154 
00155     vector<Mesh*>::const_iterator iter;
00156     for (iter = meshes.begin(); iter != meshes.end(); iter++)
00157         bbox.include((*iter)->getBoundingBox());
00158 
00159     Point3f center = bbox.getCenter() + centerOffset;
00160     Vec3f extents = bbox.getExtents();
00161     float maxExtent = extents.x;
00162     if (extents.y > maxExtent)
00163         maxExtent = extents.y;
00164     if (extents.z > maxExtent)
00165         maxExtent = extents.z;
00166 
00167     for (iter = meshes.begin(); iter != meshes.end(); iter++)
00168         (*iter)->transform(Point3f(0, 0, 0) - center, 2.0f / maxExtent);
00169 
00170 #if 0
00171     for (i = vertexLists.begin(); i != vertexLists.end(); i++)
00172         (*i)->transform(Point3f(0, 0, 0) - center, 2.0f / maxExtent);
00173 #endif
00174 }
00175 
00176 
00177 bool
00178 Model::usesTextureType(Mesh::TextureSemantic t) const
00179 {
00180     return textureUsage[static_cast<int>(t)];
00181 }
00182 
00183 
00184 class MeshComparatorAdapter : public std::binary_function<const Mesh*, const Mesh*, bool>
00185 {
00186 public:
00187     MeshComparatorAdapter(const Model::MeshComparator& c) :
00188         comparator(c)
00189     {
00190     }
00191 
00192     bool operator()(const Mesh* a, const Mesh* b) const
00193     {
00194         return comparator(*a, *b);
00195     }
00196 
00197 private:
00198     const Model::MeshComparator& comparator;
00199 };
00200 
00201 
00202 Model::OpacityComparator::OpacityComparator(const Model& _model) :
00203     model(_model)
00204 {
00205 }
00206 
00207 
00208 // Look at the material used by first primitive group in the mesh for the
00209 // opacity of the whole model.  This is a very crude way to check the opacity
00210 // of a mesh and misses many cases.
00211 float
00212 Model::OpacityComparator::getOpacity(const Mesh& mesh) const
00213 {
00214     const Mesh::PrimitiveGroup* group = mesh.getGroup(0);
00215 
00216     if (group != NULL)
00217     {
00218         const Mesh::Material* material = model.getMaterial(group->materialIndex);
00219         if (material != NULL)
00220             return material->opacity;
00221     }
00222 
00223     return 1.0f;
00224 }
00225 
00226 
00227 bool
00228 Model::OpacityComparator::operator()(const Mesh& a, const Mesh& b) const
00229 {
00230     return getOpacity(a) > getOpacity(b);
00231 }
00232 
00233 
00234 void
00235 Model::sortMeshes(const MeshComparator& comparator)
00236 {
00237     sort(meshes.begin(), meshes.end(), MeshComparatorAdapter(comparator));
00238 }

Generated on Sat Jan 14 22:30:27 2006 for Celestia by  doxygen 1.4.1