@Override public void generate( AxionElementGenerationCallback callback, Vector3f position, Matrix4f rotation, String axionParameter) { Vector3f workVector = new Vector3f(); callback.setMainBlock(position, baseBlock); int rangeInt = (int) range; for (int x = -rangeInt; x <= rangeInt; x++) { for (int y = -rangeInt; y <= rangeInt; y++) { for (int z = -rangeInt; z <= Math.min(rangeInt, maxZ); z++) { double distanceSquare = x * x + y * y + z * z; if (distanceSquare < innerRangeSquare) { workVector.set(x, y, z); rotation.transformVector(workVector); workVector.add(position); callback.setAdditionalBlock(workVector, baseBlock); } else if (distanceSquare < rangeSquare) { workVector.set(x, y, z); rotation.transformVector(workVector); workVector.add(position); callback.setAdditionalBlock(workVector, surroundBlock); } } } } callback.advance(advance); }
public void setToExtrapolateState(EntityRef entity, CharacterStateEvent state, long time) { float t = (time - state.getTime()) * 0.0001f; Vector3f newPos = new Vector3f(state.getVelocity()); newPos.scale(t); newPos.add(state.getPosition()); extrapolateLocationComponent(entity, state, newPos); extrapolateCharacterMovementComponent(entity, state); extrapolateCharacterComponent(entity, state); setPhysicsLocation(entity, newPos); }
@ReceiveEvent public void onActivate( ActivateEvent event, EntityRef entity, TunnelActionComponent tunnelActionComponent) { Vector3f dir = new Vector3f(event.getDirection()); dir.scale(4.0f); Vector3f origin = new Vector3f(event.getOrigin()); origin.add(dir); Vector3i blockPos = new Vector3i(); int particleEffects = 0; int blockCounter = tunnelActionComponent.maxDestroyedBlocks; for (int s = 0; s <= tunnelActionComponent.maxTunnelDepth; s++) { origin.add(dir); if (!worldProvider.isBlockRelevant(origin)) { break; } for (int i = 0; i < tunnelActionComponent.maxRaysCast; i++) { Vector3f direction = random.nextVector3f(); Vector3f impulse = new Vector3f(direction); impulse.scale(tunnelActionComponent.explosiveForce); for (int j = 0; j < 3; j++) { Vector3f target = new Vector3f(origin); target.x += direction.x * j; target.y += direction.y * j; target.z += direction.z * j; blockPos.set((int) target.x, (int) target.y, (int) target.z); Block currentBlock = worldProvider.getBlock(blockPos); if (currentBlock.isDestructible()) { if (particleEffects < tunnelActionComponent.maxParticalEffects) { EntityBuilder builder = entityManager.newBuilder("engine:smokeExplosion"); builder.getComponent(LocationComponent.class).setWorldPosition(target); builder.build(); particleEffects++; } if (random.nextFloat() < tunnelActionComponent.thoroughness) { EntityRef blockEntity = blockEntityRegistry.getEntityAt(blockPos); blockEntity.send( new DoDamageEvent( tunnelActionComponent.damageAmount, tunnelActionComponent.damageType)); } blockCounter--; } if (blockCounter <= 0) { return; } } } } // No blocks were destroyed, so cancel the event if (blockCounter == tunnelActionComponent.maxDestroyedBlocks) { event.consume(); } }
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; } boolean horizontalHit = false; Vector3f normalizedDir = Vector3fUtil.safeNormalize(horizMove, new Vector3f()); if (collider == null) { // ignore collision 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); /* Note: this isn't quite correct (after the first iteration the closestHitFraction is only for part of the moment) but probably close enough */ float actualDist = Math.max( 0, (dist + HORIZONTAL_PENETRATION_LEEWAY) * callback.getClosestHitFraction() - HORIZONTAL_PENETRATION_LEEWAY); if (actualDist != 0) { remainingFraction -= actualDist / dist; } if (callback.hasHit()) { if (actualDist > physics.getEpsilon()) { Vector3f actualMove = new Vector3f(normalizedDir); actualMove.scale(actualDist); position.add(actualMove); } dist -= actualDist; Vector3f newDir = new Vector3f(normalizedDir); newDir.scale(dist); float slope = callback.getHitNormalWorld().dot(new Vector3f(0, 1, 0)); // We step up if we're hitting a big slope, or if we're grazing // the ground, otherwise we move up a shallow slope. if (slope < slopeFactor || 1 - slope < physics.getEpsilon()) { boolean stepping = checkStep(collider, position, newDir, callback, slopeFactor, stepHeight); if (!stepping) { horizontalHit = true; Vector3f newHorizDir = new Vector3f(newDir.x, 0, newDir.z); Vector3f horizNormal = new Vector3f(callback.getHitNormalWorld().x, 0, callback.getHitNormalWorld().z); if (horizNormal.lengthSquared() > physics.getEpsilon()) { horizNormal.normalize(); if (lastHitNormal.dot(horizNormal) > physics.getEpsilon()) { break; } lastHitNormal.set(horizNormal); extractResidualMovement(horizNormal, newHorizDir); } newDir.set(newHorizDir); } } else { // Hitting a shallow slope, move up it Vector3f newHorizDir = new Vector3f(newDir.x, 0, newDir.z); extractResidualMovement(callback.getHitNormalWorld(), newDir); Vector3f modHorizDir = new Vector3f(newDir); modHorizDir.y = 0; newDir.scale(newHorizDir.length() / modHorizDir.length()); } float sqrDist = newDir.lengthSquared(); if (sqrDist > physics.getEpsilon()) { newDir.normalize(); if (newDir.dot(normalizedDir) <= 0.0f) { break; } } else { break; } dist = (float) Math.sqrt(sqrDist); normalizedDir.set(newDir); targetPos.set(normalizedDir); targetPos.scale(dist + HORIZONTAL_PENETRATION_LEEWAY); targetPos.add(position); } else { normalizedDir.scale(dist); position.add(normalizedDir); break; } } return horizontalHit; }
private boolean moveDown( float dist, float slopeFactor, CharacterCollider collider, Vector3f position) { if (collider == null) { position.y += dist; return false; } float remainingDist = -dist; Vector3f targetPos = new Vector3f(position); targetPos.y -= remainingDist + VERTICAL_PENETRATION_LEEWAY; Vector3f normalizedDir = new Vector3f(0, -1, 0); boolean hit = false; int iteration = 0; while (remainingDist > physics.getEpsilon() && iteration++ < 10) { SweepCallback callback = collider.sweep(position, targetPos, VERTICAL_PENETRATION, -1.0f); 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); } remainingDist -= actualDist; if (remainingDist < physics.getEpsilon()) { break; } if (callback.hasHit()) { 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; } } else { hit = true; break; } if (expectedMove.y > -physics.getEpsilon()) { hit = true; break; } normalizedDir.set(expectedMove); expectedMove.scale(-remainingDist / expectedMove.y + HORIZONTAL_PENETRATION_LEEWAY); targetPos.set(position); targetPos.add(expectedMove); } else { hit = true; break; } } else { hit = true; break; } } else { break; } } if (iteration >= 10) { hit = true; } return hit; }