skinfile_t *skinfiles;
int i, j, k, meshvertices, meshtriangles;
float biggestorigin;
- const int *inelements;
- int *outelements;
+ const unsigned int *inelements;
+ unsigned int *outelements;
+ const int *inneighbors;
+ int *outneighbors;
float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
+ // this pointers into the file data are read only through Little* functions so they can be unaligned memory
+ const float *vnormal = NULL;
+ const float *vposition = NULL;
+ const float *vtangent = NULL;
+ const float *vtexcoord = NULL;
+ const unsigned char *vblendindexes = NULL;
+ const unsigned char *vblendweights = NULL;
+ const unsigned short *framedata = NULL;
// temporary memory allocations (because the data in the file may be misaligned)
- float *vnormal = NULL;
- float *vposition = NULL;
- float *vtangent = NULL;
- float *vtexcoord = NULL;
iqmanim_t *anim = NULL;
iqmbounds_t *bounds = NULL;
iqmjoint1_t *joint1 = NULL;
iqmpose1_t *pose1 = NULL;
iqmpose_t *pose = NULL;
iqmvertexarray_t *va = NULL;
- unsigned char *vblendindexes = NULL;
- unsigned char *vblendweights = NULL;
- unsigned short *framedata = NULL;
pbase = (unsigned char *)buffer;
pend = (unsigned char *)bufferend;
anim = (iqmanim_t *)Mem_Alloc(loadmodel->mempool, header->num_anims * sizeof(iqmanim_t));
memcpy(anim, pbase + header->ofs_anims, header->num_anims * sizeof(iqmanim_t));
}
- if (header->num_framechannels)
- {
- framedata = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short) * header->num_framechannels);
- memcpy(framedata, pbase + header->ofs_frames, sizeof(unsigned short) * header->num_framechannels);
- }
if (header->ofs_bounds)
{
bounds = (iqmbounds_t *)Mem_Alloc(loadmodel->mempool, header->num_frames*sizeof(iqmbounds_t));
memcpy(bounds, pbase + header->ofs_bounds, header->num_frames*sizeof(iqmbounds_t));
}
- if (header->num_triangles)
- memcpy(loadmodel->surfmesh.data_element3i, pbase + header->ofs_triangles, sizeof(unsigned int[3]) * header->num_triangles);
- if (header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
- memcpy(loadmodel->surfmesh.data_neighbor3i, pbase + header->ofs_neighbors, sizeof(int[3]) * header->num_triangles);
if (header->num_meshes)
{
mesh = Mem_Alloc(loadmodel->mempool, header->num_meshes * sizeof(iqmmesh_t));
default: continue;
}
if (pbase + va[i].offset + vsize > pend)
- continue;
+ continue;
+ // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
switch (va[i].type)
{
case IQM_POSITION:
if (va[i].format == IQM_FLOAT && va[i].size == 3)
- {
- vposition = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * header->num_vertexes);
- memcpy(vposition, pbase + va[i].offset, sizeof(float[3]) * header->num_vertexes);
- }
+ vposition = (const float *)(pbase + va[i].offset);
break;
case IQM_TEXCOORD:
if (va[i].format == IQM_FLOAT && va[i].size == 2)
- {
- vtexcoord = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * header->num_vertexes);
- memcpy(vtexcoord, pbase + va[i].offset, sizeof(float[2]) * header->num_vertexes);
- }
+ vtexcoord = (const float *)(pbase + va[i].offset);
break;
case IQM_NORMAL:
if (va[i].format == IQM_FLOAT && va[i].size == 3)
- {
- vnormal = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * header->num_vertexes);
- memcpy(vnormal, pbase + va[i].offset, sizeof(float[3]) * header->num_vertexes);
- }
+ vnormal = (const float *)(pbase + va[i].offset);
break;
case IQM_TANGENT:
if (va[i].format == IQM_FLOAT && va[i].size == 4)
- {
- vtangent = Mem_Alloc(loadmodel->mempool, sizeof(float[4]) * header->num_vertexes);
- memcpy(vtangent, pbase + va[i].offset, sizeof(float[4]) * header->num_vertexes);
- }
+ vtangent = (const float *)(pbase + va[i].offset);
break;
case IQM_BLENDINDEXES:
if (va[i].format == IQM_UBYTE && va[i].size == 4)
- {
- vblendindexes = Mem_Alloc(loadmodel->mempool, sizeof(unsigned char[4]) * header->num_vertexes);
- memcpy(vblendindexes, pbase + va[i].offset, sizeof(unsigned char[4]) * header->num_vertexes);
- }
+ vblendindexes = (const unsigned char *)(pbase + va[i].offset);
break;
case IQM_BLENDWEIGHTS:
if (va[i].format == IQM_UBYTE && va[i].size == 4)
- {
- vblendweights = Mem_Alloc(loadmodel->mempool, sizeof(unsigned char[4]) * header->num_vertexes);
- memcpy(vblendweights, pbase + va[i].offset, sizeof(unsigned char[4]) * header->num_vertexes);
- }
+ vblendweights = (const unsigned char *)(pbase + va[i].offset);
break;
}
}
loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
// load the pose data
+ // this unaligned memory access is safe (LittleShort reads as bytes)
+ framedata = (const unsigned short *)(pbase + header->ofs_frames);
if (header->version == 1)
{
for (i = 0, k = 0;i < (int)header->num_frames;i++)
}
// load triangle data
- inelements = loadmodel->surfmesh.data_element3i;
+ // this unaligned memory access is safe (LittleLong reads as bytes)
+ inelements = (const unsigned int *)(pbase + header->ofs_triangles);
outelements = loadmodel->surfmesh.data_element3i;
for (i = 0;i < (int)header->num_triangles;i++)
{
if (header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
{
- inelements = loadmodel->surfmesh.data_neighbor3i;
- outelements = loadmodel->surfmesh.data_neighbor3i;
+ // this unaligned memory access is safe (LittleLong reads as bytes)
+ inneighbors = (const int *)(pbase + header->ofs_neighbors);
+ outneighbors = loadmodel->surfmesh.data_neighbor3i;
for (i = 0;i < (int)header->num_triangles;i++)
{
- outelements[0] = LittleLong(inelements[0]);
- outelements[1] = LittleLong(inelements[1]);
- outelements[2] = LittleLong(inelements[2]);
- outelements += 3;
- inelements += 3;
+ outneighbors[0] = LittleLong(inneighbors[0]);
+ outneighbors[1] = LittleLong(inneighbors[1]);
+ outneighbors[2] = LittleLong(inneighbors[2]);
+ outneighbors += 3;
+ inneighbors += 3;
}
}
// load vertex data
+ // this unaligned memory access is safe (LittleFloat reads as bytes)
outvertex = loadmodel->surfmesh.data_vertex3f;
for (i = 0;i < (int)header->num_vertexes;i++)
{
}
outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
+ // this unaligned memory access is safe (LittleFloat reads as bytes)
for (i = 0;i < (int)header->num_vertexes;i++)
{
outtexcoord[0] = LittleFloat(vtexcoord[0]);
outtexcoord += 2;
}
+ // this unaligned memory access is safe (LittleFloat reads as bytes)
if(vnormal)
{
outnormal = loadmodel->surfmesh.data_normal3f;
}
}
+ // this unaligned memory access is safe (LittleFloat reads as bytes)
if(vnormal && vtangent)
{
outnormal = loadmodel->surfmesh.data_normal3f;
}
}
+ // this unaligned memory access is safe (all bytes)
if (vblendindexes && vblendweights)
{
for (i = 0; i < (int)header->num_vertexes;i++)
if (anim ) Mem_Free(anim );anim = NULL;
if (bounds ) Mem_Free(bounds );bounds = NULL;
- if (framedata ) Mem_Free(framedata );framedata = NULL;
if (joint ) Mem_Free(joint );joint = NULL;
if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
if (mesh ) Mem_Free(mesh );mesh = NULL;
if (pose ) Mem_Free(pose );pose = NULL;
if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
if (va ) Mem_Free(va );va = NULL;
- if (vblendindexes) Mem_Free(vblendindexes);vblendindexes = NULL;
- if (vblendweights) Mem_Free(vblendweights);vblendweights = NULL;
- if (vnormal ) Mem_Free(vnormal );vnormal = NULL;
- if (vposition ) Mem_Free(vposition );vposition = NULL;
- if (vtangent ) Mem_Free(vtangent );vtangent = NULL;
- if (vtexcoord ) Mem_Free(vtexcoord );vtexcoord = NULL;
}