ephtracy / voxel-model

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Translation and rotation format

spaarmann opened this issue · comments

Hi there.

While writing a parser for the .vox files, I discovered that the documentation doesn't quite match what MagicaVoxel actually produces for the translation and rotation of nTRN chunks.
(Tested in the most recent, unstable 0.99.5).

(_r : int8) ROTATION, see (c)
(_t : int32x3) translation

Both of these are actually ASCII encoded versions of what they describe.

For the translation, instead of just three int32 packed after each other, there is a string of the format "x y z", i.e. the three integers encoded as ASCII and separated by a space.

Similarly, for the rotation, instead of a single byte, there is a string containing a decimal representation of that byte which then matches the format described in the documentation:

(c) ROTATION type
store a row-major rotation in the bits of a byte
for example :
R =
0 1 0
0 0 -1
-1 0 0
==>
unsigned char _r = (1 << 0) | (2 << 2) | (0 << 4) | (1 << 5) | (1 << 6)
bit | value
0-1 : 1 : index of the non-zero entry in the first row
2-3 : 2 : index of the non-zero entry in the second row
4 : 0 : the sign in the first row (0 : positive; 1 : negative)
5 : 1 : the sign in the second row (0 : positive; 1 : negative)
6 : 1 : the sign in the third row (0 : positive; 1 : negative)

As an example,

0 -1 0
1  0 0
0  0 1

is packed into 0b0010001 which is then written into the file as the string "17", i.e. the bytes 0x31 0x37.

Hope this helps anybody stumbling across the same issue, or that @ephtracy perhaps updates the repository to include this information.

@spaarmann yeah, I documented that in my pull request #33, I’m waiting on @ephtracy’s feedback ☺️

Ah, I didn't see that. I searched through the issues here, but not the PRs, I really wish I would've done that, would've saved me some time :)

I also just realized the documentation does say that DICT values are strings, so it's not exactly wrong... Still think it'd be nice to make this a bit more explicit though.

Yeah, I suppose I can edit that, what should exactly clarify? That these are in ASCII?

Sorry, this

I also just realized the documentation does say that DICT values are strings, so it's not exactly wrong... Still think it'd be nice to make this a bit more explicit though.

was commenting on the current text in the repository, not the text in your PR :)

Ahhh, thanks for clarifying 😅

I'm trying to apply the flip (rotation) in my VOX importer (C#, Unity) and stumbled over this issue.
I already figured out the (_r) dictionary value is made up of two bytes - but what does that actually mean for the "byte-encoded" rotation? Is the second byte to be discarded, how does it relate to the table of bit/value's in the documentation?

I'm also trying to figure out how to apply the rotation, I'm a really rusty on the math.
If I have to apply this rotation to every voxel in my model, could you give me a hint on how the formula needs to look?
(I'm sitting over the Math Primer by Dunn & Parberry, but I just can't map this to the solutions in the book)

               [rx1, ry1, rz1]
[x1, y1, z1] * [rx2, ry2, rz2] = ?
               [rx3, ry3, rz3]

I'm trying to apply the flip (rotation) in my VOX importer (C#, Unity) and stumbled over this issue.
I already figured out the (_r) dictionary value is made up of two bytes - but what does that actually mean for the "byte-encoded" rotation? Is the second byte to be discarded, how does it relate to the table of bit/value's in the documentation?

I'm also trying to figure out how to apply the rotation, I'm a really rusty on the math.
If I have to apply this rotation to every voxel in my model, could you give me a hint on how the formula needs to look?
(I'm sitting over the Math Primer by Dunn & Parberry, but I just can't map this to the solutions in the book)

               [rx1, ry1, rz1]
[x1, y1, z1] * [rx2, ry2, rz2] = ?
               [rx3, ry3, rz3]

@TomWor, I replied to you in the comments on my PR with this code excerpt. I think this wouldn’t be too hard convert to C#.

@mchorse I converted your code to C# and it seems to work, thanks!
Do you by any chance have a link or something on how to apply the rotation?

@mchorse I converted your code to C# and it seems to work, thanks!

No problem!

Do you by any chance have a link or something on how to apply the rotation?

Well, when you'll be constructing a mesh, you'll need to transform your vertices through the transformation matrix, that's how I do it (this.transform should be the rotation matrix that was parsed from the rotation byte).

I found this to be a good explanation of what I needed:
https://computergraphics.stackexchange.com/questions/5232/row-and-column-majored-rotation-matrix-pre-or-post-multiplied

The mesh geometry is flipped/rotated fine now, only now the translation seems a little off (applying before or after rotation?) and my Normals are flipped. But it looks like I'm getting there.

I found this to be a good explanation of what I needed:
https://computergraphics.stackexchange.com/questions/5232/row-and-column-majored-rotation-matrix-pre-or-post-multiplied

The mesh geometry is flipped/rotated fine now, only now the translation seems a little off (applying before or after rotation?) and my Normals are flipped. But it looks like I'm getting there.

As far as I remember, you need to apply matrix transformations from the mid point of the voxel chunk. I.e. if you have 16^3 object, you need to apply transformations relative to (8,8,8).

You're right. With translations I was able to get around that issue easily so far, but with flip and rotate it's a whole different story. So much so that I think I have to restructure my importer to cleanly integrate it.

commented

using DeepCore;
using DeepCore.Reflection;
using DeepCore.Voxel.Data;
using DeepCore.Voxel.Extensions.MagicaVoxel;
using DeepEditor.Common.G2D;
using DeepEditor.Common.G2D.DataGrid;
using DeepEditor.Common.Voxel;
using System;
using System.IO;
using System.Windows.Forms;

namespace SampleBattle2D.Win32
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ViewVOX(@"E:\dev\DeepWorkspace\DeepSamples2D\SampleEditors\GameEditor\voxel\MagicaVoxel\untitled.vox");
}
public static void ViewVOX(string path)
{
var file = new FileInfo(path);
var vox = MagicaVoxelFile.Load(file);
var world = vox.ConvertToVoxelWorld();
var dialog = new FormVoxelViewer();
dialog.Load += (s, e) =>
{
dialog.LoadVoxelWorld(world);
};
Application.Run(dialog);
}
}
}

commented

image
image
Why this Shape Translatoin X is 1 ?