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); }
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))); }
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); }
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); }
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); }