/** * Convert the handedness of the matrix, such that Z=-Z */ void CFMat4x4::ConvertHandedness( void ) { // http://vfxbrain.com/questions/1/how-do-i-convert-a-transformation-matrix-from-right-handed-to-left-handed-coordin XMVECTOR* pVecs = reinterpret_cast<XMVECTOR*>( this ); const static XMVECTOR vA = { 1.0f, 1.0f, -1.0f, 1.0f }; const static XMVECTOR vB = { -1.0f, -1.0f, 1.0f, -1.0f }; pVecs[0] = XMVectorMultiply( pVecs[0], vA ); pVecs[1] = XMVectorMultiply( pVecs[1], vA ); pVecs[2] = XMVectorMultiply( pVecs[2], vB ); pVecs[3] = XMVectorMultiply( pVecs[3], vA ); }
CFVec4& CFVec4::operator *= ( CFVec4Arg vArg ) { XMVECTOR& v4V = *reinterpret_cast<XMVECTOR*>( this ); const XMVECTOR& v4V2 = *reinterpret_cast<const XMVECTOR*>( &vArg ); v4V = XMVectorMultiply( v4V, v4V2 ); return *this; }
// scalar opertaors CFVec4& CFVec4::operator *= ( const FLOAT32 fArg ) { XMVECTOR v4Scaler; v4Scaler = XMVectorSet( fArg, fArg, fArg, fArg ); XMVECTOR& v4V = *reinterpret_cast<XMVECTOR*>( this ); //Negate v4V = XMVectorMultiply( v4V, v4Scaler ); return *this; }
CFVec4 CFVec4::operator * ( CFVec4Arg vArg ) const { CFVec4 v4Return; const XMVECTOR& v4V = *reinterpret_cast<const XMVECTOR*>( this ); const XMVECTOR& v4V2 = *reinterpret_cast<const XMVECTOR*>( &vArg ); XMVECTOR& v4Result = *reinterpret_cast<XMVECTOR*>( &v4Return ); //Negate v4Result = XMVectorMultiply( v4V, v4V2 ); return v4Return; }
CFVec4& CFVec4::operator /= ( const FLOAT32 fArg ) { FLOAT32 fDivisor = 1.0f / fArg; XMVECTOR v4Scaler; v4Scaler = XMVectorSet( fDivisor, fDivisor, fDivisor, fDivisor ); XMVECTOR& v4V = *reinterpret_cast<XMVECTOR*>( this ); //Negate v4V = XMVectorMultiply( v4V, v4Scaler ); return *this; }
CFVec4 CFVec4::operator * ( const FLOAT32 fArg ) const { CFVec4 v4Return; XMVECTOR v4Scaler; v4Scaler = XMVectorSet( fArg, fArg, fArg, fArg ); const XMVECTOR& v4V = *reinterpret_cast<const XMVECTOR*>( this ); XMVECTOR& v4Result = *reinterpret_cast<XMVECTOR*>( &v4Return ); //Negate v4Result = XMVectorMultiply( v4V, v4Scaler ); return v4Return; }
// static void ff::VectorKey::InitTangents(VectorKey *pKeys, size_t nKeys, float tension) { tension = (1.0f - tension) / 2.0f; for (size_t i = 0; i < nKeys; i++) { const VectorKey &keyBefore = pKeys[i ? i - 1 : nKeys - 1]; const VectorKey &keyAfter = pKeys[i + 1 < nKeys ? i + 1 : 0]; XMStoreFloat4(&pKeys[i]._tangent, XMVectorMultiply( XMVectorReplicate(tension), XMVectorSubtract( XMLoadFloat4(&keyAfter._value), XMLoadFloat4(&keyBefore._value)))); } }
static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image& destImage ) { assert( srcImage.width == destImage.width ); assert( srcImage.height == destImage.height ); ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) ); if ( !scanline ) return E_OUTOFMEMORY; const uint8_t *pSrc = srcImage.pixels; uint8_t *pDest = destImage.pixels; if ( !pSrc || !pDest ) return E_POINTER; for( size_t h = 0; h < srcImage.height; ++h ) { if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) ) return E_FAIL; XMVECTOR* ptr = scanline.get(); for( size_t w = 0; w < srcImage.width; ++w ) { XMVECTOR v = *ptr; XMVECTOR alpha = XMVectorSplatW( *ptr ); alpha = XMVectorMultiply( v, alpha ); *(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 ); } if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) ) return E_FAIL; pSrc += srcImage.rowPitch; pDest += destImage.rowPitch; } return S_OK; }
Vector3 Vector3::operator * (float other) const { Vector3 tmp(other, other, other); return Vector3(XMVectorMultiply(XMLoadFloat3(&mVector), XMLoadFloat3(&tmp.mVector))); }
Vector3& Vector3::operator *= (float other) { Vector3 tmp(other, other, other); XMStoreFloat3(&mVector, XMVectorMultiply(XMLoadFloat3(&mVector), XMLoadFloat3(&tmp.mVector))); return *this; }
bool RayTraceDataGenerator::CalcIntersect(const XMVECTOR& p1, const XMVECTOR& n, XMVECTOR* nResult, XMVECTOR* intersectLocation, float* depth) { /* // grid space vec3 grid = floor( pos ); //向下取整将坐标在网格中使用 vec3 grid_step = sign( dir ); //获取dir(方向)的正负符号<-意思就是说获取网格的步进方向,虽然只是正负 vec3 corner = max( grid_step, vec3( 0.0 ) );//负号->0 //应该是最后在步进方向上产生的偏差值,但是原因不明 // ray space vec3 inv = vec3( 1.0 ) / dir; //取倒数使得各个方向的比值倒过来 vec3 ratio = ( grid + corner - pos ) * inv;//corn+pos的小数部分 vec3 ratio_step = grid_step * inv;//不懂 //于是这个rayspace只是提供一个比值,来决定grid的步进么 // dda <-数值微分法 float hit = -1.0; for ( int i = 0; i < 128; i++ ) { if ( voxel( grid ) > 0.5 ) { hit = 1.0; break; //这里应该是可以直接退出循环的,感觉没什么区别 continue; } vec3 cp = step( ratio, ratio.yzx );//二维情况的搞清楚了,问题还有就是在三维空间上的扩展 mask = cp * ( vec3( 1.0 ) - cp.zxy ); grid += grid_step * mask; ratio += ratio_step * mask; } center = grid + vec3( 0.5 );//中心形式表示(跟grid应该没区别吧0 0) return dot(ratio - ratio_step,vec3(1.0)) * hit;//dot( ratio - ratio_step, mask ) * hit; //这里关心的是hit的深度好像 */ //p1是起点 XMVECTOR start = p1; XMVECTOR dir = n; XMVECTOR zero = XMVectorSetBinaryConstant(0, 0, 0, 0); XMVECTOR one = XMVectorSetBinaryConstant(1, 1, 1, 1); XMVECTOR grid; XMVECTOR grid_step; XMVECTOR grid_corner; grid = XMVectorFloor(start);//实际上w分量为0应该就不影响了吧( //好像DirectXMath没有提供Sign的函数(于是用了一个挺别扭的方法- - //grid_step 就是 sign_dir grid_step = DirectX::XMVectorOrInt(DirectX::XMVectorAndInt(dir, DirectX::XMVectorSplatSignMask()), DirectX::XMVectorSplatOne()); grid_corner = XMVectorClamp(grid_step, zero, one); XMVECTOR inv; XMVECTOR ratio; XMVECTOR ratio_step; inv = XMVectorReciprocal(dir); ratio = XMVectorMultiply(XMVectorSubtract(XMVectorAdd(grid, grid_corner), start), inv); ratio_step = XMVectorMultiply(grid_step, inv); bool hit = false; XMVECTOR cp; XMVECTOR mask; XMVECTOR ratioyzx; XMVECTOR cpzxy; XMFLOAT4 tmp1; XMFLOAT4 tmp2; int i; for (i = 0; i < 128; ++i)//最大深度为128 { XMStoreFloat4(&tmp1, grid); /* __try{ if (map->At(tmp1.x, tmp1.y, tmp1.z).TexType != -1) { hit = true; break; } } __except ((GetExceptionCode() == EXCEPTION_ARRAY_BOUNDS_EXCEEDED)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH) { //捕获越界错误作为跳出条件,看看有没有问题... break; } */ //理论上来说异常的话处理代价太大,还是判断一下range吧= = if ((RangeCheck(tmp1.x, tmp1.y, tmp1.z))) { if (GetLocInfo(tmp1.x, tmp1.y, tmp1.z) != -1) { hit = true; break; } } /* 修正:发生越界的时候并不一定就要终止,需要考虑到从值域外射出的射线..... 不过就算不break效率应该也比原先的算法要高...(除了要限制一下最大遍历深度这方面 */ XMStoreFloat4(&tmp1, ratio); tmp2.x = tmp1.y; tmp2.y = tmp1.z; tmp2.z = tmp1.x; ratioyzx = XMLoadFloat4(&tmp2); cp = XMVectorAndInt(XMVectorGreaterOrEqual(ratioyzx, ratio), XMVectorSplatOne());//1 or 0 XMStoreFloat4(&tmp1, cp); tmp2.x = tmp1.z; tmp2.y = tmp1.x; tmp2.z = tmp1.y; cpzxy = XMLoadFloat4(&tmp2); mask = XMVectorMultiply(cp, XMVectorSubtract(one, cpzxy)); grid += XMVectorMultiply(grid_step, mask); ratio += XMVectorMultiply(ratio_step, mask); } if (hit) { XMFLOAT4 result; result = tmp1; //所在方块 if (i == 0) { //这是在方块内部的情况 result.w = -1; return false; } XMVECTOR ftmp; ftmp = XMVectorSubtract(ratio, ratio_step);//因为取的只是mask方向的值,所以step在这里没必要乘mask *depth = XMVectorGetX(DirectX::XMVector3Dot(ftmp, mask)); ftmp = XMVectorAdd(XMVectorScale(dir,*depth) , p1); XMStoreFloat4(&tmp1, ftmp); //需要全部反过来,因为上面的式子没有取反 *intersectLocation = ftmp; result = tmp1; result.w = 0; XMVECTOR normal; normal = XMVectorMultiply(mask, grid_step); XMStoreFloat4(&tmp1, normal); //需要全部反过来,因为上面的式子没有取反 if (tmp1.x > 0.5) { //法向量为1,0,0,后方 *nResult = XMVectorSetBinaryConstant(1, 0, 0, 0); } else if (tmp1.x < -0.5) { //法向量为-1,0,0,前方 *nResult = XMVectorSetBinaryConstant(-1, 0, 0, 0); } else if (tmp1.y < -0.5) { //法向量为0,-1,0,右方 *nResult = XMVectorSetBinaryConstant(0, -1, 0, 0); } else if (tmp1.y > 0.5) { //法向量为0,1,0,左方 *nResult = XMVectorSetBinaryConstant(0, 1, 0, 0); } else if (tmp1.z < -0.5) { //法向量为0,0,-1,上方 *nResult = XMVectorSetBinaryConstant(0, 0, -1, 0); } else if (tmp1.z > 0.5) { //法向量为0,0,1,下方 *nResult = XMVectorSetBinaryConstant(0, 0, 1, 0); } return true; //return result; } else { return false; } //上面成功的进行了判断,可以得出grid编号了,不过还要算一下相交面( return false; }
_Use_decl_annotations_ __forceinline XMVECTOR __vectorcall FindSupportVectorAndReduce(XMVECTOR simplex[5], FXMVECTOR x, uint32_t* bits) { uint32_t bit = 1; uint32_t i = 0; uint32_t bitCount = 0; XMVECTOR compact[4]; uint32_t compactBits[4] = {}; for (; i < 5; ++i, bit <<= 1) { if (((*bits) & bit) == bit) { compactBits[bitCount] = bit; compact[bitCount++] = simplex[i]; } } XMVECTOR v; switch (bitCount) { case 0: // Error, empty simplex! assert(false); return XMVectorZero(); case 1: // Point v = x - compact[0]; break; case 2: // Segment { XMVECTOR edge = compact[1] - compact[0]; v = XMVector3Cross(edge, XMVector3Cross(x - compact[0], edge)); break; } case 4: // Tetrahedron { // Reduce. For each point, consider the triangle // formed by the other 3. If x & this point are on the same // side, then this point is valid. If x is on opposite side, we // drop this point XMVECTOR others[3]; uint32_t count = 0; for (uint32_t i = 0; i < 4; ++i) { XMVECTOR p = compact[i]; count = 0; for (uint32_t j = 0; j < 4; ++j) { if (i != j) { others[count++] = compact[j]; } } XMVECTOR edge0 = others[1] - others[0]; XMVECTOR edge1 = others[2] - others[0]; XMVECTOR n = XMVector3Cross(edge0, edge1); if (XMVector2LessOrEqual(XMVectorMultiply(XMVector3Dot(n, x - others[0]), XMVector3Dot(n, p - others[0])), XMVectorZero())) { (*bits) &= ~compactBits[i]; for (uint32_t j = i; j < 3; ++j) { compact[j] = compact[j + 1]; } --bitCount; break; } } if (bitCount == 4) { // Couldn't reduce the simplex. Just drop the front most point and rotate simplex[0] = compact[0]; simplex[1] = compact[1]; simplex[2] = compact[2]; *bits = 7; } __fallthrough; } case 3: // Triangle { XMVECTOR edge0 = compact[1] - compact[0]; XMVECTOR edge1 = compact[2] - compact[0]; v = XMVector3Cross(edge0, edge1); if (XMVector2Less(XMVector3Dot(v, x - compact[0]), XMVectorZero())) { v = -v; } break; } default: assert(false); return XMVectorZero(); } v = XMVector3Normalize(v); v *= XMVector3Dot(v, x - compact[0]); return v; }
void Transform::Scale(const XMFLOAT3& scale) { XMStoreFloat3(&this->scale, XMVectorMultiply(XMLoadFloat3(&this->scale), XMLoadFloat3(&scale))); isDirty = true; }
bool CollisionMesh::CheckCollisionsCustom(CollisionMesh &otherMesh) { bool collision = false; std::vector<XMFLOAT3> convexHull; std::vector<VPCNTDesc> vertices = GetVertices(); std::vector<VPCNTDesc> otherVertices = otherMesh.GetVertices(); XMMATRIX otherWorld = otherMesh.GetWorldTransform(); XMMATRIX world = GetWorldTransform(); XMFLOAT3 origin = XMFLOAT3(0.0f, 0.0f, 0.0f); // Create a vector to ease the inversion calculation (we want the opposite direction for the translation vector). XMVECTOR inverse = XMVectorSet(-1.0f, -1.0f, -1.0f, 0.0f); XMVECTOR ourOriginDisplacement = XMVector3Transform(XMVectorSet(origin.x, origin.y, origin.z, 0.0f), world); XMMATRIX ourOriginTransform = XMMatrixTranslationFromVector(XMVectorMultiply(ourOriginDisplacement, inverse)); // This is used for the purposes of moving the normals of the other object back to around (0, 0, 0). XMVECTOR theirOriginDisplacement = XMVector3Transform(XMVectorSet(origin.x, origin.y, origin.z, 0.0f), otherWorld); XMMATRIX theirOriginTransform = XMMatrixTranslationFromVector(XMVectorMultiply(theirOriginDisplacement, inverse)); XMMATRIX ourOriginTranslatedWorld = world * ourOriginTransform; XMMATRIX theirOriginTranslatedWorld = otherWorld * ourOriginTransform; XMMATRIX theirOriginTranslatedWorldNormalAdjustment = theirOriginTransform * otherWorld; // Pre-multiply the model's vertices so as to avoid transforming them during comparison. for (int vertIndex = 0; vertIndex < vertices.size(); vertIndex++) { XMStoreFloat3(&vertices[vertIndex].Position, XMVector3Transform(XMLoadFloat3(&vertices[vertIndex].Position), ourOriginTranslatedWorld)); XMStoreFloat3(&vertices[vertIndex].Normal, XMVector3Transform(XMLoadFloat3(&vertices[vertIndex].Normal), ourOriginTranslatedWorld)); } for (int otherVertIndex = 0; otherVertIndex < otherVertices.size(); otherVertIndex++) { XMStoreFloat3(&otherVertices[otherVertIndex].Position, XMVector3Transform(XMLoadFloat3(&otherVertices[otherVertIndex].Position), theirOriginTranslatedWorld)); XMStoreFloat3(&otherVertices[otherVertIndex].Normal, XMVector3Transform(XMLoadFloat3(&otherVertices[otherVertIndex].Normal), theirOriginTranslatedWorldNormalAdjustment)); } int potentialCollisions = 0; std::vector<XMFLOAT3> positions; // Now that the pre-multiplication is done, time to do our first-case checking: are we inside of it? for (int vertIndex = 0; vertIndex < vertices.size(); vertIndex++) { bool localCollision = true; XMVECTOR ourVertex = XMLoadFloat3(&vertices[vertIndex].Position); XMVECTOR ourNormal = XMLoadFloat3(&vertices[vertIndex].Normal); // For each vertex in our mesh, we'll check to see if it resides inside our other mesh. for (int otherVertIndex = 0; otherVertIndex < otherVertices.size(); otherVertIndex++) { XMVECTOR otherVertex = XMLoadFloat3(&otherVertices[otherVertIndex].Position); XMVECTOR otherNormal = XMLoadFloat3(&otherVertices[otherVertIndex].Normal); XMVECTOR difference = XMVectorSubtract(ourVertex, otherVertex); XMFLOAT3 differenceDotValue, normalDotValue; XMVECTOR diffLength = XMVector3Length(difference); XMVECTOR normLength = XMVector3Length(otherNormal); XMVECTOR magnitude = XMVectorMultiply(diffLength, normLength); XMStoreFloat3(&differenceDotValue, XMVectorDivide(XMVector3Dot(difference, otherNormal), magnitude)); // At this point, we should have the cosine of the angle. float angleInRads = acosf(differenceDotValue.x); float angleInDegs = XMConvertToDegrees(angleInRads); XMStoreFloat3(&normalDotValue, XMVector3Dot(ourNormal, otherNormal)); if (angleInDegs < 90.0f) { localCollision = false; } } if (localCollision) { positions.push_back(vertices[vertIndex].Position); } } if (positions.empty()) { // Time to do our second-case checking: is it inside of us? for (int otherVertIndex = 0; otherVertIndex < otherVertices.size(); otherVertIndex++) { bool localCollision = true; XMVECTOR otherVertex = XMLoadFloat3(&otherVertices[otherVertIndex].Position); XMVECTOR otherNormal = XMVector3Normalize(XMLoadFloat3(&otherVertices[otherVertIndex].Normal)); // For each vertex in our mesh, we'll check to see if it resides inside our other mesh. for (int vertIndex = 0; vertIndex < vertices.size(); vertIndex++) { XMVECTOR ourVertex = XMLoadFloat3(&vertices[vertIndex].Position); XMVECTOR ourNormal = XMVector3Normalize(XMLoadFloat3(&vertices[vertIndex].Normal)); XMVECTOR difference = XMVectorSubtract(otherVertex, ourVertex); XMFLOAT3 differenceDotValue, normalDotValue; XMVECTOR diffLength = XMVector3Length(difference); XMVECTOR normLength = XMVector3Length(ourNormal); XMVECTOR magnitude = XMVectorMultiply(diffLength, normLength); XMStoreFloat3(&differenceDotValue, XMVectorDivide(XMVector3Dot(difference, ourNormal), magnitude)); // At this point, we should have the cosine of the angle. float angleInRads = acosf(differenceDotValue.x); float angleInDegs = XMConvertToDegrees(angleInRads); XMStoreFloat3(&normalDotValue, XMVector3Dot(ourNormal, otherNormal)); if (angleInDegs < 90.0f) { localCollision = false; } } if (localCollision) { positions.push_back(otherVertices[otherVertIndex].Position); } } } if(positions.size()) { mDelegate->CollisionOccurred(otherMesh.mDelegate); otherMesh.mDelegate->CollisionOccurred(mDelegate); } return positions.size(); }