public static void ComputeNormals <V>(this Mesh <V> mesh) where V : struct, INormalVertex <V> { if (mesh.Topology != Topology.Triangles) { return; } float3[] normals = new float3[mesh.Vertices.Length]; for (int i = 0; i < mesh.Indices.Length / 3; i++) { float3 p0 = mesh.Vertices[mesh.Indices[i * 3 + 0]].Position; float3 p1 = mesh.Vertices[mesh.Indices[i * 3 + 1]].Position; float3 p2 = mesh.Vertices[mesh.Indices[i * 3 + 2]].Position; // Compute the normal of the triangle. float3 N = cross(p1 - p0, p2 - p0); // Add the normal to the vertices involved normals[mesh.Indices[i * 3 + 0]] += N; normals[mesh.Indices[i * 3 + 1]] += N; normals[mesh.Indices[i * 3 + 2]] += N; } // Update per-vertex normal using normal accumulation normalized. for (int i = 0; i < mesh.Vertices.Length; i++) { mesh.Vertices[i].Normal = normalize(normals[i]); } }
/// <summary> /// Welds different vertices with positions close to each other using an epsilon decimation. /// </summary> public static Mesh <V> Weld <V>(this Mesh <V> mesh, float epsilon = 0.0001f) where V : struct, IVertex <V> { // Method using decimation... // TODO: Implement other methods Dictionary <int3, int> uniqueVertices = new Dictionary <int3, int>(); int[] mappedVertices = new int[mesh.Vertices.Length]; List <V> newVertices = new List <V>(); for (int i = 0; i < mesh.Vertices.Length; i++) { V vertex = mesh.Vertices[i]; float3 p = vertex.Position; int3 cell = (int3)(p / epsilon); // convert vertex position in a discrete cell. if (!uniqueVertices.ContainsKey(cell)) { uniqueVertices.Add(cell, newVertices.Count); newVertices.Add(vertex); } mappedVertices[i] = uniqueVertices[cell]; } int[] newIndices = new int[mesh.Indices.Length]; for (int i = 0; i < mesh.Indices.Length; i++) { newIndices[i] = mappedVertices[mesh.Indices[i]]; } return(new Mesh <V>(newVertices.ToArray(), newIndices, mesh.Topology)); }
public static (float4x4, float4x4) GetViewAndProjection(Texture2D texture, float3 cameraPosition, float3 target) { // View and projection matrices var viewMatrix = Transforms.LookAtLH(cameraPosition, target, float3(0, 1, 0)); var projectionMatrix = Transforms.PerspectiveFovLH(pi_over_4, texture.Height / (float)texture.Width, 0.01f, 20); return(viewMatrix, projectionMatrix); }
static float3 EvalBezier(float3[] control, float t) { // DeCasteljau if (control.Length == 1) { return(control[0]); // stop condition } float3[] nestedPoints = new float3[control.Length - 1]; for (int i = 0; i < nestedPoints.Length; i++) { nestedPoints[i] = lerp(control[i], control[i + 1], t); } return(EvalBezier(nestedPoints, t)); }
static void LitRaycast(Texture2D texture) { // Scene Setup float3 CameraPosition = float3(3, 2f, 4); float3 LightPosition = float3(3, 5, -2); // View and projection matrices float4x4 viewMatrix = Transforms.LookAtLH(CameraPosition, float3(0, 1, 0), float3(0, 1, 0)); float4x4 projectionMatrix = Transforms.PerspectiveFovLH(pi_over_4, texture.Height / (float)texture.Width, 0.01f, 20); Scene <PositionNormal> scene = new Scene <PositionNormal>(); CreateScene(scene); // Raycaster to trace rays and check for shadow rays. Raytracer <ShadowRayPayload, PositionNormal> shadower = new Raytracer <ShadowRayPayload, PositionNormal>(); shadower.OnAnyHit += delegate(IRaycastContext context, PositionNormal attribute, ref ShadowRayPayload payload) { // If any object is found in ray-path to the light, the ray is shadowed. payload.Shadowed = true; // No neccessary to continue checking other objects return(HitResult.Stop); }; // Raycaster to trace rays and lit closest surfaces Raytracer <RayPayload, PositionNormal> raycaster = new Raytracer <RayPayload, PositionNormal>(); raycaster.OnClosestHit += delegate(IRaycastContext context, PositionNormal attribute, ref RayPayload payload) { // Move geometry attribute to world space attribute = attribute.Transform(context.FromGeometryToWorld); float3 V = normalize(CameraPosition - attribute.Position); float3 L = normalize(LightPosition - attribute.Position); float lambertFactor = max(0, dot(attribute.Normal, L)); // Check ray to light... ShadowRayPayload shadow = new ShadowRayPayload(); shadower.Trace(scene, RayDescription.FromTo( attribute.Position + attribute.Normal * 0.001f, // Move an epsilon away from the surface to avoid self-shadowing LightPosition), ref shadow); payload.Color = shadow.Shadowed ? float3(0, 0, 0) : float3(1, 1, 1) * lambertFactor; }; raycaster.OnMiss += delegate(IRaycastContext context, ref RayPayload payload) { payload.Color = float3(0, 0, 1); // Blue, as the sky. }; // Render all points of the screen for (int px = 0; px < texture.Width; px++) { for (int py = 0; py < texture.Height; py++) { RayDescription ray = RayDescription.FromScreen(px + 0.5f, py + 0.5f, texture.Width, texture.Height, inverse(viewMatrix), inverse(projectionMatrix), 0, 1000); RayPayload coloring = new RayPayload(); raycaster.Trace(scene, ray, ref coloring); texture.Write(px, py, float4(coloring.Color, 1)); } } }
public static Mesh <V> Revolution(int slices, int stacks, Func <float, float3> g, float3 axis) { return(Generative(slices, stacks, g, (v, t) => mul(float4(v, 1), Transforms.Rotate(t * 2 * pi, axis)).xyz)); }
public static Mesh <V> Extrude(int slices, int stacks, Func <float, float3> g, float3 direction) { return(Generative(slices, stacks, g, (v, t) => v + direction * t)); }
public float Distance(float3 pto, out float3 closest) { return(GTools.distanceP2L(pto, A, B, out closest)); }
public float Distance(float3 pto) { return(Distance(pto, out float3 _)); }
public Node(int _i, int _j, float3 _pos) { i = _i; j = _j; pos = _pos; }
/// <summary> /// Creates a line given by two positions in space /// </summary> public Line3D(float3 a, float3 b) { A = a; B = b; }
public void UpdateTranslation(float3 source) { Transform.TranslationVector = Transform.Position - source; }
public float3 random3(float3 min, float3 max) { return(random3() * (max - min) + min); }
public float3 gauss3(float3 mu, float3 sigma) { return(gauss3() * sigma + mu); }
/// <summary> /// Random uniform direction in a Hemisphere /// </summary> public float3 randomHSDirection(float3 N) { float NdotD; return(randomHSDirection(N, out NdotD)); }
/// <summary> /// Creates a line given by two positions in space /// </summary> public Line3D(float3 a, float3 b) { this.A = a; this.B = b; }