Пример #1
0
    override protected NPVoxModel CreateProduct(NPVoxModel reuse = null)
    {
        if (Input == null)
        {
            return(NPVoxModel.NewInvalidInstance(reuse, "No Input Setup"));;
        }

        NPVoxModel model = ((NPVoxIModelFactory)Input).GetProduct();

        if (Absolute)
        {
            NPVoxModel newModel = NPVoxModel.NewInstance(model, reuse);
            newModel.CopyOver(model);

            NPVoxSocket socket = model.GetSocketByName(SocketName);
            socket.Anchor      = NPVoxCoordUtil.ToCoord(GetTranslation() + GetPivot());
            socket.EulerAngles = GetRotation().eulerAngles;
            newModel.SetSocket(socket);

            return(newModel);
        }
        else
        {
            return(NPVoxModelTransformationUtil.MatrixTransformSocket(model, SocketName, Matrix, PivotOffset, reuse));
        }
    }
    public static NPVoxModel TransformSocket(NPVoxModel sourceModel, string socketName, Matrix4x4 transformMatrix, NPVoxModel reuse = null)
    {
        NPVoxModel transformedModel = null;

        transformedModel = NPVoxModel.NewInstance(sourceModel, reuse);
        transformedModel.CopyOver(sourceModel);

        NPVoxSocket[] sockets = new NPVoxSocket[sourceModel.Sockets.Length];
        for (int i = 0; i < sockets.Length; i++)
        {
            NPVoxSocket socket = sourceModel.Sockets[i];
            if (socket.Name == socketName)
            {
                // transform anchor
                Vector3 saveOriginalAnchor = NPVoxCoordUtil.ToVector(socket.Anchor);
                Vector3 saveTargetAnchor   = transformMatrix.MultiplyPoint(saveOriginalAnchor);
                socket.Anchor = sourceModel.Clamp(NPVoxCoordUtil.ToCoord(saveTargetAnchor));

                // transform Quaternion
                Quaternion originalRotation = Quaternion.Euler(socket.EulerAngles);
                Matrix4x4  rotated          = (Matrix4x4.TRS(Vector3.zero, originalRotation, Vector3.one) * transformMatrix);
                socket.EulerAngles = Matrix4x4Util.GetRotation(rotated).eulerAngles;
            }
            sockets[i] = socket;
        }
        transformedModel.Sockets = sockets;

        return(transformedModel);
    }
Пример #3
0
    public void Clamp_ShouldReturnClampedVoxCoord()
    {
        NPVoxModel sut = NPVoxModel.NewInstance(new NPVoxCoord(3, 3, 3));

        Assert.AreEqual(new NPVoxCoord(1, 1, 1), sut.Clamp(new NPVoxCoord(1, 1, 1)));
        Assert.AreEqual(new NPVoxCoord(0, 0, 0), sut.Clamp(new NPVoxCoord(-2, -2, -2)));
        Assert.AreEqual(new NPVoxCoord(2, 2, 2), sut.Clamp(new NPVoxCoord(7, 7, 7)));
    }
Пример #4
0
    public void Clamp_ShouldReturnClampedVoxBox()
    {
        NPVoxModel sut = NPVoxModel.NewInstance(new NPVoxCoord(3, 3, 3));
        NPVoxBox   box = sut.Clamp(new NPVoxBox(new NPVoxCoord(-2, -2, -2), new NPVoxCoord(6, 6, 6)));

        Assert.AreEqual(new NPVoxCoord(2, 2, 2), box.RightUpForward);
        Assert.AreEqual(new NPVoxCoord(0, 0, 0), box.LeftDownBack);
    }
    public static NPVoxModel CreateWithNewSize(NPVoxModel source, NPVoxBox newBounds, NPVoxModel reuse = null)
    {
        NPVoxCoord delta;
        NPVoxCoord newSize;

        CalculateResizeOffset(source.BoundingBox, newBounds, out delta, out newSize);

        NPVoxModel newModel = NPVoxModel.NewInstance(source, newSize, reuse);

        newModel.NumVoxels      = source.NumVoxels;
        newModel.NumVoxelGroups = source.NumVoxelGroups;
        newModel.Colortable     = source.Colortable != null ? (Color32[])source.Colortable.Clone() : null;
        newModel.Sockets        = source.Sockets != null ? (NPVoxSocket[])source.Sockets.Clone() : null;

        if (newModel.Sockets != null)
        {
            for (int i = 0; i < newModel.Sockets.Length; i++)
            {
                newModel.Sockets[i].Anchor = newModel.Sockets[i].Anchor + delta;
            }
        }

        bool hasVoxelGroups = source.HasVoxelGroups();

        if (hasVoxelGroups)
        {
            newModel.InitVoxelGroups();
            newModel.NumVoxelGroups = source.NumVoxelGroups;
        }

        foreach (NPVoxCoord coord in source.EnumerateVoxels())
        {
            NPVoxCoord targetCoord = coord + delta;
            newModel.SetVoxel(targetCoord, source.GetVoxel(coord));
            if (hasVoxelGroups)
            {
                newModel.SetVoxelGroup(targetCoord, source.GetVoxelGroup(coord));
            }
        }

//        newModel.InvalidateVoxelCache();

        return(newModel);
    }
Пример #6
0
    override protected NPVoxModel CreateProduct(NPVoxModel reuse = null)
    {
        if (Input == null)
        {
            return(NPVoxModel.NewInvalidInstance(reuse, "No Input Setup"));
        }

        NPVoxBoneModel model = ((NPVoxIModelFactory)Input).GetProduct() as NPVoxBoneModel;

        if (model == null)
        {
            return(NPVoxModel.NewInvalidInstance(reuse, "Can only transform bone models"));
        }

        // hack to center pivot on selected bones
        if (regenerateName)
        {
            RecenterBonePivot(model);
        }

        RegenerateName(model);

        NPVoxBox affectedBox = GetAffectedBox();

        if (affectedBox.Equals(NPVoxBox.INVALID))
        {
            NPVoxModel newInstance = NPVoxModel.NewInstance(model, reuse);
            newInstance.CopyOver(model);
            newInstance.RecalculateNumVoxels(true);
            return(newInstance);
        }
        else
        {
            reuse = NPVoxModelTransformationUtil.MatrixTransform(model, affectedBox, boneMask, Matrix, PivotOffset, ResolveConflictMethod, reuse);
            reuse.RecalculateNumVoxels(true);
            return(reuse);
        }
    }
    public static NPVoxModel Transform(NPVoxModel sourceModel, NPVoxBox affectedArea, Matrix4x4 transformMatrix, ResolveConflictMethodType resolveConflictMethod = ResolveConflictMethodType.CLOSEST, NPVoxModel reuse = null)
    {
        NPVoxBox clampedBox = sourceModel.Clamp(affectedArea);

        // calculate size & offset for new model
        NPVoxCoord size   = sourceModel.Size;
        NPVoxCoord offset = NPVoxCoord.ZERO;
        {
            NPVoxBox parentBounds = sourceModel.BoundingBox;
            NPVoxBox thisBounds   = parentBounds.Clone();

            // transform voxels
            foreach (NPVoxCoord coord in clampedBox.Enumerate())
            {
                Vector3    saveCoord = transformMatrix.MultiplyPoint(NPVoxCoordUtil.ToVector(coord));
                NPVoxCoord newCoord  = NPVoxCoordUtil.ToCoord(saveCoord);
                if (!sourceModel.IsInside(newCoord))
                {
                    thisBounds.EnlargeToInclude(newCoord);
                }
            }
            // transform sockets
            foreach (NPVoxSocket socket in sourceModel.Sockets)
            {
                NPVoxCoord newCoord = NPVoxCoordUtil.ToCoord(transformMatrix.MultiplyPoint(NPVoxCoordUtil.ToVector(socket.Anchor)));
                if (clampedBox.Contains(socket.Anchor) && !sourceModel.IsInside(newCoord))
                {
                    thisBounds.EnlargeToInclude(newCoord);
                }
            }

            CalculateResizeOffset(parentBounds, thisBounds, out offset, out size);
        }


        bool           hasVoxelGroups  = sourceModel.HasVoxelGroups();
        NPVoxBoneModel sourceBoneModel = sourceModel as NPVoxBoneModel;
        bool           hasBoneGropus   = sourceBoneModel != null;

        NPVoxModel     transformedModel     = NPVoxModel.NewInstance(sourceModel, size, reuse);
        NPVoxBoneModel transformedBoneModel = transformedModel as NPVoxBoneModel;

        if (hasVoxelGroups)
        {
            transformedModel.InitVoxelGroups();
            transformedModel.NumVoxelGroups = sourceModel.NumVoxelGroups;
        }
        if (hasBoneGropus)
        {
            transformedBoneModel.AllBones = NPVoxBone.CloneBones(sourceBoneModel.AllBones);
        }

        // 1. copy all voxels over that are not affected by the transformation
        transformedModel.NumVoxels  = sourceModel.NumVoxels;
        transformedModel.Colortable = sourceModel.Colortable;
        foreach (NPVoxCoord coord in sourceModel.EnumerateVoxels())
        {
            NPVoxCoord movedCoord = coord + offset;
            if (!clampedBox.Contains(coord))
            {
                transformedModel.SetVoxel(movedCoord, sourceModel.GetVoxel(coord));
                if (hasVoxelGroups)
                {
                    transformedModel.SetVoxelGroup(movedCoord, sourceModel.GetVoxelGroup(coord));
                }
                if (hasBoneGropus)
                {
                    transformedBoneModel.SetBoneMask(movedCoord, sourceBoneModel.GetBoneMask(coord));
                }
            }
        }

        // 2. copy all voxels that can be tranformed without conflict,
        Dictionary <NPVoxCoord, Vector3> conflictVoxels = new Dictionary <NPVoxCoord, Vector3>();

        foreach (NPVoxCoord sourceCoord in clampedBox.Enumerate())
        {
            if (sourceModel.HasVoxelFast(sourceCoord))
            {
                Vector3    saveCoord       = transformMatrix.MultiplyPoint(NPVoxCoordUtil.ToVector(sourceCoord));
                Vector3    targetCoordSave = saveCoord + NPVoxCoordUtil.ToVector(offset);
                NPVoxCoord targetCoord     = NPVoxCoordUtil.ToCoord(targetCoordSave);

                if (!transformedModel.HasVoxelFast(targetCoord))
                {
                    transformedModel.SetVoxel(targetCoord, sourceModel.GetVoxel(sourceCoord));
                    if (hasVoxelGroups)
                    {
                        transformedModel.SetVoxelGroup(targetCoord, sourceModel.GetVoxelGroup(sourceCoord));
                    }
                    if (hasBoneGropus)
                    {
                        transformedBoneModel.SetBoneMask(targetCoord, sourceBoneModel.GetBoneMask(sourceCoord));
                    }
                }
                else
                {
                    conflictVoxels[sourceCoord] = targetCoordSave;
                }
            }
        }

        // 3. try to fit in voxels that had conflicts
        int numberOfConflictsSolved = 0;

        if (resolveConflictMethod != ResolveConflictMethodType.NONE)
        {
            foreach (NPVoxCoord sourceCoord in conflictVoxels.Keys)
            {
                if (sourceModel.HasVoxelFast(sourceCoord))
                {
                    Vector3    targetSaveCoord = conflictVoxels[sourceCoord];
                    NPVoxCoord nearbyCoord     = GetNearbyCoord(transformedModel, targetSaveCoord, resolveConflictMethod);
                    if (!nearbyCoord.Equals(NPVoxCoord.INVALID))
                    {
                        transformedModel.SetVoxel(nearbyCoord, sourceModel.GetVoxel(sourceCoord));
                        if (hasVoxelGroups)
                        {
                            transformedModel.SetVoxelGroup(nearbyCoord, sourceModel.GetVoxelGroup(sourceCoord));
                        }
                        if (hasBoneGropus)
                        {
                            transformedBoneModel.SetBoneMask(nearbyCoord, sourceBoneModel.GetBoneMask(sourceCoord));
                        }
                        numberOfConflictsSolved++;
                    }
                }
            }

            if (numberOfConflictsSolved != conflictVoxels.Count)
            {
                Debug.Log(string.Format("transformation has resolved {0}/{1} conflicting voxels", numberOfConflictsSolved, conflictVoxels.Count));
            }
        }

        // 4. transform all sockets
        NPVoxSocket[] sockets = new NPVoxSocket[sourceModel.Sockets.Length];
        for (int i = 0; i < sockets.Length; i++)
        {
            NPVoxSocket socket = sourceModel.Sockets[i];
            if (clampedBox.Contains(socket.Anchor))
            {
                // transform anchor
                Vector3 saveOriginalAnchor = NPVoxCoordUtil.ToVector(socket.Anchor);
                Vector3 saveTargetAnchor   = transformMatrix.MultiplyPoint(saveOriginalAnchor) + NPVoxCoordUtil.ToVector(offset);
                socket.Anchor = NPVoxCoordUtil.ToCoord(saveTargetAnchor);

                // transform Quaternion
                Quaternion originalRotation = Quaternion.Euler(socket.EulerAngles);
                Matrix4x4  rotated          = (Matrix4x4.TRS(Vector3.zero, originalRotation, Vector3.one) * transformMatrix);
                socket.EulerAngles = Matrix4x4Util.GetRotation(rotated).eulerAngles;
            }
            else
            {
                socket.Anchor = socket.Anchor + offset;
            }
            sockets[i] = socket;
        }
        transformedModel.Sockets = sockets;


        // 5. count all voxels
        transformedModel.NumVoxels = transformedModel.NumVoxels - (conflictVoxels.Count - numberOfConflictsSolved);
        transformedModel.RecalculateNumVoxels(true);
        return(transformedModel);
    }
Пример #8
0
    public static NPVoxModel Read(BinaryReader stream, NPVoxModel reuse = null)
    {
        NPVoxModel voxModel = null;

        Color32[] colors = null;

        // check out http://voxel.codeplex.com/wikipage?title=VOX%20Format&referringTitle=Home for the file format used below
        string magic = new string(stream.ReadChars(4));

        stream.ReadInt32(); // version

        // a MagicaVoxel .vox file starts with a 'magic' 4 character 'VOX ' identifier
        if (magic == "VOX ")
        {
            while (stream.BaseStream.Position < stream.BaseStream.Length)
            {
                // each chunk has an ID, size and child chunks
                char[] chunkId   = stream.ReadChars(4);
                int    chunkSize = stream.ReadInt32();
                stream.ReadInt32(); // childChunks
                string chunkName = new string(chunkId);

                // there are only 2 chunks we only care about, and they are SIZE and XYZI
                if (chunkName == "SIZE")
                {
                    sbyte x = (sbyte)stream.ReadInt32();
                    sbyte y = (sbyte)stream.ReadInt32();
                    sbyte z = (sbyte)stream.ReadInt32();
                    voxModel = (NPVoxModel)NPVoxModel.NewInstance(new NPVoxCoord(x, y, z), reuse);
                    stream.ReadBytes(chunkSize - 4 * 3); // ???
                }
                else if (chunkName == "XYZI")
                {
                    // XYZI contains n voxels
                    int numVoxels = stream.ReadInt32();
                    voxModel.NumVoxels = numVoxels;
                    for (int i = 0; i < numVoxels; i++)
                    {
                        voxModel.SetVoxel(new NPVoxCoord(stream.ReadSByte(), stream.ReadSByte(), stream.ReadSByte()), stream.ReadByte());
                    }
                }
                else if (chunkName == "RGBA")
                {
                    colors    = new Color32[256];
                    colors[0] = new Color32(0, 0, 0, 0);

                    for (int i = 1; i < 256; i++)
                    {
                        byte r = stream.ReadByte();
                        byte g = stream.ReadByte();
                        byte b = stream.ReadByte();
                        byte a = stream.ReadByte();
                        colors[i] = new Color32(r, g, b, a);
                    }
                    stream.ReadBytes(4); // read the last color 256 which is not used
                }
                else
                {
                    stream.ReadBytes(chunkSize);    // read any excess bytes
                }
            }

            voxModel.Colortable = colors != null ? colors : DEFAULT_VOX_COLORS;
        }

        return(voxModel);
    }