228 lines
6.6 KiB
C++
228 lines
6.6 KiB
C++
#include <malloc.h>
|
|
#include "sbre_int.h"
|
|
#include "sbre.h" /* For subobject. */
|
|
|
|
static void ExpandVertices(CollMesh* pCMesh, int n) {
|
|
if(n < 100) n = 100;
|
|
pCMesh->maxv += n; n = pCMesh->maxv;
|
|
pCMesh->pVertex = (float*)realloc(pCMesh->pVertex, n*3*sizeof(float));
|
|
}
|
|
|
|
static void ExpandIndices(CollMesh* pCMesh, int n) {
|
|
if(n < 100) n = 100;
|
|
pCMesh->maxi += n; n = pCMesh->maxi;
|
|
pCMesh->pIndex = (int*)realloc(pCMesh->pIndex, n*sizeof(int));
|
|
pCMesh->pFlag = (int*)realloc(pCMesh->pFlag, sizeof(int) * n/3);
|
|
}
|
|
|
|
void ResolveVtx(Vector* pIn, Vector* pOut, RState* pState) {
|
|
Vector tv;
|
|
MatVecMult(&pState->objorient, pIn, &tv);
|
|
VecMul(&tv, pState->scale, &tv);
|
|
VecAdd(&tv, &pState->objpos, pOut);
|
|
}
|
|
|
|
static int CollFuncMatAnim(uint16* pData, Model* pMod, RState* pState) {
|
|
return 22;
|
|
}
|
|
|
|
static int CollFuncMatFixed(uint16* pData, Model* pMod, RState* pState) {
|
|
return 11;
|
|
}
|
|
|
|
static int CollFuncMatVar(uint16* pData, Model* pMod, RState* pState) {
|
|
return 2;
|
|
}
|
|
|
|
static int CollFuncZBias(uint16* pData, Model* pMod, RState* pState) {
|
|
return 4;
|
|
}
|
|
|
|
static int CollFuncTriFlat(uint16* pData, Model* pMod, RState* pState) {
|
|
Vector* pVtx = pState->pVtx;
|
|
CollMesh* pCMesh = pState->pCMesh;
|
|
if(pCMesh->maxv - pCMesh->nv < 6) ExpandVertices(pCMesh, 6);
|
|
if(pCMesh->maxi - pCMesh->ni < 6) ExpandIndices(pCMesh, 6);
|
|
|
|
int ni = pCMesh->ni; int nv = pCMesh->nv;
|
|
Vector* pOut = (Vector*)pCMesh->pVertex;
|
|
int* pIdx = pCMesh->pIndex;
|
|
pCMesh->pFlag[ni/3] = pCMesh->cflag;
|
|
|
|
for(int i = 0; i < 3; i++) {
|
|
ResolveVtx(pVtx+pData[i+1], pOut+nv, pState);
|
|
pIdx[ni++] = nv++;
|
|
}
|
|
|
|
if(pData[0] & RFLAG_XREF) {
|
|
pCMesh->pFlag[ni/3] = pCMesh->cflag;
|
|
|
|
for(int i = 0; i < 3; i++) {
|
|
Vector* pVec = pVtx + pData[3-i];
|
|
VecSet(-pVec->x, pVec->y, pVec->z, pOut+nv);
|
|
ResolveVtx(pOut+nv, pOut+nv, pState);
|
|
pIdx[ni++] = nv++;
|
|
}
|
|
}
|
|
pCMesh->ni = ni; pCMesh->nv = nv;
|
|
return 4;
|
|
}
|
|
|
|
static int CollFuncQuadFlat(uint16* pData, Model* pMod, RState* pState) {
|
|
Vector* pVtx = pState->pVtx;
|
|
CollMesh* pCMesh = pState->pCMesh;
|
|
if(pCMesh->maxv - pCMesh->nv < 8) ExpandVertices(pCMesh, 8);
|
|
if(pCMesh->maxi - pCMesh->ni < 12) ExpandIndices(pCMesh, 12);
|
|
|
|
int ni = pCMesh->ni; int nv = pCMesh->nv;
|
|
Vector* pOut = (Vector*)pCMesh->pVertex;
|
|
int* pIdx = pCMesh->pIndex;
|
|
pCMesh->pFlag[ni/3] = pCMesh->pFlag[1+ni/3] = pCMesh->cflag;
|
|
|
|
for(int i = 0; i < 4; i++) ResolveVtx(pVtx+pData[i+1], pOut+nv+i, pState);
|
|
pIdx[ni+0] = nv; pIdx[ni+1] = nv+1; pIdx[ni+2] = nv+2;
|
|
pIdx[ni+3] = nv; pIdx[ni+4] = nv+2; pIdx[ni+5] = nv+3;
|
|
ni += 6; nv += 4;
|
|
|
|
if(pData[0] & RFLAG_XREF) {
|
|
pCMesh->pFlag[ni/3] = pCMesh->pFlag[1+ni/3] = pCMesh->cflag;
|
|
|
|
for(int i = 0; i < 4; i++) {
|
|
Vector* pVec = pVtx + pData[i+1];
|
|
VecSet(-pVec->x, pVec->y, pVec->z, pOut+nv+i);
|
|
ResolveVtx(pOut+nv+i, pOut+nv+i, pState);
|
|
}
|
|
pIdx[ni+0] = nv; pIdx[ni+1] = nv+2; pIdx[ni+2] = nv + 1;
|
|
pIdx[ni+3] = nv; pIdx[ni+4] = nv+3; pIdx[ni+5] = nv + 2;
|
|
ni += 6; nv += 4;
|
|
}
|
|
pCMesh->ni = ni; pCMesh->nv = nv;
|
|
return 5;
|
|
}
|
|
|
|
static void ArrayCallback(int nv2, int ni2, Vector* pVertex, uint16* pIndex,
|
|
uint16 flags, RState* pState) {
|
|
CollMesh* pCMesh = pState->pCMesh;
|
|
if(pCMesh->maxv - pCMesh->nv < nv2*2) ExpandVertices(pCMesh, nv2*2);
|
|
if(pCMesh->maxi - pCMesh->ni < ni2*2) ExpandIndices(pCMesh, ni2*2);
|
|
|
|
int ni = pCMesh->ni; int nv = pCMesh->nv;
|
|
Vector* pOut = (Vector*)pCMesh->pVertex;
|
|
int* pIdx = pCMesh->pIndex;
|
|
int* pFlag = pCMesh->pFlag;
|
|
|
|
for(int i = 0; i < nv2; i++) ResolveVtx(pVertex+i*2, pOut+nv+i, pState);
|
|
for(int i = 0; i < ni2; i++) pIdx[ni+i] = nv+pIndex[i];
|
|
for(int i = 0; i < ni2/3; i++) pFlag[ni/3+i] = pCMesh->cflag;
|
|
ni += ni2; nv += nv2;
|
|
|
|
if(flags & RFLAG_XREF) {
|
|
for(int i = 0; i < nv2; i++) {
|
|
Vector* pVec = pVertex + i*2;
|
|
VecSet(-pVec->x, pVec->y, pVec->z, pOut+nv+i);
|
|
|
|
ResolveVtx(pOut+nv+i, pOut+nv+i, pState);
|
|
}
|
|
for(int i = 0; i < ni2; i += 3) {
|
|
pIdx[ni+i+0] = nv+pIndex[i];
|
|
pIdx[ni+i+1] = nv+pIndex[i+2];
|
|
pIdx[ni+i+2] = nv+pIndex[i+1];
|
|
}
|
|
for(int i = 0; i < ni2/3; i++) pFlag[ni/3+1] = pCMesh->cflag;
|
|
ni += ni2; nv+= nv2;
|
|
}
|
|
pCMesh->ni = ni; pCMesh->nv = nv;
|
|
}
|
|
|
|
static int CollFuncCompoundSmooth(uint16* pData, Model* pMod, RState* pState) {
|
|
pState->pCallback = ArrayCallback;
|
|
return pPrimFuncTable[*pData & 0xff](pData, pMod, pState);
|
|
}
|
|
|
|
static int CollFuncCylinder(uint16* pData, Model* pMod, RState* pState) {
|
|
pState->pCallback = ArrayCallback;
|
|
return pPrimFuncTable[*pData & 0xff](pData, pMod, pState);
|
|
}
|
|
|
|
static int CollFuncCircle(uint16* pData, Model* pMod, RState* pState) {
|
|
pState->pCallback = ArrayCallback;
|
|
return pPrimFuncTable[*pData & 0xff](pData, pMod, pState);
|
|
}
|
|
|
|
static int CollFuncTube(uint16* pData, Model* pMod, RState* pState) {
|
|
pState->pCallback = ArrayCallback;
|
|
return pPrimFuncTable[*pData & 0xff](pData, pMod, pState);
|
|
}
|
|
|
|
static int CollFuncExtrusion(uint16* pData, Model* pMod, RState* pState) {
|
|
pState->pCallback = ArrayCallback;
|
|
return pPrimFuncTable[*pData & 0xff](pData, pMod, pState);
|
|
}
|
|
|
|
/*
|
|
uint16 PFUNC_SUBOBJECT
|
|
uint16 anim
|
|
uint16 modelnum
|
|
uint16 offset
|
|
uint16 norm
|
|
uint16 zaxis
|
|
uint16 scale
|
|
*/
|
|
|
|
static int CollFuncSubObject(uint16* pData, Model* pMod, RState* pState) {
|
|
/* Return immediately if object is not present. */
|
|
if(pData[1] != 0x8000 && !pState->pObjParam->pFlag[pData[1]]) return 7;
|
|
|
|
/* Build transform matrix, offset. */
|
|
Vector v1, v2, v3, pos; Matrix m, orient;
|
|
VecNorm(pState->pVtx+pData[4], &v2);
|
|
VecNorm(pState->pVtx+pData[5], &v3);
|
|
VecCross(&v2, &v3, &v1);
|
|
m.x1 = v1.x; m.x2 = v2.x; m.x3 = v3.x;
|
|
m.y1 = v1.y; m.y2 = v2.y; m.y3 = v3.y;
|
|
m.z1 = v1.z; m.z2 = v2.z; m.z3 = v3.z;
|
|
MatMatMult(&pState->objorient, &m, &orient);
|
|
|
|
MatVecMult(&pState->objorient, pState->pVtx+pData[3], &pos);
|
|
VecMul(&pos, pState->scale, &pos);
|
|
VecAdd(&pos, &pState->objpos, &pos);
|
|
float scale = pState->scale*pData[6]*0.01f;
|
|
|
|
GenCollMeshInternal(&pos, &orient, pData[2], pState->pObjParam, scale, pState->pCMesh);
|
|
return 7;
|
|
}
|
|
|
|
static int CollFuncText(uint16* pData, Model* pMod, RState* pState) {
|
|
return 9;
|
|
}
|
|
|
|
/*
|
|
uint16 PFUNC_SETCFLAG
|
|
uint16 flag
|
|
*/
|
|
|
|
static int CollFuncSetCFlag(uint16* pData, Model* pMod, RState* pState) {
|
|
pState->pCMesh->cflag = pData[1];
|
|
return 2;
|
|
}
|
|
|
|
int (*pCollFuncTable[])(uint16*, Model*, RState*) = {
|
|
0, /* End. */
|
|
CollFuncMatAnim,
|
|
CollFuncMatFixed,
|
|
CollFuncMatVar,
|
|
CollFuncZBias,
|
|
CollFuncTriFlat,
|
|
CollFuncQuadFlat,
|
|
CollFuncCompoundSmooth, /* Just uses steps = 0. */
|
|
CollFuncCompoundSmooth,
|
|
CollFuncCircle,
|
|
CollFuncCylinder,
|
|
CollFuncTube,
|
|
CollFuncSubObject,
|
|
CollFuncText,
|
|
CollFuncExtrusion,
|
|
CollFuncSetCFlag,
|
|
};
|
|
|