/// <summary> /// Performs an intersection test against a packet of 4 rays. /// </summary> public unsafe RTC.RayPacket4 Intersects4 <Ray>(Ray[] rays, float near = 0, float far = float.PositiveInfinity, float time = 0) where Ray : IEmbreeRay { #if DEBUG if (!traversalFlags.HasFlag(TraversalFlags.Packet4)) { throw new InvalidOperationException("Traversal flags forbid 4-ray packet traversal"); } #endif var p = RTC.RayInterop.Packet4; var a = RTC.RayInterop.Activity; for (var t = 0; t < 4; ++t) { if (rays[t] != null) { a[t] = RTC.RayInterop.Active; } else { a[t] = RTC.RayInterop.Inactive; continue; } var o = rays[t].Origin; var d = rays[t].Direction; p->orgX[t] = o.X; p->orgY[t] = o.Y; p->orgZ[t] = o.Z; p->dirX[t] = d.X; p->dirY[t] = d.Y; p->dirZ[t] = d.Z; p->geomID[t] = RTC.InvalidGeometryID; p->primID[t] = RTC.InvalidGeometryID; p->instID[t] = RTC.InvalidGeometryID; p->time[t] = time; p->tnear[t] = near; p->tfar[t] = far; } RTC.Intersect4(a, scenePtr, p); return(*p); }
/// <summary> /// Commits all current instances to the scene. /// </summary> public void Commit() { foreach (var entry in instances) { var instance = entry.Value; instance.Geometry.Commit(); var xtf = new float[12] // Column-major order { instance.Transform.U.X, instance.Transform.U.Y, instance.Transform.U.Z, instance.Transform.V.X, instance.Transform.V.Y, instance.Transform.V.Z, instance.Transform.W.X, instance.Transform.W.Y, instance.Transform.W.Z, instance.Transform.T.X, instance.Transform.T.Y, instance.Transform.T.Z }; var pinned = GCHandle.Alloc(xtf, GCHandleType.Pinned); // Pin transform matrix to raw float* array RTC.SetTransform(scenePtr, entry.Key, RTC.MatrixLayout.ColumnMajor, pinned.AddrOfPinnedObject()); pinned.Free(); // Release before checking for error RTC.CheckLastError(); if (instance.Enabled) { RTC.EnableGeometry(scenePtr, entry.Key); } else { RTC.DisableGeometry(scenePtr, entry.Key); } RTC.CheckLastError(); if (sceneFlags.HasFlag(SceneFlags.Dynamic)) { RTC.UpdateGeometry(scenePtr, entry.Key); RTC.CheckLastError(); // static mesh? } } RTC.Commit(scenePtr); RTC.CheckLastError(); }
/// <summary> /// Removes a geometry from this scene. /// </summary> public Boolean Remove(Geometry geometry) { CheckDisposed(); if (geometry == null) { throw new ArgumentNullException("geometry"); } if (geometryInverse.ContainsKey(geometry)) { RTC.DeleteGeometry(NativePtr, geometry.ID); geometryMapping.Remove(geometry.ID); geometryInverse.Remove(geometry); return(true); } else { return(false); } }
/// <summary> /// Removes an instance from this scene. /// </summary> public Boolean Remove(Instance instance) { CheckDisposed(); if (instance == null) { throw new ArgumentNullException("instance"); } if (instanceInverse.ContainsKey(instance)) { RTC.DeleteGeometry(NativePtr, instance.ID); instanceMapping.Remove(instance.ID); instanceInverse.Remove(instance); return(true); } else { return(false); } }
public void Update(uint geomID, IntPtr scenePtr) { if (indices.Count / 3 == triangleCount) { var indexBuffer = RTC.MapBuffer(scenePtr, geomID, RTC.BufferType.IndexBuffer); RTC.CheckLastError(); Marshal.Copy(indices.ToArray(), 0, indexBuffer, indices.Count); RTC.UnmapBuffer(scenePtr, geomID, RTC.BufferType.IndexBuffer); } else { throw new InvalidOperationException("Index buffer length was changed."); } if (vertices.Count == vertexCount) { var vertexBuffer = RTC.MapBuffer(scenePtr, geomID, RTC.BufferType.VertexBuffer); RTC.CheckLastError(); unsafe { float *ptr = (float *)vertexBuffer; foreach (var vertex in vertices) { *(ptr++) = vertex.X; *(ptr++) = vertex.Y; *(ptr++) = vertex.Z; *(ptr++) = 1.0f; } } RTC.UnmapBuffer(scenePtr, geomID, RTC.BufferType.VertexBuffer); } else { throw new InvalidOperationException("Vertex buffer length was changed."); } }
/// <summary> /// Sets the triangles of this triangle mesh. /// </summary> public void SetTriangles(Triangle[] triangles, int srcOffset, int dstOffset, int length) { if (triangles == null) { throw new ArgumentNullException("triangles"); } else if (srcOffset < 0) { throw new ArgumentOutOfRangeException("srcOffset"); } else if (dstOffset < 0) { throw new ArgumentOutOfRangeException("dstOffset"); } else if (length < 0) { throw new ArgumentOutOfRangeException("length"); } else if (srcOffset + length > triangles.Length) { throw new ArgumentOutOfRangeException("srcOffset"); } else if (dstOffset + length > Description.NumTriangles) { throw new ArgumentOutOfRangeException("dstOffset"); } else if (length == 0) { return; } using (var triangleBuffer = new MappedBuffer <Triangle>(Parent, ID, BufferType.IndexBuffer)) { for (int t = 0; t < length; ++t) { triangleBuffer[t + dstOffset] = triangles[t + srcOffset]; } } RTC.UpdateBuffer(Parent.NativePtr, ID, BufferType.IndexBuffer); }
/// <summary> /// Sets the transformation matrix for this instance. /// </summary> /// <param name="transform">The transformation matrix entries.</param> /// <param name="layout">The layout of the matrix entries.</param> /// <remarks> /// Only the first 12 or 16 entries of the transform array are used. /// </remarks> /// <remarks> /// The transform should be uniform, i.e. no non-uniform scaling. /// </remarks> public unsafe void SetTransform(float[] transform, MatrixLayout layout) { if (transform == null) { throw new ArgumentNullException("transform"); } switch (layout) { case MatrixLayout.ColumnMajorAligned16: if (transform.Length < 16) { throw new ArgumentException("transform"); } else { break; } case MatrixLayout.ColumnMajor: case MatrixLayout.RowMajor: if (transform.Length < 12) { throw new ArgumentException("transform"); } else { break; } default: throw new ArgumentException("layout"); } fixed(float *xfm = transform) { RTC.SetTransform(Parent.NativePtr, ID, layout, xfm); } }
/// <summary> /// Commits all geometry within this scene. /// </summary> public void Commit() { CheckDisposed(); RTC.Commit(NativePtr); }
/// <summary> /// Checks the last embree error for this devices and throws exceptions as needed /// </summary> public void CheckLastError() { RTC.CheckLastError(this.devicePtr); }
/// <summary> /// Creates a new raytracing device context /// </summary> /// <param name="verbose">if true embree will run inverbose mode</param> public Device(bool verbose = false) { string cfg = verbose ? "verbose=999" : null; this.devicePtr = RTC.InitEmbree(cfg); }
/// <summary> /// If you use the RTC interop wrapper, Embree is initialized for you. /// </summary> static RTC() { RTC.Initialize(); }