/****************************************************************************** This source file is part of AstroMenace game (Hardcore 3D space shooter with spaceship upgrade possibilities.) For the latest info, see http://www.viewizard.com/ File name: Object3DCollisionMath.cpp Copyright (c) 2006-2007 Michael Kurinnoy, Viewizard All Rights Reserved. File Version: 1.2 ****************************************************************************** AstroMenace game source code available under "dual licensing" model. The licensing options available are: * Commercial Licensing. This is the appropriate option if you are creating proprietary applications and you are not prepared to distribute and share the source code of your application. Contact us for pricing at viewizard@viewizard.com * Open Source Licensing. This is the appropriate option if you want to share the source code of your application with everyone you distribute it to, and you also want to give them the right to share who uses it. You should have received a copy of the GNU General Public License version 3 with this source codes. If not, see . ******************************************************************************/ /// подключаем нужные файлы #include "Object3D.h" //----------------------------------------------------------------------------- // Проверка столкновений Sphere-Mesh //----------------------------------------------------------------------------- bool CheckMeshSphereCollisionDetection(CObject3D *Object1, CObject3D *Object2, VECTOR3D *NewLoc, int *Object1PieceNum) { if (Object1->DrawObjectList == 0) return false; for (int j=0; jDrawObjectQuantity; j++) if (Object1->DrawObjectList[j].VertexCount != 0) { if (Object1->HitBB != 0) { // находим расстояние между HitBB-ми VECTOR3D TmpLocation(Object1->DrawObjectList[j].Location); Matrix33CalcPoint(&TmpLocation, Object1->CurrentRotationMat); float Distance2 = (Object1->Location.x + TmpLocation.x + Object1->HitBBLocation[j].x - Object2->Location.x)*(Object1->Location.x + TmpLocation.x + Object1->HitBBLocation[j].x - Object2->Location.x) + (Object1->Location.y + TmpLocation.y + Object1->HitBBLocation[j].y - Object2->Location.y)*(Object1->Location.y + TmpLocation.y + Object1->HitBBLocation[j].y - Object2->Location.y) + (Object1->Location.z + TmpLocation.z + Object1->HitBBLocation[j].z - Object2->Location.z)*(Object1->Location.z + TmpLocation.z + Object1->HitBBLocation[j].z - Object2->Location.z); // если очень далеко - берем следующий HitBB // но сначала делаем еще одну проверку if (Distance2 > Object1->HitBBRadius2[j] + Object2->Radius*Object2->Radius) { // средняя точка линии VECTOR3D mid = (Object2->Location + Object2->PrevLocation) / 2.0f; // направление линии VECTOR3D dir = Object2->Location - Object2->PrevLocation; // полудлина линии float hl = dir.Length()/2.0f; dir.Normalize(); VECTOR3D T = Object1->Location + TmpLocation + Object1->HitBBLocation[j] - mid; float r; // проверяем, является ли одна из осей X,Y,Z разделяющей if ( (fabs(T.x) > Object1->HitBB[j][0].x + hl*fabs(dir.x)) || (fabs(T.y) > Object1->HitBB[j][0].y + hl*fabs(dir.y)) || (fabs(T.z) > Object1->HitBB[j][0].z + hl*fabs(dir.z)) ) continue; // проверяем X ^ dir r = Object1->HitBB[j][0].y*fabs(dir.z) + Object1->HitBB[j][0].z*fabs(dir.y); if ( fabs(T.y*dir.z - T.z*dir.y) > r ) continue; // проверяем Y ^ dir r = Object1->HitBB[j][0].x*fabs(dir.z) + Object1->HitBB[j][0].z*fabs(dir.x); if ( fabs(T.z*dir.x - T.x*dir.z) > r ) continue; // проверяем Z ^ dir r = Object1->HitBB[j][0].x*fabs(dir.y) + Object1->HitBB[j][0].y*fabs(dir.x); if ( fabs(T.x*dir.y - T.y*dir.x) > r ) continue; } } // дальше работаем с геометрией if(vw_SphereMeshCollision(Object1->Location, &(Object1->DrawObjectList[j]), Object1->CurrentRotationMat, Object2->Radius, Object2->Location, Object2->PrevLocation, NewLoc)) { *Object1PieceNum = j; return true; } } return false; } //----------------------------------------------------------------------------- // Проверка столкновений HitBB-HitBB //----------------------------------------------------------------------------- bool CheckHitBBHitBBCollisionDetection(CObject3D *Object1, CObject3D *Object2, int *Object1PieceNum, int *Object2PieceNum) { // проверяем HitBB, находим номера пересекающихся for (int i=0; iDrawObjectQuantity; i++) if (Object1->DrawObjectList[i].VertexCount != 0) { for (int j=0; jDrawObjectQuantity; j++) if (Object2->DrawObjectList[j].VertexCount != 0) { // находим расстояние между HitBB-ми VECTOR3D TmpLocation1(Object1->DrawObjectList[i].Location); Matrix33CalcPoint(&TmpLocation1, Object1->CurrentRotationMat); VECTOR3D TmpLocation2(Object2->DrawObjectList[j].Location); Matrix33CalcPoint(&TmpLocation2, Object2->CurrentRotationMat); float Distance2 = (Object1->Location.x + TmpLocation1.x + Object1->HitBBLocation[i].x - Object2->Location.x - TmpLocation2.x - Object2->HitBBLocation[j].x)* (Object1->Location.x + TmpLocation1.x + Object1->HitBBLocation[i].x - Object2->Location.x - TmpLocation2.x - Object2->HitBBLocation[j].x) + (Object1->Location.y + TmpLocation1.y + Object1->HitBBLocation[i].y - Object2->Location.y - TmpLocation2.y - Object2->HitBBLocation[j].y)* (Object1->Location.y + TmpLocation1.y + Object1->HitBBLocation[i].y - Object2->Location.y - TmpLocation2.y - Object2->HitBBLocation[j].y) + (Object1->Location.z + TmpLocation1.z + Object1->HitBBLocation[i].z - Object2->Location.z - TmpLocation2.z - Object2->HitBBLocation[j].z)* (Object1->Location.z + TmpLocation1.z + Object1->HitBBLocation[i].z - Object2->Location.z - TmpLocation2.z - Object2->HitBBLocation[j].z); // если очень далеко - берем следующий HitBB if (Distance2 > Object2->HitBBRadius2[j] + Object1->HitBBRadius2[i]) continue; // если достаточно близко - проверяем как OBB // строим матрицу, чтобы развернуть точки float TMPOldInvRotationMat[9]; memcpy(TMPOldInvRotationMat, Object1->CurrentRotationMat, 9*sizeof(float)); Matrix33InverseRotate(TMPOldInvRotationMat); float matB[9]; memcpy(matB, Object2->CurrentRotationMat, 9*sizeof(float)); Matrix33Mult(matB, TMPOldInvRotationMat); VECTOR3D vPosB = (Object2->Location + TmpLocation2 + Object2->HitBBLocation[j]) - (Object1->Location + TmpLocation1 + Object1->HitBBLocation[i]); Matrix33CalcPoint(&vPosB, TMPOldInvRotationMat); VECTOR3D XAxis(matB[0],matB[3],matB[6]); VECTOR3D YAxis(matB[1],matB[4],matB[7]); VECTOR3D ZAxis(matB[2],matB[5],matB[8]); VECTOR3D Obj1_data(Object1->HitBBSize[i].x/2.0f, Object1->HitBBSize[i].y/2.0f, Object1->HitBBSize[i].z/2.0f); VECTOR3D Obj2_data(Object2->HitBBSize[j].x/2.0f, Object2->HitBBSize[j].y/2.0f, Object2->HitBBSize[j].z/2.0f); //делаем 15 проверок, т.к. у нас 15 разделяющих осей //1 (Ra)x if(fabsf(vPosB.x) > Obj1_data.x + Obj2_data.x * fabsf(XAxis.x) + Obj2_data.y * fabsf(XAxis.y) + Obj2_data.z * fabsf(XAxis.z)) continue; //2 (Ra)y if(fabsf(vPosB.y) > Obj1_data.y + Obj2_data.x * fabsf(YAxis.x) + Obj2_data.y * fabsf(YAxis.y) + Obj2_data.z * fabsf(YAxis.z)) continue; //3 (Ra)z if(fabsf(vPosB.z) > Obj1_data.z + Obj2_data.x * fabsf(ZAxis.x) + Obj2_data.y * fabsf(ZAxis.y) + Obj2_data.z * fabsf(ZAxis.z)) continue; //4 (Rb)x if(fabsf(vPosB.x*XAxis.x+vPosB.y*YAxis.x+vPosB.z*ZAxis.x) > (Obj2_data.x+Obj1_data.x*fabsf(XAxis.x) + Obj1_data.y * fabsf(YAxis.x) + Obj1_data.z*fabsf(ZAxis.x))) continue; //5 (Rb)y if(fabsf(vPosB.x*XAxis.y+vPosB.y*YAxis.y+vPosB.z*ZAxis.y) > (Obj2_data.y+Obj1_data.x*fabsf(XAxis.y) + Obj1_data.y * fabsf(YAxis.y) + Obj1_data.z*fabsf(ZAxis.y))) continue; //6 (Rb)z if(fabsf(vPosB.x*XAxis.z+vPosB.y*YAxis.z+vPosB.z*ZAxis.z) > (Obj2_data.z+Obj1_data.x*fabsf(XAxis.z) + Obj1_data.y * fabsf(YAxis.z) + Obj1_data.z*fabsf(ZAxis.z))) continue; //7 (Ra)x X (Rb)x if(fabsf(vPosB.z*YAxis.x-vPosB.y*ZAxis.x) > Obj1_data.y*fabsf(ZAxis.x) + Obj1_data.z*fabsf(YAxis.x) + Obj2_data.y*fabsf(XAxis.z) + Obj2_data.z*fabsf(XAxis.y)) continue; //8 (Ra)x X (Rb)y if(fabsf(vPosB.z*YAxis.y-vPosB.y*ZAxis.y) > Obj1_data.y*fabsf(ZAxis.y) + Obj1_data.z*fabsf(YAxis.y) + Obj2_data.x*fabsf(XAxis.z) + Obj2_data.z*fabsf(XAxis.x)) continue; //9 (Ra)x X (Rb)z if(fabsf(vPosB.z*YAxis.z-vPosB.y*ZAxis.z) > Obj1_data.y*fabsf(ZAxis.z) + Obj1_data.z*fabsf(YAxis.z) + Obj2_data.x*fabsf(XAxis.y) + Obj2_data.y*fabsf(XAxis.x)) continue; //10 (Ra)y X (Rb)x if(fabsf(vPosB.x*ZAxis.x-vPosB.z*XAxis.x) > Obj1_data.x*fabsf(ZAxis.x) + Obj1_data.z*fabsf(XAxis.x) + Obj2_data.y*fabsf(YAxis.z) + Obj2_data.z*fabsf(YAxis.y)) continue; //11 (Ra)y X (Rb)y if(fabsf(vPosB.x*ZAxis.y-vPosB.z*XAxis.y) > Obj1_data.x*fabsf(ZAxis.y) + Obj1_data.z*fabsf(XAxis.y) + Obj2_data.x*fabsf(YAxis.z) + Obj2_data.z*fabsf(YAxis.x)) continue; //12 (Ra)y X (Rb)z if(fabsf(vPosB.x*ZAxis.z-vPosB.z*XAxis.z) > Obj1_data.x*fabsf(ZAxis.z) + Obj1_data.z*fabsf(XAxis.z) + Obj2_data.x*fabsf(YAxis.y) + Obj2_data.y*fabsf(YAxis.x)) continue; //13 (Ra)z X (Rb)x if(fabsf(vPosB.y*XAxis.x-vPosB.x*YAxis.x) > Obj1_data.x*fabsf(YAxis.x) + Obj1_data.y*fabsf(XAxis.x) + Obj2_data.y*fabsf(ZAxis.z) + Obj2_data.z*fabsf(ZAxis.y)) continue; //14 (Ra)z X (Rb)y if(fabsf(vPosB.y*XAxis.y-vPosB.x*YAxis.y) > Obj1_data.x*fabsf(YAxis.y) + Obj1_data.y*fabsf(XAxis.y) + Obj2_data.x*fabsf(ZAxis.z) + Obj2_data.z*fabsf(ZAxis.x)) continue; //15 (Ra)z X (Rb)z if(fabsf(vPosB.y*XAxis.z-vPosB.x*YAxis.z) > Obj1_data.x*fabsf(YAxis.z) + Obj1_data.y*fabsf(XAxis.z) + Obj2_data.x*fabsf(ZAxis.y) + Obj2_data.y*fabsf(ZAxis.x)) continue; // если тут, нашли пересекающиеся! *Object1PieceNum = i; *Object2PieceNum = j; return true; } } return false; } //----------------------------------------------------------------------------- // Проверка столкновений HitBB-OBB //----------------------------------------------------------------------------- bool CheckHitBBOBBCollisionDetection(CObject3D *Object1, CObject3D *Object2, int *Object1PieceNum) { // проверяем HitBB, находим номера пересекающихся for (int i=0; iDrawObjectQuantity; i++) if (Object1->DrawObjectList[i].VertexCount != 0) { // строим матрицу, чтобы развернуть точки float TMPOldInvRotationMat[9]; memcpy(TMPOldInvRotationMat, Object2->CurrentRotationMat, 9*sizeof(float)); Matrix33InverseRotate(TMPOldInvRotationMat); float matB[9]; memcpy(matB, Object1->CurrentRotationMat, 9*sizeof(float)); Matrix33Mult(matB, TMPOldInvRotationMat); VECTOR3D TmpLocation(Object1->DrawObjectList[i].Location); Matrix33CalcPoint(&TmpLocation, Object1->CurrentRotationMat); VECTOR3D vPosB = (Object1->Location + TmpLocation + Object1->HitBBLocation[i])-(Object2->Location + Object2->OBBLocation); Matrix33CalcPoint(&vPosB, TMPOldInvRotationMat); VECTOR3D XAxis(matB[0],matB[3],matB[6]); VECTOR3D YAxis(matB[1],matB[4],matB[7]); VECTOR3D ZAxis(matB[2],matB[5],matB[8]); VECTOR3D Obj2_data(Object1->HitBBSize[i].x/2.0f, Object1->HitBBSize[i].y/2.0f, Object1->HitBBSize[i].z/2.0f); VECTOR3D Obj1_data(Object2->Width/2.0f, Object2->Height/2.0f, Object2->Length/2.0f); //делаем 15 проверок, т.к. у нас 15 разделяющих осей //1 (Ra)x if(fabsf(vPosB.x) > Obj1_data.x + Obj2_data.x * fabsf(XAxis.x) + Obj2_data.y * fabsf(XAxis.y) + Obj2_data.z * fabsf(XAxis.z)) continue; //2 (Ra)y if(fabsf(vPosB.y) > Obj1_data.y + Obj2_data.x * fabsf(YAxis.x) + Obj2_data.y * fabsf(YAxis.y) + Obj2_data.z * fabsf(YAxis.z)) continue; //3 (Ra)z if(fabsf(vPosB.z) > Obj1_data.z + Obj2_data.x * fabsf(ZAxis.x) + Obj2_data.y * fabsf(ZAxis.y) + Obj2_data.z * fabsf(ZAxis.z)) continue; //4 (Rb)x if(fabsf(vPosB.x*XAxis.x+vPosB.y*YAxis.x+vPosB.z*ZAxis.x) > (Obj2_data.x+Obj1_data.x*fabsf(XAxis.x) + Obj1_data.y * fabsf(YAxis.x) + Obj1_data.z*fabsf(ZAxis.x))) continue; //5 (Rb)y if(fabsf(vPosB.x*XAxis.y+vPosB.y*YAxis.y+vPosB.z*ZAxis.y) > (Obj2_data.y+Obj1_data.x*fabsf(XAxis.y) + Obj1_data.y * fabsf(YAxis.y) + Obj1_data.z*fabsf(ZAxis.y))) continue; //6 (Rb)z if(fabsf(vPosB.x*XAxis.z+vPosB.y*YAxis.z+vPosB.z*ZAxis.z) > (Obj2_data.z+Obj1_data.x*fabsf(XAxis.z) + Obj1_data.y * fabsf(YAxis.z) + Obj1_data.z*fabsf(ZAxis.z))) continue; //7 (Ra)x X (Rb)x if(fabsf(vPosB.z*YAxis.x-vPosB.y*ZAxis.x) > Obj1_data.y*fabsf(ZAxis.x) + Obj1_data.z*fabsf(YAxis.x) + Obj2_data.y*fabsf(XAxis.z) + Obj2_data.z*fabsf(XAxis.y)) continue; //8 (Ra)x X (Rb)y if(fabsf(vPosB.z*YAxis.y-vPosB.y*ZAxis.y) > Obj1_data.y*fabsf(ZAxis.y) + Obj1_data.z*fabsf(YAxis.y) + Obj2_data.x*fabsf(XAxis.z) + Obj2_data.z*fabsf(XAxis.x)) continue; //9 (Ra)x X (Rb)z if(fabsf(vPosB.z*YAxis.z-vPosB.y*ZAxis.z) > Obj1_data.y*fabsf(ZAxis.z) + Obj1_data.z*fabsf(YAxis.z) + Obj2_data.x*fabsf(XAxis.y) + Obj2_data.y*fabsf(XAxis.x)) continue; //10 (Ra)y X (Rb)x if(fabsf(vPosB.x*ZAxis.x-vPosB.z*XAxis.x) > Obj1_data.x*fabsf(ZAxis.x) + Obj1_data.z*fabsf(XAxis.x) + Obj2_data.y*fabsf(YAxis.z) + Obj2_data.z*fabsf(YAxis.y)) continue; //11 (Ra)y X (Rb)y if(fabsf(vPosB.x*ZAxis.y-vPosB.z*XAxis.y) > Obj1_data.x*fabsf(ZAxis.y) + Obj1_data.z*fabsf(XAxis.y) + Obj2_data.x*fabsf(YAxis.z) + Obj2_data.z*fabsf(YAxis.x)) continue; //12 (Ra)y X (Rb)z if(fabsf(vPosB.x*ZAxis.z-vPosB.z*XAxis.z) > Obj1_data.x*fabsf(ZAxis.z) + Obj1_data.z*fabsf(XAxis.z) + Obj2_data.x*fabsf(YAxis.y) + Obj2_data.y*fabsf(YAxis.x)) continue; //13 (Ra)z X (Rb)x if(fabsf(vPosB.y*XAxis.x-vPosB.x*YAxis.x) > Obj1_data.x*fabsf(YAxis.x) + Obj1_data.y*fabsf(XAxis.x) + Obj2_data.y*fabsf(ZAxis.z) + Obj2_data.z*fabsf(ZAxis.y)) continue; //14 (Ra)z X (Rb)y if(fabsf(vPosB.y*XAxis.y-vPosB.x*YAxis.y) > Obj1_data.x*fabsf(YAxis.y) + Obj1_data.y*fabsf(XAxis.y) + Obj2_data.x*fabsf(ZAxis.z) + Obj2_data.z*fabsf(ZAxis.x)) continue; //15 (Ra)z X (Rb)z if(fabsf(vPosB.y*XAxis.z-vPosB.x*YAxis.z) > Obj1_data.x*fabsf(YAxis.z) + Obj1_data.y*fabsf(XAxis.z) + Obj2_data.x*fabsf(ZAxis.y) + Obj2_data.y*fabsf(ZAxis.x)) continue; // если тут, нашли пересекающиеся! *Object1PieceNum = i; return true; } return false; } //----------------------------------------------------------------------------- // Проверка столкновений геометрия больших астероидов -HitBB //----------------------------------------------------------------------------- bool CheckHitBBMeshCollisionDetection(CObject3D *Object1, CObject3D *Object2, int *Object1PieceNum) { // делаем матрицу перемещения точки, для геометрии float TransMat[16]; TransMat[0] = Object2->CurrentRotationMat[0]; TransMat[1] = Object2->CurrentRotationMat[1]; TransMat[2] = Object2->CurrentRotationMat[2]; TransMat[3] = 0.0f; TransMat[4] = Object2->CurrentRotationMat[3]; TransMat[5] = Object2->CurrentRotationMat[4]; TransMat[6] = Object2->CurrentRotationMat[5]; TransMat[7] = 0.0f; TransMat[8] = Object2->CurrentRotationMat[6]; TransMat[9] = Object2->CurrentRotationMat[7]; TransMat[10] = Object2->CurrentRotationMat[8]; TransMat[11] = 0.0f; TransMat[12] = Object2->Location.x; TransMat[13] = Object2->Location.y; TransMat[14] = Object2->Location.z; TransMat[15] = 1.0f; // проверяем HitBB, находим номера пересекающихся for (int i=0; iDrawObjectQuantity; i++) if (Object1->DrawObjectList[i].VertexCount != 0) { // параметры HitBB VECTOR3D TMPMax = Object1->HitBB[i][0]; VECTOR3D TMPMin = Object1->HitBB[i][6]; // строим матрицу, чтобы развернуть точки float TMPOldInvRotationMat[9]; memcpy(TMPOldInvRotationMat, Object1->CurrentRotationMat, 9*sizeof(float)); Matrix33InverseRotate(TMPOldInvRotationMat); // перемещаем в общие координаты, теперь это как-бы крайние точки аабб Matrix33CalcPoint(&TMPMax, TMPOldInvRotationMat); Matrix33CalcPoint(&TMPMin, TMPOldInvRotationMat); VECTOR3D TmpLocation1(Object1->DrawObjectList[i].Location); Matrix33CalcPoint(&TmpLocation1, Object1->CurrentRotationMat); VECTOR3D Center = TmpLocation1 + Object1->HitBBLocation[i] + Object1->Location; Matrix33CalcPoint(&Center, TMPOldInvRotationMat); VECTOR3D TMPMax2; VECTOR3D TMPMin2; VECTOR3D Point1; VECTOR3D Point2; VECTOR3D Point3; // проверяем все треугольники объекта for (int j=0; jDrawObjectQuantity; j++) if (Object2->DrawObjectList[j].VertexCount != 0) { // дальше работаем с геометрией // находим точку локального положения объекта в моделе VECTOR3D LocalLocation(Object2->DrawObjectList[j].Location); Matrix33CalcPoint(&LocalLocation, Object2->CurrentRotationMat); // делаем временную матрицу для объекта, т.к. портить основную нельзя float ObjTransMat[16]; memcpy(ObjTransMat, TransMat, 16*sizeof(float)); // если нужно - создаем матрицу, иначе - копируем ее if (Object2->DrawObjectList[j].Rotation.x != 0.0f || Object2->DrawObjectList[j].Rotation.y != 0.0f || Object2->DrawObjectList[j].Rotation.z != 0.0f) { float TransMatTMP[16]; Matrix44Identity(TransMatTMP); Matrix44CreateRotate(TransMatTMP, Object2->DrawObjectList[j].Rotation); Matrix44Translate(TransMatTMP, LocalLocation); // и умножаем на основную матрицу, со сведениями по всему объекту Matrix44Mult(ObjTransMat, TransMatTMP); } else { Matrix44Translate(ObjTransMat, LocalLocation); } for (int k=0; kDrawObjectList[j].VertexCount; k+=3) { int j2; if (Object2->DrawObjectList[j].IndexBuffer != 0) j2 = Object2->DrawObjectList[j].IndexBuffer[Object2->DrawObjectList[j].RangeStart+k]*Object2->DrawObjectList[j].Stride; else j2 = (Object2->DrawObjectList[j].RangeStart+k)*Object2->DrawObjectList[j].Stride; // находим точки триугольника VECTOR3D Point1; Point1.x = Object2->DrawObjectList[j].VertexBuffer[j2]; Point1.y = Object2->DrawObjectList[j].VertexBuffer[j2+1]; Point1.z = Object2->DrawObjectList[j].VertexBuffer[j2+2]; Matrix44CalcPoint(&Point1, ObjTransMat); if (Object2->DrawObjectList[j].IndexBuffer != 0) j2 = Object2->DrawObjectList[j].IndexBuffer[Object2->DrawObjectList[j].RangeStart+k+1]*Object2->DrawObjectList[j].Stride; else j2 = (Object2->DrawObjectList[j].RangeStart+k+1)*Object2->DrawObjectList[j].Stride; VECTOR3D Point2; Point2.x = Object2->DrawObjectList[j].VertexBuffer[j2]; Point2.y = Object2->DrawObjectList[j].VertexBuffer[j2+1]; Point2.z = Object2->DrawObjectList[j].VertexBuffer[j2+2]; Matrix44CalcPoint(&Point2, ObjTransMat); if (Object2->DrawObjectList[j].IndexBuffer != 0) j2 = Object2->DrawObjectList[j].IndexBuffer[Object2->DrawObjectList[j].RangeStart+k+2]*Object2->DrawObjectList[j].Stride; else j2 = (Object2->DrawObjectList[j].RangeStart+k+2)*Object2->DrawObjectList[j].Stride; VECTOR3D Point3; Point3.x = Object2->DrawObjectList[j].VertexBuffer[j2]; Point3.y = Object2->DrawObjectList[j].VertexBuffer[j2+1]; Point3.z = Object2->DrawObjectList[j].VertexBuffer[j2+2]; Matrix44CalcPoint(&Point3, ObjTransMat); // преобразуем все точки в систему первого объекта Matrix33CalcPoint(&Point1, TMPOldInvRotationMat); Matrix33CalcPoint(&Point2, TMPOldInvRotationMat); Matrix33CalcPoint(&Point3, TMPOldInvRotationMat); // сразу ставим номер *Object1PieceNum = i; // сначала проверка по точкам... if (fabsf(Center.x - Point1.x) <= TMPMax.x) if (fabsf(Center.y - Point1.y) <= TMPMax.y) if (fabsf(Center.z - Point1.z) <= TMPMax.z) return true; if (fabsf(Center.x - Point2.x) <= TMPMax.x) if (fabsf(Center.y - Point2.y) <= TMPMax.y) if (fabsf(Center.z - Point2.z) <= TMPMax.z) return true; if (fabsf(Center.x - Point3.x) <= TMPMax.x) if (fabsf(Center.y - Point3.y) <= TMPMax.y) if (fabsf(Center.z - Point3.z) <= TMPMax.z) return true; // делаем боксы, и проверяем по ним // делаем аабб TMPMax2.x = Max3(Point1.x,Point2.x,Point3.x); TMPMin2.x = Min3(Point1.x,Point2.x,Point3.x); TMPMax2.y = Max3(Point1.y,Point2.y,Point3.y); TMPMin2.y = Min3(Point1.y,Point2.y,Point3.y); TMPMax2.z = Max3(Point1.z,Point2.z,Point3.z); TMPMin2.z = Min3(Point1.z,Point2.z,Point3.z); VECTOR3D Center2((TMPMax2.x+TMPMin2.x)/2.0f,(TMPMax2.y+TMPMin2.y)/2.0f,(TMPMax2.z+TMPMin2.z)/2.0f); TMPMax2.x = TMPMax2.x - Center2.x; TMPMax2.y = TMPMax2.y - Center2.y; TMPMax2.z = TMPMax2.z - Center2.z; if (fabsf(Center.x - Center2.x) > TMPMax.x + TMPMax2.x) continue; if (fabsf(Center.y - Center2.y) > TMPMax.y + TMPMax2.y) continue; if (fabsf(Center.z - Center2.z) > TMPMax.z + TMPMax2.z) continue; return true; } } } return false; }