1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ 2 3 #ifndef _3DMODEL_H 4 #define _3DMODEL_H 5 6 #include <vector> 7 #include <string> 8 #include <set> 9 #include <map> 10 #include "Rendering/GL/VBO.h" 11 #include "System/Matrix44f.h" 12 #include "System/creg/creg_cond.h" 13 14 static const float3 DEF_MIN_SIZE( 10000.0f, 10000.0f, 10000.0f); 15 static const float3 DEF_MAX_SIZE(-10000.0f, -10000.0f, -10000.0f); 16 17 enum ModelType { 18 MODELTYPE_3DO = 0, 19 MODELTYPE_S3O = 1, 20 MODELTYPE_OBJ = 2, 21 MODELTYPE_ASS = 3, // Model loaded by Assimp library 22 MODELTYPE_OTHER = 4 // For future use. Still used in some parts of code. 23 }; 24 enum AxisMappingType { 25 AXIS_MAPPING_XYZ = 0, 26 AXIS_MAPPING_ZXY = 1, 27 AXIS_MAPPING_YZX = 2, 28 AXIS_MAPPING_XZY = 3, 29 AXIS_MAPPING_ZYX = 4, 30 AXIS_MAPPING_YXZ = 5, 31 }; 32 33 struct CollisionVolume; 34 struct S3DModel; 35 struct S3DModelPiece; 36 struct LocalModel; 37 struct LocalModelPiece; 38 39 typedef std::map<std::string, S3DModelPiece*> ModelPieceMap; 40 41 42 /** 43 * S3DModel 44 * A 3D model definition. Holds geometry (vertices/normals) and texture data as well as the piece tree. 45 * The S3DModel is static and shouldn't change once created, instead a LocalModel is used by each agent. 46 */ 47 48 struct S3DModelPiece { 49 S3DModelPiece(); 50 virtual ~S3DModelPiece(); 51 52 virtual unsigned int CreateDrawForList() const; UploadGeometryVBOsS3DModelPiece53 virtual void UploadGeometryVBOs() {} 54 GetVertexCountS3DModelPiece55 virtual unsigned int GetVertexCount() const { return 0; } GetNormalCountS3DModelPiece56 virtual unsigned int GetNormalCount() const { return 0; } GetTxCoorCountS3DModelPiece57 virtual unsigned int GetTxCoorCount() const { return 0; } 58 59 virtual const float3& GetVertexPos(const int) const = 0; 60 virtual const float3& GetNormal(const int) const = 0; GetPosOffsetS3DModelPiece61 virtual float3 GetPosOffset() const { return ZeroVector; } ShatterS3DModelPiece62 virtual void Shatter(float, int, int, const float3&, const float3&) const {} 63 ComposeRotationS3DModelPiece64 CMatrix44f& ComposeRotation(CMatrix44f& m, const float3& r) const { 65 // execute rotations in YPR order by default 66 // note: translating + rotating is faster than 67 // matrix-multiplying (but the branching hurts) 68 switch (axisMapType) { 69 case AXIS_MAPPING_XYZ: { 70 if (r.y != 0.0f) { m.RotateY(r.y * rotAxisSigns.y); } // yaw 71 if (r.x != 0.0f) { m.RotateX(r.x * rotAxisSigns.x); } // pitch 72 if (r.z != 0.0f) { m.RotateZ(r.z * rotAxisSigns.z); } // roll 73 } break; 74 75 case AXIS_MAPPING_XZY: { 76 if (r.y != 0.0f) { m.RotateZ(r.y * rotAxisSigns.y); } // yaw 77 if (r.x != 0.0f) { m.RotateX(r.x * rotAxisSigns.x); } // pitch 78 if (r.z != 0.0f) { m.RotateY(r.z * rotAxisSigns.z); } // roll 79 } break; 80 81 case AXIS_MAPPING_YXZ: 82 case AXIS_MAPPING_YZX: 83 case AXIS_MAPPING_ZXY: 84 case AXIS_MAPPING_ZYX: { 85 // FIXME: implement 86 } break; 87 } 88 89 return m; 90 } 91 ComposeTransformS3DModelPiece92 bool ComposeTransform(CMatrix44f& m, const float3& t, const float3& r, const float3& s) const { 93 bool isIdentity = true; 94 95 // NOTE: ORDER MATTERS (T(baked + script) * R(baked) * R(script) * S(baked)) 96 if (t != ZeroVector) { m = m.Translate(t); isIdentity = false; } 97 if (!hasIdentityRot) { m *= bakedRotMatrix; isIdentity = false; } 98 if (r != ZeroVector) { m = ComposeRotation(m, r); isIdentity = false; } 99 if (s != OnesVector) { m = m.Scale(s); isIdentity = false; } 100 101 return isIdentity; 102 } 103 104 // draw piece and children statically (ie. without script-transforms) 105 void DrawStatic() const; 106 SetCollisionVolumeS3DModelPiece107 void SetCollisionVolume(CollisionVolume* cv) { colvol = cv; } GetCollisionVolumeS3DModelPiece108 const CollisionVolume* GetCollisionVolume() const { return colvol; } GetCollisionVolumeS3DModelPiece109 CollisionVolume* GetCollisionVolume() { return colvol; } 110 GetChildCountS3DModelPiece111 unsigned int GetChildCount() const { return children.size(); } GetChildS3DModelPiece112 S3DModelPiece* GetChild(unsigned int i) const { return children[i]; } 113 GetDisplayListIDS3DModelPiece114 unsigned int GetDisplayListID() const { return dispListID; } SetDisplayListIDS3DModelPiece115 void SetDisplayListID(unsigned int id) { dispListID = id; } 116 HasGeometryDataS3DModelPiece117 bool HasGeometryData() const { return hasGeometryData; } HasIdentityRotationS3DModelPiece118 bool HasIdentityRotation() const { return hasIdentityRot; } 119 SetHasGeometryDataS3DModelPiece120 void SetHasGeometryData(bool b) { hasGeometryData = b; } SetHasIdentityRotationS3DModelPiece121 void SetHasIdentityRotation(bool b) { hasIdentityRot = b; } 122 123 protected: 124 virtual void DrawForList() const = 0; 125 126 public: 127 std::string name; 128 std::string parentName; 129 130 std::vector<S3DModelPiece*> children; 131 132 S3DModelPiece* parent; 133 CollisionVolume* colvol; 134 135 AxisMappingType axisMapType; 136 137 bool hasGeometryData; /// if piece contains any geometry data 138 bool hasIdentityRot; /// if bakedRotMatrix is identity 139 140 CMatrix44f bakedRotMatrix; /// baked local-space rotations (assimp-only) 141 142 float3 offset; /// local (piece-space) offset wrt. parent piece 143 float3 goffset; /// global (model-space) offset wrt. root piece 144 float3 scales; /// baked uniform scaling factors (assimp-only) 145 float3 mins; 146 float3 maxs; 147 float3 rotAxisSigns; 148 149 protected: 150 unsigned int dispListID; 151 152 VBO vboIndices; 153 VBO vboAttributes; 154 }; 155 156 157 158 struct S3DModel 159 { S3DModelS3DModel160 S3DModel() 161 : id(-1) 162 , numPieces(0) 163 , textureType(-1) 164 165 , type(MODELTYPE_OTHER) 166 167 , invertTexYAxis(false) 168 , invertTexAlpha(false) 169 170 , radius(0.0f) 171 , height(0.0f) 172 , drawRadius(0.0f) 173 174 , mins(DEF_MIN_SIZE) 175 , maxs(DEF_MAX_SIZE) 176 , relMidPos(ZeroVector) 177 178 , rootPiece(NULL) 179 { 180 } 181 GetRootPieceS3DModel182 S3DModelPiece* GetRootPiece() const { return rootPiece; } 183 S3DModelPiece* FindPiece(const std::string& name) const; 184 SetRootPieceS3DModel185 void SetRootPiece(S3DModelPiece* p) { rootPiece = p; } DrawStaticS3DModel186 void DrawStatic() const { rootPiece->DrawStatic(); } 187 void DeletePieces(S3DModelPiece* piece); 188 189 public: 190 std::string name; 191 std::string tex1; 192 std::string tex2; 193 194 int id; /// unsynced ID, starting with 1 195 int numPieces; 196 int textureType; /// FIXME: MAKE S3O ONLY (0 = 3DO, otherwise S3O or OBJ) 197 198 ModelType type; 199 200 bool invertTexYAxis; /// Turn both textures upside down before use 201 bool invertTexAlpha; /// Invert teamcolor alpha channel in S3O texture 1 202 203 float radius; 204 float height; 205 float drawRadius; 206 207 float3 mins; 208 float3 maxs; 209 float3 relMidPos; 210 211 S3DModelPiece* rootPiece; /// The piece at the base of the model hierarchy 212 ModelPieceMap pieceMap; /// Lookup table for pieces by name 213 }; 214 215 216 217 /** 218 * LocalModel 219 * Instance of S3DModel. Container for the geometric properties & piece visibility status of the agent's instance of a 3d model. 220 */ 221 222 struct LocalModelPiece 223 { 224 CR_DECLARE_STRUCT(LocalModelPiece) 225 226 LocalModelPiece(const S3DModelPiece* piece); 227 ~LocalModelPiece(); 228 AddChildLocalModelPiece229 void AddChild(LocalModelPiece* c) { children.push_back(c); } SetParentLocalModelPiece230 void SetParent(LocalModelPiece* p) { parent = p; } 231 SetLModelPieceIndexLocalModelPiece232 void SetLModelPieceIndex(unsigned int idx) { lmodelPieceIndex = idx; } SetScriptPieceIndexLocalModelPiece233 void SetScriptPieceIndex(unsigned int idx) { scriptPieceIndex = idx; } GetLModelPieceIndexLocalModelPiece234 unsigned int GetLModelPieceIndex() const { return lmodelPieceIndex; } GetScriptPieceIndexLocalModelPiece235 unsigned int GetScriptPieceIndex() const { return scriptPieceIndex; } 236 237 void Draw() const; 238 void DrawLOD(unsigned int lod) const; 239 void SetLODCount(unsigned int count); 240 241 bool UpdateMatrix(); 242 void UpdateMatricesRec(bool updateChildMatrices); 243 244 bool GetEmitDirPos(float3& pos, float3& dir) const; 245 float3 GetAbsolutePos() const; 246 SetPositionLocalModelPiece247 void SetPosition(const float3& p) { pos = p; ++numUpdatesSynced; } SetRotationLocalModelPiece248 void SetRotation(const float3& r) { rot = r; ++numUpdatesSynced; } SetDirectionLocalModelPiece249 void SetDirection(const float3& d) { dir = d; } // unused 250 GetPositionLocalModelPiece251 const float3& GetPosition() const { return pos; } GetRotationLocalModelPiece252 const float3& GetRotation() const { return rot; } GetDirectionLocalModelPiece253 const float3& GetDirection() const { return dir; } 254 GetPieceSpaceMatrixLocalModelPiece255 const CMatrix44f& GetPieceSpaceMatrix() const { return pieceSpaceMat; } GetModelSpaceMatrixLocalModelPiece256 const CMatrix44f& GetModelSpaceMatrix() const { return modelSpaceMat; } 257 GetCollisionVolumeLocalModelPiece258 const CollisionVolume* GetCollisionVolume() const { return colvol; } GetCollisionVolumeLocalModelPiece259 CollisionVolume* GetCollisionVolume() { return colvol; } 260 261 private: 262 float3 pos; // translation relative to parent LMP, *INITIALLY* equal to original->offset 263 float3 rot; // orientation relative to parent LMP, in radians (updated by scripts) 264 float3 dir; // direction from vertex[0] to vertex[1] (constant!) 265 266 CMatrix44f pieceSpaceMat; // transform relative to parent LMP (SYNCED), combines <pos> and <rot> 267 CMatrix44f modelSpaceMat; // transform relative to root LMP (SYNCED) 268 269 CollisionVolume* colvol; 270 271 unsigned numUpdatesSynced; // triggers UpdateMatrix (via UpdateMatricesRec) if != lastMatrixUpdate 272 unsigned lastMatrixUpdate; 273 274 public: 275 bool scriptSetVisible; // TODO: add (visibility) maxradius! 276 bool identityTransform; // true IFF pieceSpaceMat (!) equals identity 277 278 unsigned int lmodelPieceIndex; // index of this piece into LocalModel::pieces 279 unsigned int scriptPieceIndex; // index of this piece into UnitScript::pieces 280 unsigned int dispListID; 281 282 const S3DModelPiece* original; 283 const LocalModelPiece* parent; 284 285 std::vector<LocalModelPiece*> children; 286 std::vector<unsigned int> lodDispLists; 287 }; 288 289 290 struct LocalModel 291 { 292 CR_DECLARE_STRUCT(LocalModel) 293 LocalModelLocalModel294 LocalModel(const S3DModel* model) 295 : dirtyPieces(model->numPieces) 296 , lodCount(0) 297 { 298 assert(model->numPieces >= 1); 299 pieces.reserve(model->numPieces); 300 CreateLocalModelPieces(model->GetRootPiece()); 301 assert(pieces.size() == model->numPieces); 302 } 303 ~LocalModelLocalModel304 ~LocalModel() 305 { 306 // delete the local piece copies 307 for (std::vector<LocalModelPiece*>::iterator pi = pieces.begin(); pi != pieces.end(); ++pi) { 308 delete *pi; 309 } 310 pieces.clear(); 311 } 312 HasPieceLocalModel313 bool HasPiece(unsigned int i) const { return (i < pieces.size()); } GetPieceLocalModel314 LocalModelPiece* GetPiece(unsigned int i) const { assert(HasPiece(i)); return pieces[i]; } GetRootLocalModel315 LocalModelPiece* GetRoot() const { return GetPiece(0); } 316 DrawLocalModel317 void Draw() const { DrawPieces(); } DrawLODLocalModel318 void DrawLOD(unsigned int lod) const { 319 if (lod > lodCount) 320 return; 321 322 DrawPiecesLOD(lod); 323 } 324 UpdatePieceMatricesLocalModel325 void UpdatePieceMatrices() { 326 if (dirtyPieces > 0) { 327 pieces[0]->UpdateMatricesRec(false); 328 } 329 dirtyPieces = 0; 330 } 331 332 333 334 void DrawPieces() const; 335 void DrawPiecesLOD(unsigned int lod) const; 336 337 void SetLODCount(unsigned int count); PieceUpdatedLocalModel338 void PieceUpdated(unsigned int pieceIdx) { dirtyPieces += 1; } 339 340 void ReloadDisplayLists(); 341 342 // raw forms, the piece-index must be valid 343 // NOTE: 344 // GetRawPieceDirection is only useful for special pieces (used for emit-sfx) 345 // it returns a direction in piece-space, NOT model-space as the "Raw" suggests 346 // this direction is vertex[0].pos - vertex[1].pos for pieces with >= 2 vertices 347 // only LuaSyncedRead::GetUnitPieceDirection calls it, better mark as DEPRECATED GetRawEmitDirPosLocalModel348 void GetRawEmitDirPos(int pieceIdx, float3& emitPos, float3& emitDir) const { pieces[pieceIdx]->GetEmitDirPos(emitPos, emitDir); } GetRawPiecePosLocalModel349 float3 GetRawPiecePos(int pieceIdx) const { return pieces[pieceIdx]->GetAbsolutePos(); } GetRawPieceDirectionLocalModel350 float3 GetRawPieceDirection(int pieceIdx) const { return pieces[pieceIdx]->GetDirection(); } GetRawPieceMatrixLocalModel351 const CMatrix44f& GetRawPieceMatrix(int pieceIdx) const { return pieces[pieceIdx]->GetModelSpaceMatrix(); } 352 353 private: 354 LocalModelPiece* CreateLocalModelPieces(const S3DModelPiece* mpParent); 355 356 public: 357 // increased by UnitScript whenever a piece is transformed 358 unsigned int dirtyPieces; 359 unsigned int lodCount; 360 361 std::vector<LocalModelPiece*> pieces; 362 }; 363 364 #endif /* _3DMODEL_H */ 365