private void BevelFace(SolidFace solidFace, int num) { var face = solidFace.Face; var solid = solidFace.Solid.Copy; // Remember the original positions var vertexPositions = face.Vertices.Select(x => x.Position).ToList(); // Scale the face a bit and move it away by the bevel distance var origin = face.Origin; face.Transform(Matrix4x4.CreateScale(Vector3.One * 0.9f, origin)); face.Transform(Matrix4x4.CreateTranslation(face.Plane.Normal * num)); var vertList = face.Vertices.ToList(); // Create a face for each new edge -> old edge foreach (var edge in face.GetEdges()) { var startIndex = vertList.FindIndex(x => x.Position.EquivalentTo(edge.Start)); var endIndex = vertList.FindIndex(x => x.Position.EquivalentTo(edge.End)); var verts = new[] { vertexPositions[startIndex], vertexPositions[endIndex], edge.End, edge.Start }; var f = new MutableFace(verts, face.Texture.Clone()); solid.Faces.Add(f); } }
/// <summary> /// Checks if a ray is colliding with a solid by checking against it planes /// Uses ray vs convex polyheron algorithm /// We can do this because the solid brushes are always convex!!! /// Else we had to use a check against polygon also /// </summary> /// <param name="solid"></param> /// <param name="hitFace"></param> /// <param name="tRef"></param> /// <returns></returns> public bool IsIntersecting(Solid solid, ref SolidFace hitFace, ref float tRef) { float tfirst = 0.0f; float tlast = float.MaxValue; Vector3 origin = Origin; Vector3 direction = Direction; foreach (SolidFace face in solid.Faces) { if (face.Indices.Count < 3) { continue; } int index = face.Indices[0].Index; Vector3 pointOnPlane = solid.VertexPositions[index]; float distanceToPlane = Vector3.Dot(face.Normal, origin - pointOnPlane); float denom = Vector3.Dot(direction, face.Normal); if (Math.Abs(denom) < GeneralUtility.Epsilon) { if (distanceToPlane > 0.0f) { return(false); } } else { float t = -distanceToPlane / denom; if (denom < -GeneralUtility.Epsilon) { if (t > tfirst) { tfirst = t; hitFace = face; } } else { if (t < tlast) { tlast = t; } } if (tfirst > tlast) { return(false); } } } tRef = tfirst; return(true); }
public SolidFace CreateFace(params int[] indices) { SolidFace face = new SolidFace(); // save as trianglefan foreach (int index in indices) { face.Indices.Add(CreateIndex(index)); } return(face); }
public override bool OnMouseDown(Point mouseCurPos, MouseButtons button, BaseViewport viewport) { MapObjectGroup selectedMapObjectGroup = controller.Selection; MapObject rootMapObject = controller.GetMapObjectIfHit(mouseCurPos.X, mouseCurPos.Y, viewport); if (viewport.ViewportType == BaseViewport.ViewportTypes.PERSPECTIVE) { if (rootMapObject == null) { SetAllFacesSelected(false); selectedMapObjectGroup.Clear(); } else { SolidFaceHitOperation operation = new SolidFaceHitOperation(viewport, mouseCurPos); rootMapObject.PerformOperation(operation); SolidFace hitFace = operation.hitFace; if (modifierKey == Keys.Control) { if (!AreAnyFacesSelected(rootMapObject)) { controller.Selection.Add(rootMapObject); } hitFace.Selected = !hitFace.Selected; if (!AreAnyFacesSelected(rootMapObject)) { controller.Selection.Remove(rootMapObject); } } else if (!hitFace.Selected) { SetAllFacesSelected(false); selectedMapObjectGroup.Clear(); hitFace.Selected = true; selectedMapObjectGroup.Add(rootMapObject); } } } else if (rootMapObject == null) // deselect faces when pressing in empty ortho viewport space { SetAllFacesSelected(false); controller.Selection.Clear(); } controller.UpdateUserInterface(); return(true); }
public void Visit(Solid solid) { float tFraction = float.MaxValue; SolidFace face = null; if (ray.IsIntersecting(solid, ref face, ref tFraction)) { if (tFraction < t) { t = tFraction; hitFace = face; } } }
private void CheckIntersection(Solid solid, ref float tFraction) { SolidFace hitFace = null; if (viewport.ViewportType != BaseViewport.ViewportTypes.PERSPECTIVE) { hasIntersected = CheckBrushCenterHit(solid, ref tFraction) || CheckBrushEdgesHit(solid, ref tFraction); } else { hasIntersected = ray.IsIntersecting(solid, ref hitFace, ref tFraction); } }
private List <SolidFace> ExtractFaces(JProperty property) { if (property.Type != JTokenType.Property || !property.HasValues) { return(null); } JArray faceArray = property.Value as JArray; if (faceArray == null) { return(null); } List <SolidFace> faces = new List <SolidFace>(); foreach (JObject faceObject in faceArray.Children <JObject>()) { SolidFace face = new SolidFace(); foreach (JProperty data in faceObject.Children <JProperty>()) { switch (data.Name) { case "texture": Texture2D texture = new Texture2D(data.Value.ToString(), false); face.Texture = texture; break; case "texturemapping": face.TextureMapping = ExtractTexturemapping(data.Value <JProperty>()); break; case "indices": List <SolidIndex> indices = ExtractIndices(data.Value.Value <JArray>()); face.Indices.AddRange(indices); break; } } faces.Add(face); } if (faces.Count <= 0) { throw new RunegearFileformatErrorException("Some solid faces could not be added!"); } return(faces); }
private void PokeFace(SolidFace solidFace, int num) { var face = solidFace.Face; var solid = solidFace.Solid.Copy; // Remove the face solid.Faces.Remove(face); var center = face.Origin + face.Plane.Normal * num; foreach (var edge in face.GetEdges()) { var v1 = face.Vertices.First(x => x.Position.EquivalentTo(edge.Start)); var v2 = face.Vertices.First(x => x.Position.EquivalentTo(edge.End)); var verts = new[] { v1.Position, v2.Position, center }; var f = new MutableFace(verts, face.Texture.Clone()); solid.Faces.Add(f); } }
public override Solid CreateSolid(AABB bounds) { int piePieces = sidesPropertyControl.Sides; Solid solidCone = new Solid(); SolidFace bottomFace = new SolidFace(); // create 4 corners points for the box float halfWidth = (bounds.Max.X - bounds.Min.X) / 2.0f; float halfHeight = (bounds.Max.Y - bounds.Min.Y) / 2.0f; float halfDepth = (bounds.Max.Z - bounds.Min.Z) / 2.0f; solidCone.Bounds = (AABB)bounds.Clone(); solidCone.VertexPositions.Add(new Vector3(bounds.Center.X, bounds.Center.Y, -halfDepth)); float degToRad = (float)(Math.PI / 180.0); float radPiece = (360.0f / piePieces * degToRad); // create vertices for (int i = 0; i < piePieces; i++) { SolidIndex index = new SolidIndex(); Vector3 position = new Vector3 { X = (float)Math.Cos(i * -radPiece) * halfWidth, Y = (float)Math.Sin(i * -radPiece) * halfHeight, Z = halfDepth }; index.Index = i + 1; solidCone.VertexPositions.Add(bounds.Center + position); bottomFace.Indices.Add(index); } solidCone.Faces.Add(bottomFace); int vertexCount = solidCone.VertexPositions.Count; // generate body for (int i = 0; i < piePieces; i++) { int index = i + 1; int nextIndex = index + 1; if (nextIndex == vertexCount) { nextIndex = 1; } SolidFace bodyFace = new SolidFace(); SolidIndex a = new SolidIndex { Index = 0 }; SolidIndex b = new SolidIndex { Index = index }; SolidIndex c = new SolidIndex { Index = nextIndex }; bodyFace.Indices.Add(c); bodyFace.Indices.Add(b); bodyFace.Indices.Add(a); solidCone.Faces.Add(bodyFace); } return(solidCone); }
public override Solid CreateSolid(AABB bounds) { int piePieces = sidesPropertyControl.Sides; Solid solidCylinder = new Solid(); SolidFace topFace = new SolidFace(); SolidFace bottomFace = new SolidFace(); solidCylinder.Bounds = (AABB)bounds.Clone(); Vector3 center = bounds.Center; // create 4 corners points for the box float halfWidth = (bounds.Max.X - bounds.Min.X) / 2.0f; float halfHeight = (bounds.Max.Y - bounds.Min.Y) / 2.0f; float halfDepth = (bounds.Max.Z - bounds.Min.Z) / 2.0f; float degToRad = (float)(Math.PI / 180.0); float radPiece = (360.0f / piePieces * degToRad); // create top and bottom face for (int i = 0; i < piePieces; i++) { SolidIndex topIndex = new SolidIndex(); SolidIndex bottomIndex = new SolidIndex(); Vector3 position = new Vector3 { X = (float)Math.Cos(i * radPiece) * halfWidth, Y = (float)Math.Sin(i * radPiece) * halfHeight }; solidCylinder.VertexPositions.Add(center + new Vector3(position.X, position.Y, -halfDepth)); solidCylinder.VertexPositions.Add(center + new Vector3(position.X, position.Y, halfDepth)); topIndex.Index = i * 2; bottomIndex.Index = piePieces * 2 - (i * 2 + 1); topFace.Indices.Add(topIndex); bottomFace.Indices.Add(bottomIndex); } solidCylinder.Faces.Add(topFace); solidCylinder.Faces.Add(bottomFace); // generate body for (int i = 0; i < piePieces; i++) { int nextIndex = i + 1; if (nextIndex == piePieces) { nextIndex = 0; } SolidFace bodyFace = new SolidFace(); SolidIndex a = new SolidIndex(); SolidIndex b = new SolidIndex(); SolidIndex c = new SolidIndex(); SolidIndex d = new SolidIndex(); a.Index = i * 2; b.Index = i * 2 + 1; c.Index = nextIndex * 2 + 1; d.Index = nextIndex * 2; bodyFace.Indices.Add(a); bodyFace.Indices.Add(b); bodyFace.Indices.Add(c); bodyFace.Indices.Add(d); solidCylinder.Faces.Add(bodyFace); } return(solidCylinder); }