27 #include "../../shared/parse.h"
42 byte* animbuf =
nullptr;
47 buffer = (
const char*)animbuf;
78 anim->
from = atoi(token);
82 Com_Error(
ERR_FATAL,
"R_ModLoadAnims: start frame is higher than models frame count (%i) (model: %s)",
89 anim->
to = atoi(token);
93 Com_Error(
ERR_FATAL,
"R_ModLoadAnims: end frame is higher than models frame count (%i) (model: %s)",
100 anim->
time = (atof(token) > 0.01) ? (1000.0 / atof(token)) : (1000.0 / 0.01);
124 const int numIndexes = mesh->
num_tris * 3;
125 const int32_t* indexArray = mesh->
indexes;
129 float* texcoords, *verts, *normals, *tangents;
144 for (i = 0, j = 0; i < numIndexes; i += 3, j++) {
149 VectorSubtract(vertexes[indexArray[i + 0]].point, vertexes[indexArray[i + 1]].point, dir1);
150 VectorSubtract(vertexes[indexArray[i + 2]].point, vertexes[indexArray[i + 1]].point, dir2);
151 Vector2Subtract(stcoords[indexArray[i + 0]], stcoords[indexArray[i + 1]], dir1uv);
152 Vector2Subtract(stcoords[indexArray[i + 2]], stcoords[indexArray[i + 1]], dir2uv);
161 if ((dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]) != 0.0) {
162 const float frac = 1.0 / (dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]);
166 VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1);
168 VectorAdd(tmp1, tmp2, triangleTangents[j]);
171 VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1);
173 VectorAdd(tmp1, tmp2, triangleBitangents[j]);
196 for (j = 0; j <
len; j++) {
197 const int32_t idx = list[j] / 3;
200 VectorAdd(b, triangleBitangents[idx], b);
216 for (j = 0; j <
len; j++) {
217 const int32_t idx = list[j];
218 const int meshIndex = mesh->
indexes[list[j]];
219 Vector2Copy(stcoords[meshIndex], (texcoords + (2 * idx)));
220 VectorAdd(vertexes[meshIndex].point, translate, (verts + (3 * idx)));
240 const int32_t* intbuf;
262 buffer +=
sizeof(uint32_t);
264 intbuf = (
const int32_t*) buffer;
290 sharedTris[mesh->
indexes[i]]++;
323 const int numIndexes = mesh->
num_tris * 3;
324 const int32_t* indexArray = mesh->
indexes;
335 for (i = 0, j = 0; i < numIndexes; i += 3, j++) {
340 VectorSubtract(vertexes[indexArray[i + 0]].point, vertexes[indexArray[i + 1]].point, dir1);
341 VectorSubtract(vertexes[indexArray[i + 2]].point, vertexes[indexArray[i + 1]].point, dir2);
342 Vector2Subtract(stcoords[indexArray[i + 0]], stcoords[indexArray[i + 1]], dir1uv);
343 Vector2Subtract(stcoords[indexArray[i + 2]], stcoords[indexArray[i + 1]], dir2uv);
350 if ((dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]) != 0.0) {
351 const float frac = 1.0 / (dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]);
355 VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1);
357 VectorAdd(tmp1, tmp2, triangleTangents[j]);
360 VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1);
362 VectorAdd(tmp1, tmp2, triangleBitangents[j]);
364 const float frac = 1.0 / (0.00001);
368 VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1);
370 VectorAdd(tmp1, tmp2, triangleTangents[j]);
373 VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1);
375 VectorAdd(tmp1, tmp2, triangleBitangents[j]);
387 for (i = 0; i < numIndexes; i++) {
388 const int idx = (i - i % 3) / 3;
389 VectorCopy(triangleNormals[idx], tmpVertexes[i].normal);
390 VectorCopy(triangleTangents[idx], tmpVertexes[i].tangent);
391 VectorCopy(triangleBitangents[idx], tmpBitangents[i]);
393 for (j = 0; j < numIndexes; j++) {
394 const int idx2 = (j - j % 3) / 3;
401 if (
VectorEqual(vertexes[indexArray[i]].point, vertexes[indexArray[j]].point)
402 &&
DotProduct(triangleNormals[idx], triangleNormals[idx2]) > smoothness) {
404 VectorAdd(tmpVertexes[i].normal, triangleNormals[idx2], tmpVertexes[i].normal);
412 if (
Vector2Equal(stcoords[indexArray[i]], stcoords[indexArray[j]])
413 &&
DotProduct(triangleTangents[idx], triangleTangents[idx2]) > smoothness
414 &&
DotProduct(triangleBitangents[idx], triangleBitangents[idx2]) > smoothness) {
416 VectorAdd(tmpVertexes[i].tangent, triangleTangents[idx2], tmpVertexes[i].tangent);
417 VectorAdd(tmpBitangents[i], triangleBitangents[idx2], tmpBitangents[i]);
428 for (i = 0; i < numIndexes; i++)
432 for (i = 0; i < numIndexes; i++) {
434 if (indRemap[i] != -1)
437 for (j = i + 1; j < numIndexes; j++) {
438 if (
Vector2Equal(stcoords[indexArray[i]], stcoords[indexArray[j]])
439 &&
VectorEqual(vertexes[indexArray[i]].point, vertexes[indexArray[j]].point)
440 && (
DotProduct(tmpVertexes[i].normal, tmpVertexes[j].normal) > smoothness)
441 && (
DotProduct(tmpVertexes[i].tangent, tmpVertexes[j].tangent) > smoothness)) {
443 newIndexArray[j] = numVerts;
467 newIndexArray[
i] = numVerts++;
471 for (i = 0; i < numVerts; i++)
474 for (i = 0; i < numIndexes; i++)
475 sharedTris[newIndexArray[i]]++;
479 for (i = 0; i < numVerts; i++) {
487 for (i = 0; i < numIndexes; i++) {
488 const int idx = indexArray[indRemap[
i]];
489 const int idx2 = newIndexArray[
i];
492 VectorCopy(vertexes[idx].point, newVertexes[idx2].point);
498 for (i = 1; i < nFrames; i++) {
499 for (j = 0; j < numIndexes; j++) {
500 const int idx = indexArray[indRemap[j]] + (mesh->
num_verts *
i);
501 const int idx2 = newIndexArray[j] + (numVerts *
i);
503 VectorCopy(vertexes[idx].point, newVertexes[idx2].point);
557 Com_Error(
ERR_DROP,
"Texture is already freed and no longer uploaded, texnum is invalid for model %s",
579 const float frontlerp = 1.0 - backlerp;
580 vec_t* texcoord_array, *vertex_array_3d;
582 frame = mod->
frames + framenum;
583 oldframe = mod->
frames + oldframenum;
632 for (i = 0; i < 3; i++)
635 for (i = 0; i < mesh->
num_verts; i++, v++, ov++) {
637 move[0] + ov->
point[0] * backlerp + v->point[0] * frontlerp,
638 move[1] + ov->
point[1] * backlerp + v->point[1] * frontlerp,
639 move[2] + ov->
point[2] * backlerp + v->point[2] * frontlerp);
648 for (i = 0; i < mesh->
num_tris; i++) {
649 for (
int j = 0; j < 3; j++) {
650 const int arrayIndex = 3 * i + j;
651 const int meshIndex = mesh->
indexes[arrayIndex];
653 VectorCopy(r_mesh_verts[meshIndex], vertex_array_3d);
656 vertex_array_3d += 3;
668 const int t = mesh->
num_tris * 3 * 4;
669 const int st = mesh->
num_tris * 3 * 2;
671 assert(mesh->
verts ==
nullptr);
673 assert(mesh->
normals ==
nullptr);
#define VectorCopy(src, dest)
#define Vector2Equal(a, b)
bool R_ModLoadMDX(model_t *mod)
Tries to load a mdx file that contains the normals and the tangents for a model.
#define VectorSet(v, x, y, z)
image_t * R_AliasModelGetSkin(const char *modelFileName, const char *skin)
memPool_t * vid_modelPool
mAliasVertex_t * vertexes
void R_FillArrayData(mAliasModel_t *mod, mAliasMesh_t *mesh, float backlerp, int framenum, int oldframenum, bool prerender)
Converts the model data into the opengl arrays.
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
GLfloat * vertex_array_3d
int Com_CountTokensInBuffer(const char *buffer)
Counts the tokens in the given buffer that the Com_Parse function would extract.
void CrossProduct(const vec3_t v1, const vec3_t v2, vec3_t cross)
binary operation on vectors in a three-dimensional space
local graphics definitions
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
void Com_Printf(const char *const fmt,...)
static void R_ModCalcNormalsAndTangents(mAliasMesh_t *mesh, int framenum, const vec3_t translate, bool backlerp)
Calculates a per-vertex tangentspace basis and stores it in GL arrays attached to the mesh...
void VectorNormalizeFast(vec3_t v)
fast vector normalize routine that does not check to make sure that length != 0, nor does it return l...
void Com_Error(int code, const char *fmt,...)
image_t * R_FindImage(const char *pname, imagetype_t type)
Finds or loads the given image.
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
#define VectorMul(scalar, b, dest)
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
void R_ReallocateTexunitArray(gltexunit_t *texunit, int size)
Reallocate texcoord array of the specified texunit, if needed.
char name[MODEL_MAX_PATH]
void R_ModCalcUniqueNormalsAndTangents(mAliasMesh_t *mesh, int nFrames, float smoothness)
Calculates normals and tangents for all frames and does vertex merging based on smoothness.
void Orthogonalize(vec3_t out, const vec3_t in)
Grahm-Schmidt orthogonalization.
mIndexList_t * revIndexes
#define Vector2Subtract(a, b, dest)
#define Mem_PoolAllocTypeN(type, n, pool)
#define VectorAdd(a, b, dest)
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
void R_ModLoadAnims(mAliasModel_t *mod, const char *animname)
void Com_DefaultExtension(char *path, size_t len, const char *extension)
Sets a default extension if there is none.
QGL_EXTERN GLuint GLchar GLuint * len
image_t * R_AliasModelState(const model_t *mod, int *mesh, int *frame, int *oldFrame, int *skin)
#define Vector2Copy(src, dest)
void Com_ReplaceFilename(const char *inputPath, const char *expectedFileName, char *outputPath, size_t size)
Replaces the filename from one path with another one.
void R_ReallocateStateArrays(int size)
Reallocate arrays of GL primitives if needed.
QGL_EXTERN int GLboolean GLfloat * v
#define VectorEqual(a, b)
#define Vector4Copy(src, dest)
#define VectorSubtract(a, b, dest)
void R_ModLoadArrayData(mAliasModel_t *mod, mAliasMesh_t *mesh, bool loadNormals)
Allocates data arrays for animated models. Only called once at loading time.
void FS_FreeFile(void *buffer)