Lephisto/src/sbre/simtriang.cpp

156 lines
4.8 KiB
C++

#include <stdlib.h>
#include "jjtypes.h"
#include "sbre_int.h"
void ResolveLinearInterp(Vector* p0, Vector* p1, float t, Vector* pRes) {
Vector tv;
VecSub(p1, p0, &tv);
VecMul(&tv, t, &tv);
VecAdd(&tv, p0, pRes);
}
void ResolveQuadraticSpline(Vector* p0, Vector* p1, Vector* p2, float t, Vector* pRes) {
float invt = 1.0f - t;
Vector tv;
VecMul(p0, invt*invt, pRes);
VecMul(p1, 2.0f*t*invt, &tv);
VecAdd(&tv, pRes, pRes);
VecMul(p2, t*t, &tv);
VecAdd(&tv, pRes, pRes);
}
void ResolveCubicSpline(Vector* p0, Vector* p1, Vector* p2, Vector* p3, float t, Vector* pRes) {
float invt = 1.0f - t;
Vector tv1, tv2, tv;
VecMul(p0, invt*invt*invt, &tv1);
VecMul(p3, t*t*t, &tv);
VecAdd(&tv, &tv1, &tv1);
VecMul(p1, 3.0f*t*invt*invt, &tv2);
VecMul(p2, 3.0f*t*t*invt, &tv);
VecAdd(&tv, &tv2, &tv2);
VecAdd(&tv1, &tv2, pRes);
}
void ResolveHermiteSpline(Vector* p0, Vector* p1, Vector* n0, Vector* n1, float t, Vector* pRes) {
float t2 = t*t, t3 = t*t*t;
Vector tv1, tv2, tv;
VecMul(p0, 2*t3-3*t2+1, &tv1);
VecMul(n0, t3-2*t2+t, &tv);
VecAdd(&tv, &tv1, &tv1);
VecMul(p1, -2*t3+3*t2, &tv2);
VecMul(n1, t3-t2, &tv);
VecAdd(&tv, &tv2, &tv2);
VecAdd(&tv1, &tv2, pRes);
}
void ResolveHermiteTangent(Vector* p0, Vector* p1, Vector* n0, Vector* n1, float t, Vector* pRes) {
float t2 = t*t;
Vector tv1, tv2, tv;
VecMul(p0, 6*t2-6*t, &tv1);
VecMul(n0, 3*t2-4*t+1, &tv);
VecAdd(&tv, &tv1, &tv1);
VecMul(p1, -6*t2+6*t, &tv2);
VecMul(n1, 3*t2-2*t, &tv);
VecAdd(&tv, &tv2, &tv2);
VecAdd(&tv1, &tv2, pRes);
}
/******************************************************************************/
struct TriangPoint {
Vector pos; /* Base pos, norm. */
Vector norm;
int num; /* Count of valid vertices. */
uint16 pIndex[TRIANG_MAXSTEPS+1]; /* Index of each vertex, inside to outside. */
};
static uint16 pIndex[6*TRIANG_MAXPOINTS*(TRIANG_MAXSTEPS+1)];
static Vector pVertex[2*TRIANG_MAXPOINTS*(TRIANG_MAXSTEPS+1)];
static TriangPoint pPoint[TRIANG_MAXPOINTS];
static int numPoints = 0;
void TriangAddPoint(Vector* pPos, Vector* pNorm) {
if(numPoints == TRIANG_MAXPOINTS) return;
TriangPoint *tp = pPoint + numPoints++;
tp->pos = *pPos; tp->norm = *pNorm;
}
void Triangulate(Vector* pCPos, Vector* pCNorm, int steps,
Vector** ppVtx, int* pNV, uint16** ppIndex, int* pNI) {
/*
*Ok. For each point, find number of increments
* and generate intermediate values.
*/
int nv = 0, ni = 0;
int i; for(int i=0; i<numPoints; i++) {
Vector tv; //, tnorm, tnorm2;
TriangPoint* pCur = pPoint+i;
VecSub(pCPos, &pCur->pos, &tv);
// float len = sqrt (VecDot (&tv, &tv));
// VecCross (&pCur->norm, pCNorm, &tnorm);
// VecCross (pCNorm, &tv, &tnorm2);
// if (VecDot (&tnorm, &tnorm2) < 0.0f) VecInv (&tnorm, &tnorm);
pVertex[nv] = pCur->pos; /* Add first vertex to array. */
pVertex[nv+1] = pCur->norm;
pCur->pIndex[0] = nv>>1; nv+=2;
Vector t0, t1; /*Find tangents. */
VecMul(&pCur->norm, VecDot (&tv, &pCur->norm), &t0);
VecSub(&tv, &t0, &t0);
VecMul(pCNorm, VecDot (&tv, pCNorm), &t1);
VecSub(&tv, &t1, &t1);
if(steps > TRIANG_MAXSTEPS) pCur->num = TRIANG_MAXSTEPS;
else pCur->num = steps;
static const float pInv[] = { 1.0f, 0.5f, 0.3333333f, 0.25f, 0.2f,
0.1666667f, 0.1428571f, 0.125f, 0.1111111f, 0.1f };
float t, inc = pInv[pCur->num];
int j; for(t=inc, j=1; j<=pCur->num; j++, t+=inc) {
ResolveHermiteSpline(&pCur->pos, pCPos, &t0, &t1, t, pVertex+nv);
// ResolveHermiteTangent(&pCur->pos, pCPos, &t0, &t1, t, &tv);
// VecCross(&tv, &tnorm, pVertex+nv+1);
ResolveLinearInterp (&pCur->norm, pCNorm, t, pVertex+nv+1);
pCur->pIndex[j] = nv>>1; nv+=2;
}
}
pVertex[nv] = *pCPos; /* Add centre vertex to array. */
pVertex[nv+1] = *pCNorm;
int cindex = nv>>1; nv+=2;
/* Now render each radial strip from the centre. */
for(i=0; i<numPoints; i++) {
TriangPoint *pCur = pPoint + i;
TriangPoint *pNext = pPoint + (i+1==numPoints?0:i+1);
pIndex[ni++] = cindex;
pIndex[ni++] = pCur->pIndex[pCur->num];
pIndex[ni++] = pNext->pIndex[pNext->num];
int vc = pCur->num, vn = pNext->num;
while(vc|vn) {
if(vc) {
pIndex[ni++] = pCur->pIndex[vc];
pIndex[ni++] = pCur->pIndex[--vc];
pIndex[ni++] = pNext->pIndex[vn];
}
if(vn) {
pIndex[ni++] = pNext->pIndex[vn];
pIndex[ni++] = pCur->pIndex[vc];
pIndex[ni++] = pNext->pIndex[--vn];
}
}
}
// return data
*pNI = ni; *pNV = nv>>1;
*ppIndex = pIndex;
*ppVtx = pVertex;
numPoints = 0;
return;
}