void ExpMapGenerator::SetSmoothNormal( ExpMapParticle * pParticle, ExpMapParticle::ListEntry * pNbrs, bool bEnable ) { if ( bEnable && pParticle->m_bNormalSmoothed ) return; else if ( !bEnable && !pParticle->m_bNormalSmoothed) return; Wml::Vector3f vPos, vNorm, vNbrPos, vNbrNorm; if ( bEnable ) { float fWeightSum = 0.0f; Wml::Vector3f vAverage = Wml::Vector3f::ZERO; GetMesh()->GetVertex( pParticle->VertexID(), vPos, &vNorm); ExpMapParticle::ListEntry * pCur = pNbrs; while ( pCur != NULL ) { IMesh::VertexID nID = pCur->pParticle->VertexID(); Wml::Vector3f vNbrPos, vNbrNorm; GetMesh()->GetVertex( pCur->pParticle->VertexID(), vNbrPos, &vNbrNorm); float fWeight = 1.0f / ( (vPos - vNbrPos).Length() + (0.0001f*m_fMaxEdgeLength) ); vAverage += fWeight * vNbrNorm; fWeightSum += fWeight; pCur = pCur->pNext; } vAverage /= fWeightSum; vAverage.Normalize(); pParticle->Normal() = vAverage; } else { GetMesh()->GetNormal( pParticle->VertexID(), pParticle->Normal() ); } pParticle->WorldFrame() = Frame3f( pParticle->Position(), pParticle->Normal() ); pParticle->m_bNormalSmoothed = bEnable; }
void ExpMapGenerator::PrecomputePropagationData( ExpMapParticle * pCenterParticle, ExtPlane3f & vTangentPlane, Frame3f & vCenterWorldFrame, Wml::Matrix2f & matFrameRotate ) { // compute surface-tangent plane at particle Wml::Vector3f vNormal( pCenterParticle->Normal() ); // compute plane at this point vTangentPlane = ExtPlane3f( vNormal, pCenterParticle->Position() ); // compute 3D frame at center point //vCenterWorldFrame = Frame3f( pCenterParticle->Position(), vNormal ); vCenterWorldFrame = pCenterParticle->WorldFrame(); // rotate seed world frame Z into this particle's Z Frame3f seedWorldFrame( m_pSeedParticle->WorldFrame() ); seedWorldFrame.AlignZAxis( vCenterWorldFrame ); // compute cos(angle) between axis Wml::Vector3f vCenterAxisX( vCenterWorldFrame.Axis( Frame3f::AxisX ) ); Wml::Vector3f vSeedAxisX( seedWorldFrame.Axis( Frame3f::AxisX ) ); float fCosTheta = vCenterAxisX.Dot(vSeedAxisX); // compute rotated min-dist vector for this particle float fTmp = 1 - fCosTheta*fCosTheta; if ( fTmp < 0 ) fTmp = 0; // need to clamp so that sqrt works... float fSinTheta = (float)sqrt(fTmp); Wml::Vector3f vCross = vCenterAxisX.Cross(vSeedAxisX); if ( vCross.Dot( vNormal ) < 0 ) // get the right sign... fSinTheta = -fSinTheta; // create transposed 2D rotation matrix matFrameRotate = Wml::Matrix2f( fCosTheta, fSinTheta, -fSinTheta, fCosTheta ); }
Wml::Vector2f ExpMapGenerator::ComputeSurfaceVector( ExpMapParticle * pCenterParticle, ExpMapParticle * pNbrParticle, ExtPlane3f & vTangentPlane, Frame3f & vCenterWorldFrame, Wml::Matrix2f & matFrameRotate ) { // special case... if ( (pNbrParticle->Position() - pCenterParticle->Position()).Length() < Wml::Mathf::EPSILON ) return pCenterParticle->SurfaceVector(); // project point into plane Wml::Vector3f vPlanePoint = vTangentPlane.RotatePointIntoPlane( pNbrParticle->Position() ); // project point into coord system of frame vPlanePoint -= pCenterParticle->Position(); vCenterWorldFrame.ToFrameLocal(vPlanePoint); // now we can project into surface frame simply by dropping z (which should be 0 anyway, // since the vector lies in the plane!) Wml::Vector2f vSurfaceFrame( vPlanePoint.X(), vPlanePoint.Y() ); // reverse vector so it points back to current particle vSurfaceFrame *= -1.0f; // transform local vector into coord system of initial surface reference frame // and add accumulated surface vector return pCenterParticle->SurfaceVector() + (matFrameRotate * vSurfaceFrame); }
Wml::Vector3d rms::VectorCastfd( const Wml::Vector3f & vec ) { return Wml::Vector3d( (double)vec.X(), (double)vec.Y(), (double)vec.Z() ); }