private void Start() { transform.position = UnityEngine.Vector3.zero; //take vertices and organize them into clockwise triangles to be passed to triangle intersection function Unity.Mathematics.float3 a = tetrahderonVertices[0]; Unity.Mathematics.float3 b = tetrahderonVertices[1]; Unity.Mathematics.float3 c = tetrahderonVertices[2]; Unity.Mathematics.float3 d = tetrahderonVertices[3]; Unity.Mathematics.float3x3 triangle1 = new Unity.Mathematics.float3x3(a, b, c); Unity.Mathematics.float3x3 triangle2 = new Unity.Mathematics.float3x3(a, c, d); Unity.Mathematics.float3x3 triangle3 = new Unity.Mathematics.float3x3(a, d, b); Unity.Mathematics.float3x3 triangle4 = new Unity.Mathematics.float3x3(b, c, d); triXC = new System.Collections.Generic.List <TriangleCrossSection>(); BuildTriangle(triangle1, planePos, planeNormal); BuildTriangle(triangle2, planePos, planeNormal); BuildTriangle(triangle3, planePos, planeNormal); BuildTriangle(triangle4, planePos, planeNormal); gameObject.AddComponent <UnityEngine.MeshRenderer>(); gameObject.AddComponent <UnityEngine.MeshFilter>(); gameObject.GetComponent <MeshRenderer>().material = mat; }
public void Execute(int index) { vec3 rd = Samples[index]; vec3 ro = RayOrigin; Raycasts[index] = new RaycastCommand(ro, rd, RayLengths[index], LayerMask); }
private void updateSquares() { Unity.Mathematics.float3 a = cubeVertices[0]; Unity.Mathematics.float3 b = cubeVertices[1]; Unity.Mathematics.float3 c = cubeVertices[2]; Unity.Mathematics.float3 d = cubeVertices[3]; Unity.Mathematics.float3 e = cubeVertices[4]; Unity.Mathematics.float3 f = cubeVertices[5]; Unity.Mathematics.float3 g = cubeVertices[6]; Unity.Mathematics.float3 h = cubeVertices[7]; float3x4 square1 = new float3x4(a, b, c, d); float3x4 square2 = new float3x4(e, f, g, h); float3x4 square3 = new float3x4(d, c, g, h); float3x4 square4 = new float3x4(b, a, e, f); float3x4 square5 = new float3x4(c, b, f, g); float3x4 square6 = new float3x4(a, d, h, e); squareXC.ForEach(p => p.planePos = planePos); squareXC.ForEach(p => p.planeNormal = planeNormal); squareXC[0].squareVertices = square1; squareXC[1].squareVertices = square2; squareXC[2].squareVertices = square3; squareXC[3].squareVertices = square4; squareXC[4].squareVertices = square5; squareXC[5].squareVertices = square6; }
private void Start() { transform.position = Vector3.zero; //using same orientation as cross section function Unity.Mathematics.float3 a = cubeVertices[0]; Unity.Mathematics.float3 b = cubeVertices[1]; Unity.Mathematics.float3 c = cubeVertices[2]; Unity.Mathematics.float3 d = cubeVertices[3]; Unity.Mathematics.float3 e = cubeVertices[4]; Unity.Mathematics.float3 f = cubeVertices[5]; Unity.Mathematics.float3 g = cubeVertices[6]; Unity.Mathematics.float3 h = cubeVertices[7]; float3x4 square1 = new float3x4(a, b, c, d); float3x4 square2 = new float3x4(e, f, g, h); float3x4 square3 = new float3x4(d, c, g, h); float3x4 square4 = new float3x4(b, a, e, f); float3x4 square5 = new float3x4(c, b, f, g); float3x4 square6 = new float3x4(a, d, h, e); squareXC = new List <SquareCrossSection>(); BuildSquare(square1, planePos, planeNormal); BuildSquare(square2, planePos, planeNormal); BuildSquare(square3, planePos, planeNormal); BuildSquare(square4, planePos, planeNormal); BuildSquare(square5, planePos, planeNormal); BuildSquare(square6, planePos, planeNormal); gameObject.AddComponent <MeshRenderer>(); gameObject.AddComponent <MeshFilter>(); gameObject.GetComponent <MeshRenderer>().material = mat; }
public unsafe void RigidBodyCalculateDistancePointTest() { Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.0f; var queryPos = new float3(-10, -10, -10); rigidbody.Collider = (Collider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr(); var pointDistanceInput = new PointDistanceInput(); pointDistanceInput.Position = queryPos; pointDistanceInput.Filter = CollisionFilter.Default; var closestHit = new DistanceHit(); var allHits = new NativeList <DistanceHit>(Allocator.Temp); // OK case : with enough max distance pointDistanceInput.MaxDistance = 10000.0f; Assert.IsTrue(rigidbody.CalculateDistance(pointDistanceInput)); Assert.IsTrue(rigidbody.CalculateDistance(pointDistanceInput, out closestHit)); Assert.IsTrue(rigidbody.CalculateDistance(pointDistanceInput, ref allHits)); // Fail case : not enough max distance pointDistanceInput.MaxDistance = 1; Assert.IsFalse(rigidbody.CalculateDistance(pointDistanceInput)); Assert.IsFalse(rigidbody.CalculateDistance(pointDistanceInput, out closestHit)); Assert.IsFalse(rigidbody.CalculateDistance(pointDistanceInput, ref allHits)); }
public static void projectTriangle(Unity.Mathematics.float4[] verts, int subdiv, out Unity.Mathematics.float3[] out_verts, out int[] out_tris, IMRE.Math.ProjectionMethod method) { //break triangle into smaller triangles //use a modified Sierpiński triangle as a division mechanic (partition every triangle into 3 triangles each round). Then there are always 3^n triangles out_tris = new[] { 0, 1, 2 }; //loop subdiv times on subdivide verts. //subdivide verts calls itself, but should terminate when it reaches a case where the size of a partition is 3. /* * Case 1 - triangle of 3 verticies - split into 6 (hit else case) * Case 2 - 6 verts - split in half (two of 3). round 2, hit else case. * Case 3 - 12 verts - split in half (two of 6). round 2, split in half (four of 3), round 3 hit else case. * continue until we hit the subdiv'th case. */ for (int i = 0; i < subdiv; i++) { subdivideVerts(ref verts, ref out_tris); } out_verts = new Unity.Mathematics.float3[verts.Length]; for (int i = 0; i < verts.Length; i++) { out_verts[i] = projectPosition(verts[i]); } }
public void TestAabb() { float3 v0 = float3(100, 200, 300); float3 v1 = float3(200, 300, 400); float3 v2 = float3(50, 100, 350); Aabb a0; a0.Min = float3.zero; a0.Max = v0; Aabb a1; a1.Min = float3.zero; a1.Max = v1; Aabb a2; a2.Min = v2; a2.Max = v1; Aabb a3; a3.Min = v2; a3.Max = v0; Assert.IsTrue(a0.IsValid); Assert.IsTrue(a1.IsValid); Assert.IsTrue(a2.IsValid); Assert.IsFalse(a3.IsValid); Assert.IsTrue(a1.Contains(a0)); Assert.IsFalse(a0.Contains(a1)); Assert.IsTrue(a1.Contains(a2)); Assert.IsFalse(a2.Contains(a1)); Assert.IsFalse(a0.Contains(a2)); Assert.IsFalse(a2.Contains(a0)); // Test Expand / Contains { Aabb a5; a5.Min = v2; a5.Max = v1; float3 testPoint = float3(v2.x - 1.0f, v1.y + 1.0f, .5f * (v2.z + v1.z)); Assert.IsFalse(a5.Contains(testPoint)); a5.Expand(1.5f); Assert.IsTrue(a5.Contains(testPoint)); } // Test transform { Aabb ut; ut.Min = v0; ut.Max = v1; // Identity transform should not modify aabb Aabb outAabb = Unity.Physics.Math.TransformAabb(RigidTransform.identity, ut); TestUtils.AreEqual(ut.Min, outAabb.Min, 1e-3f); // Test translation outAabb = Unity.Physics.Math.TransformAabb(new RigidTransform(quaternion.identity, float3(100.0f, 0.0f, 0.0f)), ut); Assert.AreEqual(outAabb.Min.x, 200); Assert.AreEqual(outAabb.Min.y, 200); Assert.AreEqual(outAabb.Max.x, 300); Assert.AreEqual(outAabb.Max.z, 400); // Test rotation quaternion rot = quaternion.EulerXYZ(0.0f, 0.0f, k_pi2); outAabb = Unity.Physics.Math.TransformAabb(new RigidTransform(rot, float3.zero), ut); TestUtils.AreEqual(outAabb.Min, float3(-300.0f, 100.0f, 300.0f), 1e-3f); TestUtils.AreEqual(outAabb.Max, float3(-200.0f, 200.0f, 400.0f), 1e-3f); TestUtils.AreEqual(outAabb.SurfaceArea, ut.SurfaceArea, 1e-2f); } }
private static float Dot3(Vector3 a, Vector3 b) { #if MATHEMATICS return(dot(a, b)); #else return(Vector3.Dot(a, b)); #endif }
static float dot(vec3 a, vec3 b) { #if USE_BURST_AND_MATH return(math.dot(a, b)); #else return(Vector3.Dot(a, b)); #endif }
static vec3 normalize(vec3 a) { #if USE_BURST_AND_MATH return(math.normalize(a)); #else return(Vector3.Normalize(a)); #endif }
/// <summary> /// Checks if the position is below the maximum possible wave height. Can be used as a fast broad-phase check, before actually using the more expensive SampleWaves function /// </summary> /// <param name="position"></param> /// <param name="waterObject"></param> /// <returns></returns> public static bool CanTouchWater(Vector3 position, WaterObject waterObject) { if (!waterObject) { return(false); } return(position.y < (waterObject.transform.position.y + WaveParameters.GetMaxWaveHeight(waterObject.material))); }
/// <summary> /// Returns a position in world-space, where a ray cast from the origin in the direction hits the (flat) water level height /// </summary> /// <param name="origin"></param> /// <param name="direction"></param> /// <param name="waterLevel">Water level height in world-space</param> /// <returns></returns> public static Vector3 FindWaterLevelIntersection(Vector3 origin, Vector3 direction, float waterLevel) { float upDot = Dot3(direction, UnityEngine.Vector3.up); float angle = (Mathf.Acos(upDot) * 180f) / Mathf.PI; float depth = waterLevel - origin.y; //Distance from origin to water level along direction float hypotenuse = depth / Cosine(Mathf.Deg2Rad * angle); return(origin + (direction * hypotenuse)); }
private void BuildTriangle(Unity.Mathematics.float3x3 vertices, Unity.Mathematics.float3 planePos, Unity.Mathematics.float3 planeNorm) { UnityEngine.GameObject tri1_go = new UnityEngine.GameObject(); tri1_go.transform.parent = this.transform; tri1_go.AddComponent <TriangleCrossSection>(); triXC.Add(tri1_go.GetComponent <TriangleCrossSection>()); tri1_go.GetComponent <TriangleCrossSection>().triangleVerticies = vertices; tri1_go.GetComponent <TriangleCrossSection>().planePos = planePos; tri1_go.GetComponent <TriangleCrossSection>().planeNormal = planeNorm; tri1_go.GetComponent <TriangleCrossSection>().mat = mat; }
/// <summary> /// Faux-raycast against the water surface /// </summary> /// <param name="waterMat">Material using StylizedWater2 shader</param> /// <param name="waterLevel">Height of the reference water plane.</param> /// <param name="origin">Ray origin</param> /// <param name="direction">Ray direction</param> /// <param name="dynamicMaterial">If true, the material's wave parameters will be re-fetched with every function call</param> /// <param name="hit">Reference to a RaycastHit, hit point and normal will be set</param> public static void Raycast(Material waterMat, float waterLevel, Vector3 origin, Vector3 direction, bool dynamicMaterial, out RaycastHit hit) { Vector3 samplePos = FindWaterLevelIntersection(origin, direction, waterLevel); float waveHeight = SampleWaves(samplePos, waterMat, waterLevel, 1f, dynamicMaterial, out var normal); samplePos.y = waveHeight; hit = Buoyancy.hit; hit.normal = normal; hit.point = samplePos; }
private void BuildTetrahedron(Unity.Mathematics.float4[] vertices, Unity.Mathematics.float3 planePos, Unity.Mathematics.float3 planeNorm) { UnityEngine.GameObject tet1_go = new UnityEngine.GameObject(); tet1_go.transform.parent = this.transform; tet1_go.AddComponent <IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>(); pyramidXC.Add(tet1_go.GetComponent <IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>()); //TODO project verticies down a dimension. //tet1_go.GetComponent<IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>().tetrahderonVertices = vertices; tet1_go.GetComponent <IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>().planePos = planePos; tet1_go.GetComponent <IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>().planeNormal = planeNorm; tet1_go.GetComponent <IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>().mat = mat; }
private void BuildCube(Unity.Mathematics.float4[] vertices, Unity.Mathematics.float3 planePos, Unity.Mathematics.float3 planeNorm) { UnityEngine.GameObject cube1_go = new UnityEngine.GameObject(); cube1_go.transform.parent = this.transform; cube1_go.AddComponent <IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>(); hyperCubeXC.Add(cube1_go.GetComponent <IMRE.ScaleDimension.CrossSections.CubeCrossSection>()); //TODO project verticies down a dimension. //cube1_go.GetComponent<IMRE.ScaleDimension.CrossSections.CubeCrossSecion>().cubeVertices = vertices; cube1_go.GetComponent <IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>().planePos = planePos; cube1_go.GetComponent <IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>().planeNormal = planeNorm; cube1_go.GetComponent <IMRE.ScaleDimension.CrossSections.TetrahedronCrossSection>().mat = mat; }
private static void GetRandomDirections(vec3 halfVoxel, uint seed, ref NativeArray <vec3> samples) { int count = samples.Length; #if USE_BURST_AND_MATH Random random = new Random(seed); #endif for (int k = 0; k < count; k++) { #if USE_BURST_AND_MATH samples[k] = random.NextFloat3Direction() * halfVoxel; #else samples[k] = Vector3.Scale(Random.onUnitSphere, halfVoxel); #endif } }
public void Execute(int index) { vec3 rd = Samples[index]; vec3 ro = RayOrigin; float nearest = RayLength; for (int v = 0; v < 6; v++) { if (PlaneRaycast(ro, rd, VolumePlanes[v], out float d)) { nearest = min(nearest, d); } } RayLengths[index] = nearest; }
bool PlaneRaycast(vec3 ro, vec3 rd, vec4 plane, out float distance) { #if USE_BURST_AND_MATH float a = dot(rd, plane.xyz); float num = -dot(ro, plane.xyz) - plane.w; #else float a = dot(rd, plane); float num = -dot(ro, plane) - plane.w; #endif if (abs(a) < EPSILON) { distance = 0.0f; return(false); } distance = num / a; return(distance > 0.0); }
private void UpdateTriangles() { //take vertices and organize them into clockwise triangles to be passed to triangle intersection function Unity.Mathematics.float3 a = tetrahderonVertices[0]; Unity.Mathematics.float3 b = tetrahderonVertices[1]; Unity.Mathematics.float3 c = tetrahderonVertices[2]; Unity.Mathematics.float3 d = tetrahderonVertices[3]; Unity.Mathematics.float3x3 triangle1 = new Unity.Mathematics.float3x3(a, b, c); Unity.Mathematics.float3x3 triangle2 = new Unity.Mathematics.float3x3(a, c, d); Unity.Mathematics.float3x3 triangle3 = new Unity.Mathematics.float3x3(a, d, b); Unity.Mathematics.float3x3 triangle4 = new Unity.Mathematics.float3x3(b, c, d); triXC.ForEach(p => p.planePos = planePos); triXC.ForEach(p => p.planeNormal = planeNormal); triXC[0].triangleVerticies = triangle1; triXC[1].triangleVerticies = triangle2; triXC[2].triangleVerticies = triangle3; triXC[3].triangleVerticies = triangle4; }
public unsafe void RigidBodyCastColliderTest() { Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.0f; const float sphereRadius = 1.0f; var rayStartOK = new float3(-10, -10, -10); var rayEndOK = new float3(10, 10, 10); var rayStartFail = new float3(-10, 10, -10); var rayEndFail = new float3(10, 10, 10); rigidbody.Collider = (Collider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr(); var colliderCastInput = new ColliderCastInput(); var closestHit = new ColliderCastHit(); var allHits = new NativeList <ColliderCastHit>(Allocator.Temp); // OK case : Sphere hits the box collider float3 rayDir = rayEndOK - rayStartOK; colliderCastInput.Position = rayStartOK; colliderCastInput.Direction = rayDir; colliderCastInput.Collider = (Collider *)SphereCollider.Create(float3.zero, sphereRadius).GetUnsafePtr(); Assert.IsTrue(rigidbody.CastCollider(colliderCastInput)); Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, out closestHit)); Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, ref allHits)); // Fail case : wrong direction rayDir = rayEndFail - rayStartFail; colliderCastInput.Position = rayStartFail; colliderCastInput.Direction = rayDir; Assert.IsFalse(rigidbody.CastCollider(colliderCastInput)); Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, out closestHit)); Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, ref allHits)); }
public void TestAabbTransform() { Random rnd = new Random(0x12345678); for (int i = 0; i < 100; i++) { quaternion r = rnd.NextQuaternionRotation(); float3 t = rnd.NextFloat3(); Aabb orig = new Aabb(); orig.Include(rnd.NextFloat3()); orig.Include(rnd.NextFloat3()); Aabb outAabb1 = Unity.Physics.Math.TransformAabb(new RigidTransform(r, t), orig); Physics.Math.MTransform bFromA = new Physics.Math.MTransform(r, t); Aabb outAabb2 = Unity.Physics.Math.TransformAabb(bFromA, orig); TestUtils.AreEqual(outAabb1.Min, outAabb2.Min, 1e-3f); TestUtils.AreEqual(outAabb1.Max, outAabb2.Max, 1e-3f); } }
public unsafe void RigidBodyCastRayTest() { Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.0f; var rayStartOK = new float3(-10, -10, -10); var rayEndOK = new float3(10, 10, 10); var rayStartFail = new float3(-10, 10, -10); var rayEndFail = new float3(10, 10, 10); rigidbody.Collider = (Collider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr(); var raycastInput = new RaycastInput(); var closestHit = new RaycastHit(); var allHits = new NativeList <RaycastHit>(Allocator.Temp); // OK case : Ray hits the box collider float3 rayDir = rayEndOK - rayStartOK; raycastInput.Ray.Origin = rayStartOK; raycastInput.Ray.Direction = rayDir; raycastInput.Filter = CollisionFilter.Default; Assert.IsTrue(rigidbody.CastRay(raycastInput)); Assert.IsTrue(rigidbody.CastRay(raycastInput, out closestHit)); Assert.IsTrue(rigidbody.CastRay(raycastInput, ref allHits)); // Fail Case : wrong direction rayDir = rayEndFail - rayStartFail; raycastInput.Ray.Origin = rayStartFail; raycastInput.Ray.Direction = rayDir; Assert.IsFalse(rigidbody.CastRay(raycastInput)); Assert.IsFalse(rigidbody.CastRay(raycastInput, out closestHit)); Assert.IsFalse(rigidbody.CastRay(raycastInput, ref allHits)); }
public unsafe void RigidBodyCalculateDistanceTest() { const float size = 1.0f; const float convexRadius = 0.0f; const float sphereRadius = 1.0f; var queryPos = new float3(-10, -10, -10); BlobAssetReference <Collider> boxCollider = BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius); BlobAssetReference <Collider> sphereCollider = SphereCollider.Create(float3.zero, sphereRadius); var rigidBody = new Physics.RigidBody { WorldFromBody = RigidTransform.identity, Collider = (Collider *)boxCollider.GetUnsafePtr() }; var colliderDistanceInput = new ColliderDistanceInput { Collider = (Collider *)sphereCollider.GetUnsafePtr(), Transform = new RigidTransform(quaternion.identity, queryPos) }; var closestHit = new DistanceHit(); var allHits = new NativeList <DistanceHit>(Allocator.Temp); // OK case : with enough max distance colliderDistanceInput.MaxDistance = 10000.0f; Assert.IsTrue(rigidBody.CalculateDistance(colliderDistanceInput)); Assert.IsTrue(rigidBody.CalculateDistance(colliderDistanceInput, out closestHit)); Assert.IsTrue(rigidBody.CalculateDistance(colliderDistanceInput, ref allHits)); // Fail case : not enough max distance colliderDistanceInput.MaxDistance = 1; Assert.IsFalse(rigidBody.CalculateDistance(colliderDistanceInput)); Assert.IsFalse(rigidBody.CalculateDistance(colliderDistanceInput, out closestHit)); Assert.IsFalse(rigidBody.CalculateDistance(colliderDistanceInput, ref allHits)); }
public void GenerateControlPoints(Vector3Int newResolution, float3[] resampleOriginalPoints, Vector3Int resampleOriginalResolution) { resolution = newResolution; controlPoints = new float3[resolution.x * resolution.y * resolution.z]; for (int z = 0; z < resolution.z; z++) { for (int y = 0; y < resolution.y; y++) { for (int x = 0; x < resolution.x; x++) { int index = GetIndex(x, y, z); controlPoints[index] = new float3(x / (float)(newResolution.x - 1) - 0.5f, y / (float)(newResolution.y - 1) - 0.5f, z / (float)(newResolution.z - 1) - 0.5f); } } } if (resampleOriginalPoints != null) { var nativeArray = new NativeArray <float3>(controlPoints, Allocator.TempJob); var latticeJob = new LatticeJob { controlPoints = new NativeArray <float3>(resampleOriginalPoints, Allocator.TempJob), resolution = new int3(resampleOriginalResolution.x, resampleOriginalResolution.y, resampleOriginalResolution.z), meshToTarget = float4x4.identity, targetToMesh = float4x4.identity, vertices = nativeArray }; latticeJob.Run(controlPoints.Length); resolution = newResolution; nativeArray.CopyTo(controlPoints); nativeArray.Dispose(); } }
public void Execute(int index) { vec3 rd = Samples[index]; vec3 ro = RayOrigin; Ray ray = new Ray(ro, rd); float nearest = RayLength; // if(tempBound.IntersectRay(ray, out float d)) // { // nearest = min(abs(d), nearest); // } for (int v = 0; v < 6; v++) { if (PlaneRaycast(ro, rd, VolumePlanes[v], out float d)) { nearest = min(nearest, d); } } RayLengths[index] = nearest; }
/// <summary> /// Function to render the intersection of a plane and a triangle /// </summary> /// <param name="height"></param> /// <param name="vertices"></param> /// <param name="crossSectionRenderer"></param> public void crossSectTri(Unity.Mathematics.float3 point, Unity.Mathematics.float3 normalDirection, Unity.Mathematics.float3[] vertices, UnityEngine.LineRenderer crossSectionRenderer) { //Vertices are organized in clockwise manner starting from top //top vertex Unity.Mathematics.float3 a = vertices[0]; //bottom right Unity.Mathematics.float3 b = vertices[1]; //bottom left Unity.Mathematics.float3 c = vertices[2]; //intermediate calculations Unity.Mathematics.float3 ac_hat = (c - a) / UnityEngine.Vector3.Magnitude(c - a); Unity.Mathematics.float3 ab_hat = (b - a) / UnityEngine.Vector3.Magnitude(b - a); Unity.Mathematics.float3 bc_hat = (c - b) / UnityEngine.Vector3.Magnitude(c - b); //points of intersection on each line segment Unity.Mathematics.float3 ac_star = IMRE.Math.Operations.SegmentPlaneIntersection(a, c, point, normalDirection); Unity.Mathematics.float3 ab_star = IMRE.Math.Operations.SegmentPlaneIntersection(a, b, point, normalDirection); Unity.Mathematics.float3 bc_star = IMRE.Math.Operations.SegmentPlaneIntersection(b, c, point, normalDirection); //boolean values for if intersection hits only a vertex of the triangle bool ac_star_isEndpoint; ac_star_isEndpoint = ac_star.Equals(a) || ac_star.Equals(c); bool ab_star_isEndpoint; ab_star_isEndpoint = ab_star.Equals(a) || ab_star.Equals(b); bool bc_star_isEndpoint; bc_star_isEndpoint = bc_star.Equals(c) || bc_star.Equals(c); //booleans for if intersection hits somewhere on the segments bool ac_star_onSegment = !ac_star.Equals(new float3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity)); bool ab_star_onSegment = !ab_star.Equals(new float3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity)); bool bc_star_onSegment = !bc_star.Equals(new float3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity)); //track how many vertices the intersection hits int endpointCount = 0; if (ac_star_isEndpoint) { endpointCount++; } if (ab_star_isEndpoint) { endpointCount++; } if (bc_star_isEndpoint) { endpointCount++; } //If plane does not hit triangle if (!(ab_star_onSegment || ac_star_onSegment || bc_star_onSegment)) { crossSectionRenderer.enabled = false; UnityEngine.Debug.Log("Line does not intersect with any of triangle sides."); } //intersection is a segment (edge) of the triangle //the concept for choosing the right points of the cross section is the same for each of these subcases //two unique endpoint values else if (endpointCount >= 2 && (!ab_star.Equals(ac_star) || !ab_star.Equals(bc_star) || !ac_star.Equals(bc_star))) { crossSectionRenderer.enabled = true; //if there are two unique values, pick two. //drop the result for the edge which is within the plane //tolerance accounts for rounding errors float tolerance = .00001f; if (Unity.Mathematics.math.dot(ab_hat, normalDirection) < tolerance) { crossSectionRenderer.SetPosition(0, a); crossSectionRenderer.SetPosition(1, b); } else if (Unity.Mathematics.math.dot(ac_hat, normalDirection) < tolerance) { crossSectionRenderer.SetPosition(0, a); crossSectionRenderer.SetPosition(1, c); } else if (Unity.Mathematics.math.dot(bc_hat, normalDirection) < tolerance) { crossSectionRenderer.SetPosition(0, b); crossSectionRenderer.SetPosition(1, c); } else { Debug.LogWarning("Error in calculation of line plane intersection"); crossSectionRenderer.enabled = false; } } //intersection hits one vertex on triangle and one of the segments else if (endpointCount == 2 && ab_star.Equals(ac_star) || ab_star.Equals(bc_star) || ac_star.Equals(bc_star)) { crossSectionRenderer.enabled = true; //if point of intersection hits a, it must hit bc_star; same logic applies to remaining subcases if (ab_star.Equals(ac_star)) { crossSectionRenderer.SetPosition(0, a); crossSectionRenderer.SetPosition(1, bc_star); } else if (ab_star.Equals(bc_star)) { crossSectionRenderer.SetPosition(0, b); crossSectionRenderer.SetPosition(1, ac_star); } else if (ac_star.Equals(bc_star)) { crossSectionRenderer.SetPosition(0, c); crossSectionRenderer.SetPosition(1, ab_star); } else { Debug.LogWarning("Error in calculation of line plane intersection"); crossSectionRenderer.enabled = false; } } //intersection hits somewhere on two different segments of triangle; last remaining case else { crossSectionRenderer.enabled = true; //find out which two segments are intersected and use their calculated intersections if (ac_star_onSegment && ab_star_onSegment) { crossSectionRenderer.SetPosition(0, ac_star); crossSectionRenderer.SetPosition(1, ab_star); } else if (ac_star_onSegment && bc_star_onSegment) { crossSectionRenderer.SetPosition(0, ac_star); crossSectionRenderer.SetPosition(1, bc_star); } else if (ab_star_onSegment && bc_star_onSegment) { crossSectionRenderer.SetPosition(0, ab_star); crossSectionRenderer.SetPosition(1, bc_star); } else { Debug.LogWarning("Error in calculation of line plane intersection"); crossSectionRenderer.enabled = false; } } }
public static float3 rotate(quaternion q, float3 v) { float3 t = 2 * cross(q.value.xyz, v); return(v + q.value.w * t + cross(q.value.xyz, t)); }
/// <summary> /// Returns a quaternion view rotation given a unit length forward vector and a unit length up vector. /// The two input vectors are assumed to be unit length and not collinear. /// If these assumptions are not met use float3x3.LookRotationSafe instead. /// </summary> public static quaternion LookRotation(float3 forward, float3 up) { float3 t = normalize(cross(up, forward)); return(quaternion(float3x3(t, cross(forward, t), forward))); }
public static float3 mul(float3x3 x, float3 v) { return(mad(x.c2, v.z, mad(x.c0, v.x, x.c1 * v.y))); }