void CSplinePatch::GetPointAndNormal( Vector& position, Vector& normal ) const { // The patch equation is: // px = S * M * Gx * M^T * T^T // py = S * M * Gy * M^T * T^T // pz = S * M * Gz * M^T * T^T // where S = [s^3 s^2 s 1], T = [t^3 t^2 t 1] // M is the patch type matrix, in my case I'm using a catmull-rom // G is the array of control points. rows have constant t VMatrix controlPointsX, controlPointsY, controlPointsZ; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { int idx = m_SampleIndices[i][j]; controlPointsX[i][j] = m_ppPositions[ idx ]->x; controlPointsY[i][j] = m_ppPositions[ idx ]->y; controlPointsZ[i][j] = m_ppPositions[ idx ]->z; } } Vector4D tmp; Vector4DMultiply( controlPointsX, m_TVec, tmp ); position[0] = DotProduct4D( tmp, m_SVec ); Vector4DMultiply( controlPointsY, m_TVec, tmp ); position[1] = DotProduct4D( tmp, m_SVec ); Vector4DMultiply( controlPointsZ, m_TVec, tmp ); position[2] = DotProduct4D( tmp, m_SVec ); // Normal computation float fs2 = m_fs * m_fs; float ft2 = m_ft * m_ft; Vector4D dsvec( 3.0f * fs2, 2.0f * m_fs, 1.0f, 0.0f ); Vector4D dtvec( 3.0f * ft2, 2.0f * m_ft, 1.0f, 0.0f ); Vector4DMultiplyTranspose( s_CatmullRom, dsvec, dsvec ); Vector4DMultiplyTranspose( s_CatmullRom, dtvec, dtvec ); Vector ds, dt; Vector4DMultiply( controlPointsX, m_TVec, tmp ); ds[0] = DotProduct4D( tmp, dsvec ); Vector4DMultiply( controlPointsY, m_TVec, tmp ); ds[1] = DotProduct4D( tmp, dsvec ); Vector4DMultiply( controlPointsZ, m_TVec, tmp ); ds[2] = DotProduct4D( tmp, dsvec ); Vector4DMultiply( controlPointsX, dtvec, tmp ); dt[0] = DotProduct4D( tmp, m_SVec ); Vector4DMultiply( controlPointsY, dtvec, tmp ); dt[1] = DotProduct4D( tmp, m_SVec ); Vector4DMultiply( controlPointsZ, dtvec, tmp ); dt[2] = DotProduct4D( tmp, m_SVec ); CrossProduct( ds, dt, normal ); VectorNormalize( normal ); }
float CSplinePatch::GetChannel( int channel ) const { // The patch equation is: // px = S * M * Gx * M^T * T^T // py = S * M * Gy * M^T * T^T // pz = S * M * Gz * M^T * T^T // where S = [s^3 s^2 s 1], T = [t^3 t^2 t 1] // M is the patch type matrix, in my case I'm using a catmull-rom // G is the array of control points. rows have constant t assert( m_pChannel[channel] ); VMatrix controlPoints; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { controlPoints[i][j] = m_pChannel[channel][ m_SampleIndices[i][j] ]; } } Vector4D tmp; Vector4DMultiply( controlPoints, m_TVec, tmp ); return DotProduct4D( tmp, m_SVec ); }
void C_EnergyWave::ComputePoint( float s, float t, Vector& pt, Vector& normal, float& opacity ) { int is = (int)s; int it = (int)t; if( is >= EWAVE_NUM_HORIZONTAL_POINTS ) is -= 1; if( it >= EWAVE_NUM_VERTICAL_POINTS ) it -= 1; int idx[16]; ComputeIndices( is, it, idx ); // The patch equation is: // px = S * M * Gx * M^T * T^T // py = S * M * Gy * M^T * T^T // pz = S * M * Gz * M^T * T^T // where S = [s^3 s^2 s 1], T = [t^3 t^2 t 1] // M is the patch type matrix, in my case I'm using a catmull-rom // G is the array of control points. rows have constant t static VMatrix catmullRom( -0.5, 1.5, -1.5, 0.5, 1, -2.5, 2, -0.5, -0.5, 0, 0.5, 0, 0, 1, 0, 0 ); VMatrix controlPointsX, controlPointsY, controlPointsZ, controlPointsO; Vector pos; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { const Vector& v = m_EWaveEffect.GetPoint( idx[i * 4 + j] ); controlPointsX[j][i] = v.x; controlPointsY[j][i] = v.y; controlPointsZ[j][i] = v.z; controlPointsO[j][i] = m_EWaveEffect.ComputeOpacity( v, GetAbsOrigin() ); } } float fs = s - is; float ft = t - it; VMatrix temp, mgm[4]; MatrixTranspose( catmullRom, temp ); MatrixMultiply( controlPointsX, temp, mgm[0] ); MatrixMultiply( controlPointsY, temp, mgm[1] ); MatrixMultiply( controlPointsZ, temp, mgm[2] ); MatrixMultiply( controlPointsO, temp, mgm[3] ); MatrixMultiply( catmullRom, mgm[0], mgm[0] ); MatrixMultiply( catmullRom, mgm[1], mgm[1] ); MatrixMultiply( catmullRom, mgm[2], mgm[2] ); MatrixMultiply( catmullRom, mgm[3], mgm[3] ); Vector4D svec, tvec; float ft2 = ft * ft; tvec[0] = ft2 * ft; tvec[1] = ft2; tvec[2] = ft; tvec[3] = 1.0f; float fs2 = fs * fs; svec[0] = fs2 * fs; svec[1] = fs2; svec[2] = fs; svec[3] = 1.0f; Vector4D tmp; Vector4DMultiply( mgm[0], tvec, tmp ); pt[0] = DotProduct4D( tmp, svec ); Vector4DMultiply( mgm[1], tvec, tmp ); pt[1] = DotProduct4D( tmp, svec ); Vector4DMultiply( mgm[2], tvec, tmp ); pt[2] = DotProduct4D( tmp, svec ); Vector4DMultiply( mgm[3], tvec, tmp ); opacity = DotProduct4D( tmp, svec ); if ((s == 0.0f) || (t == 0.0f) || (s == (EWAVE_NUM_HORIZONTAL_POINTS-1.0f)) || (t == (EWAVE_NUM_VERTICAL_POINTS-1.0f)) ) { opacity = 0.0f; } if ((s <= 0.3) || (t < 0.3)) { opacity *= 0.35f; } if ((s == (EWAVE_NUM_HORIZONTAL_POINTS-0.7f)) || (t == (EWAVE_NUM_VERTICAL_POINTS-0.7f)) ) { opacity *= 0.35f; } if (opacity < 0.0f) opacity = 0.0f; else if (opacity > 255.0f) opacity = 255.0f; // Normal computation Vector4D dsvec, dtvec; dsvec[0] = 3.0f * fs2; dsvec[1] = 2.0f * fs; dsvec[2] = 1.0f; dsvec[3] = 0.0f; dtvec[0] = 3.0f * ft2; dtvec[1] = 2.0f * ft; dtvec[2] = 1.0f; dtvec[3] = 0.0f; Vector ds, dt; Vector4DMultiply( mgm[0], tvec, tmp ); ds[0] = DotProduct4D( tmp, dsvec ); Vector4DMultiply( mgm[1], tvec, tmp ); ds[1] = DotProduct4D( tmp, dsvec ); Vector4DMultiply( mgm[2], tvec, tmp ); ds[2] = DotProduct4D( tmp, dsvec ); Vector4DMultiply( mgm[0], dtvec, tmp ); dt[0] = DotProduct4D( tmp, svec ); Vector4DMultiply( mgm[1], dtvec, tmp ); dt[1] = DotProduct4D( tmp, svec ); Vector4DMultiply( mgm[2], dtvec, tmp ); dt[2] = DotProduct4D( tmp, svec ); CrossProduct( ds, dt, normal ); VectorNormalize( normal ); }