private void butSaveChanges_Click(object sender, EventArgs e) { // Check if we need to transform mesh var transform = panelRendering.GizmoTransform; if (transform != Matrix4x4.Identity) { for (int i = 0; i < _workingStatic.Mesh.VerticesPositions.Count; i++) { var position = MathC.HomogenousTransform(_workingStatic.Mesh.VerticesPositions[i], transform); _workingStatic.Mesh.VerticesPositions[i] = new Vector3(position.X, position.Y, position.Z); } for (int i = 0; i < _workingStatic.Mesh.VerticesNormals.Count; i++) { var normal = MathC.HomogenousTransform(_workingStatic.Mesh.VerticesNormals[i], transform); _workingStatic.Mesh.VerticesNormals[i] = new Vector3(normal.X, normal.Y, normal.Z); } } // Assign the edited mesh to original static mesh _wad.Statics.Remove(_workingStatic.Id); _wad.Statics.Add(_workingStatic.Id, _workingStatic); _workingStatic.Version = DataVersion.GetNext(); _tool.ToggleUnsavedChanges(); DialogResult = DialogResult.OK; Close(); }
public BoundingBox CalculateBoundingBox(AnimatedModel model, AnimatedModel skin, List <int> meshesToUse = null) { Vector3 min = new Vector3(float.MaxValue); Vector3 max = new Vector3(float.MinValue); for (int i = 0; i < skin.Meshes.Count; i++) { if (meshesToUse != null && !meshesToUse.Contains(i)) { continue; } foreach (var vertex in skin.Meshes[i].Vertices) { var transformedPosition = MathC.HomogenousTransform(vertex.Position, model.AnimationTransforms[i]); min = Vector3.Min(transformedPosition, min); max = Vector3.Max(transformedPosition, max); } } BoundingBox = new BoundingBox(new Vector3((int)min.X, (int)max.Y, (int)min.Z), new Vector3((int)max.X, (int)min.Y, (int)max.Z)); return(BoundingBox); }
public override Vector3 GetDirection() { Matrix4x4 rotation = GetRotationMatrix(); Vector3 look = MathC.HomogenousTransform(Vector3.UnitZ, rotation); return(Vector3.Normalize(look)); }
public override Vector3 GetDirection() { // Translate down the Z axis by the desired distance // between the camera and object, then rotate that // vector to find the camera offset from the target return(MathC.HomogenousTransform(new Vector3(0, 0, Distance), GetRotationMatrix())); }
public override void MoveCameraPlane(Vector3 movementVec) { Matrix4x4 rotation = GetRotationMatrix(); Vector3 look = MathC.HomogenousTransform(Vector3.UnitZ, rotation); Vector3 right = MathC.HomogenousTransform(Vector3.UnitX, rotation); Vector3 up = Vector3.Cross(look, right); Position -= movementVec.Z * look; Position -= movementVec.X * right; }
public override Matrix4x4 GetViewProjectionMatrix(float width, float height) { // Calculate up vector Matrix4x4 rotation = Matrix4x4.CreateFromYawPitchRoll(RotationY, -RotationX, 0); Vector3 up = MathC.HomogenousTransform(Vector3.UnitY, rotation); //new Vector3(0, 150, 0), Vector3.Up); Matrix4x4 View = MathC.Matrix4x4CreateLookAtLH(GetPosition(), Target, up); float aspectRatio = width / height; Matrix4x4 Projection = MathC.Matrix4x4CreatePerspectiveFieldOfViewLH(FieldOfView, aspectRatio, 20.0f, 1000000.0f); Matrix4x4 result = View * Projection; return(result); }
private bool DoMeshPicking(Ray ray, int meshIndex, out float meshDistance) { meshDistance = 0; // Transform view ray to object space space Matrix4x4 inverseObjectMatrix; if (!Matrix4x4.Invert((_editor.CurrentAnim != null ? _model.AnimationTransforms[meshIndex] : _model.BindPoseTransforms[meshIndex]), out inverseObjectMatrix)) { return(false); } Vector3 transformedRayPos = MathC.HomogenousTransform(ray.Position, inverseObjectMatrix); Vector3 transformedRayDestination = MathC.HomogenousTransform(ray.Position + ray.Direction, inverseObjectMatrix); Ray transformedRay = new Ray(transformedRayPos, transformedRayDestination - transformedRayPos); transformedRay.Direction = Vector3.Normalize(transformedRay.Direction); // Now do a ray - triangle intersection test bool hit = false; float minDistance = float.PositiveInfinity; var mesh = _skinModel.Meshes[meshIndex]; foreach (var submesh in mesh.Submeshes) { for (int k = 0; k < submesh.Value.Indices.Count; k += 3) { Vector3 p1 = mesh.Vertices[submesh.Value.Indices[k]].Position; Vector3 p2 = mesh.Vertices[submesh.Value.Indices[k + 1]].Position; Vector3 p3 = mesh.Vertices[submesh.Value.Indices[k + 2]].Position; float distance; if (Collision.RayIntersectsTriangle(transformedRay, p1, p2, p3, out distance) && distance < minDistance) { minDistance = distance; hit = true; } } } if (hit) { meshDistance = minDistance; return(true); } else { return(false); } }
public override Matrix4x4 GetViewProjectionMatrix(float width, float height) { Matrix4x4 rotation = GetRotationMatrix(); Vector3 look = MathC.HomogenousTransform(Vector3.UnitZ, rotation); Vector3 right = MathC.HomogenousTransform(Vector3.UnitX, rotation); Vector3 up = Vector3.Cross(look, right); Target = Position + 1024.0f * look; Matrix4x4 View = MathC.Matrix4x4CreateLookAtLH(Position, Target, up); float aspectRatio = width / height; Matrix4x4 Projection = MathC.Matrix4x4CreatePerspectiveFieldOfViewLH(FieldOfView, aspectRatio, 20.0f, 1000000.0f); Matrix4x4 result = View * Projection; return(result); }
public BoundingBox CalculateBoundingBox(Matrix4x4 transform) { float minX = float.MaxValue; float minY = float.MaxValue; float minZ = float.MaxValue; float maxX = float.MinValue; float maxY = float.MinValue; float maxZ = float.MinValue; foreach (Vector3 oldVertex in VerticesPositions) { var transformedVertex = MathC.HomogenousTransform(oldVertex, transform); minX = (float)Math.Min(transformedVertex.X, minX); minY = (float)Math.Min(transformedVertex.Y, minY); minZ = (float)Math.Min(transformedVertex.Z, minZ); maxX = (float)Math.Max(transformedVertex.X, maxX); maxY = (float)Math.Max(transformedVertex.Y, maxY); maxZ = (float)Math.Max(transformedVertex.Z, maxZ); } return(new BoundingBox(new Vector3(minX, maxY, minZ), new Vector3(maxX, minY, maxZ))); }
private bool DoNodePicking(Ray ray, WadMeshBoneNode node, out float nodeDistance) { nodeDistance = 0; // Transform view ray to object space space Matrix4x4 inverseObjectMatrix; if (!Matrix4x4.Invert(node.GlobalTransform, out inverseObjectMatrix)) { return(false); } Vector3 transformedRayPos = MathC.HomogenousTransform(ray.Position, inverseObjectMatrix); Vector3 transformedRayDestination = MathC.HomogenousTransform(ray.Position + ray.Direction, inverseObjectMatrix); Ray transformedRay = new Ray(transformedRayPos, transformedRayDestination - transformedRayPos); transformedRay.Direction = Vector3.Normalize(transformedRay.Direction); // Now do a ray - triangle intersection test bool hit = false; float minDistance = float.PositiveInfinity; var mesh = node.WadMesh; foreach (var poly in mesh.Polys) { if (poly.Shape == WadPolygonShape.Quad) { Vector3 p1 = mesh.VerticesPositions[poly.Index0]; Vector3 p2 = mesh.VerticesPositions[poly.Index1]; Vector3 p3 = mesh.VerticesPositions[poly.Index2]; Vector3 p4 = mesh.VerticesPositions[poly.Index3]; float distance; if (Collision.RayIntersectsTriangle(transformedRay, p1, p2, p3, out distance) && distance < minDistance) { minDistance = distance; hit = true; } if (Collision.RayIntersectsTriangle(transformedRay, p1, p3, p4, out distance) && distance < minDistance) { minDistance = distance; hit = true; } } else { Vector3 p1 = mesh.VerticesPositions[poly.Index0]; Vector3 p2 = mesh.VerticesPositions[poly.Index1]; Vector3 p3 = mesh.VerticesPositions[poly.Index2]; float distance; if (Collision.RayIntersectsTriangle(transformedRay, p1, p2, p3, out distance) && distance < minDistance) { minDistance = distance; hit = true; } } } /* * _wadRenderer.Dispose(); * foreach (var submesh in node.Bone.Children.Select(bone => bone.Mesh)) * for (int k = 0; k < submesh.Value.Indices.Count; k += 3) * { * var mesh = _wadRenderer.GetStatic(new WadStatic(new WadStaticId(0)) { Mesh = node.WadMesh }); * * Vector3 p1 = mesh.Vertices[submesh.Value.Indices[k]].Position; * Vector3 p2 = mesh.Vertices[submesh.Value.Indices[k + 1]].Position; * Vector3 p3 = mesh.Vertices[submesh.Value.Indices[k + 2]].Position; * * float distance; * if (Collision.RayIntersectsTriangle(transformedRay, p1, p2, p3, out distance) && distance < minDistance) * { * minDistance = distance; * hit = true; * } * }*/ // TODO Avoid using the renderer for pickingData transforms need to be available in wad mesh without rendering. int TODO_DoNodePicking; if (hit) { nodeDistance = minDistance; return(true); } else { return(false); } }
public PickingResultGizmo DoPicking(Ray ray) { if (!DrawGizmo) { return(null); } bool upside = Orientation == GizmoOrientation.UpsideDown; // Check for translation if (SupportTranslateX) { float unused; BoundingSphere sphereX = new BoundingSphere(Position + Vector3.UnitX * (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, TranslationConeSize / 1.5f); if (Collision.RayIntersectsSphere(ray, sphereX, out unused)) { return(new PickingResultGizmo(GizmoMode.TranslateX)); } } if (SupportTranslateY) { float unused; BoundingSphere sphereY = new BoundingSphere(Position + Vector3.UnitY * (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, TranslationConeSize / 1.5f); if (Collision.RayIntersectsSphere(ray, sphereY, out unused)) { return(new PickingResultGizmo(GizmoMode.TranslateY)); } } if (SupportTranslateZ) { float unused; BoundingSphere sphereZ = new BoundingSphere(Position - Vector3.UnitZ * (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, TranslationConeSize / 1.5f); if (Collision.RayIntersectsSphere(ray, sphereZ, out unused)) { return(new PickingResultGizmo(GizmoMode.TranslateZ)); } } // Check for scale if (SupportScale) { float unused; BoundingBox scaleX = new BoundingBox(Position + Vector3.UnitX * (upside ? -Size : Size) / 2.0f - new Vector3(ScaleCubeSize / 2.0f), Position + Vector3.UnitX * (upside ? -Size : Size) / 2.0f + new Vector3(ScaleCubeSize / 2.0f)); if (Collision.RayIntersectsBox(ray, scaleX, out unused)) { return(new PickingResultGizmo(GizmoMode.ScaleX)); } BoundingBox scaleY = new BoundingBox(Position + Vector3.UnitY * (upside ? -Size : Size) / 2.0f - new Vector3(ScaleCubeSize / 2.0f), Position + Vector3.UnitY * (upside ? -Size : Size) / 2.0f + new Vector3(ScaleCubeSize / 2.0f)); if (Collision.RayIntersectsBox(ray, scaleY, out unused)) { return(new PickingResultGizmo(GizmoMode.ScaleY)); } BoundingBox scaleZ = new BoundingBox(Position - Vector3.UnitZ * (upside ? -Size : Size) / 2.0f - new Vector3(ScaleCubeSize / 2.0f), Position - Vector3.UnitZ * (upside ? -Size : Size) / 2.0f + new Vector3(ScaleCubeSize / 2.0f)); if (Collision.RayIntersectsBox(ray, scaleZ, out unused)) { return(new PickingResultGizmo(GizmoMode.ScaleZ)); } } // Check for rotation float pickRadius = LineThickness / 2 + (Size * 0.045f); if (SupportRotationZ) { Plane planeZ = MathC.CreatePlaneAtPoint(Position, MathC.HomogenousTransform(Vector3.UnitZ, RotateMatrixZ)); Vector3 intersectionPoint; if (Collision.RayIntersectsPlane(ray, planeZ, out intersectionPoint)) { var distance = (intersectionPoint - Position).Length(); if (distance >= Size - pickRadius && distance <= Size + pickRadius) { Vector3 startDirection = Vector3.Normalize(intersectionPoint - Position); float sin = Vector3.Dot(Vector3.UnitY, startDirection); float cos = Vector3.Dot(planeZ.Normal, Vector3.Cross(Vector3.UnitY, startDirection)); return(new PickingResultGizmo(GizmoMode.RotateZ, (float)Math.Atan2(-sin, cos), distance)); } } } if (SupportRotationX) { Plane planeX = MathC.CreatePlaneAtPoint(Position, MathC.HomogenousTransform(Vector3.UnitX, RotateMatrixX)); Vector3 intersectionPoint; if (Collision.RayIntersectsPlane(ray, planeX, out intersectionPoint)) { var distance = (intersectionPoint - Position).Length(); if (distance >= Size - pickRadius && distance <= Size + pickRadius) { Vector3 startDirection = Vector3.Normalize(intersectionPoint - Position); float sin = Vector3.Dot(Vector3.UnitY, startDirection); float cos = Vector3.Dot(planeX.Normal, Vector3.Cross(Vector3.UnitY, startDirection)); return(new PickingResultGizmo(GizmoMode.RotateX, (float)Math.Atan2(-sin, cos), distance)); } } } if (SupportRotationY) { Plane planeY = MathC.CreatePlaneAtPoint(Position, MathC.HomogenousTransform(Vector3.UnitY, RotateMatrixY)); Vector3 intersectionPoint; if (Collision.RayIntersectsPlane(ray, planeY, out intersectionPoint)) { var distance = (intersectionPoint - Position).Length(); if (distance >= Size - pickRadius && distance <= Size + pickRadius) { Vector3 startDirection = Vector3.Normalize(intersectionPoint - Position); float sin = Vector3.Dot(Vector3.UnitZ, startDirection); float cos = Vector3.Dot(planeY.Normal, Vector3.Cross(Vector3.UnitZ, startDirection)); return(new PickingResultGizmo(GizmoMode.RotateY, (float)Math.Atan2(-sin, cos), distance)); } } } return(null); }
/// <returns>true, if an iteraction with the gizmo is happening</returns> public bool MouseMoved(Matrix4x4 viewProjection, Ray ray) { if (!DrawGizmo || _mode == GizmoMode.None) { return(false); } bool upside = Orientation == GizmoOrientation.UpsideDown; bool flippedScale = false; // Flip sizing dimensions if object is rotateable on Y axis if ((_mode == GizmoMode.ScaleX || _mode == GizmoMode.ScaleZ) && SupportRotationY) { flippedScale = MathC.RadToDeg(RotationY) % 180.0f >= 45.0f; } // First get the ray in 3D space from X, Y mouse coordinates switch (_mode) { case GizmoMode.TranslateX: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitY, Vector3.UnitZ, out intersection)) { GizmoMove(new Vector3(intersection.X - (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, Position.Y, Position.Z)); GizmoMoveDelta(new Vector3(intersection.X - (upside ? -Size : Size) * _arrowHeadOffsetMultiplier - Position.X, 0.0f, 0.0f)); } } break; case GizmoMode.TranslateY: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitX, Vector3.UnitZ, out intersection)) { GizmoMove(new Vector3(Position.X, intersection.Y - (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, Position.Z)); GizmoMoveDelta(new Vector3(0.0f, intersection.Y - (upside ? -Size : Size) * _arrowHeadOffsetMultiplier - Position.Y, 0.0f)); } } break; case GizmoMode.TranslateZ: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitX, Vector3.UnitY, out intersection)) { GizmoMove(new Vector3(Position.X, Position.Y, intersection.Z + (upside ? -Size : Size) * _arrowHeadOffsetMultiplier)); GizmoMoveDelta(new Vector3(0.0f, 0.0f, intersection.Z + (upside ? -Size : Size) * _arrowHeadOffsetMultiplier - Position.Z)); } } break; case GizmoMode.ScaleX: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitY, Vector3.UnitZ, out intersection)) { if (flippedScale) { GizmoScaleZ(_scaleBase.Z * (float)Math.Exp(_scaleSpeed * (intersection.X - Position.X))); } else { GizmoScaleX(_scaleBase.X * (float)Math.Exp(_scaleSpeed * (intersection.X - Position.X))); } } } break; case GizmoMode.ScaleY: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitX, Vector3.UnitZ, out intersection)) { GizmoScaleY(_scaleBase.Y * (float)Math.Exp(_scaleSpeed * (intersection.Y - Position.Y))); } } break; case GizmoMode.ScaleZ: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitX, Vector3.UnitY, out intersection)) { if (flippedScale) { GizmoScaleX(_scaleBase.X * (float)Math.Exp(_scaleSpeed * -(intersection.Z - Position.Z))); } else { GizmoScaleZ(_scaleBase.Z * (float)Math.Exp(_scaleSpeed * -(intersection.Z - Position.Z))); } } } break; case GizmoMode.RotateY: { Plane rotationPlane = MathC.CreatePlaneAtPoint(Position, MathC.HomogenousTransform(Vector3.UnitY, RotateMatrixY)); Vector3 rotationIntersection; if (Collision.RayIntersectsPlane(ray, rotationPlane, out rotationIntersection)) { Vector3 direction = rotationIntersection - Position; _rotationLastMouseRadius = direction.Length(); direction = Vector3.Normalize(direction); float sin = Vector3.Dot(Vector3.UnitZ, direction); float cos = Vector3.Dot(rotationPlane.Normal, Vector3.Cross(Vector3.UnitZ, direction)); _rotationLastMouseAngle = (float)Math.Atan2(-sin, cos); GizmoRotateY(SimplifyAngle(_rotationPickAngleOffset + _rotationLastMouseAngle)); } } break; case GizmoMode.RotateX: { Plane rotationPlane = MathC.CreatePlaneAtPoint(Position, MathC.HomogenousTransform(Vector3.UnitX, RotateMatrixX)); Vector3 rotationIntersection; if (Collision.RayIntersectsPlane(ray, rotationPlane, out rotationIntersection)) { Vector3 direction = rotationIntersection - Position; _rotationLastMouseRadius = direction.Length(); direction = Vector3.Normalize(direction); float sin = Vector3.Dot(Vector3.UnitY, direction); float cos = Vector3.Dot(rotationPlane.Normal, Vector3.Cross(Vector3.UnitY, direction)); _rotationLastMouseAngle = (float)Math.Atan2(-sin, cos); GizmoRotateX(SimplifyAngle(_rotationPickAngleOffset + _rotationLastMouseAngle)); } } break; case GizmoMode.RotateZ: { Plane rotationPlane = MathC.CreatePlaneAtPoint(Position, MathC.HomogenousTransform(Vector3.UnitZ, RotateMatrixZ)); Vector3 rotationIntersection; if (Collision.RayIntersectsPlane(ray, rotationPlane, out rotationIntersection)) { Vector3 direction = rotationIntersection - Position; _rotationLastMouseRadius = direction.Length(); direction = Vector3.Normalize(direction); float sin = Vector3.Dot(Vector3.UnitY, direction); float cos = Vector3.Dot(rotationPlane.Normal, Vector3.Cross(Vector3.UnitY, direction)); _rotationLastMouseAngle = (float)Math.Atan2(-sin, cos); GizmoRotateZ(SimplifyAngle(_rotationPickAngleOffset + _rotationLastMouseAngle)); } } break; } return(true); }
public override void MoveCameraPlane(Vector3 movementVec) { float distanceMultiplier = (float)Math.Pow(Distance / DefaultDistance, 2 / (float)3); Target += MathC.HomogenousTransform(movementVec * distanceMultiplier, GetRotationMatrix()); }