public static Mesh CreateWirePyramid(Vector3 baseCenter, float baseWidth, float baseDepth, float height, Color color) { baseWidth = Mathf.Max(Mathf.Abs(baseWidth), 1e-4f); baseDepth = Mathf.Max(Mathf.Abs(baseDepth), 1e-4f); height = Mathf.Max(Mathf.Abs(height), 1e-4f); float halfBaseWidth = baseWidth * 0.5f; float halfBaseDepth = baseDepth * 0.5f; Vector3[] positions = new Vector3[] { baseCenter - Vector3.right * halfBaseWidth - Vector3.forward * halfBaseDepth, baseCenter + Vector3.right * halfBaseWidth - Vector3.forward * halfBaseDepth, baseCenter + Vector3.right * halfBaseWidth + Vector3.forward * halfBaseDepth, baseCenter - Vector3.right * halfBaseWidth + Vector3.forward * halfBaseDepth, baseCenter + Vector3.up * height }; int[] indices = new int[] { 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 1, 4, 2, 4, 3, 4 }; Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.colors = ColorEx.GetFilledColorArray(positions.Length, color); mesh.SetIndices(indices, MeshTopology.Lines, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreateWireCircleXY(float circleRadius, int numBorderPoints, Color color) { if (circleRadius < 1e-4f || numBorderPoints < 4) { return(null); } Vector3[] positions = new Vector3[numBorderPoints]; int[] indices = new int[numBorderPoints]; float angleStep = 360.0f / (numBorderPoints - 1); for (int ptIndex = 0; ptIndex < numBorderPoints; ++ptIndex) { float angle = angleStep * ptIndex * Mathf.Deg2Rad; positions[ptIndex] = new Vector3(Mathf.Sin(angle) * circleRadius, Mathf.Cos(angle) * circleRadius, 0.0f); indices[ptIndex] = ptIndex; } Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.colors = ColorEx.GetFilledColorArray(numBorderPoints, color); mesh.SetIndices(indices, MeshTopology.LineStrip, 0); mesh.UploadMeshData(false); return(mesh); }
public void SetAxisColor(int axisIndex, Color color) { GetSglSliderLookAndFeel(axisIndex, AxisSign.Positive).Color = color; GetSglSliderLookAndFeel(axisIndex, AxisSign.Positive).CapLookAndFeel.Color = color; GetSglSliderLookAndFeel(axisIndex, AxisSign.Negative).Color = color; GetSglSliderLookAndFeel(axisIndex, AxisSign.Negative).CapLookAndFeel.Color = color; GizmoPlaneSlider3DLookAndFeel dblLookAndFeel = null; if (axisIndex == 0) { dblLookAndFeel = GetDblSliderLookAndFeel(PlaneId.YZ); _scaleGuideLookAndFeel.XAxisColor = color; } else if (axisIndex == 1) { dblLookAndFeel = GetDblSliderLookAndFeel(PlaneId.ZX); _scaleGuideLookAndFeel.YAxisColor = color; } else if (axisIndex == 2) { dblLookAndFeel = GetDblSliderLookAndFeel(PlaneId.XY); _scaleGuideLookAndFeel.ZAxisColor = color; } dblLookAndFeel.Color = ColorEx.KeepAllButAlpha(color, dblLookAndFeel.Color.a); dblLookAndFeel.BorderColor = color; }
public override void Render(Camera camera) { var sgLookAndFeel = _sceneGizmo.LookAndFeel; RTSceneGizmoCamera sceneGizmoCamera = _sceneGizmo.SceneGizmoCamera; _cap.Render(camera); if (_axisDesc.IsPositive) { GizmoLabelMaterial labelMaterial = GizmoLabelMaterial.Get; labelMaterial.SetZWriteEnabled(false); labelMaterial.SetZTestLessEqual(); labelMaterial.SetColor(ColorEx.KeepAllButAlpha(sgLookAndFeel.AxesLabelTint, _color.Value.a)); labelMaterial.SetTexture(_labelTexture); labelMaterial.SetPass(0); Vector3 gizmoAxis = _sceneGizmo.Gizmo.Transform.GetAxis3D(_axisDesc); Vector3 labelScale = Vector3Ex.FromValue(sgLookAndFeel.GetAxesLabelWorldSize(sceneGizmoCamera.Camera, _cap.Position)); Vector3 labelPos = _cap.Position + gizmoAxis * (labelScale.x * 0.5f); Vector2 labelScreenPos = sceneGizmoCamera.Camera.WorldToScreenPoint(labelPos); Vector2 midAxisScreenPos = sceneGizmoCamera.Camera.WorldToScreenPoint(_sceneGizmo.SceneGizmoCamera.LookAtPoint); Vector2 labelScreenDir = (labelScreenPos - midAxisScreenPos).normalized; float absDotCamLook = Mathf.Abs(Vector3Ex.AbsDot(sceneGizmoCamera.Look, gizmoAxis)); labelScreenPos = labelScreenPos + Vector2.Scale(labelScreenDir, Vector2Ex.FromValue(SceneGizmoLookAndFeel.AxisLabelScreenSize)) * absDotCamLook; labelPos = sceneGizmoCamera.Camera.ScreenToWorldPoint(new Vector3(labelScreenPos.x, labelScreenPos.y, (labelPos - sceneGizmoCamera.WorldPosition).magnitude)); Quaternion labelRotation = Quaternion.LookRotation(sceneGizmoCamera.Look, sceneGizmoCamera.Up); Matrix4x4 labelTransformMtx = Matrix4x4.TRS(labelPos, labelRotation, labelScale); Graphics.DrawMeshNow(MeshPool.Get.UnitQuadXY, labelTransformMtx); } }
public static Mesh CreateCoordSystemAxesLines(float axisLength, Color color) { if (axisLength < 1e-4f) { return(null); } Vector3[] positions = new Vector3[] { Vector3.zero, Vector3.right *axisLength, Vector3.up *axisLength, Vector3.forward *axisLength }; int[] indices = new int[] { 0, 1, 0, 2, 0, 3 }; Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.colors = ColorEx.GetFilledColorArray(4, color); mesh.SetIndices(indices, MeshTopology.Lines, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreateWireTriangularPrism(Vector3 baseCenter, float baseWidth, float baseDepth, float topWidth, float topDepth, float height, Color color) { baseWidth = Mathf.Max(Mathf.Abs(baseWidth), 1e-4f); baseDepth = Mathf.Max(Mathf.Abs(baseDepth), 1e-4f); topWidth = Mathf.Max(Mathf.Abs(topWidth), 1e-4f); topDepth = Mathf.Max(Mathf.Abs(topDepth), 1e-4f); height = Mathf.Max(Mathf.Abs(height), 1e-4f); List <Vector3> cornerPoints = PrismMath.CalcTriangPrismCornerPoints(baseCenter, baseWidth, baseDepth, topWidth, topDepth, height, Quaternion.identity); Vector3 baseLeftPt = cornerPoints[(int)TriangularPrismCorner.BaseLeft]; Vector3 baseRightPt = cornerPoints[(int)TriangularPrismCorner.BaseRight]; Vector3 baseForwardPt = cornerPoints[(int)TriangularPrismCorner.BaseForward]; Vector3 topLeftPt = cornerPoints[(int)TriangularPrismCorner.TopLeft]; Vector3 topRightPt = cornerPoints[(int)TriangularPrismCorner.TopRight]; Vector3 topForwardPt = cornerPoints[(int)TriangularPrismCorner.TopForward]; Vector3[] positions = new Vector3[] { baseLeftPt, baseForwardPt, baseRightPt, topLeftPt, topForwardPt, topRightPt }; int[] indices = new int[] { 0, 1, 1, 2, 2, 0, 3, 4, 4, 5, 5, 3, 0, 3, 1, 4, 2, 5 }; Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.colors = ColorEx.GetFilledColorArray(positions.Length, color); mesh.SetIndices(indices, MeshTopology.Lines, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreateWireQuadXY(Vector3 center, Vector2 size, Color color) { Vector2 halfSize = size * 0.5f; Vector3[] positions = new Vector3[] { center - Vector3.right * halfSize.x - Vector3.up * halfSize.y, center - Vector3.right * halfSize.x + Vector3.up * halfSize.y, center + Vector3.right * halfSize.x + Vector3.up * halfSize.y, center + Vector3.right * halfSize.x - Vector3.up * halfSize.y }; int[] indices = new int[] { 0, 1, 1, 2, 2, 3, 3, 0 }; Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.colors = ColorEx.GetFilledColorArray(4, color); mesh.SetIndices(indices, MeshTopology.Lines, 0); mesh.UploadMeshData(false); return(mesh); }
public UniversalGizmoLookAndFeel2D() { for (int axisIndex = 0; axisIndex < _mvSglSliderLookAndFeel.Length; ++axisIndex) { _mvSglSliderLookAndFeel[axisIndex] = new GizmoLineSlider2DLookAndFeel(); } SetMvAxisColor(0, RTSystemValues.XAxisColor); SetMvAxisColor(1, RTSystemValues.YAxisColor); SetMvAxisBorderColor(0, RTSystemValues.XAxisColor); SetMvAxisBorderColor(1, RTSystemValues.YAxisColor); SetMvSliderHoveredFillColor(RTSystemValues.HoveredAxisColor); SetMvSliderHoveredBorderColor(RTSystemValues.HoveredAxisColor); SetMvSliderCapType(GizmoCap2DType.Arrow); SetMvSliderCapFillMode(GizmoFillMode2D.Filled); SetMvSliderFillMode(GizmoFillMode2D.Filled); SetMvSliderVisible(0, AxisSign.Positive, true); SetMvSliderVisible(1, AxisSign.Positive, true); SetMvSliderCapVisible(0, AxisSign.Positive, true); SetMvSliderCapVisible(1, AxisSign.Positive, true); SetMvDblSliderFillMode(GizmoFillMode2D.Border); SetMvDblSliderColor(ColorEx.KeepAllButAlpha(Color.white, RTSystemValues.AxisAlpha)); SetMvDblSliderBorderColor(Color.white); SetMvDblSliderHoveredColor(ColorEx.KeepAllButAlpha(RTSystemValues.HoveredAxisColor, RTSystemValues.AxisAlpha)); SetMvDblSliderHoveredBorderColor(RTSystemValues.HoveredAxisColor); }
public void SetDblSliderFillAlpha(float alpha) { alpha = Mathf.Clamp(alpha, 0.0f, 1.0f); foreach (var lookAndFeel in _dblSlidersLookAndFeel) { lookAndFeel.Color = ColorEx.KeepAllButAlpha(lookAndFeel.Color, alpha); lookAndFeel.HoveredColor = ColorEx.KeepAllButAlpha(lookAndFeel.HoveredColor, alpha); } }
public static Mesh CreateLine(Vector3 startPoint, Vector3 endPoint, Color color) { Mesh mesh = new Mesh(); mesh.vertices = new Vector3[] { startPoint, endPoint }; mesh.colors = ColorEx.GetFilledColorArray(2, color); mesh.SetIndices(new int[] { 0, 1 }, MeshTopology.Lines, 0); mesh.UploadMeshData(false); return(mesh); }
/// <summary> /// Can be used to draw the tree in the scene for debugging purposes. /// </summary> public void DebugDraw() { // Setup the rendering material Material material = MaterialPool.Get.GizmoSolidHandle; material.SetInt("_IsLit", 0); material.SetColor(ColorEx.KeepAllButAlpha(Color.green, 0.3f)); material.SetPass(0); // Draw the entire tree _root.DebugDraw(); }
public void OnGUI() { var sgLookAndFeel = _sceneGizmo.LookAndFeel; Camera gizmoCamera = _sceneGizmo.SceneGizmoCamera.Camera; if (sgLookAndFeel.IsCamPrjSwitchLabelVisible) { if (_sceneGizmo.SceneGizmoCamera.SceneCamera != RTFocusCamera.Get.TargetCamera || !RTFocusCamera.Get.IsDoingProjectionSwitch) { Texture2D labelTexture = gizmoCamera.orthographic ? sgLookAndFeel.CamOrthoModeLabelTexture : sgLookAndFeel.CamPerspModeLabelTexture; GUIEx.PushColor(sgLookAndFeel.CamPrjSwitchLabelTint); Rect drawRect = RectEx.FromTexture2D(labelTexture).PlaceBelowCenterHrz(gizmoCamera.pixelRect).InvertScreenY(); drawRect.center = new Vector2(drawRect.center.x, Screen.height - 1 - _labelQuad.Center.y); GUI.DrawTexture(drawRect, labelTexture); GUIEx.PopColor(); } else { Texture2D destLabelTexture = sgLookAndFeel.CamOrthoModeLabelTexture; Texture2D sourceLabelTexture = sgLookAndFeel.CamPerspModeLabelTexture; if (RTFocusCamera.Get.PrjSwitchTransitionType == CameraPrjSwitchTransition.Type.ToPerspective) { destLabelTexture = sgLookAndFeel.CamPerspModeLabelTexture; sourceLabelTexture = sgLookAndFeel.CamOrthoModeLabelTexture; } AnimationCurve srcAnimCurve = AnimationCurve.EaseInOut(0.0f, sgLookAndFeel.CamPrjSwitchLabelTint.a, 1.0f, 0.0f); AnimationCurve destAnimCurve = AnimationCurve.EaseInOut(0.0f, 0.0f, 1.0f, sgLookAndFeel.CamPrjSwitchLabelTint.a); float destAlpha = destAnimCurve.Evaluate(RTFocusCamera.Get.PrjSwitchProgress); float srcAlpha = srcAnimCurve.Evaluate(RTFocusCamera.Get.PrjSwitchProgress); GUIEx.PushColor(ColorEx.KeepAllButAlpha(sgLookAndFeel.CamPrjSwitchLabelTint, srcAlpha)); Rect drawRect = RectEx.FromTexture2D(sourceLabelTexture).PlaceBelowCenterHrz(gizmoCamera.pixelRect).InvertScreenY(); drawRect.center = new Vector2(drawRect.center.x, Screen.height - 1 - _labelQuad.Center.y); GUI.DrawTexture(drawRect, sourceLabelTexture); GUIEx.PopColor(); GUIEx.PushColor(ColorEx.KeepAllButAlpha(sgLookAndFeel.CamPrjSwitchLabelTint, destAlpha)); drawRect = RectEx.FromTexture2D(destLabelTexture).PlaceBelowCenterHrz(gizmoCamera.pixelRect).InvertScreenY(); drawRect.center = new Vector2(drawRect.center.x, Screen.height - 1 - _labelQuad.Center.y); GUI.DrawTexture(drawRect, destLabelTexture); GUIEx.PopColor(); } } }
public void SetHoveredColor(Color hoveredColor) { foreach (var lookAndFeel in _sglSlidersLookAndFeel) { lookAndFeel.HoveredColor = hoveredColor; lookAndFeel.CapLookAndFeel.HoveredColor = hoveredColor; } foreach (var lookAndFeel in _dblSlidersLookAndFeel) { lookAndFeel.HoveredBorderColor = hoveredColor; lookAndFeel.HoveredColor = ColorEx.KeepAllButAlpha(hoveredColor, lookAndFeel.Color.a); } _midCapLookAndFeel.HoveredColor = hoveredColor; }
public static Mesh CreateCircleXY(float circleRadius, int numBorderPoints, Color color) { if (circleRadius < 1e-4f || numBorderPoints < 4) { return(null); } int numVerts = numBorderPoints + 1; int numTriangles = numBorderPoints - 1; Vector3[] positions = new Vector3[numBorderPoints + 1]; Vector3[] normals = new Vector3[positions.Length]; int[] indices = new int[numTriangles * 3]; int indexPtr = 0; positions[0] = Vector3.zero; float angleStep = 360.0f / (numBorderPoints - 1); for (int ptIndex = 0; ptIndex < numBorderPoints; ++ptIndex) { float angle = angleStep * ptIndex * Mathf.Deg2Rad; int vertIndex = ptIndex + 1; positions[vertIndex] = new Vector3(Mathf.Sin(angle) * circleRadius, Mathf.Cos(angle) * circleRadius, 0.0f); normals[vertIndex] = Vector3.forward; } for (int vertIndex = 1; vertIndex < numVerts - 1; ++vertIndex) { indices[indexPtr++] = 0; indices[indexPtr++] = vertIndex; indices[indexPtr++] = vertIndex + 1; } Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.colors = ColorEx.GetFilledColorArray(positions.Length, color); mesh.normals = normals; mesh.SetIndices(indices, MeshTopology.Triangles, 0); mesh.UploadMeshData(false); return(mesh); }
private void UpdateColor() { var sgLookAndFeel = _sceneGizmo.LookAndFeel; Color lookAndFeelColor = sgLookAndFeel.GetAxisCapColor(_axisDesc.Index, _axisDesc.Sign); if (_cap.IsHovered) { lookAndFeelColor = sgLookAndFeel.HoveredColor; } ColorTransition.State ctState = _colorTransition.TransitionState; Vector3 axis = _sceneGizmo.Gizmo.Transform.GetAxis3D(_axisDesc); float alignment = Vector3Ex.AbsDot(axis, _sceneGizmo.SceneGizmoCamera.Look); if (alignment > SceneGizmoLookAndFeel.AxisCamAlignFadeOutThreshold) { if (ctState != ColorTransition.State.CompleteFadeOut && ctState != ColorTransition.State.FadingOut) { _colorTransition.DurationInSeconds = SceneGizmoLookAndFeel.AxisCamAlignFadeOutDuration; _colorTransition.FadeOutColor = ColorEx.KeepAllButAlpha(lookAndFeelColor, SceneGizmoLookAndFeel.AxisCamAlignFadeOutAlpha); _colorTransition.BeginFadeOut(true); } } else { if (ctState != ColorTransition.State.FadingIn && ctState != ColorTransition.State.CompleteFadeIn && ctState != ColorTransition.State.Ready) { _colorTransition.DurationInSeconds = SceneGizmoLookAndFeel.AxisCamAlignFadeOutDuration; _colorTransition.FadeInColor = lookAndFeelColor; _colorTransition.BeginFadeIn(true); } else { _color.Value = lookAndFeelColor; } } _colorTransition.Update(Time.deltaTime); _cap.OverrideColor.IsActive = true; _cap.OverrideColor.Color = _color.Value; }
public static Mesh CreateQuadXZ(float width, float depth, Color color) { if (width < 1e-4f) { return(null); } if (depth < 1e-4f) { return(null); } float halfWidth = width * 0.5f; float halfDepth = depth * 0.5f; Vector3[] positions = new Vector3[] { -Vector3.right * halfWidth - Vector3.forward * halfDepth, -Vector3.right * halfWidth + Vector3.forward * halfDepth, Vector3.right *halfWidth + Vector3.forward * halfDepth, Vector3.right *halfWidth - Vector3.forward * halfDepth }; Vector3[] normals = new Vector3[] { Vector3.up, Vector3.up, Vector3.up, Vector3.up }; Vector2[] uvs = new Vector2[] { Vector2.zero, new Vector2(0.0f, 1.0f), new Vector2(1.0f, 1.0f), new Vector2(1.0f, 0.0f) }; Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.normals = normals; mesh.uv = uvs; mesh.colors = ColorEx.GetFilledColorArray(4, color); mesh.SetIndices(new int[] { 0, 1, 2, 2, 3, 0 }, MeshTopology.Triangles, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreateTriangularPrism(Vector3 baseCenter, float baseWidth, float baseDepth, float topWidth, float topDepth, float height, Color color) { baseWidth = Mathf.Max(Mathf.Abs(baseWidth), 1e-4f); baseDepth = Mathf.Max(Mathf.Abs(baseDepth), 1e-4f); topWidth = Mathf.Max(Mathf.Abs(topWidth), 1e-4f); topDepth = Mathf.Max(Mathf.Abs(topDepth), 1e-4f); height = Mathf.Max(Mathf.Abs(height), 1e-4f); List <Vector3> cornerPoints = PrismMath.CalcTriangPrismCornerPoints(baseCenter, baseWidth, baseDepth, topWidth, topDepth, height, Quaternion.identity); Vector3 baseLeftPt = cornerPoints[(int)TriangularPrismCorner.BaseLeft]; Vector3 baseRightPt = cornerPoints[(int)TriangularPrismCorner.BaseRight]; Vector3 baseForwardPt = cornerPoints[(int)TriangularPrismCorner.BaseForward]; Vector3 topLeftPt = cornerPoints[(int)TriangularPrismCorner.TopLeft]; Vector3 topRightPt = cornerPoints[(int)TriangularPrismCorner.TopRight]; Vector3 topForwardPt = cornerPoints[(int)TriangularPrismCorner.TopForward]; Vector3[] positions = new Vector3[] { // Top face topLeftPt, topForwardPt, topRightPt, // Bottom face baseLeftPt, baseRightPt, baseForwardPt, // Back face baseLeftPt, topLeftPt, topRightPt, baseRightPt, // Left face baseLeftPt, baseForwardPt, topForwardPt, topLeftPt, // Right face baseRightPt, topRightPt, topForwardPt, baseForwardPt }; int[] indices = new int[] { // Top face 0, 1, 2, // Bottom face 3, 4, 5, // Back face 6, 7, 8, 8, 9, 6, // Left face 10, 11, 12, 12, 13, 10, // Right face 14, 15, 16, 16, 17, 14 }; Vector3 leftFaceNormal = Vector3.Cross((positions[11] - positions[10]), (positions[13] - positions[10])).normalized; Vector3 rightFaceNormal = Vector3.Cross((positions[15] - positions[14]), (positions[17] - positions[14])).normalized; Vector3[] normals = new Vector3[] { // Top face Vector3.up, Vector3.up, Vector3.up, // Bottom face -Vector3.up, -Vector3.up, -Vector3.up, // Back face -Vector3.forward, -Vector3.forward, -Vector3.forward, -Vector3.forward, // Left face leftFaceNormal, leftFaceNormal, leftFaceNormal, leftFaceNormal, // Right face rightFaceNormal, rightFaceNormal, rightFaceNormal, rightFaceNormal }; Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.colors = ColorEx.GetFilledColorArray(positions.Length, color); mesh.normals = normals; mesh.SetIndices(indices, MeshTopology.Triangles, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreatePyramid(Vector3 baseCenter, float baseWidth, float baseDepth, float height, Color color) { baseWidth = Mathf.Max(Mathf.Abs(baseWidth), 1e-4f); baseDepth = Mathf.Max(Mathf.Abs(baseDepth), 1e-4f); height = Mathf.Max(Mathf.Abs(height), 1e-4f); float halfBaseWidth = baseWidth * 0.5f; float halfBaseDepth = baseDepth * 0.5f; Vector3 tipPosition = baseCenter + Vector3.up * height; Vector3[] positions = new Vector3[] { // Front face tipPosition, baseCenter + Vector3.right * halfBaseWidth - Vector3.forward * halfBaseDepth, baseCenter - Vector3.right * halfBaseWidth - Vector3.forward * halfBaseDepth, // Right face tipPosition, baseCenter + Vector3.right * halfBaseWidth + Vector3.forward * halfBaseDepth, baseCenter + Vector3.right * halfBaseWidth - Vector3.forward * halfBaseDepth, // Back face tipPosition, baseCenter - Vector3.right * halfBaseWidth + Vector3.forward * halfBaseDepth, baseCenter + Vector3.right * halfBaseWidth + Vector3.forward * halfBaseDepth, // Left face tipPosition, baseCenter - Vector3.right * halfBaseWidth - Vector3.forward * halfBaseDepth, baseCenter - Vector3.right * halfBaseWidth + Vector3.forward * halfBaseDepth, // Bottom face baseCenter - Vector3.right * halfBaseWidth - Vector3.forward * halfBaseDepth, baseCenter + Vector3.right * halfBaseWidth - Vector3.forward * halfBaseDepth, baseCenter + Vector3.right * halfBaseWidth + Vector3.forward * halfBaseDepth, baseCenter - Vector3.right * halfBaseWidth + Vector3.forward * halfBaseDepth }; int[] indices = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 12, 14, 15 }; Vector3[] normals = new Vector3[positions.Length]; for (int triangleIndex = 0; triangleIndex < 4; ++triangleIndex) { int index0 = indices[triangleIndex * 3]; int index1 = indices[triangleIndex * 3 + 1]; int index2 = indices[triangleIndex * 3 + 2]; Vector3 edge0 = positions[index1] - positions[index0]; Vector3 edge1 = positions[index2] - positions[index0]; Vector3 normal = Vector3.Cross(edge0, edge1).normalized; normals[index0] = normal; normals[index1] = normal; normals[index2] = normal; } normals[normals.Length - 4] = -Vector3.up; normals[normals.Length - 3] = -Vector3.up; normals[normals.Length - 2] = -Vector3.up; normals[normals.Length - 1] = -Vector3.up; Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.colors = ColorEx.GetFilledColorArray(positions.Length, color); mesh.normals = normals; mesh.SetIndices(indices, MeshTopology.Triangles, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreateCylindricalTorus(Vector3 center, float coreRadius, float tubeHrzRadius, float tubeVertRadius, int numTubeSlices, Color color) { if (coreRadius < 1e-4f || tubeHrzRadius < 1e-4f || numTubeSlices < 3) { return(null); } int numVertsPerTubeSlice = 8; int numVerts = numVertsPerTubeSlice * (numTubeSlices + 1); Vector3[] positions = new Vector3[numVerts]; Vector3[] normals = new Vector3[numVerts]; Vector2[] radiusDirs = new Vector2[numVerts]; int vertexPtr = 0; float tubeAngleStep = 360.0f / (numTubeSlices - 1); for (int tubeSliceIndex = 0; tubeSliceIndex <= numTubeSlices; ++tubeSliceIndex) { float tubeAngle = tubeAngleStep * tubeSliceIndex * Mathf.Deg2Rad; float cosTube = Mathf.Cos(tubeAngle); float sinTube = Mathf.Sin(tubeAngle); Vector3 tubeSliceCenterDir = new Vector3(sinTube, 0.0f, cosTube).normalized; Vector3 tubeSliceCenter = center + tubeSliceCenterDir * coreRadius; Vector2 radiusDir = new Vector2(tubeSliceCenterDir.x, tubeSliceCenterDir.z); // Top radiusDirs[vertexPtr] = radiusDir; positions[vertexPtr] = tubeSliceCenter + Vector3.up * tubeVertRadius - tubeSliceCenterDir * tubeHrzRadius; normals[vertexPtr++] = Vector3.up; radiusDirs[vertexPtr] = radiusDir; positions[vertexPtr] = tubeSliceCenter + Vector3.up * tubeVertRadius + tubeSliceCenterDir * tubeHrzRadius; normals[vertexPtr++] = Vector3.up; // Back radiusDirs[vertexPtr] = radiusDir; positions[vertexPtr] = tubeSliceCenter + Vector3.up * tubeVertRadius + tubeSliceCenterDir * tubeHrzRadius; normals[vertexPtr++] = tubeSliceCenterDir; radiusDirs[vertexPtr] = radiusDir; positions[vertexPtr] = tubeSliceCenter - Vector3.up * tubeVertRadius + tubeSliceCenterDir * tubeHrzRadius; normals[vertexPtr++] = tubeSliceCenterDir; // Bottom radiusDirs[vertexPtr] = radiusDir; positions[vertexPtr] = tubeSliceCenter - Vector3.up * tubeVertRadius + tubeSliceCenterDir * tubeHrzRadius; normals[vertexPtr++] = -Vector3.up; radiusDirs[vertexPtr] = radiusDir; positions[vertexPtr] = tubeSliceCenter - Vector3.up * tubeVertRadius - tubeSliceCenterDir * tubeHrzRadius; normals[vertexPtr++] = -Vector3.up; // Front radiusDirs[vertexPtr] = radiusDir; positions[vertexPtr] = tubeSliceCenter - Vector3.up * tubeVertRadius - tubeSliceCenterDir * tubeHrzRadius; normals[vertexPtr++] = -tubeSliceCenterDir; radiusDirs[vertexPtr] = radiusDir; positions[vertexPtr] = tubeSliceCenter + Vector3.up * tubeVertRadius - tubeSliceCenterDir * tubeHrzRadius; normals[vertexPtr++] = -tubeSliceCenterDir; } int indexPtr = 0; int numIndices = numTubeSlices * 24; int[] indices = new int[numIndices]; for (int tubeSliceIndex = 0; tubeSliceIndex < numTubeSlices - 1; ++tubeSliceIndex) { int baseIndex = tubeSliceIndex * numVertsPerTubeSlice; // Top quad indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + 1; indices[indexPtr++] = baseIndex + 1 + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + 1 + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex + numVertsPerTubeSlice; // Back quad baseIndex += 2; indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + 1; indices[indexPtr++] = baseIndex + 1 + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + 1 + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex + numVertsPerTubeSlice; // Bottom quad baseIndex += 2; indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + 1; indices[indexPtr++] = baseIndex + 1 + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + 1 + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex + numVertsPerTubeSlice; // Front quad baseIndex += 2; indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + 1; indices[indexPtr++] = baseIndex + 1 + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + 1 + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex + numVertsPerTubeSlice; } Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.normals = normals; mesh.uv2 = radiusDirs; mesh.colors = ColorEx.GetFilledColorArray(numVerts, color); mesh.SetIndices(indices, MeshTopology.Triangles, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreateCylinder(float bottomRadius, float topRadius, float height, int numSlices, int numStacks, int numBottomCapRings, int numTopCapRings, Color color) { const float minSize = 1e-4f; if (bottomRadius < minSize) { bottomRadius = minSize; } if (topRadius < minSize) { topRadius = minSize; } if (height < minSize) { height = minSize; } const int minNumSlices = 3; if (numSlices < minNumSlices) { numSlices = minNumSlices; } const int minNumStacks = 1; if (numStacks < minNumStacks) { numStacks = minNumStacks; } int minNumCapRings = 1; bool generateBottomCap = numBottomCapRings >= minNumCapRings; bool generateTopCap = numTopCapRings >= minNumCapRings; int numAxialRows = numStacks + 1; int numVertsPerRow = numSlices + 1; int numAxialVertices = numAxialRows * numVertsPerRow; int totalNumVerts = numAxialVertices; Vector3[] axialPositions = new Vector3[numAxialVertices]; Vector3[] axialNormals = new Vector3[numAxialVertices]; List <Vector3> allPositions = new List <Vector3>(numAxialVertices); List <Vector3> allNormals = new List <Vector3>(numAxialVertices); // Generate the axial vertices int vertexPtr = 0; Vector3 basePosition = Vector3.zero; Vector3 topPosition = Vector3.up * height; Vector3 cylinderUp = Vector3.up; float yPosStep = height / numStacks; float angleStep = 360.0f / numSlices; for (int axialRowIndex = 0; axialRowIndex < numAxialRows; ++axialRowIndex) { float rowYPos = basePosition.y + axialRowIndex * yPosStep; float radius = Mathf.Lerp(bottomRadius, topRadius, rowYPos / topPosition.y); for (int vIndex = 0; vIndex < numVertsPerRow; ++vIndex) { float angle = vIndex * angleStep; Vector3 normal = (new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0.0f, Mathf.Sin(angle * Mathf.Deg2Rad))).normalized; axialNormals[vertexPtr] = normal; axialPositions[vertexPtr] = basePosition + rowYPos * cylinderUp + normal * radius; ++vertexPtr; } } allPositions.AddRange(axialPositions); allNormals.AddRange(axialNormals); // Generate the axial vertex indices int indexPtr = 0; List <int> allIndices = new List <int>(100); int numAxialIndices = numSlices * numStacks * 6; int[] axialIndices = new int[numAxialIndices]; for (int axialRowIndex = 0; axialRowIndex < numAxialRows - 1; ++axialRowIndex) { for (int vIndex = 0; vIndex < numVertsPerRow - 1; ++vIndex) { int indexOffset = axialRowIndex * numVertsPerRow + vIndex; // First triangle axialIndices[indexPtr++] = indexOffset; axialIndices[indexPtr++] = indexOffset + numVertsPerRow; axialIndices[indexPtr++] = indexOffset + 1; // Second triangle axialIndices[indexPtr++] = indexOffset + numVertsPerRow; axialIndices[indexPtr++] = indexOffset + numVertsPerRow + 1; axialIndices[indexPtr++] = indexOffset + 1; } } allIndices.AddRange(axialIndices); // Generate bottom cap if necessary if (generateBottomCap) { int numVertRings = numBottomCapRings + 1; int numVertsPerRing = numSlices + 1; int numCapVerts = numVertRings * numVertsPerRing; totalNumVerts += numCapVerts; vertexPtr = 0; Vector3[] capPositions = new Vector3[numCapVerts]; Vector3[] capNormals = new Vector3[numCapVerts]; for (int ringIndex = 0; ringIndex < numVertRings; ++ringIndex) { float radius = Mathf.Lerp(bottomRadius, 0.0f, ringIndex / (float)(numVertRings - 1)); for (int vIndex = 0; vIndex < numVertsPerRing; ++vIndex) { float angle = vIndex * angleStep; Vector3 positionDir = (new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0.0f, Mathf.Sin(angle * Mathf.Deg2Rad))).normalized; capPositions[vertexPtr] = basePosition + positionDir * radius; capNormals[vertexPtr] = -cylinderUp; ++vertexPtr; } } int baseVertexIndex = allPositions.Count; allPositions.AddRange(capPositions); allNormals.AddRange(capNormals); indexPtr = 0; int numCapIndices = numSlices * numBottomCapRings * 6; int[] capIndices = new int[numCapIndices]; for (int vertexRingIndex = 0; vertexRingIndex < numVertRings - 1; ++vertexRingIndex) { for (int vIndex = 0; vIndex < numVertsPerRing - 1; ++vIndex) { int indexOffset = baseVertexIndex + vertexRingIndex * numVertsPerRing + vIndex; // First triangle capIndices[indexPtr++] = indexOffset; capIndices[indexPtr++] = indexOffset + 1; capIndices[indexPtr++] = indexOffset + numVertsPerRing; // Second triangle capIndices[indexPtr++] = indexOffset + numVertsPerRing; capIndices[indexPtr++] = indexOffset + 1; capIndices[indexPtr++] = indexOffset + numVertsPerRing + 1; } } allIndices.AddRange(capIndices); } // Generate top cap if necessary if (generateTopCap) { int numVertRings = numTopCapRings + 1; int numVertsPerRing = numSlices + 1; int numCapVerts = numVertRings * numVertsPerRing; totalNumVerts += numCapVerts; vertexPtr = 0; Vector3[] capPositions = new Vector3[numCapVerts]; Vector3[] capNormals = new Vector3[numCapVerts]; for (int ringIndex = 0; ringIndex < numVertRings; ++ringIndex) { float radius = Mathf.Lerp(topRadius, 0.0f, ringIndex / (float)(numVertRings - 1)); for (int vIndex = 0; vIndex < numVertsPerRing; ++vIndex) { float angle = vIndex * angleStep; Vector3 positionDir = (new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0.0f, Mathf.Sin(angle * Mathf.Deg2Rad))).normalized; capPositions[vertexPtr] = topPosition + positionDir * radius; capNormals[vertexPtr] = cylinderUp; ++vertexPtr; } } int baseVertexIndex = allPositions.Count; allPositions.AddRange(capPositions); allNormals.AddRange(capNormals); indexPtr = 0; int numCapIndices = numSlices * numTopCapRings * 6; int[] capIndices = new int[numCapIndices]; for (int vertexRingIndex = 0; vertexRingIndex < numVertRings - 1; ++vertexRingIndex) { for (int vIndex = 0; vIndex < numVertsPerRing - 1; ++vIndex) { int indexOffset = baseVertexIndex + vertexRingIndex * numVertsPerRing + vIndex; // First triangle capIndices[indexPtr++] = indexOffset; capIndices[indexPtr++] = indexOffset + numVertsPerRing; capIndices[indexPtr++] = indexOffset + 1; // Second triangle capIndices[indexPtr++] = indexOffset + numVertsPerRing; capIndices[indexPtr++] = indexOffset + numVertsPerRing + 1; capIndices[indexPtr++] = indexOffset + 1; } } allIndices.AddRange(capIndices); } Mesh mesh = new Mesh(); mesh.vertices = allPositions.ToArray(); mesh.normals = allNormals.ToArray(); mesh.colors = ColorEx.GetFilledColorArray(totalNumVerts, color); mesh.SetIndices(allIndices.ToArray(), MeshTopology.Triangles, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreateBox(float width, float height, float depth, Color color) { if (width < 1e-4f) { return(null); } if (height < 1e-4f) { return(null); } if (depth < 1e-4f) { return(null); } float halfWidth = width * 0.5f; float halfHeight = height * 0.5f; float halfDepth = depth * 0.5f; Vector3[] positions = new Vector3[] { // Front face new Vector3(-halfWidth, -halfHeight, -halfDepth), new Vector3(-halfWidth, halfHeight, -halfDepth), new Vector3(halfWidth, halfHeight, -halfDepth), new Vector3(halfWidth, -halfHeight, -halfDepth), // Back face new Vector3(halfWidth, -halfHeight, halfDepth), new Vector3(halfWidth, halfHeight, halfDepth), new Vector3(-halfWidth, halfHeight, halfDepth), new Vector3(-halfWidth, -halfHeight, halfDepth), // Top face new Vector3(-halfWidth, halfHeight, -halfDepth), new Vector3(-halfWidth, halfHeight, halfDepth), new Vector3(halfWidth, halfHeight, halfDepth), new Vector3(halfWidth, halfHeight, -halfDepth), // Bottom face new Vector3(halfWidth, -halfHeight, -halfDepth), new Vector3(halfWidth, -halfHeight, halfDepth), new Vector3(-halfWidth, -halfHeight, halfDepth), new Vector3(-halfWidth, -halfHeight, -halfDepth), // Left face new Vector3(-halfWidth, -halfHeight, halfDepth), new Vector3(-halfWidth, halfHeight, halfDepth), new Vector3(-halfWidth, halfHeight, -halfDepth), new Vector3(-halfWidth, -halfHeight, -halfDepth), // Right face new Vector3(halfWidth, -halfHeight, -halfDepth), new Vector3(halfWidth, halfHeight, -halfDepth), new Vector3(halfWidth, halfHeight, halfDepth), new Vector3(halfWidth, -halfHeight, halfDepth) }; Vector3[] normals = new Vector3[] { // Front face -Vector3.forward, -Vector3.forward, -Vector3.forward, -Vector3.forward, // Back face Vector3.forward, Vector3.forward, Vector3.forward, Vector3.forward, // Top face Vector3.up, Vector3.up, Vector3.up, Vector3.up, // Bottom face -Vector3.up, -Vector3.up, -Vector3.up, -Vector3.up, // Left face -Vector3.right, -Vector3.right, -Vector3.right, -Vector3.right, // Right face Vector3.right, Vector3.right, Vector3.right, Vector3.right }; int[] indices = new int[] { // Front face 0, 1, 2, 2, 3, 0, // Back face 4, 5, 6, 6, 7, 4, // Top face 8, 9, 10, 10, 11, 8, // Bottom face 12, 13, 14, 14, 15, 12, // Left face 16, 17, 18, 18, 19, 16, // Right face 20, 21, 22, 22, 23, 20 }; Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.normals = normals; mesh.colors = ColorEx.GetFilledColorArray(24, color); mesh.SetIndices(indices, MeshTopology.Triangles, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreateSphere(float radius, int numSlices, int numStacks, Color color) { if (radius < 1e-4f || numSlices < 3 || numStacks < 2) { return(null); } int numVertRows = numStacks + 1; int numVertsPerRow = numSlices + 1; int numVerts = numVertRows * numVertsPerRow; Vector3[] positions = new Vector3[numVerts]; Vector3[] normals = new Vector3[numVerts]; int vertexPtr = 0; float angleStep = 360.0f / (numVertsPerRow - 1); for (int vertRowIndex = 0; vertRowIndex < numVertRows; ++vertRowIndex) { float theta = Mathf.PI * (float)vertRowIndex / (numVertRows - 1); float cosTheta = Mathf.Cos(theta); float sinTheta = Mathf.Sin(theta); for (int vertIndex = 0; vertIndex < numVertsPerRow; ++vertIndex) { float centralAxisRotAngle = angleStep * vertIndex * Mathf.Deg2Rad; Vector3 rotatedAxis = Vector3.right * Mathf.Sin(centralAxisRotAngle) + Vector3.forward * Mathf.Cos(centralAxisRotAngle); positions[vertexPtr] = rotatedAxis * sinTheta * radius + Vector3.up * cosTheta * radius; normals[vertexPtr] = Vector3.Normalize(positions[vertexPtr]); ++vertexPtr; } } int indexPtr = 0; int numIndices = numSlices * numStacks * 6; int[] indices = new int[numIndices]; for (int vertRowIndex = 0; vertRowIndex < numVertRows - 1; ++vertRowIndex) { for (int vertIndex = 0; vertIndex < numVertsPerRow - 1; ++vertIndex) { // Calculate the index of the first vertex inside the first triangle int baseIndex = vertRowIndex * numVertsPerRow + vertIndex; // First triangle indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + numVertsPerRow; indices[indexPtr++] = baseIndex + numVertsPerRow + 1; // Second triangle indices[indexPtr++] = baseIndex + numVertsPerRow + 1; indices[indexPtr++] = baseIndex + 1; indices[indexPtr++] = baseIndex; } } Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.normals = normals; mesh.colors = ColorEx.GetFilledColorArray(numVerts, color); mesh.SetIndices(indices, MeshTopology.Triangles, 0); mesh.UploadMeshData(false); return(mesh); }
public static Mesh CreateTorus(Vector3 center, float coreRadius, float tubeRadius, int numTubeSlices, int numSlices, Color color) { if (coreRadius < 1e-4f || tubeRadius < 1e-4f || numTubeSlices < 3 || numSlices < 3) { return(null); } int numVertsPerTubeSlice = (numSlices + 1); int numVerts = numVertsPerTubeSlice * (numTubeSlices + 1); Vector3[] positions = new Vector3[numVerts]; Vector3[] normals = new Vector3[numVerts]; int vertexPtr = 0; float outerAngleStep = 360.0f / (numSlices - 1); float tubeAngleStep = 360.0f / (numTubeSlices - 1); for (int tubeSliceIndex = 0; tubeSliceIndex <= numTubeSlices; ++tubeSliceIndex) { float tubeAngle = tubeAngleStep * tubeSliceIndex * Mathf.Deg2Rad; float cosTube = Mathf.Cos(tubeAngle); float sinTube = Mathf.Sin(tubeAngle); Vector3 tubeSliceCenter = new Vector3(sinTube * coreRadius, 0.0f, cosTube * coreRadius); for (int sliceIndex = 0; sliceIndex <= numSlices; ++sliceIndex) { float outerAngle = outerAngleStep * sliceIndex * Mathf.Deg2Rad; float cosOuter = Mathf.Cos(outerAngle); float sinOuter = Mathf.Sin(outerAngle); Vector3 vPos = tubeSliceCenter; vPos.x += sinTube * sinOuter * tubeRadius; vPos.y += cosOuter * tubeRadius; vPos.z += cosTube * sinOuter * tubeRadius; vPos += center; positions[vertexPtr] = vPos; normals[vertexPtr] = (vPos - center).normalized; ++vertexPtr; } } int indexPtr = 0; int numIndices = numTubeSlices * numSlices * 6; int[] indices = new int[numIndices]; for (int tubeSliceIndex = 0; tubeSliceIndex < numTubeSlices; ++tubeSliceIndex) { for (int sliceIndex = 0; sliceIndex < numSlices; ++sliceIndex) { int baseIndex = tubeSliceIndex * numVertsPerTubeSlice + sliceIndex; indices[indexPtr++] = baseIndex; indices[indexPtr++] = baseIndex + 1; indices[indexPtr++] = baseIndex + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex + 1; indices[indexPtr++] = baseIndex + 1 + numVertsPerTubeSlice; indices[indexPtr++] = baseIndex + numVertsPerTubeSlice; } } Mesh mesh = new Mesh(); mesh.vertices = positions; mesh.normals = normals; mesh.colors = ColorEx.GetFilledColorArray(numVerts, color); mesh.SetIndices(indices, MeshTopology.Triangles, 0); mesh.UploadMeshData(false); return(mesh); }