/// <summary> /// CollDetectSphereStaticMeshOverlap /// </summary> /// <param name="oldSphere"></param> /// <param name="newSphere"></param> /// <param name="mesh"></param> /// <param name="info"></param> /// <param name="collTolerance"></param> /// <param name="collisionFunctor"></param> public static void CollDetectSphereStaticMeshOverlap(BoundingSphere oldSphere, BoundingSphere newSphere, TriangleMesh mesh, CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor) { Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero; Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero; float sphereTolR = collTolerance + newSphere.Radius; float sphereTolR2 = sphereTolR * sphereTolR; unsafe { #if USE_STACKALLOC SmallCollPointInfo *collPts = stackalloc SmallCollPointInfo[MaxLocalStackSCPI]; int *potentialTriangles = stackalloc int[MaxLocalStackTris]; { { #else SmallCollPointInfo[] collPtArray = SCPIStackAlloc(); fixed(SmallCollPointInfo *collPts = collPtArray) { int[] potTriArray = IntStackAlloc(); fixed(int *potentialTriangles = potTriArray) { #endif int numCollPts = 0; Vector3 collNormal = Vector3.Zero; BoundingBox bb = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddSphere(newSphere, ref bb); int numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb); // Deano : get the spheres centers in triangle mesh space Vector3 newSphereCen = Vector3.Transform(newSphere.Center, mesh.InverseTransformMatrix); Vector3 oldSphereCen = Vector3.Transform(oldSphere.Center, mesh.InverseTransformMatrix); for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle) { IndexedTriangle meshTriangle = mesh.GetTriangle(potentialTriangles[iTriangle]); float distToCentre = meshTriangle.Plane.DotCoordinate(newSphereCen); // BEN-BUG-FIX: Replaced 0.0f with -sphereTolR. if (distToCentre < -sphereTolR || distToCentre > sphereTolR) { continue; } int i0, i1, i2; meshTriangle.GetVertexIndices(out i0, out i1, out i2); Triangle triangle = new Triangle(mesh.GetVertex(i0), mesh.GetVertex(i1), mesh.GetVertex(i2)); float s, t; float newD2 = Distance.PointTriangleDistanceSq(out s, out t, newSphereCen, triangle); if (newD2 < sphereTolR2) { // have overlap - but actually report the old intersection float oldD2 = Distance.PointTriangleDistanceSq(out s, out t, oldSphereCen, triangle); float dist = (float)System.Math.Sqrt((float)oldD2); float depth = oldSphere.Radius - dist; Vector3 triPointSTNorm = oldSphereCen - triangle.GetPoint(s, t); JiggleMath.NormalizeSafe(ref triPointSTNorm); Vector3 collisionN = (dist > float.Epsilon) ? triPointSTNorm : triangle.Normal; // since impulse get applied at the old position Vector3 pt = oldSphere.Center - oldSphere.Radius * collisionN; if (numCollPts < MaxLocalStackSCPI) { // BEN-OPTIMISATION: Reuse existing collPts. collPts[numCollPts].R0 = pt - body0Pos; collPts[numCollPts].R1 = pt - body1Pos; collPts[numCollPts++].InitialPenetration = depth; } collNormal += collisionN; } } if (numCollPts > 0) { JiggleMath.NormalizeSafe(ref collNormal); collisionFunctor.CollisionNotify(ref info, ref collNormal, collPts, numCollPts); } #if USE_STACKALLOC } } #else FreeStackAlloc(potTriArray); } FreeStackAlloc(collPtArray); } #endif } }
private static Geometry ConvertAssimpMeshToGeometry(Ai.Mesh aiMesh, Ai.Material material, Dictionary <string, NodeInfo> nodeLookup, ref int nextBoneIndex, Dictionary <int, List <int> > nodeToBoneIndices, List <Matrix4x4> boneInverseBindMatrices, ref Matrix4x4 nodeWorldTransform, ref Matrix4x4 nodeInverseWorldTransform, List <Vector3> transformedVertices, SceneConverterOptions options) { if (!aiMesh.HasVertices) { throw new Exception("Assimp mesh has no vertices"); } var geometry = new Geometry(); var geometryTransformedVertices = new Vector3[aiMesh.VertexCount]; geometry.Vertices = aiMesh.Vertices .Select(x => new Vector3(x.X, x.Y, x.Z)) .ToArray(); for (int i = 0; i < geometry.Vertices.Length; i++) { geometryTransformedVertices[i] = Vector3.Transform(geometry.Vertices[i], nodeWorldTransform); } transformedVertices.AddRange(geometryTransformedVertices); if (aiMesh.HasNormals) { geometry.Normals = aiMesh.Normals .Select(x => new Vector3(x.X, x.Y, x.Z)) .ToArray(); } if (aiMesh.HasTextureCoords(0)) { geometry.TexCoordsChannel0 = aiMesh.TextureCoordinateChannels[0] .Select(x => new Vector2(x.X, x.Y)) .ToArray(); } if (aiMesh.HasTextureCoords(1)) { geometry.TexCoordsChannel1 = aiMesh.TextureCoordinateChannels[1] .Select(x => new Vector2(x.X, x.Y)) .ToArray(); } if (aiMesh.HasTextureCoords(2)) { geometry.TexCoordsChannel2 = aiMesh.TextureCoordinateChannels[2] .Select(x => new Vector2(x.X, x.Y)) .ToArray(); } if (aiMesh.HasVertexColors(0)) { geometry.ColorChannel0 = aiMesh.VertexColorChannels[0] .Select(x => ( uint )(( byte )(x.B * 255f) | ( byte )(x.G * 255f) << 8 | ( byte )(x.R * 255f) << 16 | ( byte )(x.A * 255f) << 24)) .ToArray(); } else if (options.GenerateVertexColors) { geometry.ColorChannel0 = new uint[geometry.VertexCount]; for (int i = 0; i < geometry.ColorChannel0.Length; i++) { geometry.ColorChannel0[i] = 0xFFFFFFFF; } } if (aiMesh.HasVertexColors(1)) { geometry.ColorChannel1 = aiMesh.VertexColorChannels[1] .Select(x => ( uint )(( byte )(x.B * 255f) | ( byte )(x.G * 255f) << 8 | ( byte )(x.R * 255f) << 16 | ( byte )(x.A * 255f) << 24)) .ToArray(); } if (aiMesh.HasFaces) { geometry.TriangleIndexType = aiMesh.VertexCount <= ushort.MaxValue ? TriangleIndexType.UInt16 : TriangleIndexType.UInt32; geometry.Triangles = aiMesh.Faces .Select(x => new Triangle(( uint )x.Indices[0], ( uint )x.Indices[1], ( uint )x.Indices[2])) .ToArray(); } if (aiMesh.HasBones) { geometry.VertexWeights = new VertexWeight[geometry.VertexCount]; for (int i = 0; i < geometry.VertexWeights.Length; i++) { geometry.VertexWeights[i].Indices = new byte[4]; geometry.VertexWeights[i].Weights = new float[4]; } var vertexWeightCounts = new int[geometry.VertexCount]; for (var i = 0; i < aiMesh.Bones.Count; i++) { var aiMeshBone = aiMesh.Bones[i]; // Find node index for the bone var boneLookupData = nodeLookup[AssimpConverterCommon.UnescapeName(aiMeshBone.Name)]; int nodeIndex = boneLookupData.Index; // Calculate inverse bind matrix var boneNode = boneLookupData.Node; var bindMatrix = boneNode.WorldTransform * nodeInverseWorldTransform; if (options.ConvertSkinToZUp) { bindMatrix *= YToZUpMatrix; } Matrix4x4.Invert(bindMatrix, out var inverseBindMatrix); // Get bone index int boneIndex; if (!nodeToBoneIndices.TryGetValue(nodeIndex, out var boneIndices)) { // No entry for the node was found, so we add a new one boneIndex = nextBoneIndex++; nodeToBoneIndices.Add(nodeIndex, new List <int>() { boneIndex }); boneInverseBindMatrices.Add(inverseBindMatrix); } else { // Entry for the node was found // Try to find the bone index based on whether the inverse bind matrix matches boneIndex = -1; foreach (int index in boneIndices) { if (boneInverseBindMatrices[index].Equals(inverseBindMatrix)) { boneIndex = index; } } if (boneIndex == -1) { // None matching inverse bind matrix was found, so we add a new entry boneIndex = nextBoneIndex++; nodeToBoneIndices[nodeIndex].Add(boneIndex); boneInverseBindMatrices.Add(inverseBindMatrix); } } foreach (var aiVertexWeight in aiMeshBone.VertexWeights) { int vertexWeightCount = vertexWeightCounts[aiVertexWeight.VertexID]++; geometry.VertexWeights[aiVertexWeight.VertexID].Indices[vertexWeightCount] = ( byte )boneIndex; geometry.VertexWeights[aiVertexWeight.VertexID].Weights[vertexWeightCount] = aiVertexWeight.Weight; } } } geometry.MaterialName = AssimpConverterCommon.UnescapeName(material.Name); geometry.BoundingBox = BoundingBox.Calculate(geometry.Vertices); geometry.BoundingSphere = BoundingSphere.Calculate(geometry.BoundingBox.Value, geometry.Vertices); geometry.Flags |= GeometryFlags.Flag80000000; return(geometry); }
/// <summary> /// Update the camera parameters. /// </summary> protected virtual void UpdateCamera() { // Capture/release mouse when the button is pressed/released if (Input.IsMouseButtonPressed(MouseButton.Right)) { Input.LockMousePosition(); } else if (Input.IsMouseButtonReleased(MouseButton.Right)) { Input.UnlockMousePosition(); } // Update rotation according to mouse deltas var rotationDelta = Vector2.Zero; if (Input.IsMouseButtonDown(MouseButton.Right)) { rotationDelta = Input.MouseDelta; } var doubleTapped = false; foreach (var gestureEvent in Input.GestureEvents) { switch (gestureEvent.Type) { case GestureType.Drag: { var drag = (GestureEventDrag)gestureEvent; rotationDelta = drag.DeltaTranslation; } break; case GestureType.Flick: break; case GestureType.LongPress: break; case GestureType.Composite: break; case GestureType.Tap: { doubleTapped = true; } break; default: throw new ArgumentOutOfRangeException(); } } // Change rotation only if changed at least once (try to keep original one) if (rotationDelta != Vector2.Zero) { applyRotation = true; } // Compute translation speed according to framerate and modifiers var translationSpeed = MoveSpeed * (float)Game.UpdateTime.Elapsed.TotalSeconds; var oldPitch = Pitch; // Take shortest path var deltaPitch = desiredPitch - Pitch; var deltaYaw = (desiredYaw - Yaw) % MathUtil.TwoPi; if (deltaYaw < 0) { deltaYaw += MathUtil.TwoPi; } if (deltaYaw > MathUtil.Pi) { deltaYaw -= MathUtil.TwoPi; } desiredYaw = Yaw + deltaYaw; // Perform orientation transition var rotationAdaptation = (float)Game.UpdateTime.Elapsed.TotalSeconds * RotationAdaptationSpeed; Yaw = Math.Abs(deltaYaw) < rotationAdaptation ? desiredYaw : Yaw + rotationAdaptation * Math.Sign(deltaYaw); Pitch = Math.Abs(deltaPitch) < rotationAdaptation ? desiredPitch : Pitch + rotationAdaptation * Math.Sign(deltaPitch); desiredYaw = Yaw -= 1.333f * rotationDelta.X * RotationSpeed; // we want to rotate faster Horizontally and Vertically desiredPitch = Pitch = MathUtil.Clamp(Pitch - rotationDelta.Y * RotationSpeed, -MathUtil.PiOverTwo, MathUtil.PiOverTwo); if (!RotationOnly) { // Compute base vectors for camera movement var rotation = Matrix.RotationYawPitchRoll(Yaw, Pitch, 0); var forward = Vector3.TransformNormal(ForwardVector, rotation); var up = Vector3.TransformNormal(UpVector, rotation); var right = Vector3.Cross(forward, up); // Update camera move: Dolly (WADS model/arrow keys) var movePosition = Vector3.Zero; if (Input.IsKeyDown(Keys.A) || Input.IsKeyDown(Keys.Left)) { movePosition += -right; } if (Input.IsKeyDown(Keys.D) || Input.IsKeyDown(Keys.Right)) { movePosition += right; } if (Input.IsKeyDown(Keys.S) || Input.IsKeyDown(Keys.Down)) { movePosition += Component.Projection == CameraProjectionMode.Perspective ? -forward : -up; } if (Input.IsKeyDown(Keys.W) || Input.IsKeyDown(Keys.Up) || doubleTapped) { movePosition += Component.Projection == CameraProjectionMode.Perspective ? forward : up; } if (Input.IsKeyDown(Keys.Q)) { movePosition += Component.Projection == CameraProjectionMode.Perspective ? -up : -forward; } if (Input.IsKeyDown(Keys.E)) { movePosition += Component.Projection == CameraProjectionMode.Perspective ? up : forward; } position += (Vector3.Normalize(movePosition) * translationSpeed); if (doubleTapped) { desiredPitch = Pitch = oldPitch; desiredYaw = Yaw; forward = -Vector3.Transform(ForwardVector, Quaternion.RotationYawPitchRoll(Yaw, Pitch, 0)); var projectedForward = Vector3.Normalize(new Vector3(forward.X, 0, forward.Z)); position -= projectedForward * translationSpeed * MouseMoveSpeedFactor; } } // Update the camera view matrix UpdateViewMatrix(); }
/// <summary> /// CollDetectSphereStaticMeshSweep /// </summary> /// <param name="oldSphere"></param> /// <param name="newSphere"></param> /// <param name="mesh"></param> /// <param name="info"></param> /// <param name="collTolerance"></param> /// <param name="collisionFunctor"></param> internal static void CollDetectSphereStaticMeshSweep(BoundingSphere oldSphere, BoundingSphere newSphere, TriangleMesh mesh, CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor) { // really use a swept test - or overlap? Vector3 delta = newSphere.Center - oldSphere.Center; if (delta.LengthSquared < (0.25f * newSphere.Radius * newSphere.Radius)) { CollDetectSphereStaticMeshOverlap(oldSphere, newSphere, mesh, info, collTolerance, collisionFunctor); } else { Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero; Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero; float sphereTolR = collTolerance + oldSphere.Radius; float sphereToR2 = sphereTolR * sphereTolR; Vector3 collNormal = Vector3.Zero; BoundingBox bb = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddSphere(oldSphere, ref bb); BoundingBoxHelper.AddSphere(newSphere, ref bb); // get the spheres centers in triangle mesh space Vector3 newSphereCen = Vector3.Transform(newSphere.Center, mesh.InverseTransformMatrix); Vector3 oldSphereCen = Vector3.Transform(oldSphere.Center, mesh.InverseTransformMatrix); unsafe { #if USE_STACKALLOC SmallCollPointInfo *collPts = stackalloc SmallCollPointInfo[MaxLocalStackSCPI]; int *potentialTriangles = stackalloc int[MaxLocalStackTris]; { { #else SmallCollPointInfo[] collPtArray = SCPIStackAlloc(); fixed(SmallCollPointInfo *collPts = collPtArray) { int[] potTriArray = IntStackAlloc(); fixed(int *potentialTriangles = potTriArray) { #endif int numCollPts = 0; int numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb); for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle) { // first test the old sphere for being on the wrong side IndexedTriangle meshTriangle = mesh.GetTriangle(potentialTriangles[iTriangle]); float distToCentreOld = meshTriangle.Plane.DotCoordinate(oldSphereCen); if (distToCentreOld <= 0.0f) { continue; } // now test the new sphere for being clear float distToCentreNew = meshTriangle.Plane.DotCoordinate(newSphereCen); if (distToCentreNew > sphereTolR) { continue; } int i0, i1, i2; meshTriangle.GetVertexIndices(out i0, out i1, out i2); Triangle triangle = new Triangle(mesh.GetVertex(i0), mesh.GetVertex(i1), mesh.GetVertex(i2)); // If the old sphere is intersecting, just use that result float s, t; float d2 = Distance.PointTriangleDistanceSq(out s, out t, oldSphereCen, triangle); if (d2 < sphereToR2) { float dist = (float)System.Math.Sqrt(d2); float depth = oldSphere.Radius - dist; Vector3 triangleN = triangle.Normal; Vector3 normSafe = oldSphereCen - triangle.GetPoint(s, t); JiggleMath.NormalizeSafe(ref normSafe); Vector3 collisionN = (dist > float.Epsilon) ? normSafe : triangleN; // since impulse gets applied at the old position Vector3 pt = oldSphere.Center - oldSphere.Radius * collisionN; if (numCollPts < MaxLocalStackSCPI) { // BEN-OPTIMISATION: Reuse existing collPts. collPts[numCollPts].R0 = pt - body0Pos; collPts[numCollPts].R1 = pt - body1Pos; collPts[numCollPts++].InitialPenetration = depth; } collNormal += collisionN; } else if (distToCentreNew < distToCentreOld) { // old sphere is not intersecting - do a sweep, but only if the sphere is moving into the // triangle Vector3 pt, N; // CHECK THIS float depth; if (Intersection.SweptSphereTriangleIntersection(out pt, out N, out depth, oldSphere, newSphere, triangle, distToCentreOld, distToCentreNew, Intersection.EdgesToTest.EdgeAll, Intersection.CornersToTest.CornerAll)) { // collision point etc must be relative to the old position because that's //where the impulses are applied float dist = (float)System.Math.Sqrt(d2); float depth2 = oldSphere.Radius - dist; Vector3 triangleN = triangle.Normal; Vector3 normSafe = oldSphereCen - triangle.GetPoint(s, t); JiggleMath.NormalizeSafe(ref normSafe); Vector3 collisionN = (dist > JiggleMath.Epsilon) ? normSafe : triangleN; // since impulse gets applied at the old position Vector3 pt2 = oldSphere.Center - oldSphere.Radius * collisionN; if (numCollPts < MaxLocalStackSCPI) { // BEN-OPTIMISATION: Reuse existing collPts. collPts[numCollPts].R0 = pt2 - body0Pos; collPts[numCollPts].R1 = pt2 - body1Pos; collPts[numCollPts++].InitialPenetration = depth; } collNormal += collisionN; } } } if (numCollPts > 0) { JiggleMath.NormalizeSafe(ref collNormal); collisionFunctor.CollisionNotify(ref info, ref collNormal, collPts, numCollPts); } } #if USE_STACKALLOC } } #else FreeStackAlloc(potTriArray); } FreeStackAlloc(collPtArray); } #endif } }
protected void moveShips(float timeElapsed) { if (timeElapsed <= 0f) { return; } // make the target drone move from side to side localTime += timeElapsed; Vector3 pos = targetDrone.Pos; pos.Z = 30f * (float)Math.Sin(localTime); targetDrone.Pos = pos; // make the vandal ship orbit missile target Vector3 desiredPos; Vector3 desiredDir; float angle = localTime * 0.5f; float desiredXOffset = 100f * (float)Math.Cos(angle); float desiredYOffset = 20f * (float)Math.Sin(angle * 0.77f); float desiredZOffset = 80f * (float)Math.Sin(angle * 0.88f); Vector3 desiredOffset = new Vector3(desiredXOffset, desiredYOffset, desiredZOffset); var target = getTargetObject(); if (missileLauncher != MissileLaunchers.VandalShip || target == null || target == vandalShip) { desiredPos = new Vector3(100f, 0f, 0f); desiredDir = -Vector3.UnitX; } else if (target == main3dScene.ActiveCamera) { desiredPos = main3dScene.ActiveCamera.Pos + -main3dScene.ActiveCamera.Dir * 300f; Quaternion cameraOrient = OpenTKHelper.neededRotation(Vector3.UnitZ, -main3dScene.ActiveCamera.Up); desiredPos += Vector3.Transform(desiredOffset * 0.1f, cameraOrient); desiredDir = (target.Pos - vandalShip.Pos).Normalized(); } else { //float desiredZOffset = 5f * (float)Math.Sin(angle + 0.2f); desiredPos = target.Pos + desiredOffset; desiredDir = (target.Pos - vandalShip.Pos).Normalized(); } Vector3 desiredMotion = desiredPos - vandalShip.Pos; const float vel = 100f; float displacement = vel * timeElapsed; Vector3 vandalNewPos; if (displacement > desiredMotion.LengthFast) { vandalNewPos = desiredPos; } else { vandalNewPos = vandalShip.Pos + desiredMotion.Normalized() * displacement; } vandalVelocity = (vandalNewPos - vandalShip.Pos) / timeElapsed; vandalShip.Pos = vandalNewPos; Quaternion vandalOrient = OpenTKHelper.neededRotation(Vector3.UnitZ, desiredDir); vandalShip.Orient(desiredDir, Vector3.Transform(Vector3.UnitY, vandalOrient)); }
public bool MouseIsIn(Vector3 m) { Vector3 mm = m.Transform (transformationsInverse); return Bounds.ContainsOrIsEqual (new Point<float> (mm.X, mm.Y)); }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { //Update the form collection FormCollection.Update(gameTime); KeyboardState keybState = Keyboard.GetState(); if (keybState.IsKeyDown(Keys.LeftShift) || keybState.IsKeyDown(Keys.RightShift)) { //il giro in 4 secondi => PI/2 al secondo float rads = (float)(gameTime.ElapsedGameTime.TotalSeconds * (Math.PI / 2)); if (keybState.IsKeyDown(Keys.A)) { StatusCurrent.DirectionalLight0Direction = Vector3.Transform(StatusCurrent.DirectionalLight0Direction, Matrix.CreateRotationY(rads)); } if (keybState.IsKeyDown(Keys.D)) { StatusCurrent.DirectionalLight0Direction = Vector3.Transform(StatusCurrent.DirectionalLight0Direction, Matrix.CreateRotationY(-rads)); } if (keybState.IsKeyDown(Keys.W)) { StatusCurrent.DirectionalLight0Direction = Vector3.Transform(StatusCurrent.DirectionalLight0Direction, Matrix.CreateRotationX(rads)); } if (keybState.IsKeyDown(Keys.S)) { StatusCurrent.DirectionalLight0Direction = Vector3.Transform(StatusCurrent.DirectionalLight0Direction, Matrix.CreateRotationX(-rads)); } } if (keybState.IsKeyDown(Keys.LeftShift) || keybState.IsKeyDown(Keys.RightShift)) { //il giro in 4 secondi => PI/2 al secondo float rads = (float)(gameTime.ElapsedGameTime.TotalSeconds * (Math.PI / 2)); if (keybState.IsKeyDown(Keys.A)) { StatusCurrent.DirectionalLight0Direction = Vector3.Transform(StatusCurrent.DirectionalLight0Direction, Matrix.CreateRotationY(rads)); } if (keybState.IsKeyDown(Keys.D)) { StatusCurrent.DirectionalLight0Direction = Vector3.Transform(StatusCurrent.DirectionalLight0Direction, Matrix.CreateRotationY(-rads)); } if (keybState.IsKeyDown(Keys.W)) { StatusCurrent.DirectionalLight0Direction = Vector3.Transform(StatusCurrent.DirectionalLight0Direction, Matrix.CreateRotationX(rads)); } if (keybState.IsKeyDown(Keys.S)) { StatusCurrent.DirectionalLight0Direction = Vector3.Transform(StatusCurrent.DirectionalLight0Direction, Matrix.CreateRotationX(-rads)); } } else { if (keybState.IsKeyDown(Keys.F1)) { StatusCurrent.TransparentSide = TraspSide.InFrontOfWhite; } if (keybState.IsKeyDown(Keys.F2)) { StatusCurrent.TransparentSide = TraspSide.RightOfWhite; } if (keybState.IsKeyDown(Keys.F3)) { StatusCurrent.TransparentSide = TraspSide.InFrontOfBlack; } if (keybState.IsKeyDown(Keys.F4)) { StatusCurrent.TransparentSide = TraspSide.RightOfBlack; } //if (keybState.IsKeyDown(Keys.F11)) // StatusCurrent.AlphaTransparency = false; //if (keybState.IsKeyDown(Keys.F12)) // StatusCurrent.AlphaTransparency = true; } //Matrix.cre base.Update(gameTime); }
public void Update(float currentTime, ElapsedTime elapsedTime) { windDisplacementX = viewer.Simulator.Weather.WindSpeedMpS.X * 0.25f; windDisplacementZ = viewer.Simulator.Weather.WindSpeedMpS.Y * 0.25f; var velocity = WorldPosition.Location - LastWorldPosition.Location; velocity.X += (WorldPosition.TileX - LastWorldPosition.TileX) * 2048; velocity.Z += (WorldPosition.TileZ - LastWorldPosition.TileZ) * 2048; velocity.Z *= -1; velocity /= elapsedTime.ClockSeconds; LastWorldPosition.Location = WorldPosition.Location; LastWorldPosition.TileX = WorldPosition.TileX; LastWorldPosition.TileZ = WorldPosition.TileZ; RetireActiveParticles(currentTime); FreeRetiredParticles(); if (ParticlesPerSecond < 0.1) { TimeParticlesLastEmitted = currentTime; } var numToBeEmitted = (int)((currentTime - TimeParticlesLastEmitted) * ParticlesPerSecond); var numCanBeEmitted = GetCountFreeParticles(); var numToEmit = Math.Min(numToBeEmitted, numCanBeEmitted); if (numToEmit > 0) { var rotation = WorldPosition.XNAMatrix; rotation.Translation = Vector3.Zero; var position = Vector3.Transform(EmitterData.XNALocation, rotation) + WorldPosition.XNAMatrix.Translation; var globalInitialVelocity = Vector3.Transform(XNAInitialVelocity, rotation) + velocity; // TODO: This should only be rotated about the Y axis and not get fully rotated. var globalTargetVelocity = Vector3.Transform(XNATargetVelocity, rotation); var time = TimeParticlesLastEmitted; for (var i = 0; i < numToEmit; i++) { time += 1 / ParticlesPerSecond; var particle = (FirstFreeParticle + 1) % MaxParticles; var vertex = particle * VerticiesPerParticle; var texture = Viewer.Random.Next(16); // Randomizes emissions. var color_Random = new Color((float)ParticleColor.R / 255f, (float)ParticleColor.G / 255f, (float)ParticleColor.B / 255f, (float)Viewer.Random.NextDouble()); // Initial velocity varies in X and Z only. var initialVelocity = globalInitialVelocity; initialVelocity.X += (float)(Viewer.Random.NextDouble() - 0.5f) * ParticleEmitterViewer.InitialSpreadRate; initialVelocity.Z += (float)(Viewer.Random.NextDouble() - 0.5f) * ParticleEmitterViewer.InitialSpreadRate; // Target/final velocity vaies in X, Y and Z. var targetVelocity = globalTargetVelocity; targetVelocity.X += Noise.Generate(time + PerlinStart[0]) * ParticleEmitterViewer.SpreadRate; targetVelocity.Y += Noise.Generate(time + PerlinStart[1]) * ParticleEmitterViewer.SpreadRate; targetVelocity.Z += Noise.Generate(time + PerlinStart[2]) * ParticleEmitterViewer.SpreadRate; // Add wind speed targetVelocity.X += windDisplacementX; targetVelocity.Z += windDisplacementZ; // ActionDuration is variable too. var duration = ParticleDuration * (1 + Noise.Generate(time + PerlinStart[3]) * ParticleEmitterViewer.DurationVariation); for (var j = 0; j < VerticiesPerParticle; j++) { Vertices[vertex + j].StartPosition_StartTime = new Vector4(position, time); Vertices[vertex + j].InitialVelocity_EndTime = new Vector4(initialVelocity, time + duration); Vertices[vertex + j].TargetVelocity_TargetTime = new Vector4(targetVelocity, ParticleEmitterViewer.DecelerationTime); Vertices[vertex + j].TileXY_Vertex_ID = new Vector4(WorldPosition.TileX, WorldPosition.TileZ, j, texture); Vertices[vertex + j].Color_Random = color_Random; } FirstFreeParticle = particle; } TimeParticlesLastEmitted = time; } }
protected override void DoRender() { // Early exit if (Lights.Count == 0) { return; } // Retrieve device context var context = this.DeviceManager.Direct3DContext; // backup existing context state int oldStencilRef = 0; RawColor4 oldBlendFactor; int oldSampleMaskRef; using (var oldVertexLayout = context.InputAssembler.InputLayout) using (var oldPixelShader = context.PixelShader.Get()) using (var oldVertexShader = context.VertexShader.Get()) using (var oldBlendState = context.OutputMerger.GetBlendState(out oldBlendFactor, out oldSampleMaskRef)) using (var oldDepthState = context.OutputMerger.GetDepthStencilState(out oldStencilRef)) using (var oldRSState = context.Rasterizer.State) { // Assign shader resources - TODO: create array in CreateDeviceDependentResources instead context.PixelShader.SetShaderResources(0, gbuffer.SRVs.ToArray().Concat(new[] { gbuffer.DSSRV }).ToArray()); // Assign the additive blend state context.OutputMerger.BlendState = blendStateAdd; // Retrieve camera parameters SharpDX.FrustumCameraParams cameraParams = Frustum.GetCameraParams(); // For each configured light for (var i = 0; i < Lights.Count; i++) { PerLight light = Lights[i]; PixelShader shader = null; // Assign shader if (light.Type == LightType.Ambient) { shader = psAmbientLight; } else if (light.Type == LightType.Directional) { shader = psDirectionalLight; } else if (light.Type == LightType.Point) { shader = psPointLight; } //else if (light.Type == LightType.Spot) // shader = psSpotLight; // Update the perLight constant buffer // Calculate view space position (for frustum checks) Vector3 lightDir = Vector3.Normalize(Lights[i].Direction); Vector4 viewSpaceDir = Vector3.Transform(lightDir, PerObject.View); light.Direction = new Vector3(viewSpaceDir.X, viewSpaceDir.Y, viewSpaceDir.Z); Vector4 viewSpacePos = Vector3.Transform(Lights[i].Position, PerObject.View); light.Position = new Vector3(viewSpacePos.X, viewSpacePos.Y, viewSpacePos.Z); context.UpdateSubresource(ref light, perLightBuffer); context.PixelShader.SetConstantBuffer(4, perLightBuffer); light.Position = Lights[i].Position; light.Direction = Lights[i].Direction; // Check if the light should be considered full screen bool isFullScreen = light.Type == LightType.Directional || light.Type == LightType.Ambient; if (!isFullScreen) { isFullScreen = (cameraParams.ZNear > viewSpacePos.Z - light.Range && cameraParams.ZFar < viewSpacePos.Z + light.Range); } if (isFullScreen) { context.OutputMerger.DepthStencilState = depthDisabled; // Use SAQuad saQuad.ShaderResources = null; saQuad.Shader = shader; saQuad.Render(); } else // Render volume { context.PixelShader.Set(shader); context.VertexShader.Set(vertexShader); Matrix world = Matrix.Identity; MeshRenderer volume = null;; switch (light.Type) { case LightType.Point: // Prepare world matrix // Ensure no abrupt light edges with +50% world.ScaleVector = Vector3.One * light.Range * 1.5f; volume = pointLightVolume; break; /* TODO: Spot light support * case LightType.Spot: * // Determine rotation! * var D = Vector3.Normalize(light.Direction); * var s1 = Vector3.Cross(D, Vector3.UnitZ); * var s2 = Vector3.Cross(D, Vector3.UnitY); * Vector3 S; * if (s1.LengthSquared() > s2.LengthSquared()) * S = s1; * else * S = s2; * var U = Vector3.Cross(D, S); * Matrix rotate = Matrix.Identity; * rotate.Forward = D; * rotate.Down = U; * rotate.Left = S; * * float scaleZ = light.Range; * // Need to Abs - if negative it will invert our model and result in incorrect normals * float scaleXY = light.Range * Math.Abs((float)Math.Tan(Math.Acos(light.SpotOuterCosine*2)/2)); * * world.ScaleVector = new Vector3(scaleXY, scaleXY, scaleZ); * world *= rotate; * volume = spotLightVolume; * break; * */ default: continue; } world.TranslationVector = light.Position; volume.World = world; // Transpose the PerObject matrices var transposed = PerObject; transposed.World = volume.World; transposed.WorldViewProjection = volume.World * PerObject.ViewProjection; transposed.Transpose(); context.UpdateSubresource(ref transposed, PerObjectBuffer); if (cameraParams.ZFar < viewSpacePos.Z + light.Range) { // Cull the back face and only render where there is something // behind the front face. context.Rasterizer.State = rsCullBack; context.OutputMerger.DepthStencilState = depthLessThan; } else { // Cull front faces and only render where there is something // before the back face. context.Rasterizer.State = rsCullFront; context.OutputMerger.DepthStencilState = depthGreaterThan; } volume.Render(); // Show the light volumes for debugging if (Debug > 0) { if (Debug == 1) { context.OutputMerger.SetDepthStencilState(depthGreaterThan); } else { context.OutputMerger.SetDepthStencilState(depthLessThan); } context.PixelShader.Set(psDebugLight); context.Rasterizer.State = rsWireframe; volume.Render(); } } } // Reset pixel shader resources (all to null) context.PixelShader.SetShaderResources(0, new ShaderResourceView[gbuffer.SRVs.Count + 1]); // Restore context states context.PixelShader.Set(oldPixelShader); context.VertexShader.Set(oldVertexShader); context.InputAssembler.InputLayout = oldVertexLayout; context.OutputMerger.SetBlendState(oldBlendState, oldBlendFactor, oldSampleMaskRef); context.OutputMerger.SetDepthStencilState(oldDepthState, oldStencilRef); context.Rasterizer.State = oldRSState; } }
public virtual void DebugDraw(ref Matrix drawMatrix) { if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW) { if (MyDebugDrawSettings.DEBUG_DRAW_NAVMESHES != MyWEMDebugDrawMode.NONE) { this.m_mesh.DebugDraw(ref drawMatrix, MyDebugDrawSettings.DEBUG_DRAW_NAVMESHES); this.m_mesh.CustomDebugDrawFaces(ref drawMatrix, MyDebugDrawSettings.DEBUG_DRAW_NAVMESHES, obj => (obj as MyNavigationTriangle).Index.ToString()); } if (MyFakes.DEBUG_DRAW_FUNNEL) { List <Vector3> .Enumerator enumerator; MyRenderProxy.DebugDrawSphere(Vector3.Transform(this.m_vertex, (Matrix)drawMatrix), 0.05f, Color.Yellow.ToVector3(), 1f, false, false, true, false); MyRenderProxy.DebugDrawSphere(Vector3.Transform(this.m_vertex + this.m_normal, (Matrix)drawMatrix), 0.05f, Color.Orange.ToVector3(), 1f, false, false, true, false); MyRenderProxy.DebugDrawSphere(Vector3.Transform(this.m_left, (Matrix)drawMatrix), 0.05f, Color.Red.ToVector3(), 1f, false, false, true, false); Color green = Color.Green; MyRenderProxy.DebugDrawSphere(Vector3.Transform(this.m_right, (Matrix)drawMatrix), 0.05f, green.ToVector3(), 1f, false, false, true, false); using (enumerator = m_debugPointsLeft.GetEnumerator()) { while (enumerator.MoveNext()) { green = Color.Red; MyRenderProxy.DebugDrawSphere(Vector3.Transform(enumerator.Current, (Matrix)drawMatrix), 0.03f, green.ToVector3(), 1f, false, false, true, false); } } using (enumerator = m_debugPointsRight.GetEnumerator()) { while (enumerator.MoveNext()) { green = Color.Green; MyRenderProxy.DebugDrawSphere(Vector3.Transform(enumerator.Current, (Matrix)drawMatrix), 0.04f, green.ToVector3(), 1f, false, false, true, false); } } Vector3?nullable = null; if (m_path != null) { using (enumerator = m_path.GetEnumerator()) { while (enumerator.MoveNext()) { Vector3 vector = Vector3.Transform(enumerator.Current, (Matrix)drawMatrix); MyRenderProxy.DebugDrawSphere(vector + (Vector3.Up * 0.2f), 0.02f, Color.Orange.ToVector3(), 1f, false, false, true, false); if (nullable != null) { MyRenderProxy.DebugDrawLine3D(nullable.Value + (Vector3.Up * 0.2f), vector + (Vector3.Up * 0.2f), Color.Orange, Color.Orange, true, false); } nullable = new Vector3?(vector); } } } nullable = null; if (m_path2 != null) { using (enumerator = m_path2.GetEnumerator()) { while (enumerator.MoveNext()) { Vector3 vector2 = Vector3.Transform(enumerator.Current, (Matrix)drawMatrix); if (nullable != null) { MyRenderProxy.DebugDrawLine3D(nullable.Value + (Vector3.Up * 0.1f), vector2 + (Vector3.Up * 0.1f), Color.Violet, Color.Violet, true, false); } nullable = new Vector3?(vector2); } } } if (m_debugFunnel.Count > 0) { FunnelState local2 = m_debugFunnel[m_debugFunnelIdx % m_debugFunnel.Count]; Vector3 vector3 = Vector3.Transform(local2.Apex, (Matrix)drawMatrix); Vector3 vector4 = vector3 + ((Vector3.Transform(local2.Left, (Matrix)drawMatrix) - vector3) * 10f); Vector3 vector5 = vector3 + ((Vector3.Transform(local2.Right, (Matrix)drawMatrix) - vector3) * 10f); Color cyan = Color.Cyan; MyRenderProxy.DebugDrawLine3D(vector3 + (Vector3.Up * 0.1f), vector4 + (Vector3.Up * 0.1f), cyan, cyan, true, false); MyRenderProxy.DebugDrawLine3D(vector3 + (Vector3.Up * 0.1f), vector5 + (Vector3.Up * 0.1f), cyan, cyan, true, false); } } } }
public void Transform(Matrix transform) { this.Center = Vector3.Transform(this.Center, transform); this.Orientation = Quaternion.CreateFromRotationMatrix(transform); }
public int CreateShadowGeometry(Vector2 pos, Rectangle viewSpace, VertexBuffer shadowVB) { Vector2 center = pos; Rectangle drawRect = viewSpace; //Calculate minimal and maximal tile index to consider for shadow calculation int minX = (int)((pos.X - drawRect.Width / 2) / TileSize); minX = minX >= 0 ? minX : 0; int minY = (int)((pos.Y - drawRect.Height / 2) / TileSize); minY = minY >= 0 ? minY : 0; int maxX = (drawRect.Width + drawRect.X) / TileSize + 1; maxX = maxX < _tiles[1].GetLength(0) ? maxX : _tiles[1].GetLength(0); int maxY = (drawRect.Height + drawRect.Y) / TileSize + 1; maxY = maxY < _tiles[1].GetLength(1) ? maxY : _tiles[1].GetLength(1); //Count vertices to make sure we fit everything into our vertex buffer int vertexCount = 0; //Iterate over all tiles we need to consider, this method is slower than using a BSP tree or something //But it is sufficient for this game //48,24 for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { //Check if there's a tile here and wether we have drawn this rect already if (_tiles[1][x, y] != null) { //Set up helper values //Offset for the diagonal of the rectangle Vector2 tileSizeVec = Vector2.Zero; // new Vector2(_tiles[1][x, y].Geometry.BoundingRect.Width * 0.5f, _tiles[1][x, y].Geometry.BoundingRect.Height * 0.5f); //mid point of the rectangle, this way we can directly compute the corners over the diagonals Vector2 midPoint = Vector2.Zero; // new Vector2(_tiles[1][x, y].Geometry.BoundingRect.Center.X, _tiles[1][x, y].Geometry.BoundingRect.Center.Y); //vector from light source to rectangles center to calculate which edges are facing away from light source tileSizeVec = new Vector2(_tiles[1][x, y].TargetRect.Width * 0.5f, _tiles[1][x, y].TargetRect.Height * 0.5f); midPoint = new Vector2(_tiles[1][x, y].TargetRect.Center.X, _tiles[1][x, y].TargetRect.Center.Y); Vector3 diff = new Vector3(midPoint - center, 0); Vector3 edge1, edge2, edge3, edge4; //Find a sensible order for the 4 edges, sort them so that if you only take the first 3 edges the left out side is closest to the center of the rectangle //This simplifies the shadow geometry calculation a lot //Note: This seems like a lot of code, but it's just 2 branches and 4 vector 3 creators /* 2* 3* * * * * * 1* 4* * x * * diff.X/tileSizeVec.X > diff.Y/tileSizeVec.Y */ float depth = 0.5f; if (diff.X * tileSizeVec.Y > diff.Y * tileSizeVec.X) { if (diff.X * tileSizeVec.Y > -diff.Y * tileSizeVec.X) { edge1 = new Vector3(midPoint + new Vector2(-tileSizeVec.X, -tileSizeVec.Y), depth); //1 edge2 = new Vector3(midPoint + new Vector2(tileSizeVec.X, -tileSizeVec.Y), depth); //2 edge3 = new Vector3(midPoint + new Vector2(tileSizeVec.X, tileSizeVec.Y), depth); //3 edge4 = new Vector3(midPoint + new Vector2(-tileSizeVec.X, tileSizeVec.Y), depth); //4 } else { edge1 = new Vector3(midPoint + new Vector2(-tileSizeVec.X, tileSizeVec.Y), depth); //4 edge2 = new Vector3(midPoint + new Vector2(-tileSizeVec.X, -tileSizeVec.Y), depth); //1 edge3 = new Vector3(midPoint + new Vector2(tileSizeVec.X, -tileSizeVec.Y), depth); //2 edge4 = new Vector3(midPoint + new Vector2(tileSizeVec.X, tileSizeVec.Y), depth); //3 } } else { if (diff.X * tileSizeVec.Y > -diff.Y * tileSizeVec.X) { edge1 = new Vector3(midPoint + new Vector2(tileSizeVec.X, -tileSizeVec.Y), depth); //2 edge2 = new Vector3(midPoint + new Vector2(tileSizeVec.X, tileSizeVec.Y), depth); //3 edge3 = new Vector3(midPoint + new Vector2(-tileSizeVec.X, tileSizeVec.Y), depth); //4 edge4 = new Vector3(midPoint + new Vector2(-tileSizeVec.X, -tileSizeVec.Y), depth); //1 } else { edge1 = new Vector3(midPoint + new Vector2(tileSizeVec.X, tileSizeVec.Y), depth); //3 edge2 = new Vector3(midPoint + new Vector2(-tileSizeVec.X, tileSizeVec.Y), depth); //4 edge3 = new Vector3(midPoint + new Vector2(-tileSizeVec.X, -tileSizeVec.Y), depth); //1 edge4 = new Vector3(midPoint + new Vector2(tileSizeVec.X, -tileSizeVec.Y), depth); //2 } } Vector3 dir1; Vector3 dir2; //Calculate some (not accurate) stretch value to make sure the shadow geometry does not end mid screen //We definitely draw way too much, but everything outside of the screen barely costs fillrate float stretch = tileSizeVec.X * tileSizeVec.Y * 200; //Check which of the 3 interesting sides are facing away from the light center and write appropriate //Geometry into the dynamic vertex buffer if (vertexCount < shadowVB.VertexCount)// && Vector3.Dot((edge1 + edge2) / 2 - new Vector3(center, 0), new Vector3(-(edge2 - edge1).Y, (edge2 - edge1).X, 0)) < 0) { dir1 = edge1 - new Vector3(center, depth); dir1.Normalize(); dir2 = edge2 - new Vector3(center, depth); dir2.Normalize(); //Some basic math basically we put in 2 triangles //The idea is this, you draw a straight line from the center of the light to the corners and elongate that line //until it is out of the screen, this way with the 2 corner points you get a trapezoid //this trapezoid is your geometry, so you split it into 2 triangles and send them into the VBO shadowVB.SetData <VertexPositionColor>(vertexCount * VertexPositionColor.VertexDeclaration.VertexStride, new VertexPositionColor[] { new VertexPositionColor(edge1 + dir1 * stretch, Color.White), new VertexPositionColor(edge1 + Vector3.Transform(dir1, Lightmap.rotateRight) * stretch, Color.Black), new VertexPositionColor(edge2 + Vector3.Transform(dir2, Lightmap.rotateLeft) * stretch, Color.Black), new VertexPositionColor(edge2 + dir2 * stretch, Color.White), new VertexPositionColor(edge1, Color.Black), new VertexPositionColor(edge2, Color.Black) }, 0, 6, VertexPositionColor.VertexDeclaration.VertexStride); vertexCount += 6; } //This is the backwards facing side, which will always be facing away, so we only need to check that the geometry fits if (vertexCount < shadowVB.VertexCount)// && Vector3.Dot((edge2+edge3)/2 - new Vector3(center, 0), new Vector3(-(edge3 - edge2).Y, (edge3 - edge2).X, 0)) < 0) { dir1 = edge2 - new Vector3(center, depth); dir1.Normalize(); dir2 = edge3 - new Vector3(center, depth); dir2.Normalize(); shadowVB.SetData <VertexPositionColor>(vertexCount * VertexPositionColor.VertexDeclaration.VertexStride, new VertexPositionColor[] { new VertexPositionColor(edge2 + dir1 * stretch, Color.White), new VertexPositionColor(edge2 + Vector3.Transform(dir1, Lightmap.rotateRight) * stretch, Color.Black), new VertexPositionColor(edge3 + Vector3.Transform(dir2, Lightmap.rotateLeft) * stretch, Color.Black), new VertexPositionColor(edge3 + dir2 * stretch, Color.White), new VertexPositionColor(edge2, Color.Black), new VertexPositionColor(edge3, Color.Black) }, 0, 6, VertexPositionColor.VertexDeclaration.VertexStride); vertexCount += 6; } else { } if (vertexCount < shadowVB.VertexCount)// && Vector3.Dot((edge3 + edge4) / 2 - new Vector3(center, 0), new Vector3(-(edge4 - edge3).Y, (edge4 - edge3).X, 0)) < 0) { dir1 = edge3 - new Vector3(center, depth); dir1.Normalize(); dir2 = edge4 - new Vector3(center, depth); dir2.Normalize(); shadowVB.SetData <VertexPositionColor>(vertexCount * VertexPositionColor.VertexDeclaration.VertexStride, new VertexPositionColor[] { new VertexPositionColor(edge3 + dir1 * stretch, Color.White), new VertexPositionColor(edge3 + Vector3.Transform(dir1, Lightmap.rotateRight) * stretch, Color.Black), new VertexPositionColor(edge4 + Vector3.Transform(dir2, Lightmap.rotateLeft) * stretch, Color.Black), new VertexPositionColor(edge4 + dir2 * stretch, Color.White), new VertexPositionColor(edge3, Color.Black), new VertexPositionColor(edge4, Color.Black), }, 0, 6, VertexPositionColor.VertexDeclaration.VertexStride); vertexCount += 6; } if (vertexCount < shadowVB.VertexCount)// && Vector3.Dot((edge4 + edge1) / 2 - new Vector3(center, 0), new Vector3(-(edge1 - edge4).Y, (edge1 - edge4).X, 0)) < 0) { dir1 = edge4 - new Vector3(center, depth); dir1.Normalize(); dir2 = edge1 - new Vector3(center, depth); dir2.Normalize(); shadowVB.SetData <VertexPositionColor>(vertexCount * VertexPositionColor.VertexDeclaration.VertexStride, new VertexPositionColor[] { new VertexPositionColor(edge4 + dir1 * stretch, Color.White), new VertexPositionColor(edge4 + Vector3.Transform(dir1, Lightmap.rotateRight) * stretch, Color.Black), new VertexPositionColor(edge1 + Vector3.Transform(dir2, Lightmap.rotateLeft) * stretch, Color.Black), new VertexPositionColor(edge1 + dir2 * stretch, Color.White), new VertexPositionColor(edge4, Color.Black), new VertexPositionColor(edge1, Color.Black), }, 0, 6, VertexPositionColor.VertexDeclaration.VertexStride); vertexCount += 6; } } } } return(vertexCount); }
private new void FixSnapTransformationBase6() { Debug.Assert(CopiedGrids.Count > 0); if (CopiedGrids.Count == 0) { return; } var hitGrid = m_hitEntity as MyCubeGrid; if (hitGrid == null) { return; } // Fix rotation of the first pasted grid Matrix hitGridRotation = hitGrid.WorldMatrix.GetOrientation(); Matrix firstRotation = PreviewGrids[0].WorldMatrix.GetOrientation(); Matrix newFirstRotation = Matrix.AlignRotationToAxes(ref firstRotation, ref hitGridRotation); Matrix rotationDelta = Matrix.Invert(firstRotation) * newFirstRotation; foreach (var grid in PreviewGrids) { Matrix rotation = grid.WorldMatrix.GetOrientation(); rotation = rotation * rotationDelta; Matrix rotationInv = Matrix.Invert(rotation); Vector3D position = m_pastePosition; MatrixD newWorld = MatrixD.CreateWorld(position, rotation.Forward, rotation.Up); Debug.Assert(newWorld.GetOrientation().IsRotation()); grid.PositionComp.SetWorldMatrix(newWorld); } bool smallOnLargeGrid = hitGrid.GridSizeEnum == MyCubeSize.Large && PreviewGrids[0].GridSizeEnum == MyCubeSize.Small; if (smallOnLargeGrid) { Vector3 pasteOffset = TransformLargeGridHitCoordToSmallGrid(m_hitPos, hitGrid.PositionComp.WorldMatrixNormalizedInv, hitGrid.GridSize); m_pastePosition = hitGrid.GridIntegerToWorld(pasteOffset); } else { // Find a collision-free position for the first paste grid along the raycast normal Vector3I collisionTestStep = Vector3I.Round(m_hitNormal); Vector3I pasteOffset = hitGrid.WorldToGridInteger(m_pastePosition); Vector3I previewGridMin = PreviewGrids[0].Min; Vector3I previewGridMax = PreviewGrids[0].Max; Vector3I previewGridSize = previewGridMax - previewGridMin + Vector3I.One; Vector3D previewGridSizeInWorld = Vector3D.TransformNormal((Vector3D)previewGridSize, PreviewGrids[0].WorldMatrix); Vector3I previewGridSizeInHitGrid = Vector3I.Abs(Vector3I.Round(Vector3D.TransformNormal(previewGridSizeInWorld, hitGrid.PositionComp.WorldMatrixNormalizedInv))); int attemptsCount = Math.Abs(Vector3I.Dot(ref collisionTestStep, ref previewGridSizeInHitGrid)); Debug.Assert(attemptsCount > 0); int i; for (i = 0; i < attemptsCount; ++i) { if (hitGrid.CanMergeCubes(PreviewGrids[0], pasteOffset)) { break; } pasteOffset += collisionTestStep; } if (i == attemptsCount) { pasteOffset = hitGrid.WorldToGridInteger(m_pastePosition); } m_pastePosition = hitGrid.GridIntegerToWorld(pasteOffset); } // Move all the grids according to the collision-free position of the first one for (int i = 0; i < PreviewGrids.Count; ++i) { var grid = PreviewGrids[i]; MatrixD matrix = grid.WorldMatrix; matrix.Translation = m_pastePosition + Vector3.Transform(m_copiedGridOffsets[i], rotationDelta); grid.PositionComp.SetWorldMatrix(matrix); } if (MyDebugDrawSettings.DEBUG_DRAW_COPY_PASTE) { MyRenderProxy.DebugDrawLine3D(m_hitPos, m_hitPos + m_hitNormal, Color.Red, Color.Green, false); } }
public static Vector3 operator *(QT Q, Vector3 v) => Vector3.Transform(v, Q.q);
public static void Test( Entity entity1, object[] boundingVolumes1, ref Matrix worldTransform1, ref Vector3 translation1, ref Quaternion rotation1, ref Vector3 scale1, Entity entity2, object[] boundingVolumes2, ref Matrix worldTransform2, ref Vector3 translation2, ref Quaternion rotation2, ref Vector3 scale2, bool needAllContacts, ref Contact contact ) { Debug.Assert(scale1.X == scale1.Y && scale1.Y == scale1.Z); Debug.Assert(scale2.X == scale2.Y && scale2.Y == scale2.Z); for (int i = 0; i < boundingVolumes1.Length; ++i) { Sphere3 sphere1 = (Sphere3)boundingVolumes1[i]; for (int j = 0; j < boundingVolumes2.Length; ++j) { Cylinder3 cylinder2 = (Cylinder3)boundingVolumes2[j]; Vector3 center1 = Vector3.Transform(sphere1.Center, worldTransform1); float radius1 = scale1.X * sphere1.Radius; Vector3 top2 = Vector3.Transform(cylinder2.Top, worldTransform2); Vector3 bottom2 = Vector3.Transform(cylinder2.Bottom, worldTransform2); float radius2 = scale2.X * cylinder2.Radius; // sphere is on same level as the cylinder if (center1.Y <= top2.Y && center1.Y >= bottom2.Y) { // distance between the two Vector3 diff = top2 - center1; diff.Y = 0; // we are only interested in horizontal distance float collisionLengthSquared = (radius2 + radius1) * (radius2 + radius1); if (diff.LengthSquared() < collisionLengthSquared) { diff.Normalize(); Vector3 point = center1 + diff * radius1; contact.AddContactPoint(ref point, ref diff); } } // above cylinder... else if (center1.Y > top2.Y) { if (center1.Y - radius1 < top2.Y) { // project to top cylinder 'plane' Vector3 projected = center1; projected.Y = top2.Y; Vector3 toProjected = projected - top2; if (toProjected.LengthSquared() < radius2 * radius2) { Vector3 normal = -Vector3.UnitY; contact.AddContactPoint(ref projected, ref normal); } else { toProjected.Normalize(); Vector3 nearestPoint = top2 + toProjected * radius2; Vector3 diff = nearestPoint - center1; if (diff.LengthSquared() < radius1 * radius1) { Vector3 normal = -Vector3.UnitY; contact.AddContactPoint(ref nearestPoint, ref normal); } } } } // below cylinder else if (center1.Y < bottom2.Y) { if (center1.Y + radius1 < bottom2.Y) { // project to bottom cylinder 'plane' Vector3 projected = center1; projected.Y = bottom2.Y; Vector3 toProjected = projected - bottom2; if (toProjected.LengthSquared() < radius2 * radius2) { Vector3 normal = Vector3.UnitY; contact.AddContactPoint(ref projected, ref normal); } else { toProjected.Normalize(); Vector3 nearestPoint = bottom2 + toProjected * radius2; Vector3 diff = nearestPoint - center1; if (diff.LengthSquared() < radius1 * radius1) { Vector3 normal = Vector3.UnitY; contact.AddContactPoint(ref nearestPoint, ref normal); } } } } else { // we covered all cases... Debug.Assert(false); } } } }
public void ProcessKinectCommands(InputManager inputManager) { inputManager.GameState.KinectVideoColors = kinectHandler.ColorImage; if (inputManager.GameState.IsKinectActive) { inputManager.GameState.IsInputActive = false; if (kinectHandler.Gesture == "TurnLeft") { // Rotate left. inputManager.GameState.IsInputActive = true; inputManager.GameState.AvatarYRotation += inputManager.GameState.TurningSpeed / 2; } if (kinectHandler.Gesture == "TurnRight") { // Rotate right. inputManager.GameState.IsInputActive = true; inputManager.GameState.AvatarYRotation -= inputManager.GameState.TurningSpeed / 2; } if (kinectHandler.Gesture == "MoveForward") { inputManager.GameState.IsInputActive = true; Matrix forwardMovement = Matrix.CreateRotationY(inputManager.GameState.AvatarYRotation); Vector3 v = new Vector3(0, 0, -inputManager.GameState.MovingSpeed); v = Vector3.Transform(v, forwardMovement); Vector3 avatarPosition = inputManager.GameState.AvatarPosition; avatarPosition.Z += v.Z; avatarPosition.X += v.X; inputManager.GameState.AvatarPosition = avatarPosition; //Console.WriteLine ("Avatar Postion:{0}", avatarPosition.ToString ()); } if (kinectHandler.Gesture == "MoveBackward") { inputManager.GameState.IsInputActive = true; Matrix forwardMovement = Matrix.CreateRotationY(inputManager.GameState.AvatarYRotation); Vector3 v = new Vector3(0, 0, inputManager.GameState.MovingSpeed); v = Vector3.Transform(v, forwardMovement); Vector3 avatarPosition = inputManager.GameState.AvatarPosition; avatarPosition.Z += v.Z; avatarPosition.X += v.X; inputManager.GameState.AvatarPosition = avatarPosition; } //if (kinectHandler.Gesture == "Swipe Up") // { // inputManager.GameState.IsInputActive = true; // Matrix forwardMovement = Matrix.CreateRotationY (inputManager.GameState.AvatarYRotation); // Vector3 v = new Vector3 (0, inputManager.GameState.MovingSpeed, 0); // v = Vector3.Transform (v, forwardMovement); // Vector3 avatarPosition = inputManager.GameState.AvatarPosition; // avatarPosition.Y += v.Y; // inputManager.GameState.AvatarPosition = avatarPosition; // } //if (kinectHandler.Gesture == "Swipe Down") // { // inputManager.GameState.IsInputActive = true; // Matrix forwardMovement = Matrix.CreateRotationY (inputManager.GameState.AvatarYRotation); // Vector3 v = new Vector3 (0, -inputManager.GameState.MovingSpeed, 0); // v = Vector3.Transform (v, forwardMovement); // Vector3 avatarPosition = inputManager.GameState.AvatarPosition; // avatarPosition.Y += v.Y; // inputManager.GameState.AvatarPosition = avatarPosition; // } //if (kinectHandler.Gesture == "Zoom In") // { // inputManager.GameState.CameraState += 1; // inputManager.GameState.CameraState %= 3; // } if (kinectHandler.Gesture == "Clear") { inputManager.GameState.IsInputActive = false; if (inputManager.GameState.ShowInfo) { inputManager.GameState.ShowInfo = false; } if (inputManager.GameState.ShowCursor) { inputManager.GameState.ShowCursor = false; } } if (kinectHandler.Gesture == "Select") { // Console.WriteLine (inputManager.GameState.ShowCursor); if (inputManager.GameState.ShowCursor) { inputManager.GameState.ShowInfo = true; } } if (kinectHandler.Gesture == "Wave Right") { inputManager.GameState.ShowCursor = true; } if (inputManager.GameState.ShowCursor) { inputManager.GameState.CursorScreenLocation = new Vector2(kinectHandler.ScaledRightHand.Position.X, kinectHandler.ScaledRightHand.Position.Y); } } }
public override void Update(GameTime gameTime) { curMouse = Mouse.GetState(); curKeys = Keyboard.GetState(); if (Game.IsActive) { if (curMouse.ScrollWheelValue < prevMouse.ScrollWheelValue) { zoom *= 1.2f; } else if (curMouse.ScrollWheelValue > prevMouse.ScrollWheelValue) { zoom /= 1.2f; } if (zoom < minZoom) { zoom = minZoom; } if (zoom > maxZoom) { zoom = maxZoom; } int w = Game.GraphicsDevice.Viewport.Width / 2; int h = Game.GraphicsDevice.Viewport.Height / 2; float dx = curMouse.X - w; float dy = curMouse.Y - h; Mouse.SetPosition(w, h); yaw -= dx * .005f; pitch -= dy * .005f; if (pitch > 0) { pitch = 0; } else if (pitch < -MathHelper.PiOver2) { pitch = -MathHelper.PiOver2; } rot = Matrix.CreateRotationX(pitch) * Matrix.CreateRotationY(yaw); rotatedTarget = Vector3.Transform(new Vector3(0, 0, -1), rot); rotatedUpVector = Vector3.Transform(new Vector3(0, 1, 0), rot); distanceFromTarget = 20 * zoom; target = physicalData.Position + headOffset; position = target + rot.Backward * distanceFromTarget; view = Matrix.CreateLookAt(position, target, rotatedUpVector); physicalData.Orientation = Quaternion.CreateFromYawPitchRoll(yaw, 0, 0); } int i = 0; foreach (Entity e in lightPoleEntities) { if (i < lightPositions.Length) { lightPositions[i++] = e.Position + e.OrientationMatrix.Up * 4; } } while (i < lightPositions.Length) { lightPositions[i++] = inactiveLightPos; } prevMouse = curMouse; prevKeys = curKeys; }
private void animate() { Animation.Sequence sequence = new Animation.Sequence(); bool originalCanPause = false; sequence.Add(new Animation.Execute(delegate() { Entity p = PlayerFactory.Instance; if (p != null) { p.Get <Model>("FirstPersonModel").Enabled.Value = false; p.Get <Model>("Model").Enabled.Value = false; p.Get <CameraController>().Enabled.Value = false; p.Get <FPSInput>().Enabled.Value = false; p.Get <UIRenderer>("UI").Enabled.Value = false; AkSoundEngine.PostEvent(AK.EVENTS.STOP_PLAYER_BREATHING_SOFT, p); } CameraStop.CinematicActive.Value = true; originalCanPause = this.main.Menu.CanPause; #if !DEVELOPMENT this.main.Menu.CanPause.Value = false; #endif })); sequence.Add(new Animation.Set <Matrix>(this.main.Camera.RotationMatrix, Matrix.CreateFromQuaternion(this.Entity.Get <Transform>().Quaternion))); sequence.Add(new Animation.Set <Vector3>(this.main.Camera.Position, Vector3.Transform(new Vector3(0, 0, this.Offset), this.Entity.Get <Transform>().Matrix))); Animation.Ease.EaseType lastEase = Animation.Ease.EaseType.None; BSpline spline = null; Entity current = this.Entity; float totalDuration = 0.0f; while (current != null) { CameraStop currentStop = current.Get <CameraStop>(); Transform currentTransform = current.Get <Transform>(); Entity next = currentStop.Next.Value.Target; CameraStop nextStop = next == null ? null : next.Get <CameraStop>(); if (!lastEase.BlendsInto(currentStop.Blend) || next == null) { if (spline != null) { spline.Add(currentTransform.Position, currentTransform.Quaternion, currentStop.Offset, currentStop.FieldOfView); } spline = new BSpline(); } float currentTime = spline.Duration; spline.Duration += currentStop.Duration; totalDuration += currentStop.Duration; if (currentStop.Blend != Animation.Ease.EaseType.None && next != null) { BSpline currentSpline = spline; currentSpline.Add(currentTransform.Position, currentTransform.Quaternion, currentStop.Offset, currentStop.FieldOfView); Transform nextTransform = next.Get <Transform>(); sequence.Add ( new Animation.Ease ( new Animation.Custom ( delegate(float x) { float lerpValue = (currentTime + x * currentStop.Duration) / currentSpline.Duration; BSpline.ControlPoint point = currentSpline.Evaluate(lerpValue); Matrix rotationMatrix = Matrix.CreateFromQuaternion(point.Orientation); this.main.Camera.FieldOfView.Value = MathHelper.Clamp(point.FieldOfView, 0.01f, (float)Math.PI * 0.99f); this.main.Camera.RotationMatrix.Value = rotationMatrix; Matrix m = rotationMatrix * Matrix.CreateTranslation(point.Position); this.main.Camera.Position.Value = Vector3.Transform(new Vector3(0, 0, point.Offset), m); }, currentStop.Duration ), currentStop.Blend ) ); } else { sequence.Add ( new Animation.Custom ( delegate(float x) { this.main.Camera.RotationMatrix.Value = Matrix.CreateFromQuaternion(currentTransform.Quaternion); this.main.Camera.Position.Value = Vector3.Transform(new Vector3(0, 0, currentStop.Offset), currentTransform.Matrix); this.main.Camera.FieldOfView.Value = MathHelper.ToRadians(currentStop.FieldOfView); }, currentStop.Duration ) ); } sequence.Add(new Animation.Execute(currentStop.OnDone)); lastEase = currentStop.Blend; current = next; } Action done = delegate() { Entity p = PlayerFactory.Instance; if (p != null) { p.Get <Model>("FirstPersonModel").Enabled.Value = true; p.Get <Model>("Model").Enabled.Value = true; p.Get <CameraController>().Enabled.Value = true; p.Get <FPSInput>().Enabled.Value = true; p.Get <UIRenderer>("UI").Enabled.Value = true; } this.main.Camera.FieldOfView.Value = this.main.Settings.FieldOfView; CameraStop.CinematicActive.Value = false; this.main.Menu.CanPause.Value = originalCanPause; }; Animation anim; if (PlayerFactory.Instance != null && totalDuration > 0.0f) // Fade in and out { anim = new Animation ( new Animation.Vector3MoveTo(this.main.Renderer.Tint, Vector3.Zero, 0.5f), new Animation.Parallel(sequence, new Animation.Vector3MoveTo(this.main.Renderer.Tint, Vector3.One, 0.5f)), new Animation.Vector3MoveTo(this.main.Renderer.Tint, Vector3.Zero, 0.5f), new Animation.Execute(done), new Animation.Vector3MoveTo(this.main.Renderer.Tint, Vector3.One, 0.5f) ); } else { // Just do it anim = new Animation ( sequence, new Animation.Execute(done) ); } anim.EnabledWhenPaused = false; WorldFactory.Instance.Add(anim); }
public Vector3 GetForward() { return(Vector3.Transform(Vector3.Backward, Rotation)); }
/// <summary> /// Transforms a specified Vector3 by a specified transformation matrix in homogeneous space /// </summary> /// <param name="v">the vector to be transformed</param> /// <param name="m">the transformation matrix</param> /// <returns>a specified vector transformed by a specified transformation matrix in homogeneous space</returns> public static Vector4 Transform(Vector3 v, Matrix4x4 m) { return v.Transform(m); }
public Vector3 GetRight() { return(Vector3.Transform(Vector3.Right, Rotation)); }
bool testProximity(int n) { Piece p = Neighbours [n]; if (p == null) return false; if (Angle != p.Angle) return false; cDelta = Bounds.Center - p.Bounds.Center; cDelta = cDelta.Transform (Matrix4.CreateRotationZ (Angle)); if ( Math.Abs (Dx - p.Dx-cDelta.X) < puzzle.TolerancePlacementPieces && Math.Abs (Dy - p.Dy-cDelta.Y) < puzzle.TolerancePlacementPieces) return true; return false; }
/// <summary> /// Gets the intersection between the box and the ray. /// </summary> /// <param name="ray">Ray to test against the box.</param> /// <param name="transform">Transform of the shape.</param> /// <param name="maximumLength">Maximum distance to travel in units of the direction vector's length.</param> /// <param name="hit">Hit data for the raycast, if any.</param> /// <returns>Whether or not the ray hit the target.</returns> public override bool RayTest(ref Ray ray, ref RigidTransform transform, float maximumLength, out RayHit hit) { hit = new RayHit(); Quaternion conjugate; Quaternion.Conjugate(ref transform.Orientation, out conjugate); Vector3 localOrigin; Vector3.Subtract(ref ray.Position, ref transform.Position, out localOrigin); Vector3.Transform(ref localOrigin, ref conjugate, out localOrigin); Vector3 localDirection; Vector3.Transform(ref ray.Direction, ref conjugate, out localDirection); Vector3 normal = Toolbox.ZeroVector; float temp, tmin = 0, tmax = maximumLength; if (Math.Abs(localDirection.X) < Toolbox.Epsilon && (localOrigin.X < -halfWidth || localOrigin.X > halfWidth)) { return(false); } float inverseDirection = 1 / localDirection.X; float t1 = (-halfWidth - localOrigin.X) * inverseDirection; float t2 = (halfWidth - localOrigin.X) * inverseDirection; var tempNormal = new Vector3(-1, 0, 0); if (t1 > t2) { temp = t1; t1 = t2; t2 = temp; tempNormal *= -1; } temp = tmin; tmin = Math.Max(tmin, t1); if (temp != tmin) { normal = tempNormal; } tmax = Math.Min(tmax, t2); if (tmin > tmax) { return(false); } if (Math.Abs(localDirection.Y) < Toolbox.Epsilon && (localOrigin.Y < -halfHeight || localOrigin.Y > halfHeight)) { return(false); } inverseDirection = 1 / localDirection.Y; t1 = (-halfHeight - localOrigin.Y) * inverseDirection; t2 = (halfHeight - localOrigin.Y) * inverseDirection; tempNormal = new Vector3(0, -1, 0); if (t1 > t2) { temp = t1; t1 = t2; t2 = temp; tempNormal *= -1; } temp = tmin; tmin = Math.Max(tmin, t1); if (temp != tmin) { normal = tempNormal; } tmax = Math.Min(tmax, t2); if (tmin > tmax) { return(false); } if (Math.Abs(localDirection.Z) < Toolbox.Epsilon && (localOrigin.Z < -halfLength || localOrigin.Z > halfLength)) { return(false); } inverseDirection = 1 / localDirection.Z; t1 = (-halfLength - localOrigin.Z) * inverseDirection; t2 = (halfLength - localOrigin.Z) * inverseDirection; tempNormal = new Vector3(0, 0, -1); if (t1 > t2) { temp = t1; t1 = t2; t2 = temp; tempNormal *= -1; } temp = tmin; tmin = Math.Max(tmin, t1); if (temp != tmin) { normal = tempNormal; } tmax = Math.Min(tmax, t2); if (tmin > tmax) { return(false); } hit.T = tmin; Vector3.Multiply(ref ray.Direction, tmin, out hit.Location); Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location); Vector3.Transform(ref normal, ref transform.Orientation, out normal); hit.Normal = normal; return(true); }