private void checkCollision(final ParticlePool pool, final int offset) { final Vector3f vel = new Vector3f(); final Vector3f halfVelDir = new Vector3f(); final Vector3f curr = new Vector3f(); for (int i = offset; i < pool.livingParticles(); i += PHYSICS_SKIP_NR) { int i3 = i * 3; curr.set(pool.position[i3 + 0], pool.position[i3 + 1], pool.position[i3 + 2]); vel.set(pool.velocity[i3 + 0], pool.velocity[i3 + 1], pool.velocity[i3 + 2]); halfVelDir.scale(0).add(vel).normalize().scale(0.5f); curr.sub(halfVelDir); float dist = (vel.length() + 0.5f) * movingAvgDelta * PHYSICS_SKIP_NR * 1.5f; vel.normalize(); HitResult hitResult = physics.rayTrace(curr, vel, dist, StandardCollisionGroup.WORLD); if (hitResult.isHit()) { pool.energy[i] = 0; } } }
@ReceiveEvent public void onItemImpact(ImpactEvent event, EntityRef entity) { RigidBody rigidBody = physics.getRigidBody(entity); if (rigidBody != null) { Vector3f vImpactNormal = new Vector3f(event.getImpactNormal()); Vector3f vImpactPoint = new Vector3f(event.getImpactPoint()); Vector3f vImpactSpeed = new Vector3f(event.getImpactSpeed()); float speedFactor = vImpactSpeed.length(); vImpactNormal.normalize(); vImpactSpeed.normalize(); float dotImpactNormal = vImpactSpeed.dot(vImpactNormal); Vector3f impactResult = vImpactNormal.mul(dotImpactNormal); impactResult = vImpactSpeed.sub(impactResult.mul(2.0f)); impactResult.normalize(); Vector3f vNewLocationVector = (new Vector3f(impactResult)).mul(event.getTravelDistance()); Vector3f vNewPosition = (new Vector3f(vImpactPoint)).add(vNewLocationVector); Vector3f vNewVelocity = (new Vector3f(impactResult)).mul(speedFactor * COLLISION_DAMPENING_MULTIPLIER); rigidBody.setLocation(vNewPosition); rigidBody.setLinearVelocity(vNewVelocity); rigidBody.setAngularVelocity(vNewVelocity); } }
private boolean vectorsAreAboutEqual(Vector3f v1, Vector3f v2) { Vector3f delta = new Vector3f(); delta.add(v1); delta.sub(v2); float epsilon = 0.0001f; float deltaSquared = delta.lengthSquared(); return deltaSquared < epsilon; }
private boolean moveHorizontal(Vector3f horizMove, CharacterCollider collider, Vector3f position, float slopeFactor, float stepHeight) { float remainingFraction = 1.0f; float dist = horizMove.length(); if (dist < physics.getEpsilon()) { return false; Vector3f normalizedDir = Vector3fUtil.safeNormalize(horizMove, new Vector3f()); normalizedDir.scale(dist); position.add(normalizedDir); return false; Vector3f targetPos = new Vector3f(normalizedDir); targetPos.scale(dist + HORIZONTAL_PENETRATION_LEEWAY); targetPos.add(position); int iteration = 0; Vector3f lastHitNormal = new Vector3f(0, 1, 0); while (remainingFraction >= 0.01f && iteration++ < 10) { SweepCallback callback = collider.sweep(position, targetPos, HORIZONTAL_PENETRATION, slopeFactor); Vector3f actualMove = new Vector3f(normalizedDir); actualMove.scale(actualDist); position.add(actualMove); Vector3f newDir = new Vector3f(normalizedDir); newDir.scale(dist); float slope = callback.getHitNormalWorld().dot(new Vector3f(0, 1, 0)); if (!stepping) {
Vector3f targetPos = new Vector3f(position); targetPos.y -= remainingDist + VERTICAL_PENETRATION_LEEWAY; Vector3f normalizedDir = new Vector3f(0, -1, 0); boolean hit = false; int iteration = 0; float actualDist = Math.max(0, (remainingDist + VERTICAL_PENETRATION_LEEWAY) * callback.getClosestHitFraction() - VERTICAL_PENETRATION_LEEWAY); Vector3f expectedMove = new Vector3f(targetPos); expectedMove.sub(position); if (expectedMove.lengthSquared() > physics.getEpsilon()) { expectedMove.normalize(); expectedMove.scale(actualDist); position.add(expectedMove); float originalSlope = callback.getHitNormalWorld().dot(new Vector3f(0, 1, 0)); if (originalSlope < slopeFactor) { float slope = callback.calculateAverageSlope(originalSlope, CHECK_FORWARD_DIST); if (slope < slopeFactor) { remainingDist -= actualDist; expectedMove.set(targetPos); expectedMove.sub(position); extractResidualMovement(callback.getHitNormalWorld(), expectedMove); float sqrDist = expectedMove.lengthSquared(); if (sqrDist > physics.getEpsilon()) { expectedMove.normalize(); if (expectedMove.dot(normalizedDir) <= 0.0f) { hit = true; break;
public static Matrix4f createViewMatrix(Vector3f eye, Vector3f center, Vector3f up) { Matrix4f m = new Matrix4f(); Vector3f f = new Vector3f(); f.sub(center, eye); f.normalize(); up.normalize(); Vector3f s = new Vector3f(); s.cross(f, up); s.normalize(); Vector3f u = new Vector3f(); u.cross(s, f); u.normalize();
private void walk(final CharacterMovementComponent movementComp, final CharacterStateEvent state, CharacterMoveInputEvent input, EntityRef entity) { Vector3f desiredVelocity = new Vector3f(input.getMovementDirection()); float lengthSquared = desiredVelocity.lengthSquared(); desiredVelocity.normalize(); desiredVelocity.scale(movementComp.speedMultiplier); float speed = desiredVelocity.length(); desiredVelocity.y = 0; if (desiredVelocity.x != 0 || desiredVelocity.z != 0) { desiredVelocity.normalize(); desiredVelocity.scale(speed); desiredVelocity.scale(maxSpeed); Vector3f velocityDiff = new Vector3f(desiredVelocity); velocityDiff.sub(state.getVelocity()); velocityDiff.scale(Math.min(movementComp.mode.scaleInertia * input.getDelta(), 1.0f)); Vector3f endVelocity = new Vector3f(state.getVelocity()); endVelocity.x += velocityDiff.x; endVelocity.z += velocityDiff.z; Vector3f moveDelta = new Vector3f(endVelocity); moveDelta.scale(input.getDelta()); CharacterCollider collider = movementComp.mode.useCollision ? physics.getCharacterCollider(entity) : null; MoveResult moveResult = move(state.getPosition(), moveDelta, (state.getMode() != MovementMode.CLIMBING && state.isGrounded() && movementComp.mode.canBeGrounded) ? movementComp.stepHeight : 0,
public AABB transform(Transform transform, float margin) { Vector3f localHalfExtents = new Vector3f(); localHalfExtents.sub(max, min); localHalfExtents.mul(HALVING_FACTOR); localHalfExtents.z += margin; Vector3f localCenter = new Vector3f(max); localCenter.add(min); localCenter.mul(HALVING_FACTOR); absBasis.m22 = Math.abs(absBasis.m22); Vector3f center = new Vector3f(localCenter); absBasis.transform(center); center.add(transform.origin); Vector3f extent = new Vector3f(); extent.x = absBasis.getRow(0).dot(localHalfExtents); extent.y = absBasis.getRow(1).dot(localHalfExtents); extent.z = absBasis.getRow(2).dot(localHalfExtents); Vector3f worldMin = new Vector3f(); worldMin.sub(center, extent); Vector3f worldMax = new Vector3f(center).add(extent);
Vector3f direction = localPlayer.getViewDirection(); Vector3f maxAllowedDistanceInDirection = direction.mul(1.5f); HitResult hitResult = physics.rayTrace(position, direction, 1.5f, StandardCollisionGroup.CHARACTER, StandardCollisionGroup.WORLD); if (hitResult.isHit()) { Vector3f possibleNewPosition = hitResult.getHitPoint(); maxAllowedDistanceInDirection = possibleNewPosition.sub(position); newPosition.add(maxAllowedDistanceInDirection.mul(0.9f)); Vector3f impulseVector = new Vector3f(direction); impulseVector.scale(dropPower); entity.send(new DropItemRequest(selectedItemEntity, entity, impulseVector,
private Vector3f extractResidualMovement(Vector3f hitNormal, Vector3f direction, float normalMag) { float movementLength = direction.length(); if (movementLength > physics.getEpsilon()) { direction.normalize(); Vector3f reflectDir = Vector3fUtil.reflect(direction, hitNormal, new Vector3f()); reflectDir.normalize(); Vector3f perpendicularDir = Vector3fUtil.getPerpendicularComponent(reflectDir, hitNormal, new Vector3f()); if (normalMag != 0.0f) { Vector3f perpComponent = new Vector3f(perpendicularDir); perpComponent.scale(normalMag * movementLength); direction.set(perpComponent); } } return direction; }
Vector3f drive = new Vector3f(); Vector3f dist = new Vector3f(worldPos); dist.sub(localPlayer.getPosition()); double distanceToPlayer = dist.lengthSquared(); ai.movementTarget.set(localPlayer.getPosition()); ai.followingPlayer = true; entity.saveComponent(ai); ai.movementTarget.set(worldPos.x + random.nextFloat(-500.0f, 500.0f), worldPos.y, worldPos.z + random.nextFloat(-500.0f, 500.0f)); ai.lastChangeOfDirectionAt = time.getGameTimeInMs(); ai.followingPlayer = false; Vector3f targetDirection = new Vector3f(); targetDirection.sub(ai.movementTarget, worldPos); targetDirection.normalize(); drive.set(targetDirection); location.getLocalRotation().set(new Vector3f(0, 1, 0), yaw); entity.saveComponent(location);
body.getAngularVelocity(comp.angularVelocity); Vector3f vLocation = Vector3f.zero(); body.getLocation(vLocation); Vector3f vDirection = new Vector3f(comp.velocity); float fDistanceThisFrame = vDirection.length(); vDirection.normalize(); Block hitBlock = worldProvider.getBlock(hitInfo.getBlockPosition()); if (hitBlock != null) { Vector3f vTravelledDistance = vLocation.sub(hitInfo.getHitPoint()); float fTravelledDistance = vTravelledDistance.length(); if (fTravelledDistance > fDistanceThisFrame) { break; if ((aCollisionGroup & bCollidesWith) != 0 || (pair.a.hasComponent(BlockComponent.class) && !pair.b.hasComponent(BlockComponent.class))) { pair.b.send(new CollideEvent(pair.a, pair.pointB, pair.pointA, pair.distance, new Vector3f(pair.normal).invert()));
normals.add(new Vector3f(0, 0, -1)); normals.add(new Vector3f(0, 0, 1)); normals.add(new Vector3f(-1, 0, 0)); normals.add(new Vector3f(1, 0, 0)); normals.add(new Vector3f(0, -1, 0)); normals.add(new Vector3f(0, 1, 0)); Vector3f closestNormal = new Vector3f(); Vector3f diff = new Vector3f(centerPointForNormal(n)); diff.sub(origin); float distance = diff.length();
/** * Creates a new AABB with the given center and extents. * * @param center The center of the AABB. * @param extent The extent of the AABB. * @return The created AABB. */ public static AABB createCenterExtent(Vector3f center, Vector3f extent) { Vector3f min = new Vector3f(center); min.sub(extent); Vector3f max = new Vector3f(center); max.add(extent); return new AABB(min, max); }
private void positionShadowMapCamera() { // We begin by setting our light coordinates at the player coordinates, ignoring the player's altitude Vector3f mainLightPosition = new Vector3f(activeCamera.getPosition().x, 0.0f, activeCamera.getPosition().z); // world-space coordinates // The shadow projected onto the ground must move in in light-space texel-steps, to avoid causing flickering. // That's why we first convert it to the previous frame's light-space coordinates and then back to world-space. shadowMapCamera.getViewProjectionMatrix().transformPoint(mainLightPosition); // to light-space mainLightPosition.set(TeraMath.fastFloor(mainLightPosition.x / texelSize) * texelSize, 0.0f, TeraMath.fastFloor(mainLightPosition.z / texelSize) * texelSize); shadowMapCamera.getInverseViewProjectionMatrix().transformPoint(mainLightPosition); // back to world-space // This is what causes the shadow map to change infrequently, to prevent flickering. // Notice that this is different from what is done above, which is about spatial steps // and is related to the player's position and texels. Vector3f quantizedMainLightDirection = getQuantizedMainLightDirection(STEP_SIZE); // The shadow map camera is placed away from the player, in the direction of the main light. Vector3f offsetFromPlayer = new Vector3f(quantizedMainLightDirection); offsetFromPlayer.scale(256.0f + 64.0f); // these hardcoded numbers are another mystery. mainLightPosition.add(offsetFromPlayer); shadowMapCamera.getPosition().set(mainLightPosition); // Finally, we adjust the shadow map camera to look toward the player Vector3f fromLightToPlayerDirection = new Vector3f(quantizedMainLightDirection); fromLightToPlayerDirection.scale(-1.0f); shadowMapCamera.getViewingDirection().set(fromLightToPlayerDirection); shadowMapCamera.update(worldRenderer.getSecondsSinceLastFrame()); }