1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
// Copyright 2019 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using UnityEngine;
namespace Mujoco {
// Additional Debug Gizmos.
public static class MjGizmos {
private const float _vectorPerpendicularityMagnitudeThreshold = 1e-6f;
public static int NumCircleSegments = 32;
private static Vector3[] _circumferenceVertices = new Vector3[] {
Vector3.right, -Vector3.right, Vector3.forward, -Vector3.forward,
};
public static Action<Vector3 /*from*/, Vector3 /*to*/> DrawLine { get; set; } = Gizmos.DrawLine;
public static Action<Vector3 /*position*/, float /*radius*/, Vector3 /*axis*/, float /*length*/,
float /*startAngle*/> DrawArc { get; set; } = MjGizmos.DrawArcInternal;
// Draws a wireframe capsule of the specified radius and height.
// The capsule's height will be aligned with the global Y axis.
// The specified height represents the height of the cylinder between two hemisphere bases.
public static void DrawWireCapsule(Vector3 position, float radius, float height) {
var offset = DrawHollowWireCylinder(position, radius, height);
// Arches marking the bases of the capsule.
DrawArc(position - offset, radius, Vector3.right, 0.5f, 0.0f);
DrawArc(position + offset, radius, Vector3.right, 0.5f, 180.0f);
DrawArc(position + offset, radius, Vector3.forward, 0.5f, -90.0f);
DrawArc(position - offset, radius, Vector3.forward, 0.5f, 90.0f);
}
// Draws a wireframe cylinder of the specified radius and height.
// The cylinder's height will be aligned with the global Y axis.
public static void DrawWireCylinder(Vector3 position, float radius, float height) {
var offset = DrawHollowWireCylinder(position, radius, height);
// Lines marking the bases of the cylinder.
for (var i = 0; i < _circumferenceVertices.Length / 2; ++i) {
var vertex = _circumferenceVertices[i * 2] * radius;
var nextVertex = _circumferenceVertices[i * 2 + 1] * radius;
DrawLine(position + offset + vertex, position + offset + nextVertex);
DrawLine(position - offset + vertex, position - offset + nextVertex);
}
}
private static Vector3 DrawHollowWireCylinder(Vector3 position, float radius, float height) {
var offset = Vector3.up * (height * 0.5f);
// Cylinder bases.
DrawArc(position + offset, radius, Vector3.up, 1.0f, 0.0f);
DrawArc(position - offset, radius, Vector3.up, 1.0f, 0.0f);
// Lines marking the sides of the cylinder.
for (var i = 0; i < _circumferenceVertices.Length; ++i) {
// Lines marking the sides of the cylinder.
var vertex = _circumferenceVertices[i] * radius;
DrawLine(position + offset + vertex, position - offset + vertex);
}
return offset;
}
// Draws an arc in the XZ plane.
// 'length' parameter, in range (0, 1], allows to define how much of the circumference should be
// drawn. In other words, it allows to draw arbitrary arcs.
// Two additional parameters, 'axis' and 'startAngle', allow to orient the figure without having
// to manipulate the value of Gizmos.matrix.
public static void DrawArcInternal(
Vector3 position, float radius, Vector3 axis, float length, float startAngle) {
var deltaAngle = 360.0f / NumCircleSegments;
var numSegments = Math.Ceiling(length * NumCircleSegments);
var perpendicular = Vector3.Cross(axis, Vector3.right);
if (perpendicular.magnitude <= _vectorPerpendicularityMagnitudeThreshold) {
perpendicular = Vector3.Cross(axis, Vector3.up);
}
perpendicular.Normalize();
var offset = perpendicular * radius;
var start = Quaternion.AngleAxis(startAngle, axis) * offset;
var angle = startAngle + deltaAngle;
for (var segment = 0; segment < numSegments; ++segment, angle += deltaAngle) {
var end = Quaternion.AngleAxis(angle, axis) * offset;
DrawLine(position + start, position + end);
start = end;
}
}
public static void DrawWirePlane(Vector3 position, float width, float height) {
var quadPoints = new Vector3[] {
new Vector3(-0.5f * width, 0, -0.5f * height),
new Vector3(0.5f * width, 0, -0.5f * height),
new Vector3(0.5f * width, 0, 0.5f * height),
new Vector3(-0.5f * width, 0, 0.5f * height),
new Vector3(-0.5f * width, 0, -0.5f * height),
new Vector3(0.5f * width, 0, 0.5f * height),
};
for (var i = 0; i < quadPoints.Length - 1; ++i) {
DrawLine(position + quadPoints[i], position + quadPoints[i + 1]);
}
}
}
}
|