/* ================== ReverseWinding ================== */ winding_t *ReverseWinding( winding_t *w ) { int i; winding_t *neww; if( w->numpoints > MAX_POINTS_ON_WINDING ) Error( "ReverseWinding: %i points", w->numpoints ); neww = AllocWinding( w->numpoints ); neww->numpoints = w->numpoints; for( i = 0; i < w->numpoints; i++ ) // add points backwards VectorCopy( w->points[w->numpoints - 1 - i], neww->points[i] ); #ifdef PARANOID CheckWinding( neww ); #endif return neww; }
/* ================= CreateBrushFaces ================= */ void CreateBrushFaces (void) { int i,j, k; vec_t r; face_t *f, *next; winding_t *w; plane_t clipplane, faceplane; mface_t *mf; vec3_t offset, point; offset[0] = offset[1] = offset[2] = 0; ClearBounds( brush_mins, brush_maxs ); brush_faces = NULL; if (!strncmp(ValueForKey(CurrentEntity, "classname"), "rotate_", 7)) { entity_t *FoundEntity; char *searchstring; char text[20]; searchstring = ValueForKey (CurrentEntity, "target"); FoundEntity = FindTargetEntity(searchstring); if (FoundEntity) GetVectorForKey(FoundEntity, "origin", offset); sprintf(text, "%g %g %g", offset[0], offset[1], offset[2]); SetKeyValue(CurrentEntity, "origin", text); } GetVectorForKey(CurrentEntity, "origin", offset); //printf("%i brushfaces at offset %f %f %f\n", numbrushfaces, offset[0], offset[1], offset[2]); for (i = 0;i < numbrushfaces;i++) { mf = &faces[i]; //printf("plane %f %f %f %f\n", mf->plane.normal[0], mf->plane.normal[1], mf->plane.normal[2], mf->plane.dist); faceplane = mf->plane; w = BaseWindingForPlane (&faceplane); //VectorNegate( faceplane.normal, point ); for (j = 0;j < numbrushfaces && w;j++) { clipplane = faces[j].plane; if( j == i/* || VectorCompare( clipplane.normal, point )*/ ) continue; // flip the plane, because we want to keep the back side VectorNegate(clipplane.normal, clipplane.normal); clipplane.dist *= -1; w = ClipWindingEpsilon (w, &clipplane, ON_EPSILON, true); } if (!w) { //printf("----- skipped plane -----\n"); continue; // overcontrained plane } // this face is a keeper f = AllocFace (); f->winding = w; for (j = 0;j < w->numpoints;j++) { for (k = 0;k < 3;k++) { point[k] = w->points[j][k] - offset[k]; r = Q_rint( point[k] ); if ( fabs( point[k] - r ) < ZERO_EPSILON) w->points[j][k] = r; else w->points[j][k] = point[k]; // check for incomplete brushes if( w->points[j][k] >= BOGUS_RANGE || w->points[j][k] <= -BOGUS_RANGE ) break; } // remove this brush if (k < 3) { FreeFace (f); for (f = brush_faces; f; f = next) { next = f->next; FreeFace (f); } brush_faces = NULL; //printf("----- skipped brush -----\n"); return; } AddPointToBounds( w->points[j], brush_mins, brush_maxs ); } CheckWinding( w ); faceplane.dist -= DotProduct(faceplane.normal, offset); f->texturenum = mf->texinfo; f->planenum = FindPlane (&faceplane, &f->planeside); f->next = brush_faces; brush_faces = f; } // Rotatable objects have to have a bounding box big enough // to account for all its rotations. if (DotProduct(offset, offset)) { vec_t delta; delta = RadiusFromBounds( brush_mins, brush_maxs ); for (k = 0;k < 3;k++) { brush_mins[k] = -delta; brush_maxs[k] = delta; } } //printf("%i : %f %f %f : %f %f %f\n", numbrushfaces, brush_mins[0], brush_mins[1], brush_mins[2], brush_maxs[0], brush_maxs[1], brush_maxs[2]); }
bool CollisionMesh::CheckCollisionsGJK1(CollisionMesh& otherMesh) { std::vector<XMFLOAT3> convexHull; bool foundOrigin = false; std::vector<VPCNTDesc> vertices = GetVertices(); std::vector<VPCNTDesc> otherVertices = otherMesh.GetVertices(); XMMATRIX otherWorld = otherMesh.GetWorldTransform(); XMMATRIX world = GetWorldTransform(); // Pre-multiply the model's vertices so as to avoid transforming them during comparison. for (int vertIndex = 0; vertIndex < vertices.size(); vertIndex++) { XMVECTOR vertexTransform = XMLoadFloat3(&vertices[vertIndex].Position); XMStoreFloat3(&vertices[vertIndex].Position, XMVector3Transform(vertexTransform, world)); } for (int otherVertIndex = 0; otherVertIndex < otherVertices.size(); otherVertIndex++) { XMVECTOR vertexTransform = XMLoadFloat3(&otherVertices[otherVertIndex].Position); XMStoreFloat3(&otherVertices[otherVertIndex].Position, XMVector3Transform(vertexTransform, otherWorld)); } // Now we get to the fun part; the subtraction. for (int vertIndex = 0; vertIndex < vertices.size() && !foundOrigin; vertIndex++) { XMFLOAT3 vertexValue = vertices[vertIndex].Position; XMVECTOR vertexTransform = XMLoadFloat3(&vertexValue); for (int otherVertIndex = 0; otherVertIndex < otherVertices.size() && !foundOrigin; otherVertIndex++) { XMVECTOR otherVertexTransform = XMLoadFloat3(&otherVertices[otherVertIndex].Position); XMFLOAT3 convexHullPoint; XMVECTOR difference = XMVectorSubtract(vertexTransform, otherVertexTransform); XMStoreFloat3(&convexHullPoint, difference); convexHull.push_back(convexHullPoint); foundOrigin = XMVector3Equal(difference, XMVectorZero()); } convexHull.push_back(vertexValue); } if (!foundOrigin) { XMFLOAT3 collisionLine = XMFLOAT3(0.0f, 1250.0f, 500.0f); printf("We ain't found shit!"); bool collision = true; int intersections = 0; for (int hullVertexIndex = 0; hullVertexIndex < convexHull.size() && convexHull.size() > 3; hullVertexIndex += 3) { int secondIndex = (hullVertexIndex + 1) % (convexHull.size() - 1); int thirdIndex = (hullVertexIndex + 2) % (convexHull.size() - 1); XMFLOAT3 firstVert = convexHull[hullVertexIndex]; XMFLOAT3 secondVert = convexHull[secondIndex]; XMFLOAT3 thirdVert = convexHull[thirdIndex]; XMFLOAT3 origin = XMFLOAT3(0.0f, 0.0f, 0.0f); // we need to check the normal. Calculate using cross product. XMVECTOR firstVector = XMVectorSet(secondVert.x - firstVert.x, secondVert.y - firstVert.y, secondVert.z - firstVert.z, 0.0f); XMVECTOR secondVector = XMVectorSet(thirdVert.x - secondVert.x, thirdVert.y - secondVert.y, thirdVert.z - secondVert.z, 0.0f); XMFLOAT3 normal; XMStoreFloat3(&normal, XMVector3Normalize(XMVector3Cross(firstVector, secondVector))); // check to ensure no parallels are detected. float firstDot = (normal.x * collisionLine.x) + (normal.y * collisionLine.y) + (normal.z * collisionLine.z); if (firstDot < 0) { float delta = -((normal.x * (origin.x - firstVert.x)) + (normal.y * (origin.y - firstVert.y)) + (normal.z * (origin.z - firstVert.y))) / firstDot; if (delta < 0) { break; } XMFLOAT3 pointToCheck = XMFLOAT3(origin.x - (collisionLine.x * delta), origin.y - (collisionLine.y * delta), origin.z * (collisionLine.z * delta)); bool firstCheck = CheckWinding(firstVert, secondVert, pointToCheck, normal); bool secondCheck = CheckWinding(secondVert, thirdVert, pointToCheck, normal); bool thirdCheck = CheckWinding(thirdVert, firstVert, pointToCheck, normal); if (firstCheck && secondCheck && thirdCheck) { intersections++; } else { collision = false; } } } if ((intersections % 2) == 1) { foundOrigin = true; } } return foundOrigin; }