public void Update(IChiselHandles handles, ChiselCylinderDefinition definition) { var tempBottomDiameterX = definition.BottomDiameterX; var tempBottomDiameterZ = definition.isEllipsoid ? definition.BottomDiameterZ : definition.BottomDiameterX; float tempTopDiameterX, tempTopDiameterZ; if (definition.type == CylinderShapeType.Cone) { tempTopDiameterX = 0; tempTopDiameterZ = 0; } else if (definition.type == CylinderShapeType.Cylinder) { tempTopDiameterX = tempBottomDiameterX; tempTopDiameterZ = tempBottomDiameterZ; } else { tempTopDiameterX = definition.TopDiameterX; tempTopDiameterZ = definition.isEllipsoid ? definition.TopDiameterZ : definition.TopDiameterX; } topY = (definition.height + definition.bottomOffset); bottomY = definition.bottomOffset; var rotate = Quaternion.AngleAxis(definition.rotation, Vector3.up); topXVector = rotate * Vector3.right * tempTopDiameterX * 0.5f; topZVector = rotate * Vector3.forward * tempTopDiameterZ * 0.5f; bottomXVector = rotate * Vector3.right * tempBottomDiameterX * 0.5f; bottomZVector = rotate * Vector3.forward * tempBottomDiameterZ * 0.5f; normal = Vector3.up; if (topY < bottomY) { normal = -Vector3.up; } else { normal = Vector3.up; } topPoint = normal * topY; bottomPoint = normal * bottomY; // Render vertical horizon of cylinder // TODO: make this work with math instead of "finding" it Vector3 bottomPointA, topPointA; Vector3 bottomPointB, topPointB; var camera = UnityEngine.Camera.current; var cameraTransform = camera.transform; var cameraPosition = handles.inverseMatrix.MultiplyPoint(cameraTransform.position); const float degreeStep = 5; var pointA = fullTopCircleHandle.GetPointAtDegree(360 - degreeStep); var pointB = fullBottomCircleHandle.GetPointAtDegree(360 - degreeStep); var camOrtho = camera.orthographic; var camForward = handles.inverseMatrix.MultiplyVector(cameraTransform.forward).normalized; var camDir = camOrtho ? camForward : (pointA - cameraPosition).normalized; var delta = (pointA - pointB).normalized; var normal3 = -Vector3.Cross(delta, Vector3.Cross((pointB - bottomPoint).normalized, delta)).normalized; var prevDot = Vector3.Dot(normal3, camDir) < 0; bool renderHorizon = false; //* bottomPointA = Vector3.zero; topPointA = Vector3.zero; bottomPointB = Vector3.zero; topPointB = Vector3.zero; var lineCount = 0; for (float degree = 0; degree < 360; degree += degreeStep) { pointA = fullTopCircleHandle.GetPointAtDegree(degree); pointB = fullBottomCircleHandle.GetPointAtDegree(degree); delta = (pointA - pointB).normalized; normal3 = -Vector3.Cross(delta, Vector3.Cross((pointB - bottomPoint).normalized, delta)).normalized; camDir = camOrtho ? camForward : (pointB - cameraPosition).normalized; var currDot = Vector3.Dot(normal3, camDir) < 0; if (prevDot != currDot) { lineCount++; if (lineCount == 1) { topPointA = pointA; bottomPointA = pointB; } else //if (lineCount == 2) { topPointB = pointA; bottomPointB = pointB; renderHorizon = true; break; } } prevDot = currDot; } #if false { var pointC = (Vector3.right * (definition.topDiameterX * 0.5f)) + (Vector3.up * (definition.height + definition.bottomOffset)); var pointD = (Vector3.right * (definition.bottomDiameterX * 0.5f)) + (Vector3.up * definition.bottomOffset); //var deltar = (pointC - pointD).normalized; //var normala = -Vector3.Cross(Vector3.forward, deltar).normalized; var DT = (cameraPosition - topPoint); var DB = (cameraPosition - bottomPoint); var DmT = DT.magnitude; var DmB = DB.magnitude; //var Dv = D / Dm; var RmT = definition.topDiameterX * 0.5f; var RmB = definition.bottomDiameterX * 0.5f; var cosAT = RmT / DmT; var cosAB = RmB / DmB; var AT = Mathf.Acos(cosAT) * Mathf.Rad2Deg; var AB = Mathf.Acos(cosAB) * Mathf.Rad2Deg; var RvT = (Quaternion.AngleAxis(AT, Vector3.up) * DT).normalized; var RvB = (Quaternion.AngleAxis(AB, Vector3.up) * DB).normalized; //var R = Rv * Rm; var angleT = Vector3.SignedAngle(Vector3.right, RvT, Vector3.up); var angleB = Vector3.SignedAngle(Vector3.right, RvB, Vector3.up); var arotationT = Quaternion.AngleAxis(angleT, Vector3.up); var arotationB = Quaternion.AngleAxis(angleB, Vector3.up); var ptA = arotationT * pointC; var ptB = arotationB * pointD; var prevCol = handles.color; handles.color = UnityEngine.Color.red; handles.DrawLine(bottomPoint, bottomPoint + Vector3.right); //handles.DrawLine(bottomPoint, bottomPoint + Vector3.forward); //handles.DrawLine(bottomPoint, bottomPoint + normala); //handles.DrawLine(bottomPoint, bottomPoint + deltar); //handles.DrawLine(bottomPoint, bottomPoint + R); handles.DrawLine(bottomPoint, bottomPoint + RvT); handles.DrawLine(bottomPoint, bottomPoint + RvB); //handles.DrawLine(bottomPoint, bottomPoint + desired); handles.DrawLine(ptA, ptB); handles.color = prevCol; } #endif /*/ * if (camera.orthographic) * { * { * var radius = definition.bottomDiameterX * 0.5f; * var center = bottomPoint; * bottomPointA = center + (cameraTransform.right * radius); * bottomPointB = center - (cameraTransform.right * radius); * } * { * var radius = definition.topDiameterX * 0.5f; * var center = topPoint; * topPointA = center + (cameraTransform.right * radius); * topPointB = center - (cameraTransform.right * radius); * } * } else * { * var handleMatrix = handles.matrix; * renderHorizon = GeometryMath.FindCircleHorizon(handleMatrix, definition.bottomDiameterX, bottomPoint, -normal, out bottomPointB, out bottomPointA); * renderHorizon = GeometryMath.FindCircleHorizon(handleMatrix, definition.topDiameterX, topPoint, normal, out topPointA, out topPointB) && renderHorizon; * * if (renderHorizon && definition.bottomDiameterX != definition.topDiameterX) * { * renderHorizon = !(GeometryMath.PointInCameraCircle(handleMatrix, bottomPointA, definition.topDiameterX, topPoint, normal) || * GeometryMath.PointInCameraCircle(handleMatrix, topPointA, definition.bottomDiameterX, bottomPoint, -normal) || * GeometryMath.PointInCameraCircle(handleMatrix, bottomPointB, definition.topDiameterX, topPoint, normal) || * GeometryMath.PointInCameraCircle(handleMatrix, topPointB, definition.bottomDiameterX, bottomPoint, -normal)); * } * } * //*/ if (!renderHorizon) { bottomPointA = Vector3.zero; topPointA = Vector3.zero; bottomPointB = Vector3.zero; topPointB = Vector3.zero; } verticalHandle1.From = bottomPointA; verticalHandle1.To = topPointA; verticalHandle2.From = bottomPointB; verticalHandle2.To = topPointB; fullTopCircleHandle.Center = topPoint; fullBottomCircleHandle.Center = bottomPoint; fullTopCircleHandle.DiameterX = tempTopDiameterX; fullTopCircleHandle.DiameterZ = tempTopDiameterZ; fullBottomCircleHandle.DiameterX = tempBottomDiameterX; fullBottomCircleHandle.DiameterZ = tempBottomDiameterZ; topHandle.Origin = topPoint; bottomHandle.Origin = bottomPoint; fullTopCircleHandle.Normal = normal; fullBottomCircleHandle.Normal = -normal; topHandle.Normal = normal; bottomHandle.Normal = -normal; if (definition.isEllipsoid) { if (bottomRadiusHandles == null || bottomRadiusHandles.Length != 4) { bottomRadiusHandles = new IChiselEllipsoidHandle[] { handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: +45f, angles: 90), // left handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: +45f + 180f, angles: 90), // right handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: -45f, angles: 90), // forward handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: -45f + 180f, angles: 90), // back }; } if (topRadiusHandles == null || topRadiusHandles.Length != 4) { topRadiusHandles = new IChiselEllipsoidHandle[] { handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: +45f, angles: 90), // left handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: +45f + 180f, angles: 90), // right handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: -45f, angles: 90), // forward handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: -45f + 180f, angles: 90), // back }; } for (int i = 0; i < bottomRadiusHandles.Length; i++) { bottomRadiusHandles[i].Center = bottomPoint; bottomRadiusHandles[i].Normal = -normal; bottomRadiusHandles[i].DiameterX = tempBottomDiameterX; bottomRadiusHandles[i].DiameterZ = tempBottomDiameterZ; bottomRadiusHandles[i].Rotation = definition.rotation; } for (int i = 0; i < topRadiusHandles.Length; i++) { topRadiusHandles[i].Center = topPoint; topRadiusHandles[i].Normal = normal; topRadiusHandles[i].DiameterX = tempTopDiameterX; topRadiusHandles[i].DiameterZ = tempTopDiameterZ; topRadiusHandles[i].Rotation = definition.rotation; } if (bottomHandles == null || bottomHandles.Length != 4) { bottomHandles = new IChiselHandle[] { bottomHandle, bottomRadiusHandles[0], bottomRadiusHandles[1], bottomRadiusHandles[2], bottomRadiusHandles[3] } } ; if (definition.type != CylinderShapeType.Cone) { if (topHandles == null || topHandles.Length != 5) { topHandles = new IChiselHandle[] { topHandle, topRadiusHandles[0], topRadiusHandles[1], topRadiusHandles[2], topRadiusHandles[3] } } ; } else { if (topHandles == null || topHandles.Length != 1) { topHandles = new IChiselHandle[] { topHandle } } ; } } else { if (bottomRadiusHandles == null || bottomRadiusHandles.Length != 1) { bottomRadiusHandles = new IChiselEllipsoidHandle[] { fullBottomCircleHandle } } ; if (topRadiusHandles == null || topRadiusHandles.Length != 1) { topRadiusHandles = new IChiselEllipsoidHandle[] { fullTopCircleHandle } } ; if (bottomHandles == null || bottomHandles.Length != 2) { bottomHandles = new IChiselHandle[] { bottomHandle, bottomRadiusHandles[0] } } ; if (definition.type != CylinderShapeType.Cone) { if (topHandles == null || topHandles.Length != 2) { topHandles = new IChiselHandle[] { topHandle, topRadiusHandles[0] } } ; } else { if (topHandles == null || topHandles.Length != 1) { topHandles = new IChiselHandle[] { topHandle } } ; } } } }