UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_model_md3.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 1997-2001 Id Software, Inc.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program 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.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 
26 #include "r_local.h"
27 
28 /*
29 ==============================================================================
30 MD3 ALIAS MODELS
31 ==============================================================================
32 */
33 
38 void R_ModLoadAliasMD3Model (model_t* mod, byte* buffer, int bufSize)
39 {
40  const dmd3_t* md3 = (dmd3_t*)buffer;
41  int version = LittleLong(md3->version);
42 
43  if (version != MD3_ALIAS_VERSION) {
44  Com_Error(ERR_DROP, "%s has wrong version number (%i should be %i)",
45  mod->name, version, MD3_ALIAS_VERSION);
46  }
47 
48  mod->type = mod_alias_md3;
49  /* byte swap the header fields and sanity check */
51  mod->alias.num_tags = LittleLong(md3->num_tags);
53 
54  if (mod->alias.num_frames <= 0)
55  Com_Error(ERR_DROP, "model %s has no frames", mod->name);
56  else if (mod->alias.num_frames > MD3_MAX_FRAMES)
57  Com_Error(ERR_DROP, "model %s has too many frames", mod->name);
58 
59  if (mod->alias.num_tags > MD3_MAX_TAGS)
60  Com_Error(ERR_DROP, "model %s has too many tags", mod->name);
61  else if (mod->alias.num_tags < 0)
62  Com_Error(ERR_DROP, "model %s has invalid number of tags", mod->name);
63 
64  if (mod->alias.num_meshes <= 0)
65  Com_Error(ERR_DROP, "model %s has no meshes", mod->name);
66  else if (mod->alias.num_meshes > MD3_MAX_MESHES)
67  Com_Error(ERR_DROP, "model %s has too many meshes", mod->name);
68 
69  /* load the frames */
70  const dmd3frame_t* pinframe = (const dmd3frame_t*)((const byte*)md3 + LittleLong(md3->ofs_frames));
72 
73  mod->radius = 0;
75 
76  int i, j, l;
77  for (i = 0; i < mod->alias.num_frames; i++, pinframe++, poutframe++) {
78  for (j = 0; j < 3; j++) {
79  poutframe->fBox.mins[j] = LittleFloat(pinframe->mins[j]);
80  poutframe->fBox.maxs[j] = LittleFloat(pinframe->maxs[j]);
81  poutframe->translate[j] = LittleFloat(pinframe->translate[j]);
82  }
83 
84  poutframe->radius = LittleFloat(pinframe->radius);
85  mod->radius = std::max(mod->radius, poutframe->radius);
86  mod->modBox.add(poutframe->fBox);
87  }
88 
89  /* load the tags */
90  if (mod->alias.num_tags) {
91  const dmd3tag_t* pintag = (const dmd3tag_t*)((const byte*)md3 + LittleLong(md3->ofs_tags));
93 
95  for (l = 0; l < mod->alias.num_tags; l++, pouttag++, pintag++) {
97  memcpy(pouttag->name, pintag->name, MD3_MAX_PATH);
98  for (i = 0; i < mod->alias.num_frames; i++, orient++) {
99  for (j = 0; j < 3; j++) {
100  orient->origin[j] = LittleFloat(pintag->orient.origin[j]);
101  orient->axis[0][j] = LittleFloat(pintag->orient.axis[0][j]);
102  orient->axis[1][j] = LittleFloat(pintag->orient.axis[1][j]);
103  orient->axis[2][j] = LittleFloat(pintag->orient.axis[2][j]);
104  }
105  }
106  }
107  }
108 
109  /* load the meshes */
110  const dmd3mesh_t* pinmesh = (const dmd3mesh_t*)((const byte*)md3 + LittleLong(md3->ofs_meshes));
112 
113  for (i = 0; i < mod->alias.num_meshes; i++, poutmesh++) {
114  memcpy(poutmesh->name, pinmesh->name, MD3_MAX_PATH);
115 
116  if (strncmp(pinmesh->id, "IDP3", 4)) {
117  Com_Error(ERR_DROP, "mesh %s in model %s has wrong id (%s should be %i)",
118  poutmesh->name, mod->name, pinmesh->id, IDMD3HEADER);
119  }
120 
121  poutmesh->num_tris = LittleLong(pinmesh->num_tris);
122  poutmesh->num_skins = LittleLong(pinmesh->num_skins);
123  poutmesh->num_verts = LittleLong(pinmesh->num_verts);
124 
125  if (poutmesh->num_skins <= 0)
126  Com_Error(ERR_DROP, "mesh %i in model %s has no skins", i, mod->name);
127  else if (poutmesh->num_skins > MD3_MAX_SHADERS)
128  Com_Error(ERR_DROP, "mesh %i in model %s has too many skins", i, mod->name);
129 
130  if (poutmesh->num_tris <= 0)
131  Com_Error(ERR_DROP, "mesh %i in model %s has no triangles", i, mod->name);
132  else if (poutmesh->num_tris > MD3_MAX_TRIANGLES)
133  Com_Error(ERR_DROP, "mesh %i in model %s has too many triangles", i, mod->name);
134 
135  if (poutmesh->num_verts <= 0)
136  Com_Error(ERR_DROP, "mesh %i in model %s has no vertices", i, mod->name);
137  else if (poutmesh->num_verts > MD3_MAX_VERTS)
138  Com_Error(ERR_DROP, "mesh %i in model %s has too many vertices", i, mod->name);
139 
140  /* register all skins */
141  const dmd3skin_t* pinskin = (const dmd3skin_t*)((const byte*)pinmesh + LittleLong(pinmesh->ofs_skins));
143 
144  for (j = 0; j < poutmesh->num_skins; j++) {
145  mAliasSkin_t* modelSkin = &poutmesh->skins[j];
146  modelSkin->skin = R_AliasModelGetSkin(mod->name, pinskin->name);
147  Q_strncpyz(modelSkin->name, modelSkin->skin->name, MODEL_MAX_PATH);
148  }
149 
150  /* load the indexes */
151  const int32_t* pinindex = (const int32_t*)((const byte*)pinmesh + LittleLong(pinmesh->ofs_tris));
152  int32_t* poutindex = poutmesh->indexes = Mem_PoolAllocTypeN(int32_t, poutmesh->num_tris * 3, vid_modelPool);
153 
154  for (j = 0; j < poutmesh->num_tris; j++, pinindex += 3, poutindex += 3) {
155  poutindex[0] = (int32_t)LittleLong(pinindex[0]);
156  poutindex[1] = (int32_t)LittleLong(pinindex[1]);
157  poutindex[2] = (int32_t)LittleLong(pinindex[2]);
158  }
159 
160  /* load the texture coordinates */
161  const dmd3coord_t* pincoord = (const dmd3coord_t*)((const byte*)pinmesh + LittleLong(pinmesh->ofs_tcs));
163 
164  for (j = 0; j < poutmesh->num_verts; j++, pincoord++) {
165  poutmesh->stcoords[j][0] = LittleFloat(pincoord->st[0]);
166  poutmesh->stcoords[j][1] = LittleFloat(pincoord->st[1]);
167  }
168 
169  /* load the vertexes and normals */
170  const dmd3vertex_t* pinvert = (const dmd3vertex_t*)((const byte*)pinmesh + LittleLong(pinmesh->ofs_verts));
172 
173  for (l = 0; l < mod->alias.num_frames; l++) {
174  for (j = 0; j < poutmesh->num_verts; j++, pinvert++, poutvert++) {
175  float lat, lng;
176 
177  poutvert->point[0] = LittleShort(pinvert->point[0]) * MD3_XYZ_SCALE;
178  poutvert->point[1] = LittleShort(pinvert->point[1]) * MD3_XYZ_SCALE;
179  poutvert->point[2] = LittleShort(pinvert->point[2]) * MD3_XYZ_SCALE;
180 
181  lat = (pinvert->norm >> 8) & 0xff;
182  lng = (pinvert->norm & 0xff);
183 
184  lat *= M_PI / 128.0f;
185  lng *= M_PI / 128.0f;
186 
187  poutvert->normal[0] = cos(lat) * sin(lng);
188  poutvert->normal[1] = sin(lat) * sin(lng);
189  poutvert->normal[2] = cos(lng);
190  }
191  }
192 
194 
195  pinmesh = (const dmd3mesh_t*)((const byte*)pinmesh + LittleLong(pinmesh->meshsize));
196 
197  R_ModLoadArrayData(&mod->alias, poutmesh, true);
198  }
199 }
mAliasTag_t * tags
Definition: qfiles.h:227
void setNegativeVolume()
Sets mins and maxs to their starting points before using addPoint.
Definition: aabb.h:98
mAliasModel_t alias
Definition: r_model.h:63
memPool_t * vid_modelPool
Definition: cl_main.cpp:90
uint32_t ofs_skins
Definition: qfiles.h:220
uint32_t ofs_verts
Definition: qfiles.h:222
image_t * R_AliasModelGetSkin(const char *modelFileName, const char *skin)
AABB modBox
Definition: r_model.h:51
mAliasVertex_t * vertexes
int32_t * indexes
mAliasSkin_t * skins
uint32_t version
Definition: qfiles.h:229
#define MD3_MAX_TRIANGLES
Definition: qfiles.h:164
image_t * skin
Definition: r_model_alias.h:92
uint32_t num_frames
Definition: qfiles.h:235
local graphics definitions
uint32_t ofs_tcs
Definition: qfiles.h:221
char name[MD3_MAX_PATH]
Definition: qfiles.h:203
uint32_t num_meshes
Definition: qfiles.h:237
float st[2]
Definition: qfiles.h:176
#define MD3_MAX_SHADERS
Definition: qfiles.h:166
#define mAliasCoord_t
Definition: r_model_alias.h:32
vec3_t maxs
Definition: aabb.h:258
vec3_t translate
Definition: r_model_alias.h:58
char id[4]
Definition: qfiles.h:208
#define MD3_ALIAS_VERSION
Definition: qfiles.h:161
uint32_t num_tags
Definition: qfiles.h:236
#define MD3_MAX_TAGS
Definition: qfiles.h:169
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
char name[MODEL_MAX_PATH]
Definition: r_model_alias.h:90
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
#define LittleShort(X)
Definition: byte.h:35
void add(const vec3_t point)
If the point is outside the box, expand the box to accommodate it.
Definition: aabb.cpp:57
#define ERR_DROP
Definition: common.h:211
#define IDMD3HEADER
Definition: qfiles.h:159
char name[MODEL_MAX_PATH]
modtype_t type
Definition: r_model.h:46
char name[MAX_QPATH]
Definition: r_image.h:62
#define M_PI
Definition: mathlib.h:34
#define MD3_MAX_VERTS
Definition: qfiles.h:165
void R_ModCalcUniqueNormalsAndTangents(mAliasMesh_t *mesh, int nFrames, float smoothness)
Calculates normals and tangents for all frames and does vertex merging based on smoothness.
char name[MAX_QPATH]
Definition: r_model.h:44
uint32_t ofs_frames
Definition: qfiles.h:240
float origin[3]
Definition: qfiles.h:193
#define MD3_XYZ_SCALE
Definition: qfiles.h:173
float axis[3][3]
Definition: qfiles.h:194
#define MODEL_MAX_PATH
Definition: r_model_alias.h:28
void R_ModLoadAliasMD3Model(model_t *mod, byte *buffer, int bufSize)
Load MD3 models from file.
Definition: r_model_md3.cpp:38
uint32_t ofs_meshes
Definition: qfiles.h:242
#define MD3_MAX_PATH
Definition: qfiles.h:170
uint32_t ofs_tags
Definition: qfiles.h:241
mAliasMesh_t * meshes
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
uint32_t meshsize
Definition: qfiles.h:224
dorientation_t orient
Definition: qfiles.h:199
QGL_EXTERN GLint i
Definition: r_gl.h:113
char name[MD3_MAX_PATH]
Definition: qfiles.h:210
#define MD3_MAX_MESHES
Definition: qfiles.h:168
uint32_t ofs_tris
Definition: qfiles.h:219
float radius
Definition: r_model.h:52
vec3_t mins
Definition: aabb.h:257
uint32_t num_skins
Definition: qfiles.h:215
#define MD3_MAX_FRAMES
Definition: qfiles.h:167
mAliasCoord_t * stcoords
char name[MD3_MAX_PATH]
Definition: qfiles.h:198
int32_t num_verts
uint8_t byte
Definition: ufotypes.h:34
QGL_EXTERN GLuint GLsizei bufSize
Definition: r_gl.h:110
uint32_t num_tris
Definition: qfiles.h:217
mAliasFrame_t * frames
uint32_t num_verts
Definition: qfiles.h:216
void R_ModLoadArrayData(mAliasModel_t *mod, mAliasMesh_t *mesh, bool loadNormals)
Allocates data arrays for animated models. Only called once at loading time.
#define LittleFloat(X)
Definition: byte.h:57
#define LittleLong(X)
Definition: byte.h:37