vengi-voxel / vengi

free and open source voxel art tools - editor, thumbnailer and format converter
http://vengi-voxel.github.io/vengi/
Other
1.11k stars 91 forks source link

VOXELFORMAT: VXL: animations broken due to flipped axis between C&C and vengi #181

Closed mgerhardy closed 8 months ago

mgerhardy commented 2 years ago

Code is in https://github.com/mgerhardy/vengi/tree/master/src/modules/voxelformat/private/commandconquer

—-

from the c&c mod haven discord:


i see in code you have matrix[col][row], Westwood's Matrix3D is Vector4 Row[3];, so row col

it's z up, x forward, y left (3dsmax coord system)


//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
//      File: VXL.bt
//   Purpose: Parses Westwood Voxel files.
// File Mask: *.vxl
//------------------------------------------------
struct Vector4
{
    float X;
    float Y;
    float Z;
    float W;
};

struct Vector3
{
    float X;
    float Y;
    float Z;
};

struct Matrix3D
{
    Vector4 Row[3];
};

struct VoxelHeader
{
    unsigned char Name[16];
    int PaletteCount;
    int LayerCount;
    int LayerInfoCount;
    int DataSize;
};

struct VoxelLayerHeader
{
    char Name[16];
    int InfoIndex;
    int field_14;
    unsigned char field_18;
    unsigned char pad[3];
};

struct VoxelLayerInfo
{
    int StartOffset;
    int EndOffset;
    int DataOffset;
    float Scale;
    Matrix3D Transform;
    Vector3 MinBounds;
    Vector3 MaxBounds;
    unsigned char SizeX;
    unsigned char SizeY;
    unsigned char SizeZ;
    unsigned char NormalType;
};

struct VoxelCubeStruct
{
    unsigned char ColorIndex;
    unsigned char NormalIndex;
};

struct VoxelPalette {
    char startPaletteRemap;
    char endPaletteRemap;
    char palette[256*3]; 
};

when the game draws a voxel it does this scaling for hva matrixes

void __thiscall MotionLibraryClass::Scale(MotionLibraryClass *this, float scale)
{
    unsigned int f; // esi
    unsigned int l; // eax
    unsigned int j; // edx
    int v5; // eax
    int v6; // eax

    f = 0;
    if ( this->FrameCount )
    {
        do
        {
            l = this->LayerCount;
            j = 0;
            if ( l )
            {
                do
                {
                    this->Matrixes[j + f * l].Row[0].W = scale * this->Matrixes[j + f * l].Row[0].W;
                    v5 = j + this->LayerCount * f;
                    this->Matrixes[v5].Row[1].W = scale * this->Matrixes[v5].Row[1].W;
                    v6 = j++ + this->LayerCount * f;
                    this->Matrixes[v6].Row[2].W = scale * this->Matrixes[v6].Row[2].W;
                    l = this->LayerCount;
                }
                while ( j < l );
            }
            ++f;
        }
        while ( f < this->FrameCount );
    }
}

not that min max stuff you had, scale is always Scale from layer info


also in case you would want to display ingame preview: https://github.com/secsome/CncVxlRenderText

this is YR VXL code

mgerhardy commented 2 years ago

https://github.com/hathlife/voxel_section_editor

mgerhardy commented 2 years ago

found in voxel_section_editor HVA.pas


// This function converts the Westwood coordinates into OpenGL's
// (x,y,z) becomes (y,z,x)
procedure THVA.WestwoodToOpenGLCoordinates;
var
   i : integer;
   Temp: single;
begin
   for i := Low(TransformMatrices) to High(TransformMatrices) do
   begin
      Temp := TransformMatrices[i][1][1];
      TransformMatrices[i][1][1] := TransformMatrices[i][2][2];
      TransformMatrices[i][2][2] := TransformMatrices[i][3][3];
      TransformMatrices[i][3][3] := Temp;
      Temp := TransformMatrices[i][1][2];
      TransformMatrices[i][1][2] := TransformMatrices[i][2][3];
      TransformMatrices[i][2][3] := TransformMatrices[i][3][1];
      TransformMatrices[i][3][1] := Temp;
      Temp := TransformMatrices[i][1][3];
      TransformMatrices[i][1][3] := TransformMatrices[i][2][1];
      TransformMatrices[i][2][1] := TransformMatrices[i][3][2];
      TransformMatrices[i][3][2] := Temp;
      Temp := TransformMatrices[i][1][4];
      TransformMatrices[i][1][4] := TransformMatrices[i][2][4];
      TransformMatrices[i][2][4] := TransformMatrices[i][3][4];
      TransformMatrices[i][3][4] := Temp;
   end;
end;

// This function converts the OpenGL coordinates into Westwood's
// (x,y,z) becomes (z,x,y)
procedure THVA.OpenGLToWestwoodCoordinates;
var
   i : integer;
   Temp: single;
begin
   for i := Low(TransformMatrices) to High(TransformMatrices) do
   begin
      Temp := TransformMatrices[i][1][1];
      TransformMatrices[i][1][1] := TransformMatrices[i][3][3];
      TransformMatrices[i][3][3] := TransformMatrices[i][2][2];
      TransformMatrices[i][2][2] := Temp;
      Temp := TransformMatrices[i][1][2];
      TransformMatrices[i][1][2] := TransformMatrices[i][3][1];
      TransformMatrices[i][3][1] := TransformMatrices[i][2][3];
      TransformMatrices[i][2][3] := Temp;
      Temp := TransformMatrices[i][1][3];
      TransformMatrices[i][1][3] := TransformMatrices[i][3][2];
      TransformMatrices[i][3][2] := TransformMatrices[i][2][1];
      TransformMatrices[i][2][1] := Temp;
      Temp := TransformMatrices[i][1][4];
      TransformMatrices[i][1][4] := TransformMatrices[i][3][4];
      TransformMatrices[i][3][4] := TransformMatrices[i][2][4];
      TransformMatrices[i][2][4] := Temp;
   end;
end;
mgerhardy commented 2 years ago

TVoxelSection.WestwoodToOpenGLCoordinates

mgerhardy commented 2 years ago

file: hva.hexpat

struct vec4_s {
    float x [[color("FF0000")]];
    float y [[color("00FF00")]];
    float z [[color("0000FF")]];
    float w [[color("FFFF00")]];
};

struct mat3x4_s {
    vec4_s row[3];
};

struct name_s {
    char buffer[16] [[color("EECCCC")]];
};

struct hva_s {
    name_s name;
    u32 numFrames;
    u32 numNodes;
    name_s nodeNames[numNodes];
};

struct frame_s {
    mat3x4_s mat[hva.numNodes];
};

hva_s hva @0x00;
frame_s frames[hva.numFrames] @sizeof(hva);

imhex hva pattern.

mgerhardy commented 2 years ago

https://www.gamedev.net/forums/topic/209830-converting-coordinate-systems-3ds-max-gtopengl/

mgerhardy commented 2 years ago

https://youtu.be/Hp3RJ1ZlxPs

mgerhardy commented 1 year ago

https://github.com/OpenRA/OpenRA/issues/4113

// Min/MaxBounds Fixed! - Stucuk
procedure TVoxelSection.DefaultTransforms;
const
   C_WWDET = 1/12;
var
   i, j: integer;
begin
   Tailer.Det := C_WWDET;

   for i := 1 to 3 do
      for j := 1 to 3 do // from memory, don't think this transform is ever used.
         if i = j then
            Tailer.Transform[i,j] := 1
         else
            Tailer.Transform[i,j] := 0;

   Tailer.MaxBounds[1] := (Tailer.XSize / 2);
   Tailer.MaxBounds[3] := (Tailer.ZSize / 2);
   Tailer.MinBounds[1] := 0 - (Tailer.XSize / 2);
   Tailer.MinBounds[3] := 0 - (Tailer.ZSize / 2);

   if VoxelType = vtAir then
   begin
      Tailer.MaxBounds[2] := (Tailer.YSize / 2);
      Tailer.MinBounds[2] := 0 - (Tailer.YSize / 2);
   end
   else
   begin
      Tailer.MaxBounds[2] := Tailer.YSize;
      Tailer.MinBounds[2] := 0;
   end;
end;
mgerhardy commented 8 months ago

TEST_F(ConvertTest, DISABLED_testVengiToVXL) was added in bb3791b37c7385858dc73a37b8f9368e251cb812

mgerhardy commented 8 months ago

loading of hmec is working now - saving still has issues left. and even though hmec is loading and animating fine, there are other models that are still shifted (maybe again pivot related...)

mgerhardy commented 8 months ago

cd3eb2a491f287b50c5336c076b2498e59973883 and a few around this one fixed the issue