void UpdateViewMatrix() { Graphics.SetMatrixMode(MatrixType.Modelview); Camera.GetView(out Graphics.View); Graphics.LoadMatrix(ref Graphics.View); Culling.CalcFrustumEquations(ref Graphics.Projection, ref Graphics.View); }
// Update is called once per frame private void Update() { //means tht it has it loaded if (_gameTime == null) { return; } if (QuestManager == null) { QuestManager = new QuestManager(); } QuestManager.Update(); //if (EnemyManager == null) //{ // EnemyManager = new EnemyManager(); //} //if (GameWasFullyLoadedAnd10SecAgo()) //{ // EnemyManager.Update(); //} AudioCollector.Update(); CreateDummySpawnPoint(); DebugInput(); DebugChangeScreenResolution(); if (Camera.main != null && _culling == null) { //bz camera needs to be initiated already _culling = new Culling(); _fustrum = new Fustrum(); } if (_fustrum != null) { _fustrum.Update(); } if (hud == null) { var hudGO = FindObjectOfType <HUDFPS>(); if (hudGO != null) { hud = hudGO.GuiText; HideShowTextMsg(); } } //if (Input.GetKeyUp(KeyCode.B)) //{ // //_staticBatch = new StaticBatch(); // //_meshBatch = new MeshBatch(); //} }
void GetNineClosest() { closestMaps = cullMaps.OrderBy(t => (t.transform.position - transform.position).sqrMagnitude) .Take(9) //or use .FirstOrDefault(); if you need just one .ToArray(); ActivateTheseAndCullAllElse(closestMaps); currentMap = GetClosest(); InvokeRepeating(nameof(CheckClosest), checkTime, checkTime); }
void UpdateViewMatrix() { Graphics.SetMatrixMode(MatrixType.Modelview); Matrix4 modelView = Camera.GetView(); View = modelView; Graphics.LoadMatrix(ref modelView); Culling.CalcFrustumEquations(ref Projection, ref modelView); }
/// <summary>Default value.</summary> /// <returns>The default value and allocate ~250B of garbage.</returns> public static CameraSettings NewDefault() => new CameraSettings { bufferClearing = BufferClearing.NewDefault(), culling = Culling.NewDefault(), renderingPathCustomFrameSettings = FrameSettings.NewDefaultCamera(), frustum = Frustum.NewDefault(), customRenderingSettings = false, volumes = Volumes.NewDefault(), flipYMode = HDAdditionalCameraData.FlipYMode.Automatic, invertFaceCulling = false, probeLayerMask = ~0, probeRangeCompressionFactor = 1.0f };
Culling[] GetNineClosest(Vector2Int coords) { Culling[] res = new Culling[9]; res[0] = cullMapsGrid[coords.x - 1, coords.y - 1]; res[1] = cullMapsGrid[coords.x, coords.y]; res[2] = cullMapsGrid[coords.x + 1, coords.y + 1]; res[3] = cullMapsGrid[coords.x - 1, coords.y - 1]; res[4] = cullMapsGrid[coords.x, coords.y]; res[5] = cullMapsGrid[coords.x + 1, coords.y + 1]; res[6] = cullMapsGrid[coords.x - 1, coords.y - 1]; res[7] = cullMapsGrid[coords.x, coords.y]; res[8] = cullMapsGrid[coords.x + 1, coords.y + 1]; return(res); }
void CullingPopup() { Culling cull = (Culling)Mathf.RoundToInt(culling.floatValue); EditorGUI.showMixedValue = culling.hasMixedValue; EditorGUI.BeginChangeCheck(); cull = (Culling)EditorGUILayout.Popup(Styles.cullingMode, (int)cull, Styles.cullNames); if (EditorGUI.EndChangeCheck()) { m_MaterialEditor.RegisterPropertyChangeUndo("Culling Mode"); culling.floatValue = (float)cull; } EditorGUI.showMixedValue = false; }
public override void Save() { XmlDocument doc = new XmlDocument(); XmlElement root = doc.CreateElement("material"); doc.AppendChild(root); //TECHNIQUES foreach (MatTechnique tech in Techniques) { root.AppendChild(tech.Save(doc)); } foreach (MatTexture tex in Textures) { root.AppendChild(tex.Save(doc)); } foreach (MatParameter param in Params) { root.AppendChild(param.Save(doc)); } XmlElement cull = doc.CreateElement("cull"); cull.SetAttribute("value", Culling.ToString().ToLower()); root.AppendChild(cull); XmlElement scull = doc.CreateElement("shadowcull"); scull.SetAttribute("value", ShadowCull.ToString().ToLower()); root.AppendChild(scull); XmlElement dbias = doc.CreateElement("depthbias"); dbias.SetAttribute("constant", DepthBiasConst.ToString()); dbias.SetAttribute("slopedscaled", DepthBiasSlope.ToString()); XmlWriterSettings xws = new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true }; using (XmlWriter xw = XmlWriter.Create(System.IO.Path.ChangeExtension(Name, "xml"), xws)) doc.Save(xw); }
public void Read(AssetReader reader) { Name = reader.ReadStringAligned(); RtBlend0.Read(reader); RtBlend1.Read(reader); RtBlend2.Read(reader); RtBlend3.Read(reader); RtBlend4.Read(reader); RtBlend5.Read(reader); RtBlend6.Read(reader); RtBlend7.Read(reader); RtSeparateBlend = reader.ReadBoolean(); reader.AlignStream(AlignType.Align4); if (IsReadZClip(reader.Version)) { ZClip.Read(reader); } ZTest.Read(reader); ZWrite.Read(reader); Culling.Read(reader); OffsetFactor.Read(reader); OffsetUnits.Read(reader); AlphaToMask.Read(reader); StencilOp.Read(reader); StencilOpFront.Read(reader); StencilOpBack.Read(reader); StencilReadMask.Read(reader); StencilWriteMask.Read(reader); StencilRef.Read(reader); FogStart.Read(reader); FogEnd.Read(reader); FogDensity.Read(reader); FogColor.Read(reader); FogMode = (FogMode)reader.ReadInt32(); GpuProgramID = reader.ReadInt32(); Tags.Read(reader); LOD = reader.ReadInt32(); Lighting = reader.ReadBoolean(); reader.AlignStream(AlignType.Align4); }
public void Read(EndianStream stream) { Name = stream.ReadStringAligned(); RtBlend0.Read(stream); RtBlend1.Read(stream); RtBlend2.Read(stream); RtBlend3.Read(stream); RtBlend4.Read(stream); RtBlend5.Read(stream); RtBlend6.Read(stream); RtBlend7.Read(stream); RtSeparateBlend = stream.ReadBoolean(); stream.AlignStream(AlignType.Align4); ZTest.Read(stream); ZWrite.Read(stream); Culling.Read(stream); OffsetFactor.Read(stream); OffsetUnits.Read(stream); AlphaToMask.Read(stream); StencilOp.Read(stream); StencilOpFront.Read(stream); StencilOpBack.Read(stream); StencilReadMask.Read(stream); StencilWriteMask.Read(stream); StencilRef.Read(stream); FogStart.Read(stream); FogEnd.Read(stream); FogDensity.Read(stream); FogColor.Read(stream); FogMode = stream.ReadInt32(); GpuProgramID = stream.ReadInt32(); Tags.Read(stream); LOD = stream.ReadInt32(); Lighting = stream.ReadBoolean(); stream.AlignStream(AlignType.Align4); }
/** * Find the all triangles intersected by InWorldRay on this pb_Object. InWorldRay is in world space. * @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit * point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front * faces, Culling.Back only tests back faces, and Culling.FrontBack tests both). */ public static bool MeshRaycast(Ray InWorldRay, qe_Mesh qe, out List<qe_RaycastHit> hits, float distance, Culling cullingMode) { /** * Transform ray into model space */ InWorldRay.origin -= qe.transform.position; // Why doesn't worldToLocalMatrix apply translation? InWorldRay.origin = qe.transform.worldToLocalMatrix * InWorldRay.origin; InWorldRay.direction = qe.transform.worldToLocalMatrix * InWorldRay.direction; Vector3[] vertices = qe.vertices; float dist = 0f; Vector3 point = Vector3.zero; float dot; // vars used in loop Vector3 nrm; // vars used in loop hits = new List<qe_RaycastHit>(); /** * Iterate faces, testing for nearest hit to ray origin. Optionally ignores backfaces. */ for(int CurFace = 0; CurFace < qe.faces.Length; ++CurFace) { int[] Indices = qe.faces[CurFace].indices; for(int CurTriangle = 0; CurTriangle < Indices.Length; CurTriangle += 3) { Vector3 a = vertices[Indices[CurTriangle+0]]; Vector3 b = vertices[Indices[CurTriangle+1]]; Vector3 c = vertices[Indices[CurTriangle+2]]; if(qe_Math.RayIntersectsTriangle(InWorldRay, a, b, c, out dist, out point)) { nrm = Vector3.Cross(b-a, c-a); switch(cullingMode) { case Culling.Front: dot = Vector3.Dot(InWorldRay.direction, -nrm); if(dot > 0f) goto case Culling.FrontBack; break; case Culling.Back: dot = Vector3.Dot(InWorldRay.direction, nrm); if(dot > 0f) goto case Culling.FrontBack; break; case Culling.FrontBack: hits.Add( new qe_RaycastHit(dist, InWorldRay.GetPoint(dist), nrm, CurFace)); break; } continue; } } } return hits.Count > 0; }
/** * Find the nearest triangle intersected by InWorldRay on this pb_Object. InWorldRay is in world space. * @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit * point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front * faces, Culling.Back only tests back faces, and Culling.FrontBack tests both). */ public static bool MeshRaycast(Ray InWorldRay, qe_Mesh mesh, out qe_RaycastHit hit, float distance, Culling cullingMode) { /** * Transform ray into model space */ InWorldRay.origin -= mesh.transform.position; // Why doesn't worldToLocalMatrix apply translation? InWorldRay.origin = mesh.transform.worldToLocalMatrix * InWorldRay.origin; InWorldRay.direction = mesh.transform.worldToLocalMatrix * InWorldRay.direction; Vector3[] vertices = mesh.vertices; float dist = 0f; Vector3 point = Vector3.zero; float OutHitPoint = Mathf.Infinity; float dot; // vars used in loop Vector3 nrm; // vars used in loop int OutHitFace = -1; Vector3 OutNrm = Vector3.zero; /** * Iterate faces, testing for nearest hit to ray origin. Optionally ignores backfaces. */ for(int CurFace = 0; CurFace < mesh.faces.Length; ++CurFace) { int[] Indices = mesh.faces[CurFace].indices; for(int CurTriangle = 0; CurTriangle < Indices.Length; CurTriangle += 3) { Vector3 a = vertices[Indices[CurTriangle+0]]; Vector3 b = vertices[Indices[CurTriangle+1]]; Vector3 c = vertices[Indices[CurTriangle+2]]; nrm = Vector3.Cross(b-a, c-a); dot = Vector3.Dot(InWorldRay.direction, nrm); bool ignore = false; switch(cullingMode) { case Culling.Front: if(dot > 0f) ignore = true; break; case Culling.Back: if(dot < 0f) ignore = true; break; } if(!ignore && qe_Math.RayIntersectsTriangle(InWorldRay, a, b, c, out dist, out point)) { if(dist > OutHitPoint || dist > distance) continue; OutNrm = nrm; OutHitFace = CurFace; OutHitPoint = dist; continue; } } } hit = new qe_RaycastHit(OutHitPoint, InWorldRay.GetPoint(OutHitPoint), OutNrm, OutHitFace); return OutHitFace > -1; }
/** * Find the all triangles intersected by InWorldRay on this pb_Object. InWorldRay is in world space. * @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit * point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front * faces, Culling.Back only tests back faces, and Culling.FrontBack tests both). */ public static bool MeshRaycast(Ray InWorldRay, qe_Mesh qe, out List <qe_RaycastHit> hits, float distance, Culling cullingMode) { /** * Transform ray into model space */ InWorldRay.origin -= qe.transform.position; // Why doesn't worldToLocalMatrix apply translation? InWorldRay.origin = qe.transform.worldToLocalMatrix * InWorldRay.origin; InWorldRay.direction = qe.transform.worldToLocalMatrix * InWorldRay.direction; Vector3[] vertices = qe.vertices; float dist = 0f; Vector3 point = Vector3.zero; float dot; // vars used in loop Vector3 nrm; // vars used in loop hits = new List <qe_RaycastHit>(); /** * Iterate faces, testing for nearest hit to ray origin. Optionally ignores backfaces. */ for (int CurFace = 0; CurFace < qe.faces.Length; ++CurFace) { int[] Indices = qe.faces[CurFace].indices; for (int CurTriangle = 0; CurTriangle < Indices.Length; CurTriangle += 3) { Vector3 a = vertices[Indices[CurTriangle + 0]]; Vector3 b = vertices[Indices[CurTriangle + 1]]; Vector3 c = vertices[Indices[CurTriangle + 2]]; if (qe_Math.RayIntersectsTriangle(InWorldRay, a, b, c, out dist, out point)) { nrm = Vector3.Cross(b - a, c - a); switch (cullingMode) { case Culling.Front: dot = Vector3.Dot(InWorldRay.direction, -nrm); if (dot > 0f) { goto case Culling.FrontBack; } break; case Culling.Back: dot = Vector3.Dot(InWorldRay.direction, nrm); if (dot > 0f) { goto case Culling.FrontBack; } break; case Culling.FrontBack: hits.Add(new qe_RaycastHit(dist, InWorldRay.GetPoint(dist), nrm, CurFace)); break; } continue; } } } return(hits.Count > 0); }
/** * Find the nearest triangle intersected by InWorldRay on this pb_Object. InWorldRay is in world space. * @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit * point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front * faces, Culling.Back only tests back faces, and Culling.FrontBack tests both). */ public static bool MeshRaycast(Ray InWorldRay, qe_Mesh mesh, out qe_RaycastHit hit, float distance, Culling cullingMode) { /** * Transform ray into model space */ InWorldRay.origin -= mesh.transform.position; // Why doesn't worldToLocalMatrix apply translation? InWorldRay.origin = mesh.transform.worldToLocalMatrix * InWorldRay.origin; InWorldRay.direction = mesh.transform.worldToLocalMatrix * InWorldRay.direction; Vector3[] vertices = mesh.vertices; float dist = 0f; Vector3 point = Vector3.zero; float OutHitPoint = Mathf.Infinity; float dot; // vars used in loop Vector3 nrm; // vars used in loop int OutHitFace = -1; Vector3 OutNrm = Vector3.zero; /** * Iterate faces, testing for nearest hit to ray origin. Optionally ignores backfaces. */ for (int CurFace = 0; CurFace < mesh.faces.Length; ++CurFace) { int[] Indices = mesh.faces[CurFace].indices; for (int CurTriangle = 0; CurTriangle < Indices.Length; CurTriangle += 3) { Vector3 a = vertices[Indices[CurTriangle + 0]]; Vector3 b = vertices[Indices[CurTriangle + 1]]; Vector3 c = vertices[Indices[CurTriangle + 2]]; nrm = Vector3.Cross(b - a, c - a); dot = Vector3.Dot(InWorldRay.direction, nrm); bool ignore = false; switch (cullingMode) { case Culling.Front: if (dot > 0f) { ignore = true; } break; case Culling.Back: if (dot < 0f) { ignore = true; } break; } if (!ignore && qe_Math.RayIntersectsTriangle(InWorldRay, a, b, c, out dist, out point)) { if (dist > OutHitPoint || dist > distance) { continue; } OutNrm = nrm; OutHitFace = CurFace; OutHitPoint = dist; continue; } } } hit = new qe_RaycastHit(OutHitPoint, InWorldRay.GetPoint(OutHitPoint), OutNrm, OutHitFace); return(OutHitFace > -1); }
void SetCulling(Culling culling) { IterateMaterials(mat => mat.SetFloat(PROP_CULLING, (float)culling)); }
/// <summary> /// Cast a ray (in model space) against a mesh. /// </summary> internal static bool MeshRaycast(Ray InRay, Vector3[] vertices, int[] triangles, out PolyRaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front) { Vector3 hitNormal, vert0, vert1, vert2; Vector3 origin = InRay.origin, direction = InRay.direction; hit = new PolyRaycastHit(Mathf.Infinity, Vector3.zero, Vector3.zero, -1); // Iterate faces, testing for nearest hit to ray origin. for (int CurTri = 0; CurTri < triangles.Length; CurTri += 3) { if (CurTri + 2 >= triangles.Length) { continue; } if (triangles[CurTri + 2] >= vertices.Length) { continue; } vert0 = vertices[triangles[CurTri + 0]]; vert1 = vertices[triangles[CurTri + 1]]; vert2 = vertices[triangles[CurTri + 2]]; // Second pass, test intersection with triangle if (Math.RayIntersectsTriangle2(origin, direction, vert0, vert1, vert2, out distance, out hitNormal)) { if (distance < hit.distance) { hit.distance = distance; hit.triangle = CurTri / 3; hit.position = InRay.GetPoint(hit.distance); hit.normal = hitNormal; } } } return(hit.triangle > -1); }
public void NewMap(Culling newMap) => cullMapsGrid[newMap.coords.x, newMap.coords.y] = newMap;
/** * Find the nearest triangle intersected by InWorldRay on this mesh. InWorldRay is in world space. * @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit * point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front * faces, Culling.Back only tests back faces, and Culling.FrontBack tests both). * Ray origin and position values are in local space. */ public static bool WorldRaycast(Ray InWorldRay, MeshFilter meshFilter, out z_RaycastHit hit, float distance, Culling cullingMode) { Ray ray = meshFilter.transform.InverseTransformRay(InWorldRay); return MeshRaycast(ray, meshFilter, out hit, distance, cullingMode); }
/// <summary> /// Cast a ray (in model space) against a mesh. /// </summary> /// <param name="InRay"></param> /// <param name="vertices"></param> /// <param name="triangles"></param> /// <param name="hit"></param> /// <param name="distance"></param> /// <param name="cullingMode"></param> /// <returns></returns> internal static bool MeshRaycast(Ray InRay, Vector3[] vertices, int[] triangles, out PolyRaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front) { float hitDistance = Mathf.Infinity; Vector3 hitNormal = Vector3.zero; // vars used in loop Vector3 vert0, vert1, vert2; int hitFace = -1; Vector3 origin = InRay.origin, direction = InRay.direction; /** * Iterate faces, testing for nearest hit to ray origin. */ for (int CurTri = 0; CurTri < triangles.Length; CurTri += 3) { if (CurTri + 2 >= triangles.Length) { continue; } if (triangles[CurTri + 2] >= vertices.Length) { continue; } vert0 = vertices[triangles[CurTri + 0]]; vert1 = vertices[triangles[CurTri + 1]]; vert2 = vertices[triangles[CurTri + 2]]; if (PolyMath.RayIntersectsTriangle2(origin, direction, vert0, vert1, vert2, ref distance, ref hitNormal)) { hitFace = CurTri / 3; hitDistance = distance; break; } } hit = new PolyRaycastHit(hitDistance, InRay.GetPoint(hitDistance), hitNormal, hitFace); return(hitFace > -1); }
/** * Find the nearest triangle intersected by InWorldRay on this mesh. InWorldRay is in world space. * @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit * point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front * faces, Culling.Back only tests back faces, and Culling.FrontBack tests both). * Ray origin and position values are in local space. */ public static bool WorldRaycast(Ray InWorldRay, Transform transform, Vector3[] vertices, int[] triangles, out z_RaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front) { Ray ray = transform.InverseTransformRay(InWorldRay); //commented out code was ommited here }
public abstract void PrepareRender(BlendMode blendMode = BlendMode.Alpha, Culling culling = Culling.None);
private void CullingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { culling = ( Culling )CullingComboBox.SelectedValue; Render(); }
protected override void OnRenderFrame(FrameEventArgs e) { PerformFpsElapsed(e.Time * 1000); Graphics.BeginFrame(this); Graphics.BindIb(defaultIb); accumulator += e.Time; Vertices = 0; if (!Focused && !ScreenLockedInput) { SetNewScreen(new PauseScreen(this)); } base.OnRenderFrame(e); CheckScheduledTasks(e.Time); float t = (float)(ticksAccumulator / ticksPeriod); LocalPlayer.SetInterpPosition(t); Graphics.Clear(); Graphics.SetMatrixMode(MatrixType.Modelview); Matrix4 modelView = Camera.GetView(e.Time); View = modelView; Graphics.LoadMatrix(ref modelView); Culling.CalcFrustumEquations(ref Projection, ref modelView); bool visible = activeScreen == null || !activeScreen.BlocksWorld; if (visible) { AxisLinesRenderer.Render(e.Time); Players.RenderModels(Graphics, e.Time, t); Players.RenderNames(Graphics, e.Time, t); CurrentCameraPos = Camera.GetCameraPos(LocalPlayer.EyePosition); ParticleManager.Render(e.Time, t); Camera.GetPickedBlock(SelectedPos); // TODO: only pick when necessary EnvRenderer.Render(e.Time); if (SelectedPos.Valid && !HideGui) { Picking.Render(e.Time, SelectedPos); } MapRenderer.Render(e.Time); SelectionManager.Render(e.Time); WeatherRenderer.Render(e.Time); Players.RenderHoveredNames(Graphics, e.Time, t); bool left = IsMousePressed(MouseButton.Left); bool middle = IsMousePressed(MouseButton.Middle); bool right = IsMousePressed(MouseButton.Right); InputHandler.PickBlocks(true, left, middle, right); if (!HideGui) { BlockHandRenderer.Render(e.Time, t); } } else { SelectedPos.SetAsInvalid(); } Graphics.Mode2D(Width, Height, EnvRenderer is StandardEnvRenderer); fpsScreen.Render(e.Time); if (activeScreen == null || !activeScreen.HidesHud) { hudScreen.Render(e.Time); } if (activeScreen != null) { activeScreen.Render(e.Time); } Graphics.Mode3D(EnvRenderer is StandardEnvRenderer); if (screenshotRequested) { TakeScreenshot(); } Graphics.EndFrame(this); }
/** * Returns true if a raycast intersects a triangle. * http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm * http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf */ public static bool RayIntersectsTriangle( Ray InRay, Vector3 InTriangleA, Vector3 InTriangleB, Vector3 InTriangleC, Culling cull, out float OutDistance, out Vector3 OutPoint) { OutDistance = 0f; OutPoint = Vector3.zero; Vector3 e1, e2; //Edge1, Edge2 Vector3 P, Q, T; float det, inv_det, u, v; float t; //Find vectors for two edges sharing V1 e1 = InTriangleB - InTriangleA; e2 = InTriangleC - InTriangleA; //Begin calculating determinant - also used to calculate `u` parameter P = Vector3.Cross(InRay.direction, e2); //if determinant is near zero, ray lies in plane of triangle det = Vector3.Dot(e1, P); // NON-CULLING if( (cull == Culling.Front && det < Mathf.Epsilon) || (det > -Mathf.Epsilon && det < Mathf.Epsilon) ) return false; inv_det = 1f / det; //calculate distance from V1 to ray origin T = InRay.origin - InTriangleA; // Calculate u parameter and test bound u = Vector3.Dot(T, P) * inv_det; //The intersection lies outside of the triangle if(u < 0f || u > 1f) return false; //Prepare to test v parameter Q = Vector3.Cross(T, e1); //Calculate V parameter and test bound v = Vector3.Dot(InRay.direction, Q) * inv_det; //The intersection lies outside of the triangle if(v < 0f || u + v > 1f) return false; t = Vector3.Dot(e2, Q) * inv_det; if(t > Mathf.Epsilon) { //ray intersection OutDistance = t; OutPoint.x = (u * InTriangleB.x + v * InTriangleC.x + (1-(u+v)) * InTriangleA.x); OutPoint.y = (u * InTriangleB.y + v * InTriangleC.y + (1-(u+v)) * InTriangleA.y); OutPoint.z = (u * InTriangleB.z + v * InTriangleC.z + (1-(u+v)) * InTriangleA.z); return true; } return false; }
void Start() { bodyRb = body.GetComponent<Rigidbody2D>(); chManager = localGM.GetComponent<CheckpointManager>(); SaveParams(); culling = GetComponent<Culling>(); }
/** * Cast a ray (in model space) against a mesh. */ public static bool MeshRaycast(Ray InRay, MeshFilter meshFilter, out z_RaycastHit hit, float distance, Culling cullingMode) { Mesh mesh = meshFilter.sharedMesh; float dist = 0f; Vector3 point = Vector3.zero; float OutHitPoint = Mathf.Infinity; float dot; // vars used in loop Vector3 nrm; // vars used in loop int OutHitFace = -1; Vector3 OutNrm = Vector3.zero; /** * Iterate faces, testing for nearest hit to ray origin. Optionally ignores backfaces. */ Vector3[] vertices = mesh.vertices; int[] triangles = mesh.triangles; for(int CurTri = 0; CurTri < triangles.Length; CurTri += 3) { Vector3 a = vertices[triangles[CurTri+0]]; Vector3 b = vertices[triangles[CurTri+1]]; Vector3 c = vertices[triangles[CurTri+2]]; nrm = Vector3.Cross(b-a, c-a); dot = Vector3.Dot(InRay.direction, nrm); bool ignore = false; switch(cullingMode) { case Culling.Front: if(dot > 0f) ignore = true; break; case Culling.Back: if(dot < 0f) ignore = true; break; } if(!ignore && z_Math.RayIntersectsTriangle(InRay, a, b, c, out dist, out point)) { if(dist > OutHitPoint || dist > distance) continue; OutNrm = nrm; OutHitFace = CurTri / 3; OutHitPoint = dist; continue; } } hit = new z_RaycastHit( OutHitPoint, InRay.GetPoint(OutHitPoint), OutNrm, OutHitFace); return OutHitFace > -1; }
/** * Find the nearest triangle intersected by InWorldRay on this mesh. InWorldRay is in world space. * @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit * point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front * faces, Culling.Back only tests back faces, and Culling.FrontBack tests both). * Ray origin and position values are in local space. */ public static bool WorldRaycast(Ray InWorldRay, Transform transform, Vector3[] vertices, int[] triangles, out z_RaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front) { Ray ray = transform.InverseTransformRay(InWorldRay); return(MeshRaycast(ray, vertices, triangles, out hit, distance, cullingMode)); }
/// <summary> /// Find the nearest triangle intersected by InWorldRay on this mesh. InWorldRay is in world space. /// @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit /// point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front /// faces, Culling.Back only tests back faces, and Culling.FrontBack tests both). /// Ray origin and position values are in local space. /// </summary> /// <param name="InWorldRay"></param> /// <param name="transform"></param> /// <param name="vertices"></param> /// <param name="triangles"></param> /// <param name="hit"></param> /// <param name="distance"></param> /// <param name="cullingMode"></param> /// <returns></returns> internal static bool WorldRaycast(Ray InWorldRay, Transform transform, Vector3[] vertices, int[] triangles, out PolyRaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front) { //null checks, must have a transform, vertices and triangles if (transform == null || vertices == null || triangles == null) { hit = null; return(false); } Ray ray = transform.InverseTransformRay(InWorldRay); return(MeshRaycast(ray, vertices, triangles, out hit, distance, cullingMode)); }
/** * Cast a ray (in model space) against a mesh. */ public static bool MeshRaycast(Ray InRay, Vector3[] vertices, int[] triangles, out z_RaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front) { // float dot; // vars used in loop float hitDistance = Mathf.Infinity; Vector3 hitNormal = new Vector3(0f, 0f, 0f); // vars used in loop Vector3 a, b, c; int hitFace = -1; Vector3 o = InRay.origin, d = InRay.direction; /** * Iterate faces, testing for nearest hit to ray origin. */ for (int CurTri = 0; CurTri < triangles.Length; CurTri += 3) { a = vertices[triangles[CurTri + 0]]; b = vertices[triangles[CurTri + 1]]; c = vertices[triangles[CurTri + 2]]; if (z_Math.RayIntersectsTriangle2(o, d, a, b, c, ref distance, ref hitNormal)) { hitFace = CurTri / 3; hitDistance = distance; break; } } hit = new z_RaycastHit(hitDistance, InRay.GetPoint(hitDistance), hitNormal, hitFace); return(hitFace > -1); }
#pragma warning restore IDE1006 /** * Returns true if a raycast intersects a triangle. * http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm * http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf */ public static bool RayIntersectsTriangle( Ray InRay, Vector3 InTriangleA, Vector3 InTriangleB, Vector3 InTriangleC, Culling cull, out float OutDistance, out Vector3 OutPoint) { OutDistance = 0f; OutPoint = Vector3.zero; Vector3 e1, e2; //Edge1, Edge2 Vector3 P, Q, T; float det, inv_det, u, v; float t; //Find vectors for two edges sharing V1 e1 = InTriangleB - InTriangleA; e2 = InTriangleC - InTriangleA; //Begin calculating determinant - also used to calculate `u` parameter P = Vector3.Cross(InRay.direction, e2); //if determinant is near zero, ray lies in plane of triangle det = Vector3.Dot(e1, P); // NON-CULLING if ((cull == Culling.Front && det < Mathf.Epsilon) || (det > -Mathf.Epsilon && det < Mathf.Epsilon)) { return(false); } inv_det = 1f / det; //calculate distance from V1 to ray origin T = InRay.origin - InTriangleA; // Calculate u parameter and test bound u = Vector3.Dot(T, P) * inv_det; //The intersection lies outside of the triangle if (u < 0f || u > 1f) { return(false); } //Prepare to test v parameter Q = Vector3.Cross(T, e1); //Calculate V parameter and test bound v = Vector3.Dot(InRay.direction, Q) * inv_det; //The intersection lies outside of the triangle if (v < 0f || u + v > 1f) { return(false); } t = Vector3.Dot(e2, Q) * inv_det; if (t > Mathf.Epsilon) { //ray intersection OutDistance = t; OutPoint.x = (u * InTriangleB.x + v * InTriangleC.x + (1 - (u + v)) * InTriangleA.x); OutPoint.y = (u * InTriangleB.y + v * InTriangleC.y + (1 - (u + v)) * InTriangleA.y); OutPoint.z = (u * InTriangleB.z + v * InTriangleC.z + (1 - (u + v)) * InTriangleA.z); return(true); } return(false); }