public override bool PreciseIntersect(ref SSRay worldSpaceRay, ref float distanceAlongRay) { SSRay localRay = worldSpaceRay.Transformed(this.worldMat.Inverted()); SSAbstractMesh mesh = this._mesh; bool hit = false; float localNearestContact = float.MaxValue; if (mesh == null) { return(true); // no mesh to test } else { // precise meshIntersect bool global_hit = mesh.TraverseTriangles((state, V1, V2, V3) => { float contact; if (OpenTKHelper.TriangleRayIntersectionTest(V1, V2, V3, localRay.pos, localRay.dir, out contact)) { hit = true; localNearestContact = Math.Min(localNearestContact, contact); Console.WriteLine("Triangle Hit @ {0} : Object {1}", contact, Name); } return(false); // don't short circuit }); if (hit) { float worldSpaceContactDistance = -localNearestContact * this.Scale.LengthFast; Console.WriteLine("Nearest Triangle Hit @ {0} vs Sphere {1} : Object {2}", worldSpaceContactDistance, distanceAlongRay, Name); distanceAlongRay = worldSpaceContactDistance; } return(global_hit || hit); } }
protected bool _perInstanceIntersectionTest(SSAbstractMesh abstrMesh, int i, ref SSRay localRay, out float localContact) { var pos = instanceData.readPosition(i); var masterScale = instanceData.readMasterScale(i); var scale = instanceData.readComponentScale(i) * masterScale; if (abstrMesh == null) { // no way to be any more precise except hitting a generic sphere float radius = Math.Max(scale.Z, Math.Max(scale.X, scale.Y)); var sphere = new SSSphere(pos, radius); return(sphere.IntersectsRay(ref localRay, out localContact)); } else { // When using SSAbstractMesh we can invoke its preciseIntersect() Matrix4 instanceMat = Matrix4.CreateScale(scale) * Matrix4.CreateTranslation(pos); SSRay instanceRay = localRay.Transformed(instanceMat.Inverted()); float instanceContact; if (abstrMesh.preciseIntersect(ref instanceRay, out instanceContact)) { Vector3 instanceContactPt = instanceRay.pos + instanceContact * instanceRay.dir; Vector3 localContactPt = Vector3.Transform(instanceContactPt, instanceMat); localContact = (localContactPt - localRay.pos).Length; return(true); } else { localContact = float.PositiveInfinity; return(false); } } }
public SSObjectMesh(SSAbstractMesh mesh) : this() { this.Mesh = mesh; this.renderState.castsShadow = true; // SSObjectMesh casts shadow by default this.renderState.receivesShadows = true; // SSObjectMesh receives shadow by default _setupMesh(); }
public SSObjectMesh(SSAbstractMesh mesh) : this() { this.Mesh = mesh; this.renderState.castsShadow = true; // SSObjectMesh casts shadow by default this.renderState.receivesShadows = true; // SSObjectMesh receives shadow by default _setupMesh (); }
public SSObjectBillboard(SSAbstractMesh mesh, bool enableOcclusionTest = false) { Mesh = mesh; isOcclusionQueueryEnabled = enableOcclusionTest; if (isOcclusionQueueryEnabled) { GL_query_id = GL.GenQuery(); } }
public SSObjectMesh(SSAbstractMesh mesh) : this() { this.Mesh = mesh; this.renderState.castsShadow = true; // SSObjectMesh casts shadow by default }
public override bool PreciseIntersect(ref SSRay worldSpaceRay, ref float distanceAlongRay) { SSRay localRay = worldSpaceRay.Transformed(this.worldMat.Inverted()); SSAbstractMesh abstrMesh = this.mesh as SSAbstractMesh; float nearestLocalRayContact = float.PositiveInfinity; if (useBVHForIntersections) { if (_bvh == null) { _bvh = new SSInstanceBVH(this.instanceData); for (int i = 0; i < instanceData.activeBlockLength; ++i) { if (instanceData.isValid(i)) { _bvh.addObject(i); } } } List <ssBVHNode <int> > nodesHit = _bvh.traverseRay(localRay); foreach (var node in nodesHit) { if (!node.IsLeaf) { continue; } foreach (int i in node.gobjects) { if (!instanceData.isValid(i)) { continue; } float localContact; if (_perInstanceIntersectionTest(abstrMesh, i, ref localRay, out localContact)) { if (localContact < nearestLocalRayContact) { nearestLocalRayContact = localContact; } } } } } else { // no BVH is used for (int i = 0; i < instanceData.activeBlockLength; ++i) { if (!instanceData.isValid(i)) { continue; } float localContact; if (_perInstanceIntersectionTest(abstrMesh, i, ref localRay, out localContact)) { if (localContact < nearestLocalRayContact) { nearestLocalRayContact = localContact; } } } } if (nearestLocalRayContact < float.PositiveInfinity) { Vector3 localContactPt = localRay.pos + nearestLocalRayContact * localRay.dir; Vector3 worldContactPt = Vector3.Transform(localContactPt, this.worldMat); distanceAlongRay = (worldContactPt - worldSpaceRay.pos).Length; return(true); } else { distanceAlongRay = float.PositiveInfinity; return(false); } }
public SSObjectMeshSky(SSAbstractMesh mesh) : base(mesh) { }
public SSObjectOcclusionQueuery(SSAbstractMesh mesh) { Mesh = mesh; _gl_query_id = GL.GenQuery(); }