]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/renderer/Model_md3.cpp
Use the same OpenAL headers on all platforms.
[icculus/iodoom3.git] / neo / renderer / Model_md3.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28 #include "../idlib/precompiled.h"
29 #pragma hdrstop
30
31 #include "tr_local.h"
32 #include "Model_local.h"
33 #include "Model_md3.h"
34
35 /***********************************************************************
36
37         idMD3Mesh
38
39 ***********************************************************************/
40
41 #define LL(x) x=LittleLong(x)
42
43 /*
44 =================
45 idRenderModelMD3::InitFromFile
46 =================
47 */
48 void idRenderModelMD3::InitFromFile( const char *fileName ) {
49         int                                     i, j;
50         md3Header_t                     *pinmodel;
51     md3Frame_t                  *frame;
52         md3Surface_t            *surf;
53         md3Shader_t                     *shader;
54         md3Triangle_t           *tri;
55         md3St_t                         *st;
56         md3XyzNormal_t          *xyz;
57         md3Tag_t                        *tag;
58         void                            *buffer;
59         int                                     version;
60         int                                     size;
61
62
63         name = fileName;
64
65         size = fileSystem->ReadFile( fileName, &buffer, NULL );
66         if (!size || size<0 ) {
67                 return;
68         }
69
70         pinmodel = (md3Header_t *)buffer;
71
72         version = LittleLong (pinmodel->version);
73         if (version != MD3_VERSION) {
74                 fileSystem->FreeFile( buffer );
75                 common->Warning( "InitFromFile: %s has wrong version (%i should be %i)",
76                                  fileName, version, MD3_VERSION);
77                 return;
78         }
79
80         size = LittleLong(pinmodel->ofsEnd);
81         dataSize += size;
82         md3 = (md3Header_t *)Mem_Alloc( size );
83
84         memcpy (md3, buffer, LittleLong(pinmodel->ofsEnd) );
85
86     LL(md3->ident);
87     LL(md3->version);
88     LL(md3->numFrames);
89     LL(md3->numTags);
90     LL(md3->numSurfaces);
91     LL(md3->ofsFrames);
92     LL(md3->ofsTags);
93     LL(md3->ofsSurfaces);
94     LL(md3->ofsEnd);
95
96         if ( md3->numFrames < 1 ) {
97                 common->Warning( "InitFromFile: %s has no frames", fileName );
98                 fileSystem->FreeFile( buffer );
99                 return;
100         }
101     
102         // swap all the frames
103     frame = (md3Frame_t *) ( (byte *)md3 + md3->ofsFrames );
104     for ( i = 0 ; i < md3->numFrames ; i++, frame++) {
105         frame->radius = LittleFloat( frame->radius );
106         for ( j = 0 ; j < 3 ; j++ ) {
107             frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
108             frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
109                 frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
110         }
111         }
112
113         // swap all the tags
114     tag = (md3Tag_t *) ( (byte *)md3 + md3->ofsTags );
115     for ( i = 0 ; i < md3->numTags * md3->numFrames ; i++, tag++) {
116         for ( j = 0 ; j < 3 ; j++ ) {
117                         tag->origin[j] = LittleFloat( tag->origin[j] );
118                         tag->axis[0][j] = LittleFloat( tag->axis[0][j] );
119                         tag->axis[1][j] = LittleFloat( tag->axis[1][j] );
120                         tag->axis[2][j] = LittleFloat( tag->axis[2][j] );
121         }
122         }
123
124         // swap all the surfaces
125         surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces );
126         for ( i = 0 ; i < md3->numSurfaces ; i++) {
127
128         LL(surf->ident);
129         LL(surf->flags);
130         LL(surf->numFrames);
131         LL(surf->numShaders);
132         LL(surf->numTriangles);
133         LL(surf->ofsTriangles);
134         LL(surf->numVerts);
135         LL(surf->ofsShaders);
136         LL(surf->ofsSt);
137         LL(surf->ofsXyzNormals);
138         LL(surf->ofsEnd);
139                 
140                 if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
141                         common->Error( "InitFromFile: %s has more than %i verts on a surface (%i)",
142                                 fileName, SHADER_MAX_VERTEXES, surf->numVerts );
143                 }
144                 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
145                         common->Error( "InitFromFile: %s has more than %i triangles on a surface (%i)",
146                                 fileName, SHADER_MAX_INDEXES / 3, surf->numTriangles );
147                 }
148         
149                 // change to surface identifier
150                 surf->ident = 0;        //SF_MD3;
151
152                 // lowercase the surface name so skin compares are faster
153                 int slen = (int)strlen( surf->name );
154                 for( j = 0; j < slen; j++ ) {
155                         surf->name[j] = tolower( surf->name[j] );
156                 }
157
158                 // strip off a trailing _1 or _2
159                 // this is a crutch for q3data being a mess
160                 j = strlen( surf->name );
161                 if ( j > 2 && surf->name[j-2] == '_' ) {
162                         surf->name[j-2] = 0;
163                 }
164
165         // register the shaders
166         shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
167         for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) {
168             const idMaterial *sh;
169
170             sh = declManager->FindMaterial( shader->name );
171                         shader->shader = sh;
172         }
173
174                 // swap all the triangles
175                 tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
176                 for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
177                         LL(tri->indexes[0]);
178                         LL(tri->indexes[1]);
179                         LL(tri->indexes[2]);
180                 }
181
182                 // swap all the ST
183         st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
184         for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
185             st->st[0] = LittleFloat( st->st[0] );
186             st->st[1] = LittleFloat( st->st[1] );
187         }
188
189                 // swap all the XyzNormals
190         xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
191         for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) 
192                 {
193             xyz->xyz[0] = LittleShort( xyz->xyz[0] );
194             xyz->xyz[1] = LittleShort( xyz->xyz[1] );
195             xyz->xyz[2] = LittleShort( xyz->xyz[2] );
196
197             xyz->normal = LittleShort( xyz->normal );
198         }
199
200
201                 // find the next surface
202                 surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
203         }
204     
205         fileSystem->FreeFile( buffer );
206 }
207
208 /*
209 =================
210 idRenderModelMD3::IsDynamicModel
211 =================
212 */
213 dynamicModel_t idRenderModelMD3::IsDynamicModel() const {
214         return DM_CACHED;
215 }
216
217 /*
218 =================
219 idRenderModelMD3::LerpMeshVertexes
220 =================
221 */
222 void idRenderModelMD3::LerpMeshVertexes ( srfTriangles_t *tri, const struct md3Surface_s *surf, const float backlerp, const int frame, const int oldframe ) const {
223         short   *oldXyz, *newXyz;
224         float   oldXyzScale, newXyzScale;
225         int             vertNum;
226         int             numVerts;
227
228         newXyz = (short *)((byte *)surf + surf->ofsXyzNormals) + (frame * surf->numVerts * 4);
229
230         newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
231
232         numVerts = surf->numVerts;
233
234         if ( backlerp == 0 ) {
235                 //
236                 // just copy the vertexes
237                 //
238                 for (vertNum=0 ; vertNum < numVerts ; vertNum++, newXyz += 4 ) {
239
240                         idDrawVert *outvert = &tri->verts[tri->numVerts];
241
242                         outvert->xyz.x = newXyz[0] * newXyzScale;
243                         outvert->xyz.y = newXyz[1] * newXyzScale;
244                         outvert->xyz.z = newXyz[2] * newXyzScale;
245
246                         tri->numVerts++;
247                 }
248         } else {
249                 //
250                 // interpolate and copy the vertexes
251                 //
252                 oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals) + (oldframe * surf->numVerts * 4);
253
254                 oldXyzScale = MD3_XYZ_SCALE * backlerp;
255
256                 for (vertNum=0 ; vertNum < numVerts ; vertNum++, oldXyz += 4, newXyz += 4 ) {
257
258                         idDrawVert *outvert = &tri->verts[tri->numVerts];
259
260                         // interpolate the xyz
261                         outvert->xyz.x = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
262                         outvert->xyz.y = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
263                         outvert->xyz.z = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
264
265                         tri->numVerts++;
266                 }
267         }
268 }
269
270 /*
271 =============
272 idRenderModelMD3::InstantiateDynamicModel
273 =============
274 */
275 idRenderModel *idRenderModelMD3::InstantiateDynamicModel( const struct renderEntity_s *ent, const struct viewDef_s *view, idRenderModel *cachedModel ) {
276         int                             i, j;
277         float                   backlerp;
278         int *                   triangles;
279         float *                 texCoords;
280         int                             indexes;
281         int                             numVerts;
282         md3Surface_t *  surface;
283         int                             frame, oldframe;
284         idRenderModelStatic     *staticModel;
285
286         if ( cachedModel ) {
287                 delete cachedModel;
288                 cachedModel = NULL;
289         }
290
291         staticModel = new idRenderModelStatic;
292         staticModel->bounds.Clear();
293
294         surface = (md3Surface_t *) ((byte *)md3 + md3->ofsSurfaces);
295
296         // TODO: these need set by an entity
297         frame = ent->shaderParms[SHADERPARM_MD3_FRAME];                 // probably want to keep frames < 1000 or so
298         oldframe = ent->shaderParms[SHADERPARM_MD3_LASTFRAME];
299         backlerp = ent->shaderParms[SHADERPARM_MD3_BACKLERP];
300
301         for( i = 0; i < md3->numSurfaces; i++ ) {
302
303                 srfTriangles_t *tri = R_AllocStaticTriSurf();
304                 R_AllocStaticTriSurfVerts( tri, surface->numVerts );
305                 R_AllocStaticTriSurfIndexes( tri, surface->numTriangles * 3 );
306                 tri->bounds.Clear();
307
308                 modelSurface_t  surf;
309
310                 surf.geometry = tri;
311
312                 md3Shader_t* shaders = (md3Shader_t *) ((byte *)surface + surface->ofsShaders);
313                 surf.shader = shaders->shader;
314
315                 LerpMeshVertexes( tri, surface, backlerp, frame, oldframe );
316
317                 triangles = (int *) ((byte *)surface + surface->ofsTriangles);
318                 indexes = surface->numTriangles * 3;
319                 for (j = 0 ; j < indexes ; j++) {
320                         tri->indexes[j] = triangles[j];
321                 }
322                 tri->numIndexes += indexes;
323
324                 texCoords = (float *) ((byte *)surface + surface->ofsSt);
325
326                 numVerts = surface->numVerts;
327                 for ( j = 0; j < numVerts; j++ ) {
328                         idDrawVert *stri = &tri->verts[j];
329                         stri->st[0] = texCoords[j*2+0];
330                         stri->st[1] = texCoords[j*2+1];
331                 }
332
333                 R_BoundTriSurf( tri );
334
335                 staticModel->AddSurface( surf );
336                 staticModel->bounds.AddPoint( surf.geometry->bounds[0] );
337                 staticModel->bounds.AddPoint( surf.geometry->bounds[1] );
338
339                 // find the next surface
340                 surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd );
341         }
342
343         return staticModel;
344 }
345
346 /*
347 =====================
348 idRenderModelMD3::Bounds
349 =====================
350 */
351
352 idBounds idRenderModelMD3::Bounds(const struct renderEntity_s *ent) const {
353         idBounds                ret;
354
355         ret.Clear();
356
357         if (!ent || !md3) {
358                 // just give it the editor bounds
359                 ret.AddPoint(idVec3(-10,-10,-10));
360                 ret.AddPoint(idVec3( 10, 10, 10));
361                 return ret;
362         }
363
364         md3Frame_t      *frame = (md3Frame_t *)( (byte *)md3 + md3->ofsFrames );
365
366         ret.AddPoint( frame->bounds[0] );
367         ret.AddPoint( frame->bounds[1] );
368
369         return ret;
370 }
371