00001
00002
00003
00004
00005
00006
00007
00008
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,
00034 8,
00035 12,
00036 16,
00037 4,
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
00080
00081
00082
00083
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
00209
00210
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 }