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