aboutsummaryrefslogtreecommitdiff
path: root/src/parsec/e_vtxani.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parsec/e_vtxani.cpp')
-rw-r--r--src/parsec/e_vtxani.cpp554
1 files changed, 554 insertions, 0 deletions
diff --git a/src/parsec/e_vtxani.cpp b/src/parsec/e_vtxani.cpp
new file mode 100644
index 0000000..987f674
--- /dev/null
+++ b/src/parsec/e_vtxani.cpp
@@ -0,0 +1,554 @@
+/*
+ * PARSEC - Vertex Animations
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:34 $
+ *
+ * Orginally written by:
+ * Copyright (c) Markus Hadwiger <msh@parsec.org> 2000
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// C library
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// compilation flags/debug support
+#include "config.h"
+#include "debug.h"
+
+// general definitions
+#include "general.h"
+#include "objstruc.h"
+
+// global externals
+#include "globals.h"
+
+// local module header
+#include "e_vtxani.h"
+
+// proprietary module headers
+#include "obj_ctrl.h"
+
+
+
+// base index correction macro ------------------------------------------------
+//
+#define CORRECT_BASE(w,b) ( ( (w) != NULL ) ? ( &(w)[ b ] ) : NULL )
+
+
+// make the specified vertex anim current in the supplied object --------------
+//
+int VtxAnimMakeCurrent( GenObject *gobj, dword animid )
+{
+ ASSERT( gobj != NULL );
+ ASSERT( animid <= gobj->NumVtxAnims );
+
+ VtxAnimState *anim = &gobj->VtxAnimStates[ animid ];
+
+ // vertex anim beyond contains the base object info array
+ dword *baseinfo = (dword *) &gobj->VtxAnimStates[ gobj->NumVtxAnims ];
+
+ // store id of active subobject
+ baseinfo[ 0 ] = animid;
+
+ // switch to base object
+ gobj->NumVerts = (dword) baseinfo[ 1 ];
+ gobj->NumPolyVerts = (dword) baseinfo[ 2 ];
+ gobj->NumNormals = (dword) baseinfo[ 3 ];
+ gobj->VertexList = (Vertex3 *) baseinfo[ 4 ];
+ gobj->NumPolys = (dword) baseinfo[ 5 ];
+ gobj->PolyList = (Poly *) baseinfo[ 6 ];
+ gobj->NumFaces = (dword) baseinfo[ 7 ];
+ gobj->FaceList = (Face *) baseinfo[ 8 ];
+ gobj->SortedPolyList = (dword *) baseinfo[ 9 ];
+ gobj->NumWedges = (dword) baseinfo[ 10 ];
+ gobj->WedgeVertIndxs = (dword *) baseinfo[ 11 ];
+ gobj->WedgeNormals = (Vector3 *) baseinfo[ 12 ];
+ gobj->WedgeColors = (colrgba_s *) baseinfo[ 13 ];
+ gobj->WedgeTexCoords = (TexCoord2 *) baseinfo[ 14 ];
+ gobj->WedgeLighted = (colrgba_s *) baseinfo[ 15 ];
+ gobj->WedgeSpecular = (colrgba_s *) baseinfo[ 16 ];
+ gobj->WedgeFogged = (colrgba_s *) baseinfo[ 17 ];
+
+ // switch to subobject
+ if ( animid < gobj->NumVtxAnims ) {
+
+ int vertexbase = anim->VertexBase;
+ int polybase = anim->PolyBase;
+ int facebase = anim->FaceBase;
+ int wedgebase = anim->WedgeBase;
+
+ // switch geometry to subobject of vertex anim
+ gobj->NumVerts = anim->NumVerts;
+ gobj->NumPolyVerts = anim->NumPolyVerts;
+ gobj->NumNormals = anim->NumNormals;
+ gobj->VertexList = &gobj->VertexList[ vertexbase ];
+ gobj->NumPolys = anim->NumPolys;
+ gobj->PolyList = &gobj->PolyList[ polybase ];
+ gobj->NumFaces = anim->NumFaces;
+ gobj->FaceList = &gobj->FaceList[ facebase ];
+ gobj->SortedPolyList = CORRECT_BASE( gobj->SortedPolyList, polybase );
+ gobj->NumWedges = anim->NumWedges;
+ gobj->WedgeVertIndxs = CORRECT_BASE( gobj->WedgeVertIndxs, wedgebase );
+ gobj->WedgeNormals = CORRECT_BASE( gobj->WedgeNormals, wedgebase );
+ gobj->WedgeColors = CORRECT_BASE( gobj->WedgeColors, wedgebase );
+ gobj->WedgeTexCoords = CORRECT_BASE( gobj->WedgeTexCoords, wedgebase );
+ gobj->WedgeLighted = CORRECT_BASE( gobj->WedgeLighted, wedgebase );
+ gobj->WedgeSpecular = CORRECT_BASE( gobj->WedgeSpecular, wedgebase );
+ gobj->WedgeFogged = CORRECT_BASE( gobj->WedgeFogged, wedgebase );
+ }
+
+ return TRUE;
+}
+
+
+// create a new vertex anim (append) for the supplied set of faces ------------
+//
+VtxAnimState *VtxAnimCreateFromFaceList( GenObject *gobj, dword lod, int numfaces, dword *faceids )
+{
+ ASSERT( gobj != NULL );
+ ASSERT( faceids != NULL );
+
+ // offset of vertex anim state array (needed for lod)
+ int vtxanimoffset = 0;
+
+ // make sure destination lod is current
+ if ( gobj->NumLodObjects > 0 ) {
+
+ ASSERT( gobj->LodObjects != NULL );
+
+ // check for invalid lod
+ if ( lod >= gobj->NumLodObjects ) {
+ return NULL;
+ }
+
+ // switch lod if necessary
+ if ( lod != gobj->CurrentLod ) {
+ OBJ_SwitchObjectLod( gobj, lod );
+ }
+
+ // we have an equal-sized vertex anim array for
+ // each lod present. these are totally independent.
+ vtxanimoffset = lod * ( gobj->NumVtxAnims + 1 );
+
+ } else {
+
+ ASSERT( gobj->CurrentLod == 0 );
+ ASSERT( gobj->LodObjects == NULL );
+
+ // check for invalid lod
+ if ( lod != 0 ) {
+ return NULL;
+ }
+ }
+
+ // check for free state
+ if ( gobj->ActiveVtxAnims >= gobj->NumVtxAnims ) {
+ return NULL;
+ }
+
+ // create in next free state
+ int animid = gobj->ActiveVtxAnims;
+ VtxAnimState *anim = &gobj->VtxAnimStates[ animid + vtxanimoffset ];
+
+ Face *facelist = gobj->FaceList;
+ Poly *polylist = gobj->PolyList;
+ Vertex3 *vertexlist = gobj->VertexList;
+
+ // alloc mem for sets
+ size_t setmemsize = 0;
+ setmemsize += gobj->NumFaces;
+ setmemsize += gobj->NumPolys;
+ setmemsize += gobj->NumVerts;
+ setmemsize += gobj->NumWedges;
+ byte *setmemblock = (byte *) ALLOCMEM( setmemsize );
+ if ( setmemblock == NULL )
+ OUTOFMEM( 0 );
+ memset( setmemblock, 0, setmemsize );
+
+ byte *faceset = &setmemblock[ 0 ];
+ byte *polyset = &faceset[ gobj->NumFaces ];
+ byte *vertexset = &polyset[ gobj->NumPolys ];
+ byte *wedgeset = &vertexset[ gobj->NumVerts ];
+
+ // construct in/out map for faces and normals
+ int findx = 0;
+ for ( findx = 0; findx < numfaces; findx++ ) {
+ ASSERT( faceids[ findx ] < gobj->NumFaces );
+ faceset[ faceids[ findx ] ] = 1;
+ vertexset[ facelist[ faceids[ findx ] ].FaceNormalIndx ] = 1;
+ }
+
+ // construct in/out map for polys and vertices
+ unsigned int polyid = 0;
+ for ( polyid = 0; polyid < gobj->NumPolys; polyid++ ) {
+ polyset[ polyid ] = faceset[ polylist[ polyid ].FaceIndx ];
+ if ( polyset[ polyid ] ) {
+ for ( unsigned int vindx = 0; vindx < polylist[ polyid ].NumVerts; vindx++ ) {
+ vertexset[ polylist[ polyid ].VertIndxs[ vindx ] ] = 1;
+ }
+ }
+ }
+
+ // construct in/out map for wedges
+ unsigned int wedgeid = 0;
+ for ( wedgeid = 0; wedgeid < gobj->NumWedges; wedgeid++ ) {
+ ASSERT( gobj->WedgeVertIndxs != NULL );
+ wedgeset[ wedgeid ] = vertexset[ gobj->WedgeVertIndxs[ wedgeid ] ];
+ }
+
+ // count normals
+ int numnormals = 0;
+ unsigned int setindx = 0;
+ for ( setindx = 0; setindx < gobj->NumNormals; setindx++ ) {
+ numnormals += vertexset[ setindx ];
+ }
+
+ // count vertices
+ int numpolyverts = 0;
+ for ( ; setindx < gobj->NumVerts; setindx++ ) {
+ numpolyverts += vertexset[ setindx ];
+ }
+
+ // count polys
+ int numpolys = 0;
+ for ( setindx = 0; setindx < gobj->NumPolys; setindx++ ) {
+ numpolys += polyset[ setindx ];
+ }
+
+ // count wedges
+ int numwedges = 0;
+ for ( setindx = 0; setindx < gobj->NumWedges; setindx++ ) {
+ numwedges += wedgeset[ setindx ];
+ }
+
+ // determine base indexes
+ dword facebase = gobj->NumFaces - numfaces;
+ dword polybase = gobj->NumPolys - numpolys;
+ dword vertexbase = gobj->NumVerts - numnormals - numpolyverts;
+ dword wedgebase = gobj->NumWedges - numwedges;
+
+ // alloc mem for maps
+ size_t mapmemsize = 0;
+ mapmemsize += gobj->NumFaces;
+ mapmemsize += gobj->NumPolys;
+ mapmemsize += gobj->NumVerts;
+ mapmemsize += gobj->NumWedges;
+ mapmemsize += gobj->NumPolys;
+ mapmemsize *= sizeof( dword );
+ dword *mapmemblock = (dword *) ALLOCMEM( mapmemsize );
+ if ( mapmemblock == NULL )
+ OUTOFMEM( 0 );
+ memset( mapmemblock, 0, mapmemsize );
+
+ dword *facemap = &mapmemblock[ 0 ];
+ dword *polymap = &facemap[ gobj->NumFaces ];
+ dword *vertexmap = &polymap[ gobj->NumPolys ];
+ dword *wedgemap = &vertexmap[ gobj->NumVerts ];
+ dword *stpolymap = &wedgemap[ gobj->NumWedges ];
+
+ // construct id map for faces
+ int insetindx = facebase;
+ int outsetindx = 0;
+ unsigned int faceid = 0;
+ for ( faceid = 0; faceid < gobj->NumFaces; faceid++ ) {
+ facemap[ faceid ] = faceset[ faceid ] ? insetindx++ : outsetindx++;
+ }
+
+ // construct id map for polys
+ insetindx = polybase;
+ outsetindx = 0;
+ for ( polyid = 0; polyid < gobj->NumPolys; polyid++ ) {
+ polymap[ polyid ] = polyset[ polyid ] ? insetindx++ : outsetindx++;
+ }
+
+ // construct id map for vertices
+ insetindx = vertexbase;
+ outsetindx = 0;
+ unsigned int vtxid = 0;
+ for ( vtxid = 0; vtxid < gobj->NumVerts; vtxid++ ) {
+ vertexmap[ vtxid ] = vertexset[ vtxid ] ? insetindx++ : outsetindx++;
+ }
+
+ // construct id map for wedges
+ insetindx = wedgebase;
+ outsetindx = 0;
+ for ( wedgeid = 0; wedgeid < gobj->NumWedges; wedgeid++ ) {
+ wedgemap[ wedgeid ] = wedgeset[ wedgeid ] ? insetindx++ : outsetindx++;
+ }
+
+ // construct index map for sorted poly list
+ if ( gobj->SortedPolyList != NULL ) {
+ insetindx = polybase;
+ outsetindx = 0;
+ for ( polyid = 0; polyid < gobj->NumPolys; polyid++ ) {
+ stpolymap[ polyid ] = polyset[ gobj->SortedPolyList[ polyid ] ] ?
+ insetindx++ : outsetindx++;
+ }
+ }
+
+ // apply map to normal ids embedded in faces
+ for ( faceid = 0; faceid < gobj->NumFaces; faceid++ ) {
+ int normalid = facelist[ faceid ].FaceNormalIndx;
+ facelist[ faceid ].FaceNormalIndx = vertexmap[ normalid ];
+ if ( vertexset[ normalid ] ) {
+ facelist[ faceid ].FaceNormalIndx -= vertexbase;
+ }
+ }
+
+ // apply map to face and vertex ids embedded in polys
+ for ( polyid = 0; polyid < gobj->NumPolys; polyid++ ) {
+ int faceid = polylist[ polyid ].FaceIndx;
+ polylist[ polyid ].FaceIndx = facemap[ faceid ];
+ if ( faceset[ faceid ] ) {
+ polylist[ polyid ].FaceIndx -= facebase;
+ }
+ dword flags = polylist[ polyid ].Flags;
+ int wbase = ( flags & POLYFLAG_CORNERCOLORS ) ? 2 : 1;
+ dword *vertindxs = polylist[ polyid ].VertIndxs;
+ dword *wedgeindxs = &vertindxs[ polylist[ polyid ].NumVerts * wbase ];
+ for ( unsigned int vindx = 0; vindx < polylist[ polyid ].NumVerts; vindx++ ) {
+ int vtxid = vertindxs[ vindx ];
+ vertindxs[ vindx ] = vertexmap[ vtxid ];
+ if ( vertexset[ vtxid ] ) {
+ vertindxs[ vindx ] -= vertexbase;
+ }
+ if ( flags & POLYFLAG_WEDGEINDEXES ) {
+ int vtxwedge = wedgeindxs[ vindx ];
+ wedgeindxs[ vindx ] = wedgemap[ vtxwedge ];
+ if ( wedgeset[ vtxwedge ] ) {
+ wedgeindxs[ vindx ] -= wedgebase;
+ }
+ }
+ }
+ }
+
+ // apply map to wedge vertex indexes
+ for ( wedgeid = 0; wedgeid < gobj->NumWedges; wedgeid++ ) {
+ int vtxid = gobj->WedgeVertIndxs[ wedgeid ];
+ gobj->WedgeVertIndxs[ wedgeid ] = vertexmap[ vtxid ];
+ if ( vertexset[ vtxid ] ) {
+ gobj->WedgeVertIndxs[ wedgeid ] -= vertexbase;
+ }
+ }
+
+ // in-place reorder facelist according to map
+ for ( faceid = 0; faceid < gobj->NumFaces; ) {
+
+ // proceed if current pos correct
+ if ( facemap[ faceid ] == faceid ) {
+ faceid++;
+ continue;
+ }
+
+ // swap face data
+ Face temp = facelist[ facemap[ faceid ] ];
+ facelist[ facemap[ faceid ] ] = facelist[ faceid ];
+ facelist[ faceid ] = temp;
+
+ // swap map ids
+ dword dstid = facemap[ faceid ];
+ facemap[ faceid ] = facemap[ dstid ];
+ facemap[ dstid ] = dstid;
+ }
+
+ if ( gobj->SortedPolyList != NULL ) {
+
+ // in-place reorder sorted poly id list
+ for ( polyid = 0; polyid < gobj->NumPolys; ) {
+
+ // proceed if current pos correct
+ if ( stpolymap[ polyid ] == polyid ) {
+ polyid++;
+ continue;
+ }
+
+ // swap poly data
+ dword temp = gobj->SortedPolyList[ stpolymap[ polyid ] ];
+ gobj->SortedPolyList[ stpolymap[ polyid ] ] = gobj->SortedPolyList[ polyid ];
+ gobj->SortedPolyList[ polyid ] = temp;
+
+ // swap map ids
+ dword dstid = stpolymap[ polyid ];
+ stpolymap[ polyid ] = stpolymap[ dstid ];
+ stpolymap[ dstid ] = dstid;
+ }
+
+ // apply map to sorted poly id list
+ for ( polyid = 0; polyid < gobj->NumPolys; polyid++ ) {
+ int sortid = gobj->SortedPolyList[ polyid ];
+ gobj->SortedPolyList[ polyid ] = polymap[ sortid ];
+ if ( polyset[ sortid ] ) {
+ gobj->SortedPolyList[ polyid ] -= polybase;
+ }
+ }
+ }
+
+ // in-place reorder polylist according to map
+ for ( polyid = 0; polyid < gobj->NumPolys; ) {
+
+ // proceed if current pos correct
+ if ( polymap[ polyid ] == polyid ) {
+ polyid++;
+ continue;
+ }
+
+ // swap poly data
+ Poly temp = polylist[ polymap[ polyid ] ];
+ polylist[ polymap[ polyid ] ] = polylist[ polyid ];
+ polylist[ polyid ] = temp;
+
+ // swap map ids
+ dword dstid = polymap[ polyid ];
+ polymap[ polyid ] = polymap[ dstid ];
+ polymap[ dstid ] = dstid;
+ }
+
+ // in-place reorder vertexlist according to map
+ for ( vtxid = 0; vtxid < gobj->NumVerts; ) {
+
+ // proceed if current pos correct
+ if ( vertexmap[ vtxid ] == vtxid ) {
+ vtxid++;
+ continue;
+ }
+
+ // swap vertex data
+ Vertex3 temp = vertexlist[ vertexmap[ vtxid ] ];
+ vertexlist[ vertexmap[ vtxid ] ] = vertexlist[ vtxid ];
+ vertexlist[ vtxid ] = temp;
+
+ // swap map ids
+ dword dstid = vertexmap[ vtxid ];
+ vertexmap[ vtxid ] = vertexmap[ dstid ];
+ vertexmap[ dstid ] = dstid;
+ }
+
+ // in-place reorder wedgelists according to map
+ for ( wedgeid = 0; wedgeid < gobj->NumWedges; ) {
+
+ // proceed if current pos correct
+ if ( wedgemap[ wedgeid ] == wedgeid ) {
+ wedgeid++;
+ continue;
+ }
+
+ // swap wedge data
+ dword tempindx = gobj->WedgeVertIndxs[ wedgemap[ wedgeid ] ];
+ gobj->WedgeVertIndxs[ wedgemap[ wedgeid ] ] = gobj->WedgeVertIndxs[ wedgeid ];
+ gobj->WedgeVertIndxs[ wedgeid ] = tempindx;
+
+ if ( gobj->WedgeNormals != NULL ) {
+ Vector3 tempnormal = gobj->WedgeNormals[ wedgemap[ wedgeid ] ];
+ gobj->WedgeNormals[ wedgemap[ wedgeid ] ] = gobj->WedgeNormals[ wedgeid ];
+ gobj->WedgeNormals[ wedgeid ] = tempnormal;
+
+ }
+
+ if ( gobj->WedgeColors != NULL ) {
+ colrgba_s tempcolor = gobj->WedgeColors[ wedgemap[ wedgeid ] ];
+ gobj->WedgeColors[ wedgemap[ wedgeid ] ] = gobj->WedgeColors[ wedgeid ];
+ gobj->WedgeColors[ wedgeid ] = tempcolor;
+
+ }
+
+ if ( gobj->WedgeTexCoords != NULL ) {
+ TexCoord2 temptexcoord = gobj->WedgeTexCoords[ wedgemap[ wedgeid ] ];
+ gobj->WedgeTexCoords[ wedgemap[ wedgeid ] ] = gobj->WedgeTexCoords[ wedgeid ];
+ gobj->WedgeTexCoords[ wedgeid ] = temptexcoord;
+
+ }
+
+ // swap map ids
+ dword dstid = wedgemap[ wedgeid ];
+ wedgemap[ wedgeid ] = wedgemap[ dstid ];
+ wedgemap[ dstid ] = dstid;
+ }
+
+ // free maps and sets
+ FREEMEM( mapmemblock );
+ FREEMEM( setmemblock );
+
+ // set anim info
+ anim->NumVerts = numnormals + numpolyverts;
+ anim->NumPolyVerts = numpolyverts;
+ anim->NumNormals = numnormals;
+ anim->VertexBase = vertexbase;
+ anim->NumPolys = numpolys;
+ anim->PolyBase = polybase;
+ anim->NumFaces = numfaces;
+ anim->FaceBase = facebase;
+ anim->NumWedges = numwedges;
+ anim->WedgeBase = wedgebase;
+
+ // shrink base object
+ gobj->NumVerts -= anim->NumVerts;
+ gobj->NumPolyVerts -= anim->NumPolyVerts;
+ gobj->NumNormals -= anim->NumNormals;
+ gobj->NumPolys -= anim->NumPolys;
+ gobj->NumFaces -= anim->NumFaces;
+ gobj->NumWedges -= anim->NumWedges;
+
+ // make anim active
+ gobj->ActiveVtxAnims++;
+
+ // update lod info if necessary
+ if ( gobj->NumLodObjects > 0 ) {
+
+ GenLodObject *lodobj = gobj->LodObjects[ lod ].LodObject;
+ ASSERT( lodobj != NULL );
+
+ lodobj->NumVerts = gobj->NumVerts;
+ lodobj->NumPolyVerts = gobj->NumPolyVerts;
+ lodobj->NumNormals = gobj->NumNormals;
+ lodobj->NumPolys = gobj->NumPolys;
+ lodobj->NumFaces = gobj->NumFaces;
+ lodobj->NumWedges = gobj->NumWedges;
+ lodobj->ActiveVtxAnims = gobj->ActiveVtxAnims;
+ }
+
+ // vertex anim beyond is treated as base object info array
+ int baseinfoid = gobj->NumVtxAnims + vtxanimoffset;
+ uintptr_t *baseinfo = (uintptr_t *) &gobj->VtxAnimStates[ baseinfoid ];
+
+ // store id of base object as active subobject
+ baseinfo[ 0 ] = gobj->NumVtxAnims;
+
+ // save base object info
+ baseinfo[ 1 ] = (dword) gobj->NumVerts;
+ baseinfo[ 2 ] = (dword) gobj->NumPolyVerts;
+ baseinfo[ 3 ] = (dword) gobj->NumNormals;
+ baseinfo[ 4 ] = (uintptr_t) gobj->VertexList;
+ baseinfo[ 5 ] = (dword) gobj->NumPolys;
+ baseinfo[ 6 ] = (uintptr_t) gobj->PolyList;
+ baseinfo[ 7 ] = (dword) gobj->NumFaces;
+ baseinfo[ 8 ] = (uintptr_t) gobj->FaceList;
+ baseinfo[ 9 ] = (uintptr_t) gobj->SortedPolyList;
+ baseinfo[ 10 ] = (dword) gobj->NumWedges;
+ baseinfo[ 11 ] = (uintptr_t) gobj->WedgeVertIndxs;
+ baseinfo[ 12 ] = (uintptr_t) gobj->WedgeNormals;
+ baseinfo[ 13 ] = (uintptr_t) gobj->WedgeColors;
+ baseinfo[ 14 ] = (uintptr_t) gobj->WedgeTexCoords;
+ baseinfo[ 15 ] = (uintptr_t) gobj->WedgeLighted;
+ baseinfo[ 16 ] = (uintptr_t) gobj->WedgeSpecular;
+ baseinfo[ 17 ] = (uintptr_t) gobj->WedgeFogged;
+
+ return anim;
+}
+
+
+