Skip to content

Commit

Permalink
More quaternion methods, arrow primitive
Browse files Browse the repository at this point in the history
  • Loading branch information
qkmaxware committed Sep 5, 2020
1 parent 0bda741 commit 7424e5b
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 1 deletion.
19 changes: 19 additions & 0 deletions Geometry.Test/suites/Geometry/Primitives/Arrow.test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using Qkmaxware.Geometry;
using Qkmaxware.Geometry.IO;
using Qkmaxware.Geometry.Primitives;

namespace Qkmaxware.Testing {

[TestClass]
public class ArrowTest : PrimitiveTest {
[TestMethod]
public void TestArrow() {
var geom = new Arrow(1, 0.08, 8);
SaveGeometry("arrow", geom);
}
}

}
2 changes: 1 addition & 1 deletion Geometry/Geometry.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<PropertyGroup>
<PackageId>Qkmaxware.Geometry</PackageId>
<Version>1.0.5</Version>
<Version>1.0.6</Version>
<Authors>Colin Halseth</Authors>
<PackageTags>geometry creation manipulation</PackageTags>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
Expand Down
37 changes: 37 additions & 0 deletions Geometry/src/Geometry/Primitives/Arrow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Linq;
using System.Collections.Generic;

namespace Qkmaxware.Geometry.Primitives {

/// <summary>
/// Arrow pointing in the +Z axis
/// </summary>
public class Arrow : Mesh {
/// <summary>
/// Create a new arrow with the given length
/// </summary>
/// <param name="length">length of the arrow</param>
/// <param name="radius">radius of the arrow head</param>
/// <param name="resolution">subdivision level</param>
public Arrow(double length = 1, double radius = 0.08, int resolution = 8) {
var innerRadius = 0.6 * radius;
var lineLength = 0.8 * length;
var pointLength = 0.2 * length;
this.AppendRange(new Cylinder(
upperRadius: innerRadius,
lowerRadius: innerRadius,
height: lineLength,
centre: Vec3.K * (lineLength / 2),
resolution: resolution
));
this.AppendRange(new Cone(
radius: radius,
height: pointLength,
centre: Vec3.K * lineLength,
resolution: resolution
));
}
}

}
50 changes: 50 additions & 0 deletions Geometry/src/Geometry/Quat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,56 @@ public static Quat AngleAxis(Vec3 axis, double angle) {
).Normalized;
}

/// <summary>
/// Create a quaternion representing a rotation looking in the desired direction
/// </summary>
/// <param name="direction">look direction</param>
/// <returns>rotation</returns>
public static Quat LookRotation(Vec3 direction) {
return LookRotation(direction, Vec3.K);
}

/// <summary>
/// Create a quaternion representing a rotation looking in the desired direction
/// </summary>
/// <param name="direction">look direction</param>
/// <param name="upwards">planar normal direction</param>
/// <returns>rotation</returns>
public static Quat LookRotation(Vec3 direction, Vec3 upwards) {
if (direction == Vec3.Zero)
return Quat.Identity;

if (upwards != direction) {
upwards = upwards.Normalized;
var v = direction + upwards * -Vec3.Dot(upwards, direction);
var q = Quat.FromToRotation(Vec3.J, v);
return Quat.FromToRotation(v, direction) * q;
} else {
return Quat.FromToRotation(Vec3.J, direction);
}
}

/// <summary>
/// Create a rotation from one vector to another
/// </summary>
/// <param name="u">first vector</param>
/// <param name="v">second vector</param>
/// <returns>rotation from the first to the second</returns>
public static Quat FromToRotation(Vec3 u, Vec3 v) {
u = u.Normalized;
v = v.Normalized;

var k_cos_theta = Vec3.Dot(u,v);
var k = Math.Sqrt(u.SqrLength * v.SqrLength);

if (k_cos_theta / k == -1) {
// 180 degree rotation on any orthogonal vector
return new Quat(u.Orthogonal.Normalized, 0);
} else {
return new Quat(Vec3.Cross(u,v), k_cos_theta + k).Normalized;
}
}

/// <summary>
/// Sum of two quaternions
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions Geometry/src/Geometry/Vec3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,21 @@ public Vec3 Normalized {
/// </summary>
public Vec3 Flipped => -1 * this;

/// <summary>
/// Returns an arbitrary vector orthogonal to this one
/// </summary>
/// <value>orthogonal vector</value>
public Vec3 Orthogonal {
get {
var x = Math.Abs(this.X);
var y = Math.Abs(this.Y);
var z = Math.Abs(this.Z);

var other = x < y ? (x < z ? Vec3.I : Vec3.K) : (y < z ? Vec3.J : Vec3.K);
return Vec3.Cross(this, other);
}
}

/// <summary>
/// Max component of this vector
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Geometry in this library is modeled as a collection of triangular faces whose ve
| Torus | Torus with configurable radii | <img width="128" src="docs/img/PrimitiveTorus.png"/> |
| Frustum | Pyramidal Frustums | <img width="128" src="docs/img/PrimitiveFrustum.png"/> |
| Nosecone | Varieties of aerodynamic nosecones | <img width="128" height="256" src="docs/img/PrimitiveNoseconeBiconic.png"/> <img width="128" height="256" src="docs/img/PrimitiveNoseconeParabolic.png"/>|
| Arrow | Vertically pointing arrow | <img width="256" src="docs/img/PrimitiveArrow.png"/> |
| TextMesh | String to mesh based on 3d font character set<br>Default font based on Blender3D's [BFont](https://github.com/blender/blender/blob/master/release/datafiles/LICENSE-bfont.ttf.txt). | <img width="256" src="docs/img/PrimitiveTextMesh.png"/> |

## Transformations for Building Geometries
Expand Down
Binary file added docs/img/PrimitiveArrow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions docs/tutorials/01.Creating.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,21 @@ public static Nosecone Haack (double C, double radius, double height, int resolu
<img width="128" height="256" src="/Geometry/img/PrimitiveNoseconeSecant.png"/>
</div>

### Arrow
Arrows are pointers looking in the +Z direction.

**Constructors**
```cs
/// <param name="length">length of the arrow</param>
/// <param name="radius">radius of the arrow head</param>
/// <param name="resolution">subdivision level</param>
public Arrow(double length = 1, double radius = 0.08, int resolution = 8)
```

<div style="text-align: center">
<img width="128" height="256" src="/Geometry/img/PrimitiveArrow.png"/>
</div>


### TextMesh
TextMesh creates meshes from string data by converting each letter to a 3G geometry. Custom fonts are used to map each character to their appropriate geometry.
Expand Down

0 comments on commit 7424e5b

Please sign in to comment.