// Determines if 3D ray and triangle have a unique intersection. // If true and rpoint is not NULL, returns intersection point. bool Intersects(const Ray3D& ray, const Triangle3D& tri, Point3D *rpoint) { Vector3D n( Vector3D( ( tri[1] - tri[0] ) ^ ( tri[2] - tri[1] ) ).normalized() ); // check if coplanar if ( abs( n * ray.direction ) < epsilon ) return false; // check if ray is facing away from plane if ( ( tri[0] - ray.origin ) * ray.direction < 0.f ) return false; float d = -( n[0] * tri[0][0] + n[1] * tri[0][1] + n[2] * tri[0][2] ); Point3D isect; // if point intersects plane if ( Intersects( Line3D( ray.origin, ray.direction ), Plane3D( n[0], n[1], n[2], d ), &isect ) ) { int count = 0; for ( int i = 0; i < 3; ++i ) { int next = (i == 2) ? 0 : i + 1; float side = (( isect - tri[i] ) ^ ( tri[next] - isect )) * n; count += ( (side < 0.f) ? -1 : 1 ); } // if point is within triangle's boundaries if ( abs( count ) == 3 ) { if ( rpoint ) *rpoint = isect; return true; } } return false; }
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nShowCmd) { INIT short State = 1; DWORD DefaultTime = timeGetTime(); CLSystem LSystem; CTriangle3D Triangle3D(L"Texture.jpg",3.0f); CCube3D Cube3D(L"Texture.jpg",3.0f); CPlane3D Plane3D(L"Grass.jpg",8.0f); LSystem.LoadFile("gfractal.ini"); CMandelbrot Mandelbrot; CMandelbrot3D Mandelbrot3D; Cube3D.Load(); BEGIN if(timeGetTime()-DefaultTime > 100){ if(Input.Keyboard(DIK_F1)&&State!=1&&State!=2){ UnloadAll(); Cube3D.Load(); State = 1; } if(Input.Keyboard(DIK_1)&&State!=1&&State==2){ UnloadAll(); Cube3D.Load(); State = 1; } if(Input.Keyboard(DIK_2)&&State==1&&State!=2){ UnloadAll(); Triangle3D.Load(); State = 2; } if(Input.Keyboard(DIK_F2)&&State!=3){ UnloadAll(); Plane3D.Load(); State = 3; } if(Input.Keyboard(DIK_F3)&&State!=4){ UnloadAll(); LSystem.Load(); State = 4; } if(Input.Keyboard(DIK_F4)&&State!=5){ UnloadAll(); Mandelbrot.Load(); State = 5; } if(Input.Keyboard(DIK_F5)&&State!=6){ UnloadAll(); Mandelbrot3D.Load(); State = 6; } DefaultTime = timeGetTime(); } if(State == 1) Cube3D.Update(); if(State == 2) Triangle3D.Update(); if(State == 3) Plane3D.Update(); if(State == 4) LSystem.Update(); if(State == 5) Mandelbrot.Update(); if(State == 6) Mandelbrot3D.Update(); END }
Plane3D Line3D::toPlane(Point3D &p) { Eigen::VectorXd v; Eigen::Vector4d plane; v = this->v; this->plucker_vector_swap(v); this->plucker_vector2matrix(this->m, v); plane = this->m * p.getPoint(); return Plane3D(plane); }
// Determines if 3D segment and triangle have a unique intersection. // If true and rpoint is not NULL, returns intersection point. bool Intersects(const Segment3D& seg, const Triangle3D& tri, Point3D *rpoint) { Vector3D n = ( tri[1] - tri[0] ) ^ ( tri[2] - tri[1] ); float a = n[0], b = n[1], c = n[2]; float d = -( a * tri[0][0] + b * tri[0][1] + c * tri[0][2] ); if ( !Intersects( seg, Plane3D( a, b, c, d ), rpoint ) ) return false; return tri.contains( *rpoint ); }
void Player::CheckProjectileDamageRadius(Projectile* pProjectile) { if (IsDead()) { return; } if (pProjectile->CanAttackPlayer() == false && pProjectile->IsReturnToPlayer() == false) { return; } vec3 projectileHitboxCenter = GetProjectileHitboxCenter(); vec3 toProjectile = projectileHitboxCenter - pProjectile->GetCenter(); bool hitByProjectile = false; if (m_eProjectileHitboxType == eProjectileHitboxType_Sphere) { if (length(toProjectile) < GetRadius() + pProjectile->GetRadius()) { hitByProjectile = true; } } else if (m_eProjectileHitboxType == eProjectileHitboxType_Cube) { Plane3D planes[6]; Matrix4x4 rotationMatrix; rotationMatrix.SetYRotation(DegToRad(GetRotation())); planes[0] = Plane3D(rotationMatrix * vec3(-1.0f, 0.0f, 0.0f), projectileHitboxCenter + (rotationMatrix * vec3(m_projectileHitboxXLength, 0.0f, 0.0f))); planes[1] = Plane3D(rotationMatrix * vec3(1.0f, 0.0f, 0.0f), projectileHitboxCenter + (rotationMatrix * vec3(-m_projectileHitboxXLength, 0.0f, 0.0f))); planes[2] = Plane3D(rotationMatrix * vec3(0.0f, -1.0f, 0.0f), projectileHitboxCenter + (rotationMatrix * vec3(0.0f, m_projectileHitboxYLength, 0.0f))); planes[3] = Plane3D(rotationMatrix * vec3(0.0f, 1.0f, 0.0f), projectileHitboxCenter + (rotationMatrix * vec3(0.0f, -m_projectileHitboxYLength, 0.0f))); planes[4] = Plane3D(rotationMatrix * vec3(0.0f, 0.0f, -1.0f), projectileHitboxCenter + (rotationMatrix * vec3(0.0f, 0.0f, m_projectileHitboxZLength))); planes[5] = Plane3D(rotationMatrix * vec3(0.0f, 0.0f, 1.0f), projectileHitboxCenter + (rotationMatrix * vec3(0.0f, 0.0f, -m_projectileHitboxZLength))); float distance; int inside = 0; vec3 normal; for (int i = 0; i < 6; i++) { distance = planes[i].GetPointDistance(pProjectile->GetCenter()); if (distance < -pProjectile->GetRadius()) { // Outside... } else if (distance < pProjectile->GetRadius()) { // Intersecting.. inside++; } else { // Inside... inside++; } } if (inside == 6) { hitByProjectile = true; } } if (hitByProjectile) { if (pProjectile->IsReturnToPlayer()) { if (pProjectile->CanCatch()) { pProjectile->PlayerCatch(); m_bCanThrowWeapon = true; if (IsBoomerang()) { m_pVoxelCharacter->SetRenderRightWeapon(true); m_pVoxelCharacter->BlendIntoAnimation(AnimationSections_FullBody, true, AnimationSections_FullBody, "SwordAttack1", 0.01f); m_pVoxelCharacter->BlendIntoAnimation(AnimationSections_Right_Arm_Hand, false, AnimationSections_Right_Arm_Hand, "SwordAttack1", 0.01f); // Start weapon trails if (m_pVoxelCharacter->GetRightWeapon()) { if (m_pVoxelCharacter->IsRightWeaponLoaded()) { m_pVoxelCharacter->GetRightWeapon()->StartWeaponTrails(); } } } } } else { vec3 knockbackDirection = (normalize(pProjectile->GetVelocity())*2.0f) + vec3(0.0f, 1.0f, 0.0f); knockbackDirection = normalize(knockbackDirection); Colour damageColour = Colour(1.0f, 1.0f, 1.0f); float knockbackAmount = 16.0f; DoDamage(15.0f, damageColour, knockbackDirection, knockbackAmount, false); pProjectile->Explode(); } } }
// Collision bool Player::CheckCollisions(vec3 positionCheck, vec3 previousPosition, vec3 *pNormal, vec3 *pMovement, bool *pStepUpBlock) { vec3 movementCache = *pMovement; // World collision bool worldCollision = false; float radius = GetRadius(); int blockX, blockY, blockZ; vec3 blockPos; int blockXAbove, blockYAbove, blockZAbove; vec3 blockPosAbove; int numChecks = 1 + (int)(radius / (Chunk::BLOCK_RENDER_SIZE* 2.0f)); bool canAllStepUp = false; bool firstStepUp = true; for (int x = -numChecks; x <= numChecks; x++) { for (int y = -numChecks; y <= numChecks; y++) { for (int z = -numChecks; z <= numChecks; z++) { bool isStepUp = false; *pNormal = vec3(0.0f, 0.0f, 0.0f); Chunk* pChunk = GetCachedGridChunkOrFromPosition(positionCheck + vec3((Chunk::BLOCK_RENDER_SIZE*2.0f)*x, (Chunk::BLOCK_RENDER_SIZE*2.0f)*y, (Chunk::BLOCK_RENDER_SIZE*2.0f)*z)); bool active = m_pChunkManager->GetBlockActiveFrom3DPosition(positionCheck.x + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*x), positionCheck.y + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*y), positionCheck.z + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*z), &blockPos, &blockX, &blockY, &blockZ, &pChunk); bool activeAbove = false; bool activeAbove2 = false; if (active == false) { if (pChunk == NULL || pChunk->IsSetup() == false) { *pMovement = vec3(0.0f, 0.0f, 0.0f); worldCollision = true; } } else if (active == true) { Plane3D planes[6]; planes[0] = Plane3D(vec3(-1.0f, 0.0f, 0.0f), vec3(Chunk::BLOCK_RENDER_SIZE, 0.0f, 0.0f)); planes[1] = Plane3D(vec3(1.0f, 0.0f, 0.0f), vec3(-Chunk::BLOCK_RENDER_SIZE, 0.0f, 0.0f)); planes[2] = Plane3D(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, Chunk::BLOCK_RENDER_SIZE, 0.0f)); planes[3] = Plane3D(vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, -Chunk::BLOCK_RENDER_SIZE, 0.0f)); planes[4] = Plane3D(vec3(0.0f, 0.0f, -1.0f), vec3(0.0f, 0.0f, Chunk::BLOCK_RENDER_SIZE)); planes[5] = Plane3D(vec3(0.0f, 0.0f, 1.0f), vec3(0.0f, 0.0f, -Chunk::BLOCK_RENDER_SIZE)); float distance; int inside = 0; bool insideCache[6]; for (int i = 0; i < 6; i++) { vec3 pointToCheck = blockPos - previousPosition; distance = planes[i].GetPointDistance(pointToCheck); if (distance < -radius) { // Outside... insideCache[i] = false; } else if (distance < radius) { // Intersecting.. insideCache[i] = true; } else { // Inside... insideCache[i] = true; } } for (int i = 0; i < 6; i++) { vec3 pointToCheck = blockPos - positionCheck; distance = planes[i].GetPointDistance(pointToCheck); if (distance < -radius) { // Outside... } else if (distance < radius) { // Intersecting.. inside++; if (insideCache[i] == false) { *pNormal += planes[i].mNormal; } } else { // Inside... inside++; if (insideCache[i] == false) { *pNormal += planes[i].mNormal; } } } if (inside == 6) { if (y == 0) // We only want to check on the same y-level as the players position. { vec3 posCheck1 = vec3(positionCheck.x + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*x), positionCheck.y + (Chunk::BLOCK_RENDER_SIZE*2.0f), positionCheck.z + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*z)); vec3 posCheck2 = vec3(positionCheck.x + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*x), positionCheck.y + (Chunk::BLOCK_RENDER_SIZE*4.0f), positionCheck.z + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*z)); Chunk* pChunkAbove = GetCachedGridChunkOrFromPosition(vec3(posCheck1.x, posCheck1.y, posCheck1.z)); activeAbove = m_pChunkManager->GetBlockActiveFrom3DPosition(posCheck1.x, posCheck1.y, posCheck1.z, &blockPosAbove, &blockXAbove, &blockYAbove, &blockZAbove, &pChunkAbove); Chunk* pChunkAbove2 = GetCachedGridChunkOrFromPosition(vec3(posCheck2.x, posCheck2.y, posCheck2.z)); activeAbove2 = m_pChunkManager->GetBlockActiveFrom3DPosition(posCheck2.x, posCheck2.y, posCheck2.z, &blockPosAbove, &blockXAbove, &blockYAbove, &blockZAbove, &pChunkAbove2); if ((activeAbove == false) && (activeAbove2 == false)) { if (firstStepUp) { canAllStepUp = true; } isStepUp = true; } else { canAllStepUp = false; } firstStepUp = false; } if (length(*pNormal) <= 1.0f) { if (length(*pNormal) > 0.0f) { *pNormal = normalize(*pNormal); } float dotResult = dot(*pNormal, *pMovement); *pNormal *= dotResult; *pMovement -= *pNormal; worldCollision = true; } } } } } } *pStepUpBlock = canAllStepUp; if (worldCollision) return true; *pMovement = movementCache; return false; }
Plane3D Cone3D::get_base_plane() const { return Plane3D(seg_.get_point(1), seg_.get_point(0)-seg_.get_point(1)); }
bool Item::CheckCollisions(vec3 positionCheck, vec3 previousPosition, vec3 *pNormal, vec3 *pMovement) { float radius = GetRadius(); vec3 movementCache = *pMovement; // World collisions bool worldCollision = false; vec3 floorPosition; if (m_pChunkManager->FindClosestFloor(positionCheck, &floorPosition) == false) { *pMovement = vec3(0.0f, 0.0f, 0.0f); return true; } else { int blockX, blockY, blockZ; vec3 blockPos; int numChecks = 1 + (int)(radius / (Chunk::BLOCK_RENDER_SIZE* 2.0f)); for (int x = -numChecks; x <= numChecks; x++) { for (int y = -numChecks; y <= numChecks; y++) { for (int z = -numChecks; z <= numChecks; z++) { *pNormal = vec3(0.0f, 0.0f, 0.0f); Chunk* pChunk = GetCachedGridChunkOrFromPosition(positionCheck + vec3((Chunk::BLOCK_RENDER_SIZE*2.0f)*x, (Chunk::BLOCK_RENDER_SIZE*2.0f)*y, (Chunk::BLOCK_RENDER_SIZE*2.0f)*z)); bool active = m_pChunkManager->GetBlockActiveFrom3DPosition(positionCheck.x + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*x), positionCheck.y + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*y), positionCheck.z + ((Chunk::BLOCK_RENDER_SIZE*2.0f)*z), &blockPos, &blockX, &blockY, &blockZ, &pChunk); if (active == false) { if (pChunk == NULL || pChunk->IsSetup() == false) { *pMovement = vec3(0.0f, 0.0f, 0.0f); worldCollision = false; } } else if (active == true) { Plane3D planes[6]; planes[0] = Plane3D(vec3(-1.0f, 0.0f, 0.0f), vec3(Chunk::BLOCK_RENDER_SIZE, 0.0f, 0.0f)); planes[1] = Plane3D(vec3(1.0f, 0.0f, 0.0f), vec3(-Chunk::BLOCK_RENDER_SIZE, 0.0f, 0.0f)); planes[2] = Plane3D(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, Chunk::BLOCK_RENDER_SIZE, 0.0f)); planes[3] = Plane3D(vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, -Chunk::BLOCK_RENDER_SIZE, 0.0f)); planes[4] = Plane3D(vec3(0.0f, 0.0f, -1.0f), vec3(0.0f, 0.0f, Chunk::BLOCK_RENDER_SIZE)); planes[5] = Plane3D(vec3(0.0f, 0.0f, 1.0f), vec3(0.0f, 0.0f, -Chunk::BLOCK_RENDER_SIZE)); float distance; int inside = 0; bool insideCache[6]; for (int i = 0; i < 6; i++) { vec3 pointToCheck = blockPos - previousPosition; distance = planes[i].GetPointDistance(pointToCheck); if (distance < -radius) { // Outside... insideCache[i] = false; } else if (distance < radius) { // Intersecting.. insideCache[i] = true; } else { // Inside... insideCache[i] = true; } } for (int i = 0; i < 6; i++) { vec3 pointToCheck = blockPos - positionCheck; distance = planes[i].GetPointDistance(pointToCheck); if (distance < -radius) { // Outside... } else if (distance < radius) { // Intersecting.. inside++; if (insideCache[i] == false) { *pNormal += planes[i].mNormal; } } else { // Inside... inside++; if (insideCache[i] == false) { *pNormal += planes[i].mNormal; } } } if (inside == 6) { if (length(*pNormal) <= 1.0f) { if (length(*pNormal) > 0.0f) { *pNormal = normalize(*pNormal); } float dotResult = dot(*pNormal, *pMovement); *pNormal *= dotResult; *pMovement -= *pNormal; worldCollision = true; } } } } } } } if (worldCollision) return true; *pMovement = movementCache; return false; }