00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 typedef struct mobjvert_s {
00028 int vert;
00029 int normal;
00030 int texcoord;
00031 } mobjvert_t;
00032
00033 typedef struct mobjtri_s {
00034 mobjvert_t verts[3];
00035 } mobjtri_t;
00036
00037 typedef struct mobj_s {
00038 int num_verts;
00039 int num_verts_parsed;
00040 float *verts;
00041
00042 int num_normals;
00043 int num_normals_parsed;
00044 float *normals;
00045
00046 int num_texcoords;
00047 int num_texcoords_parsed;
00048 float *texcoords;
00049
00050 int num_tris;
00051 int num_tris_parsed;
00052 mobjtri_t *tris;
00053 } mobj_t;
00054
00055 #include "r_local.h"
00056 #include "../../shared/parse.h"
00057
00058 static void R_LoadObjModelVertexArrays (mobj_t *obj, model_t *mod)
00059 {
00060 const mobjtri_t *t;
00061 int i, j, vertind, coordind;
00062 mAliasMesh_t *mesh = mod->alias.meshes;
00063 const int v = obj->num_tris * 3 * 3;
00064 const int st = obj->num_tris * 3 * 2;
00065
00066 vertind = coordind = 0;
00067
00068 t = obj->tris;
00069
00070 mesh->num_tris = obj->num_tris;
00071 mesh->num_verts = obj->num_verts;
00072
00073 mesh->verts = (float *)Mem_PoolAlloc(sizeof(float) * v, vid_modelPool, 0);
00074 mesh->normals = (float *)Mem_PoolAlloc(sizeof(float) * v, vid_modelPool, 0);
00075 mesh->texcoords = (float *)Mem_PoolAlloc(sizeof(float) * st, vid_modelPool, 0);
00076
00077
00078 for (i = 0; i < obj->num_tris; i++, t++) {
00079 const mobjvert_t *v = t->verts;
00080
00081
00082 for (j = 0; j < 3; j++, v++) {
00083 assert(v->vert - 1 >= 0);
00084 VectorCopy((&obj->verts[(v->vert - 1) * 3]), (&mesh->verts[vertind + j * 3]));
00085
00086 if (v->normal) {
00087 assert(v->normal - 1 >= 0);
00088 VectorCopy((&obj->normals[(v->normal - 1) * 3]), (&mesh->normals[vertind + j * 3]));
00089 }
00090
00091 if (v->texcoord) {
00092 assert(v->texcoord - 1 >= 0);
00093 memcpy(&mesh->texcoords[coordind + j * 2], &obj->texcoords[(v->texcoord - 1) * 2], sizeof(vec2_t));
00094 }
00095 }
00096
00097 coordind += 6;
00098 vertind += 9;
00099 }
00100 }
00101
00102 #define MAX_OBJ_FACE_VERTS 128
00103
00107 static void R_LoadObjModelTris (mobj_t *obj, const mobjvert_t *verts, int count)
00108 {
00109 int i;
00110
00111 if (!obj->tris)
00112 return;
00113
00114 assert(count < MAX_OBJ_FACE_VERTS);
00115
00116 for (i = 0; i < count; i++) {
00117 const int v0 = 0;
00118 const int v1 = 1 + i;
00119 const int v2 = 2 + i;
00120
00121 mobjtri_t *t = &obj->tris[obj->num_tris_parsed + i];
00122 assert(obj->num_tris_parsed + i < obj->num_tris);
00123
00124 t->verts[0] = verts[v0];
00125 t->verts[1] = verts[v1];
00126 t->verts[2] = verts[v2];
00127 }
00128 }
00129
00140 static int R_LoadObjModelFace (const model_t *mod, mobj_t *obj, const char *line)
00141 {
00142 mobjvert_t *v, verts[MAX_OBJ_FACE_VERTS];
00143 const char *d;
00144 char *e;
00145 char tok[32];
00146 int i, tris;
00147
00148 memset(verts, 0, sizeof(verts));
00149 i = 0;
00150
00151 while (qtrue) {
00152 const char *c = Com_Parse(&line);
00153
00154 if (c[0] == '\0')
00155 break;
00156
00157 if (i == MAX_OBJ_FACE_VERTS)
00158 Com_Error(ERR_DROP, "R_LoadObjModelFace: too many vertexes: %s.", mod->name);
00159
00160
00161 if (!obj->tris) {
00162 i++;
00163 continue;
00164 }
00165
00166 d = c;
00167 v = &verts[i++];
00168
00169 memset(tok, 0, sizeof(tok));
00170 e = tok;
00171
00172
00173 while (d[0] != '\0') {
00174
00175 if (d[0] == '/') {
00176 if (!v->vert)
00177 v->vert = atoi(tok);
00178 else if (!v->texcoord)
00179 v->texcoord = atoi(tok);
00180 else if (!v->normal)
00181 v->normal = atoi(tok);
00182
00183 memset(tok, 0, sizeof(tok));
00184 e = tok;
00185
00186 d++;
00187 continue;
00188 }
00189
00190 *e++ = *d++;
00191 }
00192
00193
00194 if (!v->vert)
00195 v->vert = atoi(tok);
00196 else if (!v->texcoord)
00197 v->texcoord = atoi(tok);
00198 else if (!v->normal)
00199 v->normal = atoi(tok);
00200
00201 if (v->vert < 0 || v->texcoord < 0 || v->normal < 0)
00202 Com_Error(ERR_DROP, "R_LoadObjModelFace: bad indices: %s (%i:%i:%i).",
00203 mod->name, v->vert, v->texcoord, v->normal);
00204 }
00205
00206
00207 tris = i - 2;
00208
00209 if (tris < 1)
00210 Com_Error(ERR_DROP, "R_LoadObjModelFace: too few vertexes: %s.", mod->name);
00211
00212
00213 R_LoadObjModelTris(obj, verts, tris);
00214
00215 return tris;
00216 }
00217
00218
00223 static void R_LoadObjModelLine (model_t *mod, mobj_t *obj, char *line)
00224 {
00225 if (!line || line[0] == '\0')
00226 return;
00227
00228 if (!strncmp(line, "v ", 2)) {
00229 if (obj->verts) {
00230 float *f = obj->verts + obj->num_verts_parsed * 3;
00231
00232 if (sscanf(line + 2, "%f %f %f", &f[0], &f[2], &f[1]) != 3)
00233 Com_Error(ERR_DROP, "R_LoadObjModelLine: Malformed vertex for %s: %s.",
00234 mod->name, line);
00235
00236 obj->num_verts_parsed++;
00237 } else
00238 obj->num_verts++;
00239 } else if (!strncmp(line, "vn ", 3)) {
00240 if (obj->normals) {
00241 float *f = obj->normals + obj->num_normals_parsed * 3;
00242
00243 if (sscanf(line + 3, "%f %f %f", &f[0], &f[1], &f[2]) != 3)
00244 Com_Error(ERR_DROP, "R_LoadObjModelLine: Malformed normal for %s: %s.",
00245 mod->name, line);
00246
00247 obj->num_normals_parsed++;
00248 } else
00249 obj->num_normals++;
00250 } else if (!strncmp(line, "vt ", 3)) {
00251 if (obj->texcoords) {
00252 float *f = obj->texcoords + obj->num_texcoords_parsed * 2;
00253
00254 if (sscanf(line + 3, "%f %f", &f[0], &f[1]) != 2)
00255 Com_Error(ERR_DROP, "R_LoadObjModelLine: Malformed texcoord for %s: %s.",
00256 mod->name, line);
00257
00258 f[1] = -f[1];
00259 obj->num_texcoords_parsed++;
00260 } else
00261 obj->num_texcoords++;
00262 } else if (!strncmp(line, "f ", 2)) {
00263 if (obj->tris)
00264 obj->num_tris_parsed += R_LoadObjModelFace(mod, obj, line + 2);
00265 else
00266 obj->num_tris += R_LoadObjModelFace(mod, obj, line + 2);
00267 } else {
00268 Com_DPrintf(DEBUG_RENDERER, "R_LoadObjModelLine: Unsupported line for %s: %s.\n",
00269 mod->name, line);
00270 }
00271 }
00272
00273 static void R_LoadObjSkin (model_t *mod)
00274 {
00275 char skinPath[MAX_QPATH];
00276 mAliasMesh_t *mesh = &mod->alias.meshes[0];
00277
00278 Com_StripExtension(mod->name, skinPath, sizeof(skinPath));
00279
00280 mesh->num_skins = 1;
00281 mesh->skins = Mem_PoolAlloc(sizeof(mAliasSkin_t), vid_modelPool, 0);
00282 mesh->skins[0].skin = R_AliasModelGetSkin(mod->name, skinPath);
00283 Q_strncpyz(mesh->skins[0].name, mesh->skins[0].skin->name, sizeof(mesh->skins[0].name));
00284 }
00285
00290 static void R_LoadObjModel_ (model_t *mod, mobj_t *obj, const byte *buffer, int bufSize)
00291 {
00292 char line[MAX_STRING_CHARS];
00293 const byte *c;
00294 qboolean comment;
00295 int i;
00296
00297 c = buffer;
00298 comment = qfalse;
00299 i = 0;
00300
00301 while (c[0] != '\0') {
00302 if (c[0] == '#') {
00303 comment = qtrue;
00304 c++;
00305 continue;
00306 }
00307
00308 if (c[0] == '\r' || c[0] == '\n') {
00309 line[i++] = 0;
00310 i = 0;
00311
00312 if (!comment)
00313 R_LoadObjModelLine(mod, obj, Com_Trim(line));
00314
00315 comment = qfalse;
00316 c++;
00317 continue;
00318 }
00319
00320 line[i++] = *c++;
00321 }
00322 }
00323
00324 void R_LoadObjModel (model_t *mod, byte *buffer, int bufSize)
00325 {
00326 mobj_t obj;
00327 const float *v;
00328 int i;
00329
00330 mod->type = mod_obj;
00331
00332 mod->alias.num_frames = 1;
00333 mod->alias.num_meshes = 1;
00334
00335 memset(&obj, 0, sizeof(obj));
00336
00337
00338 R_LoadObjModel_(mod, &obj, buffer, bufSize);
00339
00340 if (!obj.num_verts || !obj.num_texcoords || !obj.num_tris)
00341 Com_Error(ERR_DROP, "R_LoadObjModel: Failed to resolve model data: %s (%i %i %i %i)\n",
00342 mod->name, obj.num_verts, obj.num_texcoords, obj.num_tris, obj.num_normals);
00343
00344
00345 obj.verts = (float *)Mem_PoolAlloc(obj.num_verts * sizeof(float) * 3, vid_modelPool, 0);
00346 if (obj.num_normals)
00347 obj.normals = (float *)Mem_PoolAlloc(obj.num_normals * sizeof(float) * 3, vid_modelPool, 0);
00348 obj.texcoords = (float *)Mem_PoolAlloc(obj.num_texcoords * sizeof(float) * 2, vid_modelPool, 0);
00349 obj.tris = (mobjtri_t *)Mem_PoolAlloc(obj.num_tris * sizeof(mobjtri_t), vid_modelPool, 0);
00350
00351
00352 R_LoadObjModel_(mod, &obj, buffer, bufSize);
00353
00354 v = obj.verts;
00355
00356 for (i = 0; i < obj.num_verts; i++, v += 3)
00357 AddPointToBounds(v, mod->mins, mod->maxs);
00358
00359
00360 mod->alias.meshes = Mem_PoolAlloc(sizeof(mAliasMesh_t), vid_modelPool, 0);
00361
00362
00363 R_LoadObjSkin(mod);
00364
00365
00366 R_LoadObjModelVertexArrays(&obj, mod);
00367
00368
00369 Mem_Free(obj.verts);
00370 Mem_Free(obj.normals);
00371 Mem_Free(obj.texcoords);
00372 Mem_Free(obj.tris);
00373 }