//生成一个绕任意轴旋转的矩阵(弧度制) void Matrix44Rotate( matrix44& mat44, float ax, float ay, float az, float angle ) { Matrix44Identity( mat44 ); float sinx = sin( angle ); float cosx = cos( angle ); float cosx2 = 1.0f - cosx; float len = sqrt( ax * ax + ay * ay + az * az ); float x = ax / len; float y = ay / len; float z = az / len; mat44._v1._x = x*x * cosx2 + cosx; mat44._v1._y = x*y * cosx2 + z * sinx; mat44._v1._z = x*z * cosx2 - y * sinx; mat44._v2._x = x*y * cosx2 - z * sinx; mat44._v2._y = y*y * cosx2 + cosx; mat44._v2._z = y*z * cosx2 + x * sinx; mat44._v3._x = x*z * cosx2 + y * sinx; mat44._v3._y = y*z * cosx2 - x * sinx; mat44._v3._z = z*z * cosx2 + cosx; }
//生成一个缩放矩阵 void Matrix44Scale( matrix44& mat44, float xScale, float yScale, float zScale ) { Matrix44Identity( mat44 ); mat44._v1._x = xScale; mat44._v2._y = yScale; mat44._v3._z = zScale; }
//生成一个平移矩阵 void Matrix44Translate( matrix44& mat44, float x, float y, float z ) { Matrix44Identity( mat44 ); mat44._v4._x = x; mat44._v4._y = y; mat44._v4._z = z; }
//生成一个绕Z轴旋转矩阵(弧度制) void Matrix44RotateZ( matrix44& mat44, float angle ) { Matrix44Identity( mat44 ); float sinx= sin( angle ); float cosx= cos( angle ); mat44._v1._x = cosx; mat44._v1._y = sinx; mat44._v2._x = -sinx; mat44._v2._y = cosx; }
//生成一个沿指定轴缩放的矩阵 void Matrix44ScaleAxis( matrix44& mat44, const vertex3& axis, float scale ) { Matrix44Identity( mat44 ); float kone = scale - 1; float xy = axis._x * axis._y; float xz = axis._x * axis._z; float yz = axis._y * axis._z; mat44._v1 = Vertex4( 1 + kone * axis._x*axis._x, kone * xy, kone * xz, 0 ); mat44._v2 = Vertex4( mat44._v1._y, 1 + kone * axis._y*axis._y, kone * yz, 0 ); mat44._v3 = Vertex4( mat44._v1._z, mat44._v2._z, 1 + kone * axis._z*axis._z, 0 ); }
//----------------------------------------------------------------------------- // Проверка столкновений Sphere-Mesh //----------------------------------------------------------------------------- bool vw_SphereMeshCollision(VECTOR3D Object1Location, eObjectBlock *Object1DrawObjectList, float Object1RotationMatrix[9], float Object2Radius, VECTOR3D Object2Location, VECTOR3D Object2PrevLocation, VECTOR3D *CollisionLocation) { // если не передали геометрию - делать тут нечего if (Object1DrawObjectList == 0) return false; // делаем матрицу перемещения точек, для геометрии float TransMat[16]; TransMat[0] = Object1RotationMatrix[0]; TransMat[1] = Object1RotationMatrix[1]; TransMat[2] = Object1RotationMatrix[2]; TransMat[3] = 0.0f; TransMat[4] = Object1RotationMatrix[3]; TransMat[5] = Object1RotationMatrix[4]; TransMat[6] = Object1RotationMatrix[5]; TransMat[7] = 0.0f; TransMat[8] = Object1RotationMatrix[6]; TransMat[9] = Object1RotationMatrix[7]; TransMat[10] = Object1RotationMatrix[8]; TransMat[11] = 0.0f; TransMat[12] = Object1Location.x; TransMat[13] = Object1Location.y; TransMat[14] = Object1Location.z; TransMat[15] = 1.0f; // находим точку локального положения объекта в моделе VECTOR3D LocalLocation(Object1DrawObjectList->Location); Matrix33CalcPoint(&LocalLocation, Object1RotationMatrix); // если нужно - создаем матрицу, иначе - копируем ее if (Object1DrawObjectList->Rotation.x != 0.0f || Object1DrawObjectList->Rotation.y != 0.0f || Object1DrawObjectList->Rotation.z != 0.0f) { float TransMatTMP[16]; Matrix44Identity(TransMatTMP); Matrix44CreateRotate(TransMatTMP, Object1DrawObjectList->Rotation); Matrix44Translate(TransMatTMP, LocalLocation); // и умножаем на основную матрицу, со сведениями по всему объекту Matrix44Mult(TransMat, TransMatTMP); } else { Matrix44Translate(TransMat, LocalLocation); } // проверяем все треугольники объекта for (int i=0; i<Object1DrawObjectList->VertexCount; i+=3) { // находим 3 точки треугольника (с учетом индекс буфера) int j2; if (Object1DrawObjectList->IndexBuffer != 0) j2 = Object1DrawObjectList->IndexBuffer[Object1DrawObjectList->RangeStart+i]*Object1DrawObjectList->VertexStride; else j2 = (Object1DrawObjectList->RangeStart+i)*Object1DrawObjectList->VertexStride; // находим точки триугольника VECTOR3D Point1; Point1.x = Object1DrawObjectList->VertexBuffer[j2]; Point1.y = Object1DrawObjectList->VertexBuffer[j2+1]; Point1.z = Object1DrawObjectList->VertexBuffer[j2+2]; Matrix44CalcPoint(&Point1, TransMat); if (Object1DrawObjectList->IndexBuffer != 0) j2 = Object1DrawObjectList->IndexBuffer[Object1DrawObjectList->RangeStart+i+1]*Object1DrawObjectList->VertexStride; else j2 = (Object1DrawObjectList->RangeStart+i+1)*Object1DrawObjectList->VertexStride; VECTOR3D Point2; Point2.x = Object1DrawObjectList->VertexBuffer[j2]; Point2.y = Object1DrawObjectList->VertexBuffer[j2+1]; Point2.z = Object1DrawObjectList->VertexBuffer[j2+2]; Matrix44CalcPoint(&Point2, TransMat); if (Object1DrawObjectList->IndexBuffer != 0) j2 = Object1DrawObjectList->IndexBuffer[Object1DrawObjectList->RangeStart+i+2]*Object1DrawObjectList->VertexStride; else j2 = (Object1DrawObjectList->RangeStart+i+2)*Object1DrawObjectList->VertexStride; VECTOR3D Point3; Point3.x = Object1DrawObjectList->VertexBuffer[j2]; Point3.y = Object1DrawObjectList->VertexBuffer[j2+1]; Point3.z = Object1DrawObjectList->VertexBuffer[j2+2]; Matrix44CalcPoint(&Point3, TransMat); // находим 2 вектора, образующих плоскость VECTOR3D PlaneVector1 = Point2 - Point1; VECTOR3D PlaneVector2 = Point3 - Point1; // находим нормаль плоскости VECTOR3D NormalVector = PlaneVector1; NormalVector.Multiply(PlaneVector2); NormalVector.Normalize(); // проверка, сферы // - в сфере или нет?, т.е. расстояние от плоскости до центра сферы // - по нормале находим точку на плоскости // - точка принадлежит треугольнику? // находим расстояние от точки до плоскости float Distance = (Object2Location - Point1)*NormalVector; // если точка дальше радиуса - нам тут делать нечего, берем следующую точку if (fabsf(Distance) <= Object2Radius) { // находим реальную точку пересечения с плоскостью VECTOR3D IntercPoint = Object2Location - (NormalVector^Distance); // передаем точку и флаг успешной коллизии if (vw_PointInTriangle(IntercPoint, Point1, Point2, Point3)) { *CollisionLocation = IntercPoint; return true; } } // проверка, сферы // если от точек до текущего положения расстояние меньше float Object2Radius2 = Object2Radius*Object2Radius; // находим расстояние VECTOR3D DistancePoint1 = Object2Location - Point1; float Distance2Point1 = DistancePoint1.x*DistancePoint1.x + DistancePoint1.y*DistancePoint1.y + DistancePoint1.z*DistancePoint1.z; if (Distance2Point1 <= Object2Radius2) { *CollisionLocation = Point1; return true; } // находим расстояние VECTOR3D DistancePoint2 = Object2Location - Point2; float Distance2Point2 = DistancePoint2.x*DistancePoint2.x + DistancePoint2.y*DistancePoint2.y + DistancePoint2.z*DistancePoint2.z; if (Distance2Point2 <= Object2Radius2) { *CollisionLocation = Point2; return true; } // находим расстояние VECTOR3D DistancePoint3 = Object2Location - Point3; float Distance2Point3 = DistancePoint3.x*DistancePoint3.x + DistancePoint3.y*DistancePoint3.y + DistancePoint3.z*DistancePoint3.z; if (Distance2Point3 <= Object2Radius2) { *CollisionLocation = Point3; return true; } // проверка луч, старое положение - новое положение объекта // - пересекает плоскость (обе точки с одной стороны? знак, или ноль) // - точка пересечения плоскости // - принадлежит треугольнику? // проверка, если это фронт-часть, нормально... иначе - берем следующую VECTOR3D vDir1 = Point1 - Object2PrevLocation; float d1 = vDir1*NormalVector; if (d1>0.001f) continue; // находим расстояние от плоскости до точки float originDistance = NormalVector*Point1; // пересечение прямой с плоскостью VECTOR3D vLineDir = Object2Location - Object2PrevLocation; // может и не нужно этого делать... т.к. все и так хорошо работает в нашем случае //vLineDir.Normalize(); float Numerator = - (NormalVector.x * Object2PrevLocation.x + // Use the plane equation with the normal and the line NormalVector.y * Object2PrevLocation.y + NormalVector.z * Object2PrevLocation.z - originDistance); float Denominator = NormalVector*vLineDir; if( Denominator == 0.0) continue; float dist = Numerator / Denominator; // зная расстояние, находим точку пересечения с плоскостью VECTOR3D IntercPoint = Object2PrevLocation + (vLineDir ^ dist); // проверяем, на отрезке или нет (до этого работали с прямой/лучем) if ((Object2PrevLocation-IntercPoint)*(Object2Location-IntercPoint) >= 0.0f) continue; // передаем точку и флаг успешной коллизии if (vw_PointInTriangle(IntercPoint, Point1, Point2, Point3)) { *CollisionLocation = IntercPoint; return true; } } return false; }
void gamerRenderInitAllObjects( tAnimModel const* pAnimModel, tAnimSequence* pAnimSequence, tAnimHierarchy const* pAnimHierarchy ) { const float fStartingPosRadius = 5.0f; Matrix44Identity( &gIdentityMat ); siNumRenderObjects = 1; saRenderObjects = sGameRenderObjectFactory.alloc( siNumRenderObjects ); saAnimModelInstances = sAnimModelInstanceFactory.alloc( siNumRenderObjects ); saObjectInfo = sVectorFactory.alloc( siNumRenderObjects * 3 ); saAnimHierarchies = sAnimHierarchyFactory.alloc( siNumRenderObjects ); memset( saObjectInfo, 0, sizeof( tVector4 ) * siNumRenderObjects * 3 ); float fAnglePart = ( 2.0f * 3.14159f ) / (float)siNumRenderObjects; int iCount = 0; for( int i = 0; i < siNumRenderObjects; i++ ) { // animation model instance tAnimModelInstance* pAnimModelInstance = &saAnimModelInstances[i]; animModelInstanceInit( pAnimModelInstance ); animModelInstanceSet( pAnimModelInstance, pAnimModel ); animModelInstanceSetupGL( pAnimModelInstance ); tGameRenderObject* pRenderObject = &saRenderObjects[i]; pRenderObject->miType = RENDEROBJECT_ANIMMODEL; pRenderObject->mpAnimModelInstance = &saAnimModelInstances[i]; // position, heading and speed pRenderObject->mpPosition = &saObjectInfo[iCount++]; pRenderObject->mpSize = &saObjectInfo[iCount++]; pRenderObject->mpHeading = &saObjectInfo[iCount++]; pRenderObject->mfSpeed = 0.0f; pRenderObject->mpPosition->fW = 1.0f; pRenderObject->mpSize->fW = 1.0f; pRenderObject->mpHeading->fW = 1.0f; // heading tVector4 xVec = { 1.0f, 0.0f, 0.0f, 1.0f }; tMatrix44 rotMatY; Matrix44RotateY( &rotMatY, fAnglePart * (float)i ); Matrix44Transform( pRenderObject->mpHeading, &xVec, &rotMatY ); Vector4Normalize( pRenderObject->mpHeading, pRenderObject->mpHeading ); // position pRenderObject->mpPosition->fX = pRenderObject->mpHeading->fX * fStartingPosRadius - 15.0f; pRenderObject->mpPosition->fZ = pRenderObject->mpHeading->fZ * fStartingPosRadius; pRenderObject->mfAnimMult = 0.5f + (float)( rand() % 500 ) * 0.001f; pRenderObject->mfSpeed = pRenderObject->mfAnimMult; pRenderObject->mfSpeed *= 0.01f; pRenderObject->mpSize->fX = 1.5f; pRenderObject->mpSize->fY = 1.5f; pRenderObject->mpSize->fZ = 1.5f; // duplicate of the hierarchy for storing skin matrices animHierarchyCopy( &saAnimHierarchies[i], pAnimHierarchy, &gJointFactory, &gMatrixFactory ); // use this hierarchy for this model instance pAnimModelInstance->mpAnimHierarchy = &saAnimHierarchies[i]; pAnimModelInstance->mpAnimModel = pAnimModel; pAnimModelInstance->maRotations = (tVector4 *)malloc( sizeof( tVector4 ) ); pAnimModelInstance->maPositions = (tVector4 *)malloc( sizeof( tVector4 ) ); pAnimModelInstance->maScalings = (tVector4 *)malloc( sizeof( tVector4 ) ); pAnimModelInstance->maRotatePivot = (tVector4 *)malloc( sizeof( tVector4 ) ); pAnimModelInstance->maScalePivot = (tVector4 *)malloc( sizeof( tVector4 ) ); //memcpy( pAnimModelInstance->maRotatePivot, &pAnimModel->mCenter, sizeof( tVector4 ) ); //memcpy( pAnimModelInstance->maScalePivot, &pAnimModel->mCenter, sizeof( tVector4 ) ); memset( pAnimModelInstance->maRotatePivot, 0, sizeof( tVector4 ) ); memset( pAnimModelInstance->maScalePivot, 0, sizeof( tVector4 ) ); pAnimModelInstance->miNumXForms = 1; } spAnimSequence = pAnimSequence; }
void gamerRenderUpdateAllObjects( float fTime ) { double fElapsed4 = 0.0f; double fElapsed6 = 0.0f; double fElapsed7 = 0.0f; double fElapsed8 = 0.0f; double fElapsed9 = 0.0f; double fElapsed10 = 0.0f; double fStart, fEnd; double fPartStart, fPartEnd; int iNumJoints = saAnimHierarchies[0].miNumJoints; /*tVector4* aPositions = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints ); tVector4* aScalings = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints ); tQuaternion* aRotations = (tQuaternion *)malloc( sizeof( tQuaternion ) * iNumJoints ); tVector4* aRotationVecs = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints ); tMatrix44* aAnimMatrices = (tMatrix44 *)malloc( sizeof( tMatrix44 ) * iNumJoints ); */ // allocate for all the objects and their joints tVector4** aaPositions = (tVector4 **)malloc( sizeof( tVector4* ) * siNumRenderObjects ); tVector4** aaScalings = (tVector4 **)malloc( sizeof( tVector4* ) * siNumRenderObjects ); tQuaternion** aaRotations = (tQuaternion **)malloc( sizeof( tQuaternion* ) * siNumRenderObjects ); tVector4** aaRotationVecs = (tVector4 **)malloc( sizeof( tVector4* ) * siNumRenderObjects ); tMatrix44** aaAnimMatrices = (tMatrix44 **)malloc( sizeof( tMatrix44* ) * siNumRenderObjects ); for( int i = 0; i < siNumRenderObjects; i++ ) { aaPositions[i] = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints ); aaScalings[i] = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints ); aaRotations[i] = (tQuaternion *)malloc( sizeof( tQuaternion ) * iNumJoints ); aaRotationVecs[i] = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints ); aaAnimMatrices[i] = (tMatrix44 *)malloc( sizeof( tMatrix44 ) * iNumJoints ); for( int j = 0; j < iNumJoints; j++ ) { Matrix44Identity( &aaAnimMatrices[i][j] ); } } /*for( int i = 0; i < iNumJoints; i++ ) { Matrix44Identity( &aAnimMatrices[i] ); }*/ fPartStart = getTime(); #if 0 // update anim model instances' transform for( int i = 0; i < siNumRenderObjects; i++ ) { fStart = getTime(); //animSequencePlay( spAnimSequence, aPositions, aScalings, aRotations, aRotationVecs, aAnimMatrices, sfTime ); tGameRenderObject* pGameRenderObject = &saRenderObjects[i]; tAnimModelInstance* pAnimModelInstance = pGameRenderObject->mpAnimModelInstance; // y rotation angle float fAngle = atan2f( pGameRenderObject->mpHeading->fZ, pGameRenderObject->mpHeading->fX ) - 3.14159f * 0.5f; pAnimModelInstance->mRotation.fY = fAngle; // update position tVector4 dPos; Vector4MultScalar( &dPos, pGameRenderObject->mpHeading, pGameRenderObject->mfSpeed ); tVector4* pPos = pGameRenderObject->mpPosition; tVector4 newPos; Vector4Add( &newPos, pPos, &dPos ); memcpy( pGameRenderObject->mpPosition, &newPos, sizeof( tVector4 ) ); memcpy( &pAnimModelInstance->mPosition, &newPos, sizeof( tVector4 ) ); memcpy( &pAnimModelInstance->mScaling, pGameRenderObject->mpSize, sizeof( tVector4 ) ); fEnd = getTime(); fElapsed0 += ( fEnd - fStart ); } #endif // #if 0 fPartEnd = getTime(); fElapsed7 = fPartEnd - fPartEnd; fPartStart = fPartEnd; tVector4** paPositions = aaPositions; tVector4** paScalings = aaScalings; tVector4** paRotationVecs = aaRotationVecs; tQuaternion** paRotations = aaRotations; tMatrix44** paAnimMatrices = aaAnimMatrices; // update joint in hierarchy matrices for( int i = 0; i < siNumRenderObjects; i++ ) { tJob job; tJointJobData jobData; jobData.mpSequence = spAnimSequence; jobData.mpHierarchy = &saAnimHierarchies[0]; jobData.maPositions = *paPositions; //aPositions; jobData.maScalings = *paScalings; //aScalings; jobData.maRotations = *paRotations; //aRotations; jobData.maRotationVecs = *paRotationVecs; //aRotationVecs; jobData.mfTime = fTime * saRenderObjects[i].mfAnimMult; jobData.maAnimMatrices = *paAnimMatrices; //aAnimMatrices; jobData.mpResultAnimHiearchy = &saAnimHierarchies[i]; job.mpfnFunc = updateJointValuesAndMatrices; job.miDataSize = sizeof( tJointJobData ); job.mpData = &jobData; jobManagerAddJob( gpJobManager, &job ); ++paPositions; ++paScalings; ++paRotations; ++paRotationVecs; ++paAnimMatrices; } // for i = 0 to num render objects jobManagerWait( gpJobManager ); // update all the joint's matrices /*for( int i = 0; i < siNumRenderObjects; i++ ) { fStart = getTime(); animSequenceUpdateJointAnimValues( spAnimSequence, &saAnimHierarchies[0], aaPositions[i], aaScalings[i], aaRotations[i], aaRotationVecs[i], fTime * saRenderObjects[i].mfAnimMult ); jobManagerWait( gpJobManager ); fEnd = getTime(); fElapsed1 += ( fEnd - fStart ); fStart = fEnd; animSequenceUpdateAnimMatrices( spAnimSequence, &saAnimHierarchies[0], aaPositions[i], aaScalings[i], aaRotations[i], aaRotationVecs[i], aaAnimMatrices[i] ); jobManagerWait( gpJobManager ); fElapsed2 += ( fEnd - fStart ); fStart = fEnd; updateJointMatrices( &saAnimHierarchies[i], aaAnimMatrices[i] ); jobManagerWait( gpJobManager ); fElapsed3 += ( fEnd - fStart ); fStart = fEnd; } jobManagerWait( gpJobManager ); */ fPartEnd = getTime(); fElapsed8 = fPartEnd - fPartStart; // update the xform of the total model for( int i = 0; i < siNumRenderObjects; i++ ) { animModelInstanceUpdateXForm( &saAnimModelInstances[i] ); } // transform position and normal fPartStart = getTime(); fStart = getTime(); for( int i = 0; i < siNumRenderObjects; i++ ) { animModelInstanceUpdate( &saAnimModelInstances[i] ); } jobManagerWait( gpJobManager ); fEnd = getTime(); fElapsed4 += ( fEnd - fStart ); fStart = fEnd; fPartEnd = getTime(); fElapsed9 = fPartEnd - fPartStart; WTFASSERT2( fPartEnd >= fPartStart, "WTF" ); fStart = getTime(); // TODO: OPTIMIZE COPY VB DATA for( int i = 0; i < siNumRenderObjects; i++ ) { animModelInstanceCopyVBData( &saAnimModelInstances[i] ); } fEnd = getTime(); fElapsed6 = fEnd - fStart; fPartEnd = getTime(); fElapsed10 = fPartEnd - fPartStart; fPartStart = fPartEnd; #if 0 OUTPUT( "********************\n" ); OUTPUT( "elapsed 0 = %.4f\n", fElapsed0 ); OUTPUT( "elapsed 1 = %.4f\n", fElapsed1 ); OUTPUT( "elapsed 2 = %.4f\n", fElapsed2 ); OUTPUT( "elapsed 3 = %.4f\n", fElapsed3 ); OUTPUT( "elapsed 4 = %.4f\n", fElapsed4 ); OUTPUT( "elapsed 5 = %.4f\n", fElapsed5 ); OUTPUT( "elapsed 6 = %.4f\n", fElapsed6 ); OUTPUT( "elapsed 7 = %.4f\n", fElapsed7 ); OUTPUT( "elapsed 8 = %.4f\n", fElapsed8 ); OUTPUT( "elapsed 9 = %.4f\n", fElapsed9 ); OUTPUT( "elapsed 10 = %.4f\n", fElapsed10 ); OUTPUT( "total elapsed = %.4f\n", fTotalElapsed ); OUTPUT( "********************\n" ); #endif // #if 0 /*free( aPositions ); free( aScalings ); free( aRotations ); free( aRotationVecs ); free( aAnimMatrices );*/ for( int i = 0; i < siNumRenderObjects; i++ ) { free( aaPositions[i] ); free( aaScalings[i] ); free( aaRotations[i] ); free( aaRotationVecs[i] ); free( aaAnimMatrices[i] ); } free( aaPositions ); free( aaScalings ); free( aaRotations ); free( aaRotationVecs ); free( aaAnimMatrices ); }