// slow, accessing verticesWithAttributes directly is faster public SpatialVectorDouble[] getVertexPositionsAsVector3Array() { var positionAccessor = verticesWithAttributes.double4PositionAccessor; SpatialVectorDouble[] result = new SpatialVectorDouble[verticesWithAttributes.numberOfVertices]; for (int i = 0; i < verticesWithAttributes.numberOfVertices; i++) { result[i] = new SpatialVectorDouble(new double[] { positionAccessor[i][0], positionAccessor[i][1], positionAccessor[i][2], }); } return(result); }
public bool checkIntersectPosition(SpatialVectorDouble position) { for (int i = 0; i < k / 2; i++) { double dotOfBaseVectorWithPosition = SpatialVectorDouble.dot(baseVectors[i], position); if (min[i] > dotOfBaseVectorWithPosition || max[i] < dotOfBaseVectorWithPosition) { return(false); } } return(true); }
public void command(HersheyInterpreter.EnumCommandType command, float x, float y) { SpatialVectorDouble currentPosition = new SpatialVectorDouble(new double[] { x, y }).componentMultiplication(scale) + center; if (command == HersheyInterpreter.EnumCommandType.MOVE) { lastPosition = currentPosition; return; } lineCommandInterpreter.drawLine((float)lastPosition.x, (float)lastPosition.y, (float)currentPosition.x, (float)currentPosition.y); lastPosition = currentPosition; }
// \param dt the time diference of one simulation step, can be changed at runtime // \param targetDirection should be normalized // \param controller controller of the controlled entity public VehicleAlignToCommand(PhysicsEngine physicsEngine, double dt, SpatialVectorDouble targetDirection, EntityController controller, ulong controlledObjectId, double targetDerivationDistance, Pid.Configuration yawPidConfiguration, Pid.Configuration pitchPidConfiguration) { this.physicsEngine = physicsEngine; this.dt = dt; this.controller = controller; this.targetDirection = targetDirection; this.controlledObjectId = controlledObjectId; this.targetDerivationDistance = targetDerivationDistance; Trace.Assert(physicsEngine.existObjectById(controlledObjectId)); // object must exist hold by the physics engine yawPid = Pid.makeByTargetAndConfiguration(0, yawPidConfiguration); pitchPid = Pid.makeByTargetAndConfiguration(0, pitchPidConfiguration); }
// doesn't add the entity to the entity manager public Entity buildFromTemplate(GameObjectTemplate template, SpatialVectorDouble globalPosition, SpatialVectorDouble globalVelocity) { IList <IComponent> entityComponents = new List <IComponent>(); PhysicsComponent physicsComponent = buildPhysicsComponentOfMainbody(template, globalPosition, globalVelocity); entityComponents.Add(physicsComponent); IList <ColliderComponent> colliderComponents = buildColliderComponents(template); // add physicsComponent with colliders to physics world physicsEngine.physicsAndMeshPairs.Add(new PhysicsComponentAndCollidersPair(physicsComponent, colliderComponents)); // add solids SolidCluster solidCluster = buildSolidCluster(template); if (solidCluster.solids.Count > 0) { solidResponsibility.mapping.physicsObjectIdToSolidCluster[physicsComponent.id] = solidCluster; } // add effects IList <game.responsibilities.Effect> effects = buildEffects(template); if (effects.Count > 0) { effectResponsibility.physicsObjectIdToEffects[physicsComponent.id] = effects; } // add special attributes buildSpecialAttributes(template, entityComponents); // add thrusters and recalculate thruster angular rotation cache buildThrustersAndAddToObjectAndRecalcThrusterRelatedCache(template, physicsComponent); // add rendering mesh buildAndAddRenderingMesh(template, physicsComponent); // misc // PID controller configuration readPidControllerConfiguration(template, physicsComponent.id); return(Entity.make(entityComponents)); }
// helper static SpatialVectorDouble calcImpulse(SpatialVectorDouble relativeVelocity, double mass) { // e = 1/2 * m * v² double velocityMagnitude = relativeVelocity.length; if (velocityMagnitude < double.Epsilon) { return(new SpatialVectorDouble(new double[] { 0, 0, 0 })); } else { return(relativeVelocity.normalized().scale(0.5 * mass * velocityMagnitude * velocityMagnitude)); } }
// recalculates the convex hull based on the convex hull void recalcConvexHull() { boundingVolume.convexHull = new SpatialVectorDouble[boundingVolume.kdop.k]; for (int baseVectorI = 0; baseVectorI < boundingVolume.kdop.baseVectors.Length; baseVectorI++) { SpatialVectorDouble baseVector = boundingVolume.kdop.baseVectors[baseVectorI]; // the plane is the normal and w of the plane is the dot product of the point on the plane and the normal, which is the min/max value of the k-dop // the normal of the plane is the base vector of the k-dop for max and the negative normal for min boundingVolume.convexHull[baseVectorI] = new SpatialVectorDouble(new double[] { -baseVector[0], -baseVector[1], -baseVector[2], boundingVolume.kdop.min[baseVectorI] }); boundingVolume.convexHull[boundingVolume.kdop.k / 2 + baseVectorI] = new SpatialVectorDouble(new double[] { baseVector[0], baseVector[1], baseVector[2], -boundingVolume.kdop.max[baseVectorI] }); } }
public static ClosedLoop generateStandardOutline( float insetWidth, float insetHeight, SpatialVectorDouble size ) { ClosedLoop outline = new ClosedLoop(); outline.points.Add(new SpatialVectorDouble(new double[] { 0.0f, 0.0f })); outline.points.Add(new SpatialVectorDouble(new double[] { size.x, 0.0f })); outline.points.Add(new SpatialVectorDouble(new double[] { size.x, size.y - insetHeight })); outline.points.Add(new SpatialVectorDouble(new double[] { size.x - insetWidth, size.y })); outline.points.Add(new SpatialVectorDouble(new double[] { 0.0f, size.y })); return(outline); }
void moveAllPhysicsComponents(IEnumerable <PhysicsComponent> physicsComponents) { // NOTE PERFORMANCE< can't be parallelized because it is using one RungeKutta acceleration helper object // accesses and operations of it would overlap in parallel execution > foreach (PhysicsComponent iPhysicsComponent in physicsComponents) { // update acceleration for rungeKutta4.acceleration ((Acceleration)rungeKutta4.acceleration).accelerationForCurrentBody = iPhysicsComponent.linearAcceleration; SpatialVectorDouble oldPosition = iPhysicsComponent.position; rungeKutta4.integrate(ref iPhysicsComponent.rungeKutta4State, 0, (float)dt); iPhysicsComponent.updatePosition(iPhysicsComponent.position, oldPosition); } }
private void renderEdge(SpatialVectorDouble vertex0, SpatialVectorDouble vertex1) { Matrix point0 = new Matrix(new double[] { vertex0.x, vertex0.y, vertex0.z, vertex0.w }, 1); Matrix point1 = new Matrix(new double[] { vertex1.x, vertex1.y, vertex1.z, vertex1.w }, 1); Matrix projectedPoint0 = modelViewProjection * point0; Matrix projectedPoint1 = modelViewProjection * point1; Matrix normalizedProjectedPoint0 = SoftwareRendererUtilities.project(projectedPoint0); Matrix normalizedProjectedPoint1 = SoftwareRendererUtilities.project(projectedPoint1); graphics.DrawLine(pen, viewSize / 2 + (int)normalizedProjectedPoint0[0, 0], viewSize / 2 + (int)normalizedProjectedPoint0[1, 0], viewSize / 2 + (int)normalizedProjectedPoint1[0, 0], viewSize / 2 + (int)normalizedProjectedPoint1[1, 0]); }
public static KDop makeAabbKDopByCenterAndRadius(SpatialVectorDouble center, double radius) { Debug.Assert(radius > 0.0); KDop result = new KDop(KDop.BASEVECTORSOFKDOP6, 6, true); result.min[0] = center.x - radius; result.min[1] = center.y - radius; result.min[2] = center.z - radius; result.max[0] = center.x + radius; result.max[1] = center.y + radius; result.max[2] = center.z + radius; return(result); }
public EnumNonPreemptiveTaskState process() { bool objectExists; PhysicsComponent controlledObject = tryGetControlledObject(out objectExists); if (!objectExists) { return(EnumNonPreemptiveTaskState.FINISHEDSUCCESSFUL); // we finished if the object we have to align doesn't exist anymore } SpatialVectorDouble forwardVector = controlledObject.forwardVector, upVector = controlledObject.upVector, sideVector = controlledObject.sideVector; double dotOfUpVectorAndTargetDirection = SpatialVectorDouble.dot(upVector, targetDirection), dotOfSideVectorAndTargetDirection = SpatialVectorDouble.dot(sideVector, targetDirection), dotOfForwardVectorAndTargetDirection = SpatialVectorDouble.dot(forwardVector, targetDirection); //if (processingBegun) { //pitchPid.reset(dotOfUpVectorAndTargetDirection); //yawPid.reset(dotOfSideVectorAndTargetDirection); //} //processingBegun = false; // the dot product results are like our rotation delta of the different axis // now we need to put these into our PID's for the different axis to get the control value(s) double currentPitchDerivative, currentYawDerivative; double pitchControl = pitchPid.step(dotOfUpVectorAndTargetDirection, dt, out currentPitchDerivative); double yawControl = yawPid.step(dotOfSideVectorAndTargetDirection, dt, out currentYawDerivative); // send it to the controller controller.inputPitch = (float)pitchControl; controller.inputYaw = (float)yawControl; // check for termination criterium of this Command if (Math.dist2FromZero(currentPitchDerivative, currentYawDerivative) < targetDerivationDistance) { return(EnumNonPreemptiveTaskState.FINISHEDSUCCESSFUL); } return(EnumNonPreemptiveTaskState.INPROGRESS); }
void calcForcesForRigidBodies() { // TODO PERFORMANCE< parallel for > foreach (PhysicsComponent iPhysicsComponent in physicsAndMeshPairs.Select(v => v.physicsComponent)) { // see https://github.com/PtrMan/SpaceSimCore/blob/master/src/physics/PhysicsEngine.cpp#L87 iPhysicsComponent.eulerAngularAcceleration = new SpatialVectorDouble(new double[] { 0, 0, 0 }); foreach (AttachedForce iterationAttachedForce in iPhysicsComponent.attachedForces) { SpatialVectorDouble localForce = iterationAttachedForce.forceVectorInNewton; applyForceToLinearAndAngularVelocity(iPhysicsComponent, localForce, iterationAttachedForce.objectLocalPosition); } } }
public static KDop calculateKdopFromVerticesAndbaseVectors(IList <SpatialVectorDouble> vertices, SpatialVectorDouble[] baseVectors, bool baseVectorsStartWithAabb) { uint k = (uint)baseVectors.Length * 2; KDop result = new KDop(baseVectors, k, baseVectorsStartWithAabb); foreach (SpatialVectorDouble iterationVertex in vertices) { for (int baseVectorI = 0; baseVectorI < baseVectors.Length; baseVectorI++) { double dotWithIterationVector = SpatialVectorDouble.dot(iterationVertex, baseVectors[baseVectorI]); result.min[baseVectorI] = System.Math.Min(result.min[baseVectorI], dotWithIterationVector); result.max[baseVectorI] = System.Math.Max(result.max[baseVectorI], dotWithIterationVector); } } return(result); }
public void integrate(ref RungeKutta4State state, float t, float dt) { Derivative a, b, c, d, dummy; dummy.dx = new SpatialVectorDouble(new double[] { 0.0, 0.0, 0.0 }); dummy.dv = new SpatialVectorDouble(new double[] { 0.0, 0.0, 0.0 }); a = evaluate(ref state, t, 0.0f, ref dummy); b = evaluate(ref state, t, dt * 0.5f, ref a); c = evaluate(ref state, t, dt * 0.5f, ref b); d = evaluate(ref state, t, dt, ref c); SpatialVectorDouble dxdt = (a.dx + (b.dx + c.dx).scale(2.0f) + d.dx).scale(1.0f / 6.0f); SpatialVectorDouble dvdt = (a.dv + (b.dv + c.dv).scale(2.0f) + d.dv).scale(1.0f / 6.0f); state.x = state.x + dxdt.scale(dt); state.v = state.v + dvdt.scale(dt); }
// useful for acceleration with radiation or a shockwave public static void accelerateByRadialPressure(SpatialVectorDouble energySourcePosition, double energyInJoules, IList <FracturedParticle> particles) { foreach (FracturedParticle iParticle in particles) { SpatialVectorDouble diff = iParticle.relativePosition - energySourcePosition; double distance = diff.length; if (distance > 0.0) { double surfaceAreaOfRadiationSphereAtDistance = Area.ofSphere(distance); double surfaceAreaOfProjectedSphere = ProjectedArea.ofSphere(iParticle.radius); double absorbedEnergyRatio = System.Math.Min(surfaceAreaOfProjectedSphere / surfaceAreaOfRadiationSphereAtDistance, 1.0); double absolvedEnergyInJoules = absorbedEnergyRatio * energyInJoules; iParticle.accelerateByEnergyInJoules(diff.normalized(), absolvedEnergyInJoules); } } }
public static SpatialVectorDouble calcPlaneByFace(MeshWithExplicitFaces.Face face, SpatialVectorDouble[] vertices, int normalSideness = 1) { SpatialVectorDouble p0 = vertices[face.verticesIndices[0]]; SpatialVectorDouble p1 = vertices[face.verticesIndices[1]]; SpatialVectorDouble p2 = vertices[face.verticesIndices[2]]; SpatialVectorDouble diff01 = p1 - p0; SpatialVectorDouble diff02 = p2 - p0; SpatialVectorDouble normal = SpatialVectorDouble.crossProduct(diff01, diff02).normalized(); if (normalSideness == -1) { normal = new SpatialVectorDouble(new double[] { -normal.x, -normal.y, -normal.z }); } double w = -Plane.calcW(p0, normal); return(new SpatialVectorDouble(new double[] { normal.x, normal.y, normal.z, w })); // plane is normal,w }
// tests if a sphere is inside the frustum public EnumFrustumIntersectionResult calcContainsForSphere(FrustumSphere sphere) { for (int i = 0; i < planes.Length; i++) { // find the distance to this plane double distance = SpatialVectorDouble.dot(planes[i].normal, sphere.position) + planes[i].distance; if (distance < -sphere.radius) { return(EnumFrustumIntersectionResult.OUTSIDE); } if (System.Math.Abs(distance) < sphere.radius) { return(EnumFrustumIntersectionResult.INTERSECT); } } return(EnumFrustumIntersectionResult.INSIDE); }
IList <FracturedParticle> fractureSolidWithPositionAndRotation(SpatialVectorDouble objectGlobalPosition, Quaternion objectRotation, SolidCluster.SolidWithPositionAndRotation solidWithPositionAndRotation) { uint roughtlyNumberOfFracturedElements = 64; IList <FracturedParticle> fracturedParticles = SimpleFracturing.fractureSolid(solidWithPositionAndRotation.solid, roughtlyNumberOfFracturedElements); // transform positions from local to global foreach (FracturedParticle iFracturedParticle in fracturedParticles) { Matrix localToGlobalTranslation = MatrixUtilities.calcLocalToGlobalTranslationMatrix(objectGlobalPosition); Matrix localToGlobalRotation = QuaternionUtilities.convToRotationMatrix4(objectRotation); Matrix localToGlobal = (localToGlobalTranslation * localToGlobalRotation) * MatrixUtilities.calcLocalToGlobalRotationAndTranslationMatrix(solidWithPositionAndRotation.localPosition, solidWithPositionAndRotation.localRotation); iFracturedParticle.relativePosition = SpatialVectorUtilities.toVector3(new SpatialVectorDouble(localToGlobal * SpatialVectorUtilities.toVector4(iFracturedParticle.relativePosition).asMatrix)); } return(fracturedParticles); }
// generalized way to rotate in a specific direction public void controlSolve(PhysicsComponent @object, float roll, float pitch, float yaw) { IList <ThrusterResponsibility.ThrusterBinding> thrusterBindings; if (!thrusterResponsibility.physicsObjectIdToThrusters.TryGetValue(@object.id, out thrusterBindings)) { return; } SpatialVectorDouble rotationTargetVector = new SpatialVectorDouble(new double[] { roll, yaw, pitch }); // vulkan coordinate system rotation double maximalAngularAccelerationMagnitude = 0.0; foreach (var iThrusterBinding in thrusterBindings) { maximalAngularAccelerationMagnitude = System.Math.Max(maximalAngularAccelerationMagnitude, iThrusterBinding.additionalInformation.cachedAngularAccelerationOnObject.length); } foreach (var iThrusterBinding in thrusterBindings) { SpatialVectorDouble normalizedAngularAccelerationOnObject; if (iThrusterBinding.additionalInformation.cachedAngularAccelerationOnObject.length < double.Epsilon) { normalizedAngularAccelerationOnObject = new SpatialVectorDouble(new double[] { 0, 0, 0 }); } else { SpatialVectorDouble cachedAngularAccelerationOnObject = iThrusterBinding.additionalInformation.cachedAngularAccelerationOnObject; double normalizedMangitude = cachedAngularAccelerationOnObject.length / maximalAngularAccelerationMagnitude; normalizedAngularAccelerationOnObject = cachedAngularAccelerationOnObject.normalized().scale(normalizedMangitude); } // calculate the relative thrust by the dot product because we want to rotate the best way in the wished rotation acceleration (given by roll, pitch, yaw) double relativeThrust = SpatialVectorDouble.dot(normalizedAngularAccelerationOnObject, rotationTargetVector); relativeThrust = System.Math.Max(relativeThrust, 0); // thruster can only thrust positivly iThrusterBinding.relative += (float)relativeThrust; // now we add to not cancel away the effects of the other thrusters } }
// calculates the gravitational forces and coresponding accelerations public void calcForcesAndAccelerationsForPhysicsComponents(IEnumerable <PhysicsComponent> physicsComponents) { foreach (PhysicsComponent iPhysicsComponent in physicsComponents) { SpatialVectorDouble sumOfForce = new SpatialVectorDouble(new double[] { 0, 0, 0 }); foreach (CelestialObjectWithPosition iCelestialObject in celestialObjects) { SpatialVectorDouble extrapolatedPosition = iPhysicsComponent.rungeKutta4State.x + iPhysicsComponent.rungeKutta4State.v.scale(PhysicsEngine.dt); SpatialVectorDouble difference = iCelestialObject.position - extrapolatedPosition; SpatialVectorDouble direction = difference.normalized(); double distanceSquared = difference.lengthSquared; double forceMagnitude = Orbit.calculateForceBetweenObjectsByDistance(iPhysicsComponent.mass, iCelestialObject.celestialObject.mass, distanceSquared); sumOfForce += direction.scale(forceMagnitude); } SpatialVectorDouble acceleration = sumOfForce.scale(iPhysicsComponent.invMass); iPhysicsComponent.linearAcceleration += acceleration; } }
// inertia tensor can be null for particles which don't rotate internal PhysicsComponent(SpatialVectorDouble position, SpatialVectorDouble velocity, double mass, Matrix?inertiaTensor, ulong id) { Trace.Assert(position.height == 3 && velocity.height == 3); this.privateId = id; this.mass = mass; this.position = position; this.internalLastPosition = position; // TODO< minus last time step velocity ? > this.velocity = velocity; rotation = QuaternionUtilities.makeIdentity(); eulerLocalAngularVelocity = new SpatialVectorDouble(new double[] { 0, 0, 0 }); if (inertiaTensor != null) { Trace.Assert(inertiaTensor.Value.height == 3 && inertiaTensor.Value.width == 3); this.internalInertiaTensor = new ChangeCallbackCalculateInverse(); this.internalInertiaTensor.set(inertiaTensor.Value); } }
public void draw(GuiElementDrawCommandHandle handle, SpatialVectorDouble position) { if (graphics == null) { return; } if (handle.id == 0xdeadf00d) // pseudo special handle to ignore rendering { return; } GuiElementDrawCommand drawCommand = guiElementDrawCommands.drawCommandsById[handle.id]; if (drawCommand.type == GuiElementDrawCommand.EnumType.CLOSEDLOOPGEOMETRY) { Point[] points = new Point[drawCommand.closedLoopGeometry.Count + 1]; for (int i = 0; i < drawCommand.closedLoopGeometry.Count; i++) { // TODO< pull size of screen from context > points[i] = new Point((int)((drawCommand.closedLoopGeometry[i].x + position.x) * 150.0f), (int)((drawCommand.closedLoopGeometry[i].y + position.y) * 150.0f)); } points[points.Length - 1] = new Point((int)((drawCommand.closedLoopGeometry[0].x + position.x) * 150.0f), (int)((drawCommand.closedLoopGeometry[0].y + position.y) * 150.0f)); graphics.DrawLines(new Pen(Brushes.Black), points); } else if (drawCommand.type == GuiElementDrawCommand.EnumType.LINES) { foreach (var iLine in drawCommand.lines) { graphics.DrawLine( new Pen(Brushes.Black), (int)((iLine.a.x + position.x) * 150.0f), (int)((iLine.a.y + position.y) * 150.0f), (int)((iLine.b.x + position.x) * 150.0f), (int)((iLine.b.y + position.y) * 150.0f) ); } } }
public void renderString(string @string, SpatialVectorDouble signScale, SpatialVectorDouble position) { Debug.Assert(lineRendererDriver != null); SpatialVectorDouble currentPosition = position.deepClone(); // TODO< find optimal scale > const float rescalingFactor = 1.0f / 16.0f; lineRendererDriver.scale = signScale.scale(rescalingFactor); // normalize scale with scale of a typical sign int i = 0; foreach (char @char in @string) { lineRendererDriver.center = currentPosition; // continue with next sign if we can't look it up if (!signToHersheyCommandIndex.ContainsKey(@char)) { continue; } int commandIndex = signToHersheyCommandIndex[@char];// (60+30-1) + 3*30; // signToHersheyCommandIndex[@char]; string hersheyCommands = hersheyCommandsOfLetters[commandIndex]; hesheyInterpreter.interpret(hersheyCommands, lineRendererDriver); float widthBeforeRescaling = lineRendererDriver.positionRight - lineRendererDriver.positionLeft; // width is the difference float width = (widthBeforeRescaling * rescalingFactor) * (float)signScale.x; currentPosition.x += width; i++;// for testing } }
public void tick( SpatialVectorDouble mousePosition, MouseStateTracker.EnumMouseButtonState mouseButtonState ) { IEnumerable <GuiElement> elementsWhichOverlapMousePosition = mousePositionChecker.getElementsWhichOverlapTheMousePosition(mousePosition); if (mouseButtonState == MouseStateTracker.EnumMouseButtonState.WASDOWN) { // update selection selectionInteraction.eventMouseReleased(mousePosition); // mousebutton was released, send message to all elements below the current mouse position foreach (GuiElement iElement in elementsWhichOverlapMousePosition) { if (iElement is IReactingToMouse) { ((IReactingToMouse)iElement).reactingToMouse.wasClicked(mousePosition); } } } }
private void renderMesh(TransformedMeshComponent transformedMeshComponent) { foreach (MeshWithExplicitFaces.Face iterationFace in transformedMeshComponent.meshComponent.mesh.faces) { for (int edgeI = 0; edgeI < iterationFace.verticesIndices.Length - 1; edgeI++) { int vertexIndex0 = (int)iterationFace.verticesIndices[edgeI]; int vertexIndex1 = (int)iterationFace.verticesIndices[edgeI + 1]; SpatialVectorDouble vertex0 = translateTo4ComponentVector(transformedMeshComponent.transformedVertices[vertexIndex0]); SpatialVectorDouble vertex1 = translateTo4ComponentVector(transformedMeshComponent.transformedVertices[vertexIndex1]); renderEdge(vertex0, vertex1); } { int vertexIndex0 = (int)iterationFace.verticesIndices[iterationFace.verticesIndices.Length - 1]; int vertexIndex1 = (int)iterationFace.verticesIndices[0]; SpatialVectorDouble vertex0 = translateTo4ComponentVector(transformedMeshComponent.transformedVertices[vertexIndex0]); SpatialVectorDouble vertex1 = translateTo4ComponentVector(transformedMeshComponent.transformedVertices[vertexIndex1]); renderEdge(vertex0, vertex1); } } }
// called from outside when the mouse button was released public void eventMouseReleased(SpatialVectorDouble mousePosition) { IEnumerable <GuiElement> guiElementsUnderMousePositionAsEnumerable = positionChecker.getElementsWhichOverlapTheMousePosition(mousePosition); IList <GuiElement> guiElementsUnderMousePosition = new List <GuiElement>(guiElementsUnderMousePositionAsEnumerable); if (guiElementsUnderMousePosition.Count > 0) { // change the selection // we just take first GuiElement in case of multiple // NOTE< could be a problem if there are multiple elements under the mouse position, we let it this way for now > GuiElement elementUnderMousePosition = guiElementsUnderMousePosition[0]; // delesection trySendDeselectionToElementIfNotSameElement(elementUnderMousePosition); // selection if (!isSameAsAlreadySelectedElement(elementUnderMousePosition)) { changeSelectionTo(elementUnderMousePosition); } } }
static void applyForceToLinearAndAngularVelocity(PhysicsComponent physicsComponent, SpatialVectorDouble localForce, SpatialVectorDouble objectLocalPositionOfForce) { { // linear part // to calculate the linear component we use the dot product double scaleOfLinearForce = 0.0; if (localForce.length > double.Epsilon) { double dotOfForceAndLocalPosition = SpatialVectorDouble.dot(localForce.normalized(), objectLocalPositionOfForce.normalized()); scaleOfLinearForce = System.Math.Abs(dotOfForceAndLocalPosition); } // the linear force (and resulting acceleration) is the force scaled by the dot product Matrix rotationMatrix = physicsComponent.calcLocalToGlobalRotationMatrix(); Matrix globalForceAsMatrix = rotationMatrix * SpatialVectorUtilities.toVector4(localForce).asMatrix; SpatialVectorDouble globalForce = SpatialVectorUtilities.toVector3(new SpatialVectorDouble(globalForceAsMatrix)); physicsComponent.linearAcceleration += globalForce.scale(scaleOfLinearForce * physicsComponent.invMass); } { // angular part physicsComponent.eulerAngularAcceleration += physicsComponent.calcAngularAccelerationOfRigidBodyForAppliedForce(objectLocalPositionOfForce, localForce); } }
static IList <ColliderComponent> buildColliderComponents(GameObjectTemplate template) { IList <ColliderComponent> colliderComponents = new List <ColliderComponent>(); foreach (Collider iCollider in template.colliders) { SpatialVectorDouble colliderComponentSize = new SpatialVectorDouble(iCollider.size); SpatialVectorDouble colliderComponentLocalPosition = new SpatialVectorDouble(iCollider.localPosition); SpatialVectorDouble colliderComponentLocalRotation = new SpatialVectorDouble(iCollider.localRotation); ColliderComponent colliderComponent; if (template.mainMassShapeType == "box") { colliderComponent = ColliderComponent.makeBox(colliderComponentSize, colliderComponentLocalPosition, colliderComponentLocalRotation); } else { throw new Exception("Invalid collider shapeType " + iCollider.shapeType); } colliderComponents.Add(colliderComponent); } return(colliderComponents); }
private Solid(EnumShapeType shapeType, Composition composition, SpatialVectorDouble size) { this.privateShapeType = shapeType; this.size = size; this.composition = composition; }