1 /* 2 3 Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc. 4 and the "Aleph One" developers. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 This license is contained in the file "COPYING", 17 which is included with this source code; it is available online at 18 http://www.gnu.org/licenses/gpl.html 19 20 3D-Model Object Storage 21 It is intended to be as OpenGL-friendly as is reasonably possible 22 23 By Loren Petrich, June 16, 2001 24 */ 25 #ifndef MODEL_3D 26 #define MODEL_3D 27 28 #include "cseries.h" 29 30 #ifdef HAVE_OPENGL 31 32 #ifdef HAVE_OPENGL 33 #include "OGL_Headers.h" 34 #endif 35 36 #include <vector> 37 #include "vec3.h" 38 39 using std::vector; 40 41 42 // For boned models; calculate vertices from these 43 struct Model3D_VertexSource 44 { 45 GLfloat Position[3]; // Use this directly for the neutral positions 46 GLshort Bone0, Bone1; // Indices of the two bones (NONE is no bone) 47 GLfloat Blend; // Blend factor: limits are 0 = first bone, 1 = second bone. 48 }; 49 50 51 // Bone definition: the bones are in order of traversal, with the bone tree 52 // specified with pushing and popping of bones on the stack. 53 // There is an assumed root bone below all the others. 54 struct Model3D_Bone 55 { 56 enum 57 { 58 Pop = 0x0001, 59 Push = 0x0002 60 }; 61 62 // The bones' positions are all referred to the overall coordinate system 63 // instead of to their parents' positions, as in Tomb Raider. 64 GLfloat Position[3]; 65 66 // Tomb-Raider-like system for traversing a tree with reference to a stack of bones; 67 // "pop" removes a bone from that stack and makes it the current one, while 68 // "push" adds the current bone to that stack. 69 // The pop is done before the push if both are present; 70 // both are done before using the bone. 71 GLushort Flags; 72 }; 73 74 75 // Frame definition: a set of bone transforms, one for each bone in order. 76 // The angles are in a form suitable for the Marathon engine's trig-function lookup tables. 77 struct Model3D_Frame 78 { 79 GLfloat Offset[3]; 80 GLshort Angles[3]; 81 }; 82 83 // In Brian Barnes's code, a sequence has some overall transformations in it 84 struct Model3D_SeqFrame: public Model3D_Frame 85 { 86 GLshort Frame; 87 }; 88 89 90 // For including a transformation from read-in model space to rendered model space; 91 // also used to implement the skeletal animation. 92 struct Model3D_Transform 93 { 94 GLfloat M[3][4]; 95 96 void Identity(); // Sets to the identity matrix 97 }; 98 99 100 struct Model3D 101 { 102 // Assumed dimensions: 103 // Positions: 3 104 // Texture coordinates: 2 105 // Normals: 3 106 // Colors: 3 [should an alpha channel also be included?] 107 108 // Positions assumed to be 3-dimensional 109 vector<GLfloat> Positions; PosBaseModel3D110 GLfloat *PosBase() {return &Positions[0];} 111 112 // Texture coordinates assumed to be 2-dimensional 113 // Parallel to the vertex-position array 114 vector<GLfloat> TxtrCoords; TCBaseModel3D115 GLfloat *TCBase() {return &TxtrCoords[0];} 116 117 // Normals assumed to be 3-dimensional 118 // Parallel to the vertex-position array 119 vector<GLfloat> Normals; NormBaseModel3D120 GLfloat *NormBase() {return &Normals[0];} 121 122 // Tangents assumed to be 4-dimensional 123 vector<vec4> Tangents; TangentBaseModel3D124 GLfloat *TangentBase() {return &Tangents[0][0];} 125 126 // Vertex colors (useful for by-hand vertex lighting) 127 // Parallel to the vertex-position array 128 vector<GLfloat> Colors; ColBaseModel3D129 GLfloat *ColBase() {return &Colors[0];} 130 131 // Vertex-source indices; into vertex-source array: 132 vector<GLushort> VtxSrcIndices; VtxSIBaseModel3D133 GLushort *VtxSIBase() {return &VtxSrcIndices[0];} 134 135 // Vertex-source array: useful with boned models 136 vector<Model3D_VertexSource> VtxSources; VtxSrcBaseModel3D137 Model3D_VertexSource *VtxSrcBase() {return &VtxSources[0];} 138 139 // Normal-source array; has the same dimension as the normals if used. 140 vector<GLfloat> NormSources; NormSrcBaseModel3D141 GLfloat *NormSrcBase() {return &NormSources[0];} 142 143 // Vertex-source inverse indices: 144 // list of all the vertex indices associated with each vertex source, 145 // with a list of pointer indices into that list. Which has an extra pointer 146 // for just off the end of the last, to simplify the readoff 147 vector<GLushort> InverseVSIndices; InverseVIBaseModel3D148 GLushort *InverseVIBase() {return &InverseVSIndices[0];} 149 vector<GLushort> InvVSIPointers; InvVSIPtrBaseModel3D150 GLushort *InvVSIPtrBase() {return &InvVSIPointers[0];} 151 152 // Bone array: the bones are in traversal order 153 vector<Model3D_Bone> Bones; BoneBaseModel3D154 Model3D_Bone *BoneBase() {return &Bones[0];} 155 156 // List of indices into the aforementioned vertices; 157 // the list is a list of triangles. 158 vector<GLushort> VertIndices; VIBaseModel3D159 GLushort *VIBase() {return &VertIndices[0];} NumVIModel3D160 size_t NumVI() {return VertIndices.size();} 161 162 // Frame array: each member is actually the transform to do on each bone; 163 // each frame has [number of bones] of these. 164 vector<Model3D_Frame> Frames; FrameBaseModel3D165 Model3D_Frame *FrameBase() {return &Frames[0];} 166 167 // True number of frames: the above number divided by the number of bones; 168 // return zero if no bones TrueNumFramesModel3D169 size_t TrueNumFrames() {return Bones.empty() ? 0 : (Frames.size()/Bones.size());} 170 171 // Sequence frames: 172 vector<Model3D_SeqFrame> SeqFrames; SeqFrmBaseModel3D173 Model3D_SeqFrame *SeqFrmBase() {return &SeqFrames[0];} 174 175 // Sequence-frame pointer indices: actually one more than there are sequences, 176 // to simplify finding which frames are members -- much like the vertex-source 177 // inverse indices. 178 vector<GLushort> SeqFrmPointers; SFPtrBaseModel3D179 GLushort *SFPtrBase() {return &SeqFrmPointers[0];} 180 181 // True number of sequences: TrueNumSeqsModel3D182 int TrueNumSeqs() {return std::max(int(SeqFrmPointers.size()-1),0);} 183 184 // Add-on transforms for the positions and the normals 185 Model3D_Transform TransformPos, TransformNorm; 186 187 // Bounding box (first index: 0 = min, 1 = max) 188 GLfloat BoundingBox[2][3]; 189 190 // From the position data 191 void FindBoundingBox(); 192 193 #if 0 194 // For debugging bounding-box-handling code 195 // NULL means don't render one set of edges 196 void RenderBoundingBox(const GLfloat *EdgeColor, const GLfloat *DiagonalColor); 197 #endif 198 199 // Process the normals in various ways 200 enum 201 { 202 None, // Gets rid of them 203 Original, // Uses the model's original normals 204 Reversed, // Reverses the direction of the original normals 205 ClockwiseSide, // Normals point in the sides' clockwise direction 206 CounterclockwiseSide, // Normals point in the sides' counterclockwise direction 207 NUMBER_OF_NORMAL_TYPES 208 }; 209 // The second is for deciding whether a vertex is to have 210 // the average of its neighboring polygons' normals 211 // or whether a vertex is to be split into separate vertices, 212 // each with a polygon's normal 213 void AdjustNormals(int NormalType, float SmoothThreshold = 0.5); 214 215 // So they all have length 1 NormalizeNormalsModel3D216 void NormalizeNormals() {AdjustNormals(Original);} 217 void CalculateTangents(); 218 219 // Erase everything 220 void Clear(); 221 222 // Build the trig tables for use in doing the transformations for frames and sequences; 223 // do this if build_trig_tables() in world.h was not already called elsewhere. 224 static void BuildTrigTables(); 225 226 // Build vertex-source inverse indices; these are for speeding up the translation process. 227 void BuildInverseVSIndices(); 228 229 // Find positions of vertices 230 // when a vertex-source array, bones, frames, and sequences are present. 231 // No arguments is for the model's neutral position (uses only source array); 232 // this is also the case for bad frame and sequence indices. 233 234 // The position-finding has an argument that determines whether to use the model's 235 // overall transform -- only applied to animated models. 236 237 // The frame and sequence position finders have a crossfade fraction 238 // and a second frame ID; these are for making smooth animations. 239 240 // Returns whether vertex-source data was used (present in animated models) 241 bool FindPositions_Neutral(bool UseModelTransform); 242 243 // Returns whether or not the indices were within range. 244 bool FindPositions_Frame(bool UseModelTransform, 245 GLshort FrameIndex, GLfloat MixFrac = 0, GLshort AddlFrameIndex = 0); 246 247 // returns 0 for out-of-range sequence 248 GLshort NumSeqFrames(GLshort SeqIndex); 249 250 // Returns whether or not the indices were in range. 251 bool FindPositions_Sequence(bool UseModelTransform, GLshort SeqIndex, 252 GLshort FrameIndex, GLfloat MixFrac = 0, GLshort AddlFrameIndex = 0); 253 254 // Constructor Model3DModel3D255 Model3D() {FindBoundingBox(); TransformPos.Identity(); TransformNorm.Identity();} 256 }; 257 258 #endif 259 struct Model3D; 260 #endif 261