Example #1
0
        public unsafe void PlaneFieldOffsetTest()
        {
            Plane *ptr = (Plane *)0;

            Assert.Equal(new IntPtr(0), new IntPtr(&ptr->Normal));
            Assert.Equal(new IntPtr(12), new IntPtr(&ptr->D));
        }
Example #2
0
        public unsafe bool IsBox(out Vector3 dimensions, out Vector3 center)
        {
            dimensions = new Vector3();
            center     = new Vector3();

            if (_faceCount != 12)
            {
                return(false);
            }

            Plane *planes = stackalloc Plane[6];

            var vbStream = _vb.Map(MapType.Read);
            var ibStream = _ib.Map(MapType.Read);

            CreateBoxPlanes(planes, 6, vbStream, ibStream);

            /*
             *  A box must have 4 orthogonal an one paraller plane to every plane conforming the box
             */

            for (int i = 0; i < 6; i++)
            {
                int ortoCount     = 0;
                int parallerCount = 0;

                for (int j = 0; j < 6; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }

                    var dot = Vector3.Dot(planes[i].Normal, planes[j].Normal);
                    if (dot == 0 || dot.IsZero())
                    {
                        ortoCount++;
                    }
                    else if (dot == -1 || dot.IsEqual(-1))
                    {
                        parallerCount++;
                    }
                }

                if (parallerCount != 1 || ortoCount != 4)
                {
                    _vb.Unmap();
                    _ib.Unmap();
                    return(false);
                }
            }

            FindDimensions(vbStream, out center, out dimensions);

            _vb.Unmap();
            _ib.Unmap();

            return(true);
        }
Example #3
0
 public void Init()
 {
     p = (Plane *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <Plane>() * 10000, UnsafeUtility.AlignOf <Plane>(), Allocator.Persistent);
     for (int i = 0; i < 10000; ++i)
     {
         p[i] = new Plane {
             NormalAndDistance = new float4(1.0f)
         };
     }
 }
Example #4
0
        public unsafe bool IsPlane(out Plane plane)
        {
            plane = new Plane();
            if (_faceCount != 2)
            {
                return(false);
            }

            var vbStream = _vb.Map(MapType.Read);
            var ibStream = _ib.Map(MapType.Read);

            Plane *planes = stackalloc Plane[2];

            try
            {
                int posOffset = VertexDescriptor.OffsetOf(IASemantic.Position, 0);
                int size      = VertexDescriptor.Size;

                byte *vbPter = (byte *)vbStream + posOffset;
                byte *ibPter = (byte *)ibStream;

                for (int iface = 0; iface < _faceCount; iface++)
                {
                    Vector3 p0;
                    Vector3 p1;
                    Vector3 p2;

                    if (_is16BitIndices)
                    {
                        p0 = *(Vector3 *)(vbPter + size * ((short *)ibPter)[iface * 3]);
                        p1 = *(Vector3 *)(vbPter + size * ((short *)ibPter)[iface * 3 + 1]);
                        p2 = *(Vector3 *)(vbPter + size * ((short *)ibPter)[iface * 3 + 2]);
                    }
                    else
                    {
                        p0 = *(Vector3 *)(vbPter + size * ((int *)ibPter)[iface * 3]);
                        p1 = *(Vector3 *)(vbPter + size * ((int *)ibPter)[iface * 3 + 1]);
                        p2 = *(Vector3 *)(vbPter + size * ((int *)ibPter)[iface * 3 + 2]);
                    }
                    planes[iface] = new Plane(p0, p1, p2);
                }
            }
            finally
            {
                _vb.Unmap();
                _ib.Unmap();
            }

            if (Plane.Equals(planes[0], planes[1]))
            {
                plane = planes[0];
                return(true);
            }
            return(false);
        }
Example #5
0
 public void Init()
 {
     rng = new Random(1);
     p   = (Plane *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <Plane>() * iterations, UnsafeUtility.AlignOf <Plane>(), Allocator.Persistent);
     for (int i = 0; i < iterations; ++i)
     {
         p[i] = new Plane {
             NormalAndDistance = new float4(1.0f)
         };
     }
 }
Example #6
0
        private unsafe bool Contains(Plane *planes, int size, Plane p)
        {
            for (int i = 0; i < size; i++)
            {
                if (Plane.Equals(planes[i], p))
                {
                    return(true);
                }
            }

            return(false);
        }
Example #7
0
        public unsafe void PlaneFieldOffsetTest()
        {
            Plane plane = new Plane();

            float *basePtr  = &plane.Normal.X; // Take address of first element
            Plane *planePtr = &plane;          // Take address of whole Plane

            Assert.Equal(new IntPtr(basePtr), new IntPtr(planePtr));

            Assert.Equal(new IntPtr(basePtr + 0), new IntPtr(&plane.Normal));
            Assert.Equal(new IntPtr(basePtr + 3), new IntPtr(&plane.D));
        }
Example #8
0
        public ContainmentType Contains(Vector3 *point)
        {
            Plane *planes = (Plane *)Unsafe.AsPointer(ref _planes); // Is this safe?

            for (int i = 0; i < 6; i++)
            {
                if (Plane.DotCoordinate(planes[i], *point) < 0)
                {
                    return(ContainmentType.Disjoint);
                }
            }

            return(ContainmentType.Contains);
        }
Example #9
0
        public ContainmentType Contains(ref BoundingBox box)
        {
            Plane *planes = (Plane *)Unsafe.AsPointer(ref _planes);

            ContainmentType result = ContainmentType.Contains;

            for (int i = 0; i < 6; i++)
            {
                Plane plane = planes[i];

                // Approach: http://zach.in.tu-clausthal.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html

                Vector3 positive = new Vector3(box.Minimum.X, box.Minimum.Y, box.Minimum.Z);
                Vector3 negative = new Vector3(box.Maximum.X, box.Maximum.Y, box.Maximum.Z);

                if (plane.Normal.X >= 0)
                {
                    positive.X = box.Maximum.X;
                    negative.X = box.Minimum.X;
                }
                if (plane.Normal.Y >= 0)
                {
                    positive.Y = box.Maximum.Y;
                    negative.Y = box.Minimum.Y;
                }
                if (plane.Normal.Z >= 0)
                {
                    positive.Z = box.Maximum.Z;
                    negative.Z = box.Minimum.Z;
                }

                // If the positive vertex is outside (behind plane), the box is disjoint.
                float positiveDistance = Plane.DotCoordinate(plane, positive);
                if (positiveDistance < 0)
                {
                    return(ContainmentType.Disjoint);
                }

                // If the negative vertex is outside (behind plane), the box is intersecting.
                // Because the above check failed, the positive vertex is in front of the plane,
                // and the negative vertex is behind. Thus, the box is intersecting this plane.
                float negativeDistance = Plane.DotCoordinate(plane, negative);
                if (negativeDistance < 0)
                {
                    result = ContainmentType.Intersects;
                }
            }

            return(result);
        }
Example #10
0
        public ContainmentType Contains(BoundingSphere sphere)
        {
            Plane *planes = (Plane *)Unsafe.AsPointer(ref _planes);

            ContainmentType result = ContainmentType.Contains;

            for (int i = 0; i < 6; i++)
            {
                float distance = Plane.DotCoordinate(planes[i], sphere.Center);
                if (distance < -sphere.Radius)
                {
                    return(ContainmentType.Disjoint);
                }
                else if (distance < sphere.Radius)
                {
                    result = ContainmentType.Intersects;
                }
            }

            return(result);
        }
Example #11
0
        unsafe private void CreateBoxPlanes(Plane *planes, int planesCount, IntPtr vbStream, IntPtr ibStream)
        {
            int posOffset = VertexDescriptor.OffsetOf(IASemantic.Position, 0);
            int size      = VertexDescriptor.Size;

            byte *vbPter = (byte *)vbStream + posOffset;
            byte *ibPter = (byte *)ibStream;
            int   k      = 0;

            for (int iface = 0; iface < _faceCount; iface++)
            {
                Vector3 p0;
                Vector3 p1;
                Vector3 p2;

                if (_is16BitIndices)
                {
                    p0 = *(Vector3 *)(vbPter + size * ((short *)ibPter)[iface * 3]);
                    p1 = *(Vector3 *)(vbPter + size * ((short *)ibPter)[iface * 3 + 1]);
                    p2 = *(Vector3 *)(vbPter + size * ((short *)ibPter)[iface * 3 + 2]);
                }
                else
                {
                    p0 = *(Vector3 *)(vbPter + size * ((int *)ibPter)[iface * 3]);
                    p1 = *(Vector3 *)(vbPter + size * ((int *)ibPter)[iface * 3 + 1]);
                    p2 = *(Vector3 *)(vbPter + size * ((int *)ibPter)[iface * 3 + 2]);
                }
                var facePlane = new Plane(p0, p1, p2);
                if (!Contains(planes, planesCount, facePlane))
                {
                    if (k >= planesCount)
                    {
                        throw new IndexOutOfRangeException();
                    }

                    planes[k++] = facePlane;
                }
            }
        }
Example #12
0
        private static void GetCullingPlanes(ref Matrix4x4 invVp, Plane *frustumPlanes)
        {
            Vector3 nearLeftButtom  = invVp.MultiplyPoint(new Vector3(-1, -1, 1));
            Vector3 nearLeftTop     = invVp.MultiplyPoint(new Vector3(-1, 1, 1));
            Vector3 nearRightButtom = invVp.MultiplyPoint(new Vector3(1, -1, 1));
            Vector3 nearRightTop    = invVp.MultiplyPoint(new Vector3(1, 1, 1));
            Vector3 farLeftButtom   = invVp.MultiplyPoint(new Vector3(-1, -1, 0));
            Vector3 farLeftTop      = invVp.MultiplyPoint(new Vector3(-1, 1, 0));
            Vector3 farRightButtom  = invVp.MultiplyPoint(new Vector3(1, -1, 0));
            Vector3 farRightTop     = invVp.MultiplyPoint(new Vector3(1, 1, 0));

            //Near
            frustumPlanes[0] = new Plane(nearRightTop, nearRightButtom, nearLeftButtom);
            //Up
            frustumPlanes[1] = new Plane(farLeftTop, farRightTop, nearRightTop);
            //Down
            frustumPlanes[2] = new Plane(nearRightButtom, farRightButtom, farLeftButtom);
            //Left
            frustumPlanes[3] = new Plane(farLeftButtom, farLeftTop, nearLeftTop);
            //Right
            frustumPlanes[4] = new Plane(farRightButtom, nearRightButtom, nearRightTop);
            //Far
            frustumPlanes[5] = new Plane(farLeftButtom, farRightButtom, farRightTop);
        }
Example #13
0
 public unsafe void Conjugate(Plane *input, Plane *output, int count)
 {
     Detail.sw012(false, &input->P0, P1, default, &output->P0, count);
Example #14
0
        private unsafe void UpdateIndexBufferCPU(CCommandList cmd, Graphics.CGfxCamera Camera)
        {
            if (mCpuDrawIndexBuffer == null)
            {
                return;
            }
            CBMeshBatch cbMesh = new CBMeshBatch();
            {
                var pPlanes = stackalloc Plane[6];
                Camera.CullingFrustum.GetPlanes(pPlanes);
                CBMeshBatch *pCBuffer  = &cbMesh;
                Plane *      planesTar = (Plane *)pCBuffer;
                for (uint i = 0; i < 6; i++)
                {
                    planesTar[i] = pPlanes[i];
                }
                cbMesh.GpuDrivenCameraPosition = Camera.CullingFrustum.TipPos;
                BoundingBox box = new BoundingBox();
                Camera.CullingFrustum.GetBoundBox(ref box);
                cbMesh.GpuDrivenFrustumMinPoint = box.Minimum;
                cbMesh.GpuDrivenFrustumMaxPoint = box.Maximum;
                cbMesh.MeshBatchVertexStride    = (uint)AllVertices.Count;
                cbMesh.ClusterNumber            = (uint)GpuClusters.Count;

                UpdateCBMeshbatch(cmd, Camera);
            }

            UInt32_3 tri = new UInt32_3();

            mDrawIndices.Clear();
            for (int i = 0; i < GpuClusters.Count; i++)
            {
                var cluster = GpuClusters[i];
                var GpuDrivenCameraDirection = GpuClusters[i].BoundCenter - cbMesh.GpuDrivenCameraPosition;
                var cameraDirInBoundSpace    = Vector3.TransposeTransformNormal(GpuDrivenCameraDirection, GpuInstanceDatas[(int)cluster.InstanceId].InvMatrix);
                if (FrustumCull(ref cluster, ref cbMesh) == false)
                {
                    UInt64 visBits = 0;
                    if (cameraDirInBoundSpace.X >= 0)
                    {
                        visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_NX];
                    }
                    else
                    {
                        visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_X];
                    }
                    if (cameraDirInBoundSpace.Y >= 0)
                    {
                        visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_NY];
                    }
                    else
                    {
                        visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_Y];
                    }
                    if (cameraDirInBoundSpace.Z >= 0)
                    {
                        visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_NZ];
                    }
                    else
                    {
                        visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_Z];
                    }

                    uint InstanceStartIndex = cbMesh.MeshBatchVertexStride * cluster.InstanceId;
                    for (int j = 0; j < cluster.FaceCount; j++)
                    {
                        if (TestBit(visBits, j) == false)
                        {
                            continue;
                        }
                        int srcIndex = (int)(cluster.StartFaceIndex + j) * 3;
                        tri.x = InstanceStartIndex + AllIndices[srcIndex];
                        tri.y = InstanceStartIndex + AllIndices[srcIndex + 1];
                        tri.z = InstanceStartIndex + AllIndices[srcIndex + 2];
                        mDrawIndices.Add(tri);
                    }
                }
            }

            mDrawArgs.InstanceCount         = 1;
            mDrawArgs.IndexCountPerInstance = (uint)mDrawIndices.Count * 3;
            uint size = (uint)(mDrawIndices.Count * sizeof(UInt32_3));

            if (mCpuDrawIndexBuffer.Desc.ByteWidth > size)
            {
                mCpuDrawIndexBuffer.UpdateBuffData(cmd, mDrawIndices.GetBufferPtr(), size);
            }
        }
Example #15
0
 public unsafe void GetPlanes(Plane *pPlanes)
 {
     SDK_v3dxFrustum_GetPlanes(CoreObject, pPlanes);
 }
Example #16
0
 public unsafe void Conjugate(Plane *input, Plane *output, int count)
 {
     Detail.sw012(true, &input->P0, P1, P2, &output->P0, count);
 }
Example #17
0
 public unsafe extern static Plane *D3DXPlaneScale(Plane *pOut, Plane *pP, float s);
Example #18
0
 public unsafe extern static Vector3 *D3DXPlaneIntersectLine(Vector3 *pOut, Plane *pP, Vector3 *pV1, Vector3 *pV2);
Example #19
0
        // If we resort the vertexes so all silverts come first, we can save some work here.
        public unsafe static LocalTrace R_LocalTrace(Vector3 start, Vector3 end, float radius, SrfTriangles tri)
        {
            int        i, j;
            Plane *    planes = stackalloc Plane[4];
            LocalTrace hit = new();
            int        c_testEdges, c_testPlanes, c_intersect;
            Vector3    startDir;
            byte       totalOr;
            float      radiusSqr;
            var        tri_verts = tri.verts.Value; var tri_indexes = tri.indexes.Value; var tri_facePlanes = tri.facePlanes.Value;

#if TEST_TRACE
            Stopwatch trace_timer = new();
            trace_timer.Start();
#endif

            hit.fraction = 1f;

            // create two planes orthogonal to each other that intersect along the trace
            startDir = end - start;
            startDir.Normalize();
            startDir.NormalVectors(out planes[0].Normal, out planes[1].Normal);
            planes[0].d = -start * planes[0].Normal;
            planes[1].d = -start * planes[1].Normal;

            // create front and end planes so the trace is on the positive sides of both
            planes[2] = startDir; planes[2].d = -start * planes[2].Normal;
            planes[3] = -startDir; planes[3].d = -end * planes[3].Normal;

            // catagorize each point against the four planes
            var cullBits = stackalloc byte[tri.numVerts];

            fixed(DrawVert *vertsD = tri_verts) Simd.TracePointCull(cullBits, out totalOr, radius, planes, vertsD, tri.numVerts);

            // if we don't have points on both sides of both the ray planes, no intersection
            if (((totalOr ^ (totalOr >> 4)) & 3) != 0) /*common.Printf("nothing crossed the trace planes\n");*/ return {
                (hit);
            }

            // if we don't have any points between front and end, no intersection
            if (((totalOr ^ (totalOr >> 1)) & 4) != 0) /*common.Printf("trace didn't reach any triangles\n");*/ return {
                (hit);
            }

            // scan for triangles that cross both planes
            c_testPlanes = c_testEdges = c_intersect = 0;

            radiusSqr = MathX.Square(radius);
            startDir  = end - start;

            if (tri.facePlanes == null || !tri.facePlanesCalculated)
            {
                R_DeriveFacePlanes(tri);
            }

            for (i = 0, j = 0; i < tri.numIndexes; i += 3, j++)
            {
                float   d1, d2, f, d, edgeLengthSqr; byte triOr;
                Vector3 cross, edge; Vector3[] dir = new Vector3[3];

                // get sidedness info for the triangle
                triOr  = cullBits[tri_indexes[i + 0]];
                triOr |= cullBits[tri_indexes[i + 1]];
                triOr |= cullBits[tri_indexes[i + 2]];

                // if we don't have points on both sides of both the ray planes, no intersection
                if (((triOr ^ (triOr >> 4)) & 3) != 0)
                {
                    continue;
                }

                // if we don't have any points between front and end, no intersection
                if (((triOr ^ (triOr >> 1)) & 4) != 0)
                {
                    continue;
                }

                c_testPlanes++;

                ref Plane plane = ref tri_facePlanes[j];
                d1 = plane.Distance(start);
                d2 = plane.Distance(end);

                if (d1 <= d2)
                {
                    continue;                 // comning at it from behind or parallel
                }
                if (d1 < 0f)
                {
                    continue;                // starts past it
                }
                if (d2 > 0f)
                {
                    continue;                // finishes in front of it
                }
                f = d1 / (d1 - d2);
                if (f < 0f)
                {
                    continue;               // shouldn't happen
                }
                if (f >= hit.fraction)
                {
                    continue;                          // have already hit something closer
                }
                c_testEdges++;

                // find the exact point of impact with the plane
                var point = start + f * startDir;

                // see if the point is within the three edges if radius > 0 the triangle is expanded with a circle in the triangle plane

                dir[0] = tri_verts[tri_indexes[i + 0]].xyz - point;
                dir[1] = tri_verts[tri_indexes[i + 1]].xyz - point;

                cross = dir[0].Cross(dir[1]);
                d     = plane.Normal * cross;
                if (d > 0f)
                {
                    if (radiusSqr <= 0f)
                    {
                        continue;
                    }
                    edge          = tri_verts[tri_indexes[i + 0]].xyz - tri_verts[tri_indexes[i + 1]].xyz;
                    edgeLengthSqr = edge.LengthSqr;
                    if (cross.LengthSqr > edgeLengthSqr * radiusSqr)
                    {
                        continue;
                    }
                    d = edge * dir[0];
                    if (d < 0f)
                    {
                        edge = tri_verts[tri_indexes[i + 0]].xyz - tri_verts[tri_indexes[i + 2]].xyz;
                        d    = edge * dir[0];
                        if (d < 0f && dir[0].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                    else if (d > edgeLengthSqr)
                    {
                        edge = tri_verts[tri_indexes[i + 1]].xyz - tri_verts[tri_indexes[i + 2]].xyz;
                        d    = edge * dir[1];
                        if (d < 0f && dir[1].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                }

                dir[2] = tri_verts[tri_indexes[i + 2]].xyz - point;

                cross = dir[1].Cross(dir[2]);
                d     = plane.Normal * cross;
                if (d > 0f)
                {
                    if (radiusSqr <= 0f)
                    {
                        continue;
                    }
                    edge          = tri_verts[tri_indexes[i + 1]].xyz - tri_verts[tri_indexes[i + 2]].xyz;
                    edgeLengthSqr = edge.LengthSqr;
                    if (cross.LengthSqr > edgeLengthSqr * radiusSqr)
                    {
                        continue;
                    }
                    d = edge * dir[1];
                    if (d < 0f)
                    {
                        edge = tri_verts[tri_indexes[i + 1]].xyz - tri_verts[tri_indexes[i + 0]].xyz;
                        d    = edge * dir[1];
                        if (d < 0f && dir[1].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                    else if (d > edgeLengthSqr)
                    {
                        edge = tri_verts[tri_indexes[i + 2]].xyz - tri_verts[tri_indexes[i + 0]].xyz;
                        d    = edge * dir[2];
                        if (d < 0f && dir[2].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                }

                cross = dir[2].Cross(dir[0]);
                d     = plane.Normal * cross;
                if (d > 0f)
                {
                    if (radiusSqr <= 0f)
                    {
                        continue;
                    }
                    edge          = tri_verts[tri_indexes[i + 2]].xyz - tri_verts[tri_indexes[i + 0]].xyz;
                    edgeLengthSqr = edge.LengthSqr;
                    if (cross.LengthSqr > edgeLengthSqr * radiusSqr)
                    {
                        continue;
                    }
                    d = edge * dir[2];
                    if (d < 0f)
                    {
                        edge = tri_verts[tri_indexes[i + 2]].xyz - tri_verts[tri_indexes[i + 1]].xyz;
                        d    = edge * dir[2];
                        if (d < 0f && dir[2].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                    else if (d > edgeLengthSqr)
                    {
                        edge = tri_verts[tri_indexes[i + 0]].xyz - tri_verts[tri_indexes[i + 1]].xyz;
                        d    = edge * dir[0];
                        if (d < 0f && dir[0].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                }

                // we hit it
                c_intersect++;

                hit.fraction   = f;
                hit.normal     = plane.Normal;
                hit.point      = point;
                hit.indexes[0] = tri_indexes[i];
                hit.indexes[1] = tri_indexes[i + 1];
                hit.indexes[2] = tri_indexes[i + 2];
            }