Пример #1
0
        public Box3f ToWorldBox(Box3f box)
        {
            Frame3f f  = new Frame3f(box.Center, box.AxisX, box.AxisY, box.AxisZ);
            Frame3f fS = ToWorldFrame(f);

            return(new Box3f(fS.Origin, fS.X, fS.Y, fS.Z, GetSceneScale() * box.Extent));
        }
Пример #2
0
        public AxisAlignedBox3f GetPrintMeshesBounds(bool bPrecise)
        {
            AxisAlignedBox3f b = AxisAlignedBox3f.Empty;

            foreach (PrintMeshSO so in PrintMeshes)
            {
                if (SceneUtil.IsVisible(so) == false)
                {
                    continue;
                }

                if (bPrecise)
                {
                    var xform = SceneTransforms.ObjectToSceneXForm(so);
                    foreach (Vector3d v in so.Mesh.Vertices())
                    {
                        b.Contain((Vector3f)xform.TransformP(v));
                    }
                }
                else
                {
                    Box3f sobox = so.GetBoundingBox(CoordSpace.SceneCoords);
                    if (sobox.Volume > 0)
                    {
                        foreach (Vector3d v in sobox.VerticesItr())
                        {
                            b.Contain(v);
                        }
                    }
                }
            }
            return(b);
        }
        private void CreateParticles(Box3f exclusion)
        {
            int numX = (int)(Bounds.Width / Diameter);
            int numY = (int)(Bounds.Height / Diameter);
            int numZ = (int)(Bounds.Depth / Diameter);

            Positions = new List <Vector3f>();

            for (int z = 0; z < numZ; z++)
            {
                for (int y = 0; y < numY; y++)
                {
                    for (int x = 0; x < numX; x++)
                    {
                        Vector3f pos = new Vector3f();
                        pos.x = Diameter * x + Bounds.Min.x + Spacing;
                        pos.y = Diameter * y + Bounds.Min.y + Spacing;
                        pos.z = Diameter * z + Bounds.Min.z + Spacing;

                        if (!exclusion.Contains(pos))
                        {
                            Positions.Add(pos);
                        }
                    }
                }
            }
        }
Пример #4
0
        public static float SqrDistanceFromBox(Box3f box, Vector3f p)
        {
            float sqDist = 0.0f;

            if (p.x < box.Min.x)
            {
                sqDist += (box.Min.x - p.x) * (box.Min.x - p.x);
            }
            if (p.x > box.Max.x)
            {
                sqDist += (p.x - box.Max.x) * (p.x - box.Max.x);
            }

            if (p.y < box.Min.y)
            {
                sqDist += (box.Min.y - p.y) * (box.Min.y - p.y);
            }
            if (p.y > box.Max.y)
            {
                sqDist += (p.y - box.Max.y) * (p.y - box.Max.y);
            }

            if (p.z < box.Min.z)
            {
                sqDist += (box.Min.z - p.z) * (box.Min.z - p.z);
            }
            if (p.z > box.Max.z)
            {
                sqDist += (p.z - box.Max.z) * (p.z - box.Max.z);
            }

            return(sqDist);
        }
Пример #5
0
        public virtual void Setup()
        {
            // push history stream, so that we can do undo/redo internal to tool,
            // that will not end up in external history
            push_history_stream();

            // clear selection here so that multi-select GroupSO goes away, otherwise
            // when we copy frmaes below, they are relative to that GroupSO, and things move
            inputSelection = new List <SceneObject>(Scene.Selected);
            set_allow_selection_changes(true);
            Scene.ClearSelection();
            set_allow_selection_changes(false);

            objects = new List <TargetObject>();
            foreach (var so in InputSOs)
            {
                TargetObject o = new TargetObject();

                o.SO         = so;
                o.InputMeshV = new DVector <double>(o.SO.Mesh.VerticesBuffer);
                if (o.SO.Mesh.HasVertexNormals)
                {
                    o.InputMeshN = new DVector <float>(o.SO.Mesh.NormalsBuffer);
                }
                o.objFrame            = so.GetLocalFrame(CoordSpace.ObjectCoords);
                o.sceneFrame          = so.GetLocalFrame(CoordSpace.SceneCoords);
                o.sceneToObjUnitScale = SceneTransforms.SceneToObject(o.SO, 1.0f);

                o.localScale  = so.GetLocalScale();
                o.localBounds = so.GetLocalBoundingBox();
                Box3f sb = so.GetBoundingBox(CoordSpace.SceneCoords);
                o.sceneBounds = sb.ToAABB();

                o.curLocalScale = o.localScale;
                o.curSceneFrame = o.sceneFrame;

                objects.Add(o);
            }

            if (false && objects.Count == 1)
            {
                originalDims = objects[0].localBounds;
            }
            else
            {
                originalDims = objects[0].sceneBounds;
                for (int k = 1; k < objects.Count; ++k)
                {
                    originalDims.Contain(objects[k].sceneBounds);
                }
            }
            currentDims   = originalDims;
            sharedOriginS = (Vector3f)originalDims.Point(0, -1, 0);

            initialize_parameters();
        }
Пример #6
0
 public void MarkAsStatic(Box3f bounds)
 {
     for (int i = 0; i < NumParticles; i++)
     {
         if (bounds.Contains(Positions[i]))
         {
             StaticConstraints.Add(new StaticConstraint3d(this, i));
         }
     }
 }
Пример #7
0
        /// <summary>
        /// input box is in Object (local) coords of so, apply all intermediate
        /// transforms to get it to Scene coords
        /// </summary>
        public static Box3f ObjectToScene(SceneObject so, Box3f box)
        {
            Frame3f f  = new Frame3f(box.Center, box.AxisX, box.AxisY, box.AxisZ);
            Frame3f fS = ObjectToScene(so, f);
            // [TODO] could maybe figure out nonuniform scaling by applying this to
            //   box-corner-pt vector instead, and taking dots before/after?
            float scale = ObjectToSceneV(so, Vector3f.OneNormalized).Length;

            return(new Box3f(fS.Origin, fS.X, fS.Y, fS.Z, scale * box.Extent));
        }
Пример #8
0
        internal MCPTable2(MCP mcp, int index, AssetLoader loader)
            : base(mcp, index)
        {
            var reader = loader.Reader;

            Unknowns.ReadInt32s(reader, 1);
            loader.Expect(index);

            int count1  = reader.ReadInt32();
            int offset1 = reader.ReadInt32();

            Table1U1 = mcp.GetTable1Slice(count1, offset1);

            Box = loader.ReadCheckedAbsoluteBox3f();
        }
Пример #9
0
        public void UpdateBounds()
        {
            Vector3f min = new Vector3f(float.PositiveInfinity);
            Vector3f max = new Vector3f(float.NegativeInfinity);

            for (int i = 0; i < NumParticles; i++)
            {
                min.Min(Positions[i]);
                max.Max(Positions[i]);
            }

            min -= ParticleRadius;
            max += ParticleRadius;

            Bounds = new Box3f(min, max);
        }
Пример #10
0
 public static bool BoxContainsPoint(Box3f box, Vector3f p)
 {
     if (p.x > box.Max.x || p.x < box.Min.x)
     {
         return(false);
     }
     if (p.y > box.Max.y || p.y < box.Min.y)
     {
         return(false);
     }
     if (p.z > box.Max.z || p.z < box.Min.z)
     {
         return(false);
     }
     return(true);
 }
Пример #11
0
 public static bool BoxIntersectsBox(Box3f box0, Box3f box1)
 {
     if (box0.Max.x < box1.Min.x || box0.Min.x > box1.Max.x)
     {
         return(false);
     }
     if (box0.Max.y < box1.Min.y || box0.Min.y > box1.Max.y)
     {
         return(false);
     }
     if (box0.Max.z < box1.Min.z || box0.Min.z > box1.Max.z)
     {
         return(false);
     }
     return(true);
 }
Пример #12
0
        /// <summary>
        /// input box is in Scene, apply all intermediate inverse
        /// transforms to get it to local frame of SO
        /// </summary>
        public static Box3f SceneToObject(SceneObject so, Box3f box)
        {
            Frame3f f  = new Frame3f(box.Center, box.AxisX, box.AxisY, box.AxisZ);
            Frame3f fL = SceneToObject(so, f);

            // [TODO] make more efficient...
            Vector3f dv       = box.Extent.x * box.AxisX + box.Extent.y * box.AxisY + box.Extent.z * box.AxisZ;
            Frame3f  fCornerS = new Frame3f(box.Center + dv);
            Frame3f  fCornerL = SceneToObject(so, fCornerS);
            Vector3f dvL      = fCornerL.Origin - fL.Origin;
            Vector3f scales   = new Vector3f(
                dvL.Dot(fCornerL.X) / box.Extent.x,
                dvL.Dot(fCornerL.Y) / box.Extent.y,
                dvL.Dot(fCornerL.Z) / box.Extent.z);

            return(new Box3f(fL.Origin, fL.X, fL.Y, fL.Z, scales * box.Extent));
        }
Пример #13
0
        public void CreateBoundary(float radius, float density)
        {
            InnerBounds = new Box3f(-8, 4, 0, 10, -2, 4);
            //new Box3f(-8, 8, 0, 10, -2, 4);
            OuterBounds = InnerBounds;

            float thickness = 1.2f;

            OuterBounds.Min -= new Vector3f(radius * 2 * thickness);
            OuterBounds.Max += new Vector3f(radius * 2 * thickness);

            ParticleSource source = new ParticlesFromBounds(radius, OuterBounds, InnerBounds);

            Boundary = new FluidBoundary3d(source, radius, density, Matrix4x4f.Identity);

            CreateBoundaryVisualize();
        }
Пример #14
0
        virtual public AxisAlignedBox3f GetLocalBoundingBox()
        {
            if (vChildren.Count == 0)
            {
                return(new AxisAlignedBox3f(Vector3f.Zero, 0.5f));
            }
            Box3d combine = vChildren[0].GetBoundingBox(CoordSpace.SceneCoords);

            for (int k = 1; k < vChildren.Count; ++k)
            {
                Box3d childbox = vChildren[k].GetBoundingBox(CoordSpace.SceneCoords);
                combine = Box3d.Merge(ref combine, ref childbox);
            }
            Box3f boxLocal = SceneTransforms.SceneToObject(this, (Box3f)combine);

            return(boxLocal.ToAABB());
        }
Пример #15
0
        /// <summary>
        /// Compute AABB of scene in given space. Note that this will *not* be the same box
        /// in world space as in scene space.
        /// This computation ignores SOs with zero volume.
        /// </summary>
        public AxisAlignedBox3f GetBoundingBox(CoordSpace eSpace, bool bIncludeBoundsObjects)
        {
            if (eSpace == CoordSpace.ObjectCoords)
            {
                eSpace = CoordSpace.SceneCoords;
            }

            AxisAlignedBox3f b = AxisAlignedBox3f.Empty;

            foreach (SceneObject so in SceneObjects)
            {
                Box3f sobox = so.GetBoundingBox(eSpace);
                if (sobox.Volume > 0)
                {
                    foreach (Vector3d v in sobox.VerticesItr())
                    {
                        b.Contain(v);
                    }
                }
            }
            if (bIncludeBoundsObjects)
            {
                AxisAlignedBox3f sceneBounds =
                    UnityUtil.GetGeometryBoundingBox(BoundsObjects, true);
                if (sceneBounds.Volume > 0)
                {
                    if (eSpace == CoordSpace.WorldCoords)
                    {
                        for (int k = 0; k < 8; ++k)
                        {
                            b.Contain(ToWorldP(sceneBounds.Corner(k)));
                        }
                    }
                    else
                    {
                        b.Contain(sceneBounds);
                    }
                }
            }
            if (b.Volume == 0)
            {
                b = new AxisAlignedBox3f(1.0f);
            }
            return(b);
        }
Пример #16
0
        public static Vector3f ClosestPointOnBox(Box3f box, Vector3f p)
        {
            Vector3f c;

            if (p.x < box.Min.x)
            {
                c.x = box.Min.x;
            }
            else if (p.x > box.Max.x)
            {
                c.x = box.Max.x;
            }
            else
            {
                c.x = p.x;
            }

            if (p.y < box.Min.y)
            {
                c.y = box.Min.y;
            }
            else if (p.y > box.Max.y)
            {
                c.y = box.Max.y;
            }
            else
            {
                c.y = p.y;
            }

            if (p.z < box.Min.z)
            {
                c.z = box.Min.z;
            }
            else if (p.z > box.Max.z)
            {
                c.z = box.Max.z;
            }
            else
            {
                c.z = p.z;
            }

            return(c);
        }
Пример #17
0
        virtual public Box3f GetBoundingBox(CoordSpace eSpace)
        {
            Box3f box = new Box3f(GetLocalBoundingBox());

            if (eSpace == CoordSpace.ObjectCoords)
            {
                return(box);
            }
            else if (eSpace == CoordSpace.SceneCoords)
            {
                return(SceneTransforms.ObjectToScene(this, box));
            }
            else
            {
                box = SceneTransforms.ObjectToScene(this, box);
                return(GetScene().ToWorldBox(box));
            }
        }
Пример #18
0
        public static void DrawBounds(Camera camera, Color color, Box3f bounds, Matrix4x4f localToWorld)
        {
            if (camera == null)
            {
                return;
            }

            bounds.GetCorners(m_corners4f);

            IList <Vector4> verts = Vertices(8);

            for (int i = 0; i < 8; i++)
            {
                verts[i] = MathConverter.ToVector4(localToWorld * m_corners4f[i]);
            }

            DrawVerticesAsLines(camera, color, verts, m_cube);
        }
Пример #19
0
        internal ModelBone(FolderAsset folder, int index, AssetLoader loader)
            : base(folder, index, loader)
        {
            var reader = loader.Reader;

            Position             = reader.ReadVector3f();
            Name                 = reader.ReadStringzAtUInt32(Encoding);
            Angle                = Angle3.Radians(reader.ReadVector3f());
            parentIndex          = reader.ReadInt16();
            firstChildIndex      = reader.ReadInt16();
            Scale                = reader.ReadVector3f();
            nextSiblingIndex     = reader.ReadInt16();
            previousSiblingIndex = reader.ReadInt16();
            var min = reader.ReadVector3f();

            Unknowns.ReadInt32s(reader, 1);             // 0 or 1
            var max = reader.ReadVector3f();

            Bounds = new Box3f(min, max);
            reader.RequireZeroes(4 * 13);
        }
Пример #20
0
        public void CreateFluid(float radius, float density)
        {
            //To make less particles decrease the size of the bounds or increase the radius.
            //Make sure fluid bounds fits inside the boundrys bounds.
            FluidBounds = new Box3f(-8, 0, 0, 8, -2, 2);//new Box3f(-7, 6, 1, 7, -2, 4);


            FluidParticlesWithConstraint source = new FluidParticlesWithConstraint(radius, FluidBounds, Boundary.NumParticles);

            System.Random rnd = new System.Random(0);

            Body          = new FluidBody3d(source, radius, density, Matrix4x4f.Identity);
            Body.Dampning = 0.0f;
            Body.AddBoundry(Boundary);
            Body.RandomizePositions(rnd, radius * 0.01f);
            Body.RandomizePositionOrder(rnd);

            Debug.Log(Body.NumParticles);


            CreateFluidVisualize();
        }
Пример #21
0
        public static bool BoxIntersectsCircle(Box3f box, Sphere3f sphere)
        {
            if (sphere.Center.x - sphere.Radius > box.Max.x ||
                sphere.Center.x + sphere.Radius < box.Min.x)
            {
                return(false);
            }

            if (sphere.Center.y - sphere.Radius > box.Max.y ||
                sphere.Center.y + sphere.Radius < box.Min.y)
            {
                return(false);
            }

            if (sphere.Center.z - sphere.Radius > box.Max.z ||
                sphere.Center.z + sphere.Radius < box.Min.z)
            {
                return(false);
            }

            return(true);
        }
Пример #22
0
        public static void RecenterAboveOrigin(FScene scene, SceneObject so, bool bInteractive)
        {
            Frame3f          curFrameO = so.GetLocalFrame(CoordSpace.ObjectCoords);
            AxisAlignedBox3f bounds    = so.GetLocalBoundingBox();
            Box3f            box       = new Box3f(bounds);

            box = curFrameO.FromFrame(ref box);
            AxisAlignedBox3f boundsS = box.ToAABB();

            Vector3f c  = boundsS.Center - 0.5f * boundsS.Height * Vector3f.AxisY;
            Vector3f dt = -c;

            if (dt.MaxAbs > MathUtil.ZeroTolerancef)
            {
                Frame3f           newFrameO = curFrameO.Translated(dt);
                TransformSOChange change    = new TransformSOChange(so, curFrameO, newFrameO, CoordSpace.ObjectCoords);
                scene.History.PushChange(change, false);
                if (bInteractive)
                {
                    scene.History.PushInteractionCheckpoint();
                }
            }
        }
 public ParticlesFromBounds(float spacing, Box3f bounds, Box3f exclusion) : base(spacing)
 {
     Bounds = bounds;
     CreateParticles(exclusion);
 }
 public ParticlesFromBounds(float spacing, Box3f bounds) : base(spacing)
 {
     Bounds = bounds;
     CreateParticles();
 }
Пример #25
0
        /// <summary>
        /// Returns new tree with all points deleted which are inside.
        /// </summary>
        public static IPointCloudNode Delete(this IPointCloudNode root,
                                             Func <IPointCloudNode, bool> isNodeFullyInside,
                                             Func <IPointCloudNode, bool> isNodeFullyOutside,
                                             Func <V3d, bool> isPositionInside,
                                             Storage storage, CancellationToken ct,
                                             int splitLimit
                                             )
        {
            if (root == null)
            {
                return(null);
            }

            var f = root as FilteredNode;

            if (f != null)
            {
                var filter = f.Filter as ISpatialFilter;
                if (filter != null)
                {
                    bool remove(IPointCloudNode n) => filter.IsFullyInside(n) && isNodeFullyInside(n);
                    bool keep(IPointCloudNode n) => filter.IsFullyOutside(n) || isNodeFullyOutside(n);
                    bool contains(V3d pt) => filter.Contains(pt) && isPositionInside(pt);

                    var res = f.Node.Delete(remove, keep, contains, storage, ct, splitLimit);
                    return(FilteredNode.Create(res, f.Filter));
                }
                else
                {
                    throw new NotImplementedException("cannot delete on PointCloud with non-spatial filter");
                }
            }


            if (isNodeFullyInside(root))
            {
                return(null);
            }
            if (isNodeFullyOutside(root))
            {
                if (!root.IsMaterialized)
                {
                    root = root.Materialize();
                }
                return(root);
            }

            if (root.IsLeaf)
            {
                var ps    = root.HasPositions ? new List <V3f>() : null;
                var cs    = root.HasColors ? new List <C4b>() : null;
                var ns    = root.HasNormals ? new List <V3f>() : null;
                var js    = root.HasIntensities ? new List <int>() : null;
                var ks    = root.HasClassifications ? new List <byte>() : null;
                var oldPs = root.Positions?.Value;
                var oldCs = root.Colors?.Value;
                var oldNs = root.Normals?.Value;
                var oldIs = root.Intensities?.Value;
                var oldKs = root.Classifications?.Value;
                var bbabs = Box3d.Invalid;
                var bbloc = Box3f.Invalid;

                for (var i = 0; i < oldPs.Length; i++)
                {
                    var pabs = (V3d)oldPs[i] + root.Center;
                    if (!isPositionInside(pabs))
                    {
                        if (oldPs != null)
                        {
                            ps.Add(oldPs[i]);
                        }
                        if (oldCs != null)
                        {
                            cs.Add(oldCs[i]);
                        }
                        if (oldNs != null)
                        {
                            ns.Add(oldNs[i]);
                        }
                        if (oldIs != null)
                        {
                            js.Add(oldIs[i]);
                        }
                        if (oldKs != null)
                        {
                            ks.Add(oldKs[i]);
                        }
                        bbabs.ExtendBy(pabs);
                        bbloc.ExtendBy(oldPs[i]);
                    }
                }

                if (ps.Count == 0)
                {
                    return(null);
                }

                var psa   = ps.ToArray();
                var newId = Guid.NewGuid();
                var kd    = psa.Length < 1 ? null : psa.BuildKdTree();

                Guid psId = Guid.NewGuid();
                Guid kdId = kd != null?Guid.NewGuid() : Guid.Empty;

                Guid csId = cs != null?Guid.NewGuid() : Guid.Empty;

                Guid nsId = ns != null?Guid.NewGuid() : Guid.Empty;

                Guid isId = js != null?Guid.NewGuid() : Guid.Empty;

                Guid ksId = ks != null?Guid.NewGuid() : Guid.Empty;

                storage.Add(psId, psa);

                var data = ImmutableDictionary <Durable.Def, object> .Empty
                           .Add(Durable.Octree.NodeId, newId)
                           .Add(Durable.Octree.Cell, root.Cell)
                           .Add(Durable.Octree.BoundingBoxExactGlobal, bbabs)
                           .Add(Durable.Octree.BoundingBoxExactLocal, bbloc)
                           .Add(Durable.Octree.PositionsLocal3fReference, psId)
                           .Add(Durable.Octree.PointCountCell, ps.Count)
                           .Add(Durable.Octree.PointCountTreeLeafs, (long)ps.Count)
                           .Add(Durable.Octree.MaxTreeDepth, 0)
                           .Add(Durable.Octree.MinTreeDepth, 0)
                ;


                if (kd != null)
                {
                    storage.Add(kdId, kd.Data);
                    data = data.Add(Durable.Octree.PointRkdTreeFDataReference, kdId);
                }
                if (cs != null)
                {
                    storage.Add(csId, cs.ToArray());
                    data = data.Add(Durable.Octree.Colors4bReference, csId);
                }
                if (ns != null)
                {
                    storage.Add(nsId, ns.ToArray());
                    data = data.Add(Durable.Octree.Normals3fReference, nsId);
                }
                if (js != null)
                {
                    storage.Add(isId, js.ToArray());
                    data = data.Add(Durable.Octree.Intensities1iReference, isId);
                }
                if (ks != null)
                {
                    storage.Add(ksId, ks.ToArray());
                    data = data.Add(Durable.Octree.Classifications1bReference, ksId);
                }

                // MinTreeDepth MaxTreeDepth SubNodeIds??
                return(new PointSetNode(data, storage, writeToStore: true));
            }
            else
            {
                var subnodes       = root.Subnodes.Map((r) => r?.Value?.Delete(isNodeFullyInside, isNodeFullyOutside, isPositionInside, storage, ct, splitLimit));
                var pointCountTree = subnodes.Sum((n) => n != null ? n.PointCountTree : 0);
                if (pointCountTree == 0)
                {
                    return(null);
                }
                else if (pointCountTree <= splitLimit)
                {
                    var psabs = root.HasPositions ? new List <V3d>() : null;
                    var cs    = root.HasColors ? new List <C4b>() : null;
                    var ns    = root.HasNormals ? new List <V3f>() : null;
                    var js    = root.HasIntensities ? new List <int>() : null;
                    var ks    = root.HasClassifications ? new List <byte>() : null;
                    foreach (var c in subnodes)
                    {
                        if (c != null)
                        {
                            MergeExtensions.CollectEverything(c, psabs, cs, ns, js, ks);
                        }
                    }
                    Debug.Assert(psabs.Count == pointCountTree);
                    var psa = psabs.MapToArray((p) => (V3f)(p - root.Center));
                    var kd  = psa.Length < 1 ? null : psa.BuildKdTree();


                    Guid psId = Guid.NewGuid();
                    Guid kdId = kd != null?Guid.NewGuid() : Guid.Empty;

                    Guid csId = cs != null?Guid.NewGuid() : Guid.Empty;

                    Guid nsId = ns != null?Guid.NewGuid() : Guid.Empty;

                    Guid isId = js != null?Guid.NewGuid() : Guid.Empty;

                    Guid ksId = ks != null?Guid.NewGuid() : Guid.Empty;

                    var bbabs = new Box3d(psabs);

                    var newId = Guid.NewGuid();
                    storage.Add(psId, psa);

                    var data = ImmutableDictionary <Durable.Def, object> .Empty
                               .Add(Durable.Octree.NodeId, newId)
                               .Add(Durable.Octree.Cell, root.Cell)
                               .Add(Durable.Octree.BoundingBoxExactGlobal, bbabs)
                               .Add(Durable.Octree.BoundingBoxExactLocal, (Box3f)(bbabs - root.Center))
                               .Add(Durable.Octree.PositionsLocal3fReference, psId)
                               .Add(Durable.Octree.PointCountCell, (int)pointCountTree)
                               .Add(Durable.Octree.PointCountTreeLeafs, pointCountTree)
                               .Add(Durable.Octree.MaxTreeDepth, 0)
                               .Add(Durable.Octree.MinTreeDepth, 0)
                    ;

                    if (kd != null)
                    {
                        storage.Add(kdId, kd.Data);
                        data = data.Add(Durable.Octree.PointRkdTreeFDataReference, kdId);
                    }
                    if (cs != null)
                    {
                        storage.Add(csId, cs.ToArray());
                        data = data.Add(Durable.Octree.Colors4bReference, csId);
                    }
                    if (ns != null)
                    {
                        storage.Add(nsId, ns.ToArray());
                        data = data.Add(Durable.Octree.Normals3fReference, nsId);
                    }
                    if (js != null)
                    {
                        storage.Add(isId, js.ToArray());
                        data = data.Add(Durable.Octree.Intensities1iReference, isId);
                    }
                    if (ks != null)
                    {
                        storage.Add(ksId, ks.ToArray());
                        data = data.Add(Durable.Octree.Classifications1bReference, ksId);
                    }

                    // MinTreeDepth MaxTreeDepth SubNodeIds??
                    return(new PointSetNode(data, storage, writeToStore: true));
                }
                else
                {
                    var bbabs  = new Box3d(subnodes.Map(n => n != null ? n.BoundingBoxExactGlobal : Box3d.Invalid));
                    var subids = subnodes.Map(n => n != null ? n.Id : Guid.Empty);

                    var maxDepth = subnodes.Max(n => n != null ? n.MaxTreeDepth + 1 : 0);
                    var minDepth = subnodes.Min(n => n != null ? n.MinTreeDepth + 1 : 0);


                    var octreeSplitLimit = splitLimit;
                    var fractions        = LodExtensions.ComputeLodFractions(subnodes);
                    var counts           = LodExtensions.ComputeLodCounts(octreeSplitLimit, fractions);

                    // generate LoD data ...
                    var needsCs = subnodes.Any(x => x != null ? x.HasColors : false);
                    var needsNs = subnodes.Any(x => x != null ? x.HasNormals : false);
                    var needsIs = subnodes.Any(x => x != null ? x.HasIntensities : false);
                    var needsKs = subnodes.Any(x => x != null ? x.HasClassifications : false);

                    var subcenters = subnodes.Map(x => x?.Center);
                    var lodPs      = LodExtensions.AggregateSubPositions(counts, octreeSplitLimit, root.Center, subcenters, subnodes.Map(x => x?.Positions?.Value));
                    var lodCs      = needsCs ? LodExtensions.AggregateSubArrays(counts, octreeSplitLimit, subnodes.Map(x => x?.Colors?.Value)) : null;
                    var lodIs      = needsIs ? LodExtensions.AggregateSubArrays(counts, octreeSplitLimit, subnodes.Map(x => x?.Intensities?.Value)) : null;
                    var lodKs      = needsKs ? LodExtensions.AggregateSubArrays(counts, octreeSplitLimit, subnodes.Map(x => x?.Classifications?.Value)) : null;
                    var lodNs      = needsNs ? LodExtensions.AggregateSubArrays(counts, octreeSplitLimit, subnodes.Map(x => x?.Normals?.Value)) : null;
                    var lodKd      = lodPs.Length < 1 ? null : lodPs.BuildKdTree();


                    Guid psId = Guid.NewGuid();
                    Guid kdId = lodKd != null?Guid.NewGuid() : Guid.Empty;

                    Guid csId = lodCs != null?Guid.NewGuid() : Guid.Empty;

                    Guid nsId = lodNs != null?Guid.NewGuid() : Guid.Empty;

                    Guid isId = lodIs != null?Guid.NewGuid() : Guid.Empty;

                    Guid ksId = lodKs != null?Guid.NewGuid() : Guid.Empty;


                    var newId = Guid.NewGuid();
                    storage.Add(psId, lodPs);

                    var bbloc = new Box3f(lodPs);

                    // be inner node
                    var data = ImmutableDictionary <Durable.Def, object> .Empty
                               .Add(Durable.Octree.SubnodesGuids, subids)
                               .Add(Durable.Octree.NodeId, newId)
                               .Add(Durable.Octree.Cell, root.Cell)
                               .Add(Durable.Octree.BoundingBoxExactGlobal, bbabs)
                               .Add(Durable.Octree.BoundingBoxExactLocal, bbloc)
                               .Add(Durable.Octree.PositionsLocal3fReference, psId)
                               .Add(Durable.Octree.PointCountCell, lodPs.Length)
                               .Add(Durable.Octree.PointCountTreeLeafs, pointCountTree)
                               .Add(Durable.Octree.MaxTreeDepth, maxDepth)
                               .Add(Durable.Octree.MinTreeDepth, minDepth)
                    ;


                    if (lodKd != null)
                    {
                        storage.Add(kdId, lodKd.Data);
                        data = data.Add(Durable.Octree.PointRkdTreeFDataReference, kdId);
                    }
                    if (lodCs != null)
                    {
                        storage.Add(csId, lodCs);
                        data = data.Add(Durable.Octree.Colors4bReference, csId);
                    }
                    if (lodNs != null)
                    {
                        storage.Add(nsId, lodNs);
                        data = data.Add(Durable.Octree.Normals3fReference, nsId);
                    }
                    if (lodIs != null)
                    {
                        storage.Add(isId, lodIs);
                        data = data.Add(Durable.Octree.Intensities1iReference, isId);
                    }
                    if (lodKs != null)
                    {
                        storage.Add(ksId, lodKs);
                        data = data.Add(Durable.Octree.Classifications1bReference, ksId);
                    }

                    // MinTreeDepth MaxTreeDepth SubNodeIds??
                    return(new PointSetNode(data, storage, writeToStore: true));
                }
            }
        }
            public PointSetNode ToPointSetCell(Storage storage, bool isTemporaryImportNode)
            {
                var center = new V3d(_centerX, _centerY, _centerZ);

                V3f[]  ps = null;
                C4b[]  cs = null;
                V3f[]  ns = null;
                int[]  js = null;
                byte[] ks = null;

                if (_ia != null)
                {
                    var allPs = _octree.m_ps;
                    var count = _ia.Count;

                    ps = new V3f[count];
                    for (var i = 0; i < count; i++)
                    {
                        ps[i] = (V3f)(allPs[_ia[i]] - center);
                    }

                    if (_octree.m_cs != null)
                    {
                        var allCs = _octree.m_cs;
                        cs = new C4b[count];
                        for (var i = 0; i < count; i++)
                        {
                            cs[i] = allCs[_ia[i]];
                        }
                    }

                    if (_octree.m_ns != null)
                    {
                        var allNs = _octree.m_ns;
                        ns = new V3f[count];
                        for (var i = 0; i < count; i++)
                        {
                            ns[i] = allNs[_ia[i]];
                        }
                    }

                    if (_octree.m_is != null)
                    {
                        var allIs = _octree.m_is;
                        js = new int[count];
                        for (var i = 0; i < count; i++)
                        {
                            js[i] = allIs[_ia[i]];
                        }
                    }

                    if (_octree.m_ks != null)
                    {
                        var allKs = _octree.m_ks;
                        ks = new byte[count];
                        for (var i = 0; i < count; i++)
                        {
                            ks[i] = allKs[_ia[i]];
                        }
                    }
                }

                Guid?psId = ps != null ? (Guid?)Guid.NewGuid() : null;
                Guid?csId = cs != null ? (Guid?)Guid.NewGuid() : null;
                Guid?nsId = ns != null ? (Guid?)Guid.NewGuid() : null;
                Guid?isId = js != null ? (Guid?)Guid.NewGuid() : null;
                Guid?ksId = ks != null ? (Guid?)Guid.NewGuid() : null;

                var subcells   = _subnodes?.Map(x => x?.ToPointSetCell(storage, isTemporaryImportNode));
                var subcellIds = subcells?.Map(x => x?.Id);
                var isLeaf     = _subnodes == null;

#if DEBUG
                if (_subnodes != null)
                {
                    if (ps != null)
                    {
                        throw new InvalidOperationException("Invariant d98ea55b-760c-4564-8076-ce9cf7d293a0.");
                    }

                    for (var i = 0; i < 8; i++)
                    {
                        var sn = _subnodes[i]; if (sn == null)
                        {
                            continue;
                        }
                        if (sn._cell.Exponent != this._cell.Exponent - 1)
                        {
                            throw new InvalidOperationException("Invariant 2c33afb4-683b-4f71-9e1f-36ec4a79fba1.");
                        }
                    }
                }
#endif
                var pointCountTreeLeafs = subcells != null
                    ? subcells.Sum(n => n != null?n.PointCountTree : 0)
                                          : ps.Length
                ;

                var data = ImmutableDictionary <Durable.Def, object> .Empty
                           .Add(Durable.Octree.NodeId, Guid.NewGuid())
                           .Add(Durable.Octree.Cell, _cell)
                           .Add(Durable.Octree.PointCountTreeLeafs, pointCountTreeLeafs)
                ;

                if (isTemporaryImportNode)
                {
                    data = data.Add(PointSetNode.TemporaryImportNode, 0);
                }

                if (psId != null)
                {
                    storage.Add(psId.ToString(), ps);
                    var bbExactLocal = new Box3f(ps);

                    data = data
                           .Add(Durable.Octree.PointCountCell, ps.Length)
                           .Add(Durable.Octree.PositionsLocal3fReference, psId.Value)
                           .Add(Durable.Octree.BoundingBoxExactLocal, bbExactLocal)
                    ;

                    if (isLeaf)
                    {
                        var bbExactGlobal = (Box3d)bbExactLocal + center;
                        data = data
                               .Add(Durable.Octree.BoundingBoxExactGlobal, bbExactGlobal)
                        ;
                    }
                }
                else
                {
                    data = data
                           .Add(Durable.Octree.PointCountCell, 0)
                    ;
                }

                if (csId != null)
                {
                    storage.Add(csId.ToString(), cs); data = data.Add(Durable.Octree.Colors4bReference, csId.Value);
                }
                if (nsId != null)
                {
                    storage.Add(nsId.ToString(), ns); data = data.Add(Durable.Octree.Normals3fReference, nsId.Value);
                }
                if (isId != null)
                {
                    storage.Add(isId.ToString(), js); data = data.Add(Durable.Octree.Intensities1iReference, isId.Value);
                }
                if (ksId != null)
                {
                    storage.Add(ksId.ToString(), ks); data = data.Add(Durable.Octree.Classifications1bReference, ksId.Value);
                }

                if (isLeaf) // leaf
                {
                    var result = new PointSetNode(data, storage, writeToStore: true);
                    if (storage.GetPointCloudNode(result.Id) == null)
                    {
                        throw new InvalidOperationException("Invariant d1022027-2dbf-4b11-9b40-4829436f5789.");
                    }
                    return(result);
                }
                else
                {
                    for (var i = 0; i < 8; i++)
                    {
                        var x = subcellIds[i];
                        if (x.HasValue)
                        {
                            var id = x.Value;
                            if (storage.GetPointCloudNode(id) == null)
                            {
                                throw new InvalidOperationException("Invariant 01830b8b-3c0e-4a8b-a1bd-bfd1b1be1844.");
                            }
                        }
                    }
                    var bbExactGlobal = new Box3d(subcells.Where(x => x != null).Select(x => x.BoundingBoxExactGlobal));
                    data = data
                           .Add(Durable.Octree.BoundingBoxExactGlobal, bbExactGlobal)
                           .Add(Durable.Octree.SubnodesGuids, subcellIds.Map(x => x ?? Guid.Empty))
                    ;
                    var result = new PointSetNode(data, storage, writeToStore: true);
                    if (storage.GetPointCloudNode(result.Id) == null)
                    {
                        throw new InvalidOperationException("Invariant 7b09eccb-b6a0-4b99-be7a-eeff53b6a98b.");
                    }
                    return(result);
                }
            }
Пример #27
0
        internal Model(AssetLoader loader)
            : base(loader)
        {
            Asset        context = loader.Context;
            string       name    = loader.Name;
            BinaryReader reader  = loader.Reader;

            FolderAsset textureArchive = null;

            FolderAsset bonesFolder              = new FolderAsset(this, "Bones");
            FolderAsset materialsFolder          = new FolderAsset(this, "Materials");
            FolderAsset meshesFolder             = new FolderAsset(this, "Meshes");
            FolderAsset vertexDeclarationsFolder = new FolderAsset(this, "Vertex declarations");

            ArrayBackedList <byte> bufferData = new ArrayBackedList <byte>();

            if (context != null && context.Parent is FolderAsset)
            {
                // @"/map/m##_##_##_##/m*.flver.dcx" for DS1; textures are in the @"/map/m##/" folder.
                if (name.StartsWith(@"map/m"))
                {
                    string      folderName = name.Substring(4, 3);
                    FolderAsset maps       = (FolderAsset)context.Parent.Parent;
                    foreach (FolderAsset child in maps.Children)
                    {
                        if (child.Name == folderName)
                        {
                            textureArchive = child;
                            break;
                        }
                    }
                }
                else
                {
                    textureArchive = (FolderAsset)context.Parent;
                }
            }

#if Marking
            MarkingStream markingStream = loader.StartMarking(out reader);
#endif

            loader.ExpectMagic(Magic);
            char endian = (char)reader.ReadByte();

            switch (endian)
            {
            case 'L':
                ByteOrder = ByteOrder.LittleEndian;
                break;

            case 'B':
                reader    = loader.MakeBigEndian();
                ByteOrder = ByteOrder.BigEndian;
                break;

            default:
                throw new Exception();
            }

            using (reader) {
                // Read header.
                loader.Expect((byte)0);
                Version = (ModelVersion)reader.ReadInt32();
                if (Version != ModelVersion.DarkSouls && Version != ModelVersion.DarkSouls2)
                {
                    loader.AddError(loader.Position - 4, "Unknown model version " + VersionString + "; will try to load it anyway.");
                }
                int dataOffset = reader.ReadInt32();
                int dataSize   = reader.ReadInt32();
                if (((dataOffset + dataSize + 31) & ~31) != reader.BaseStream.Length)
                {
                    loader.AddError(loader.Position - 4, "Data size and offset aren't correct.");
                }

                int boneUnknownCount = reader.ReadInt32();
                int materialCount    = reader.ReadInt32();
                int boneCount        = reader.ReadInt32();

                int meshCount  = reader.ReadInt32();
                int meshCount2 = reader.ReadInt32();
                if (meshCount != meshCount2)
                {
                    loader.AddError(loader.Position - 4, "Mesh count 1 and 2 aren't the same.");
                }

                Bounds = new Box3f(reader.ReadVector3f(), reader.ReadVector3f());
                Unknowns.ReadInt32s(reader, 1);                 // Possible the non-degenerate triangle count. Seems related.
                int triangleCount = reader.ReadInt32();

                loader.Expect(IsDS1 ? 272 : 0x10010100);
                loader.Expect(IsDS1 ? 0 : 0xFFFF);

                int partCount = reader.ReadInt32();
                int vertexDeclarationCount = reader.ReadInt32();
                int materialParameterCount = reader.ReadInt32();
                loader.Expect(IsDS1 ? 0 : 0x1000000);
                loader.ExpectZeroes(4, 8);

                // Calculate offsets.
                long boneUnknownsOffset       = HeaderSize;
                long materialsOffset          = boneUnknownsOffset + boneUnknownCount * ModelBoneUnknown.DataSize;
                long bonesOffset              = materialsOffset + materialCount * ModelMaterial.DataSize;
                long meshesOffset             = bonesOffset + boneCount * ModelBone.DataSize;
                long detailLevelsOffset       = meshesOffset + meshCount * ModelMesh.DataSize;
                long meshVerticesOffset       = detailLevelsOffset + partCount * ModelDetailLevel.DataSize;
                long vertexDeclarationsOffset = meshVerticesOffset + meshCount * ModelMesh.DataSizeVertexHeader;
                long materialParametersOffset = vertexDeclarationsOffset + vertexDeclarationCount * ModelVertexDeclaration.DataSize;
                long postHeaderOffset         = materialParametersOffset + materialParameterCount * ModelMaterialParameter.DataSize;

                // BoneUnknowns
                ExpectedOffset(loader, boneUnknownsOffset, typeof(ModelBoneUnknown).Name);
                for (int index = 0; index < boneUnknownCount; index++)
                {
                    boneUnknowns.Add(new ModelBoneUnknown(bonesFolder, index, loader));
                }

                // Materials
                ExpectedOffset(loader, materialsOffset, typeof(ModelMaterial).Name);
                for (int index = 0; index < materialCount; index++)
                {
                    materials.Add(new ModelMaterial(materialsFolder, index, loader));
                }
                int expectedMaterialParameterCount = materialCount > 0 ? materials[materialCount - 1].ParameterEndIndex : 0;
                if (expectedMaterialParameterCount != materialParameterCount)
                {
                    loader.AddError(null, "Expected material parameter count {0} doesn't match actual count {1}.", expectedMaterialParameterCount, materialParameterCount);
                }

                // Bones
                ExpectedOffset(loader, bonesOffset, typeof(ModelBone).Name);
                for (int index = 0; index < boneCount; index++)
                {
                    bones.Add(new ModelBone(bonesFolder, index, loader));
                }

                // Meshes
                ExpectedOffset(loader, meshesOffset, typeof(ModelMesh).Name);
                for (int index = 0; index < meshCount; index++)
                {
                    meshes.Add(new ModelMesh(meshesFolder, index, loader));
                }
                int expectedPartCount = meshCount > 0 ? meshes[meshCount - 1].PartEndIndex : 0;
                if (expectedPartCount != partCount)
                {
                    throw new InvalidDataException("Expected part count doesn't match actual count.");
                }

                // Detail levels
                ExpectedOffset(loader, detailLevelsOffset, typeof(ModelDetailLevel).Name);
                foreach (ModelMesh mesh in meshes)
                {
                    mesh.ReadDetailLevels(loader, dataOffset, bufferData);
                    detailLevels.AddRange(mesh.DetailLevels);
                }

                // Mesh vertices
                ExpectedOffset(loader, meshVerticesOffset, typeof(ModelMesh).Name + " vertex header");
                foreach (ModelMesh mesh in meshes)
                {
                    mesh.ReadVertexHeaders(reader, dataOffset, bufferData);
                }

                // Vertex declarations
                ExpectedOffset(loader, vertexDeclarationsOffset, typeof(ModelVertexDeclaration).Name);
                for (int index = 0; index < vertexDeclarationCount; index++)
                {
                    vertexDeclarations.Add(new ModelVertexDeclaration(vertexDeclarationsFolder, index, loader));
                }

                // Material parameters
                ExpectedOffset(loader, materialParametersOffset, typeof(ModelMaterialParameter).Name);
                foreach (ModelMaterial material in materials)
                {
                    material.ReadParameters(loader, textureArchive);
                    materialParameters.AddRange(material.Parameters);
                }

                ExpectedOffset(loader, postHeaderOffset, "Post-header");

#if Marking
                if (markingStream != null)
                {
                    markingStream.Report(loader);
                }
#endif // Marking

#if SkippedChecks
                /*int vertexDataSize = 0, indexCount = 0, indexSize = 0, vertexCount = 0, expectedTriangleCount = 0, nondegenerateTriangleCount = 0;
                 * foreach (var mesh in Meshes) {
                 *      vertexDataSize += mesh.VertexCount * mesh.VertexSize;
                 *      vertexCount += mesh.VertexCount;
                 *      foreach (var part in mesh.Parts) {
                 *              indexCount += part.Indices.Length;
                 *              indexSize += part.Indices.Length * 2;
                 *              expectedTriangleCount += part.Indices.Length - 2;
                 *              for (int index = 0; index < part.Indices.Length - 2; index++) {
                 *                      if (part.Indices[index] != part.Indices[index + 1] && part.Indices[index + 1] != part.Indices[index + 2] && part.Indices[index] != part.Indices[index + 2])
                 *                              nondegenerateTriangleCount++;
                 *              }
                 *      }
                 * }
                 * if (Math.Abs(expectedTriangleCount - triangleCount) > partCount)
                 *      throw new InvalidDataException("Expected triangle count doesn't match the read value.");*/
#endif
            }

            Buffer = new GraphicsBuffer(bufferData.Count == 0 ? 1 : bufferData.Count);
            Buffer.Write(0, bufferData.Array, 0, bufferData.Count);
        }
Пример #28
0
 public void Write(Box3f x)
 {
     Write(x.Min); Write(x.Max);
 }
 public FluidParticlesWithConstraint(float spacing, Box3f bounds, int boundaryCount) : base(spacing)
 {
     Bounds             = bounds;
     this.boundaryCount = boundaryCount;
     CreateParticles();
 }