Example #1
0
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;
}
Example #2
0
// 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;
}
Example #3
0
void Item::UpdatePhysics(float dt)
{
	vec3 acceleration = (m_gravityDirection * 9.81f) * 4.0f;

	// Integrate velocity
	m_velocity += acceleration * dt;

	// Integrate angular velocity and rotation
	vec3 angularAcceleration(0.0f, 0.0f, 0.0f);
	m_angularVelocity += angularAcceleration * dt;
	m_rotation += m_angularVelocity * dt;

	if (m_worldCollide)
	{
		int blockX, blockY, blockZ;
		vec3 blockPos;

		// Check collision
		{
			vec3 velocityToUse = m_velocity;
			vec3 velAmount = velocityToUse*dt;
			vec3 pNormal;
			int numberDivision = 1;
			while (length(velAmount) >= 1.0f)
			{
				numberDivision++;
				velAmount = velocityToUse*(dt / numberDivision);
			}
			for (int i = 0; i < numberDivision; i++)
			{
				float dtToUse = (dt / numberDivision) + ((dt / numberDivision) * i);
				vec3 posToCheck = GetCenter() + velocityToUse*dtToUse;
				bool stepUp = false;
				if (CheckCollisions(posToCheck, m_previousPosition, &pNormal, &velAmount))
				{
					// Reset velocity, we don't have any bounce
					m_velocity = vec3(0.0f, 0.0f, 0.0f);
					velocityToUse = vec3(0.0f, 0.0f, 0.0f);
				}
			}

			// Integrate position
			m_position += velocityToUse * dt;
		}

		// Owning chunks
		if (m_pOwningChunk != NULL && m_pOwningChunk->IsSetup() && m_pOwningChunk->IsInsideChunk(m_position))
		{
			Chunk* pChunk = GetCachedGridChunkOrFromPosition(m_position);
			bool active = m_pChunkManager->GetBlockActiveFrom3DPosition(m_position.x, m_position.y, m_position.z, &blockPos, &blockX, &blockY, &blockZ, &pChunk);

			if (active == true)
			{
				// Roll back the integration, since we will intersect the block otherwise
				m_position -= m_velocity * dt;

				m_velocity = vec3(0.0f, 0.0f, 0.0f);
			}
		}
		else
		{
			if (m_pOwningChunk != NULL)
			{
				m_pOwningChunk->RemoveItem(this);
			}

			m_pOwningChunk = m_pChunkManager->GetChunkFromPosition(m_position.x, m_position.y, m_position.z);

			if (m_pOwningChunk != NULL)
			{
				m_pOwningChunk->AddItem(this);
			}

			if (m_pOwningChunk == NULL)
			{
				m_position -= m_velocity * dt;
				m_velocity = vec3(0.0f, 0.0f, 0.0f);
			}
		}
	}
	else
	{
		// Integrate position
		m_position += m_velocity * dt;
	}

	m_previousPosition = GetCenter();
}