Code:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Security.Permissions;
using static Zlib.Zlib;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SKINEFFECT_FOR_GXD
{
public bool mCheckTwoSide;
public bool mCheckRadiation;
public float mRadiationSpeed;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public float[] mRadiationLowLimit;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public float[] mRadiationHighLimit;
public bool mCheckLightBright;
public bool mCheckCameraSpecularEffect;
public int mCameraSpecularEffectSort;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public float[] mCameraSpecularEffectMaterialValue;
public float mCameraSpecularEffectMaterialPower;
public float mCameraSpecularEffectLightAddValue;
public bool mCheckTextureAnimation;
public float mTextureAnimationSpeed;
public bool mCheckUVScroll1;
public int mUVScrollSort1;
public float mUVScrollSpeed1;
public bool mCheckBillboard;
public int mBillboardSort;
public bool mCheckUVScroll2;
public int mUVScrollSort2;
public float mUVScrollSpeed2;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SKINSIZE_FOR_GXD
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] float[] mBoxMin;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] float[] mBoxMax;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] float[] mCenter;
float mRadius;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SKINWEIGHT_FOR_GXD
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public int[] mBoneIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public float[] mBlendValue;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TRIS_FOR_GXD
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public ushort[] a;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SKINVERTEX_FOR_GXD
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] mV;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] mN;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public float[] mT;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WORLDVERTEX_FOR_GXD
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] mV;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] mN;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public float[] mT1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public float[] mT2;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WORLDTRIS_FOR_GXD
{
public int mTextureIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public WORLDVERTEX_FOR_GXD[] mVertex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public float[] mPlaneInfo;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public float[] mSphereInfo;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct QUADTREENODE_FOR_GXD
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] mBoxMin;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] mBoxMax;
public int mTrisNum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public int mTrisIndex;//int *mTrisIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public int[] mChildNodeIndex;
}
class TEXTURE_FOR_GXD
{
private bool CheckTwoPowerNumber( int tNumber ){ return true; }
public bool mCheckValidState;
public int mFileDataSize;
public byte[] mFileData;
public Texture2D mTextureInfo;
public int mProcessModeCase;
public int mAlphaModeCase;
public int mOrgAlphaModeCase;
public bool mUseSharedMaterial;
public void OnDestroy(){}
public void Init(){ mCheckValidState = false; }
public void Free(){}
public bool LoadFromTGA( byte[] tFileName, int tProcessModeCase, bool tCheckCreateTexture, bool tCheckRemoveFileData ){ return true; }
public bool LoadFromDDS( byte[] tFileName, int tProcessModeCase, bool tCheckCreateTexture, bool tCheckRemoveFileData ){ return true; }
public bool SaveToTGA( byte[] tFileName ){ return true; }
public bool SaveToDDS( byte[] tFileName ){ return true; }
public bool Save( FileStream hFile ){ return true; }
public bool Load( byte[] tData, ref int tPosition )//FileStream hFile, bool tCheckCreateTexture, bool tCheckRemoveFileData )
{
if( tData.Length - tPosition < 16 )
{
return false;
}
int DDSHeaderSize = 128;
int height;
int width;
byte[] dxtBytes;
string dxtFormat;
TextureFormat textureFormat;
int tCheckSize = BitConverter.ToInt32( tData, tPosition );
int tOriginalSize = BitConverter.ToInt32( tData, tPosition + 4 );
int tCompressSize = BitConverter.ToInt32( tData, tPosition + 8 );
Debug.Log($"TEXTURE_FOR_GXD Position:{tPosition}");
if( tCheckSize + 8 != tOriginalSize )
{
mUseSharedMaterial = true;
return false;
}
tPosition = tPosition + 12;
ZLIB_FOR_GXD tUncompress = Decompress( tData, ref tPosition, tOriginalSize, tCompressSize );
mFileData = tUncompress.mOriginalData;
int ddsSizeCheck = mFileData[4];
if (ddsSizeCheck != 124)
{
//File.WriteAllBytes( $"test_{tPosition}.hex", mFileData );
Debug.LogErrorFormat($"not DDS DXT texture.{mFileData[4]},{mFileData[3]}");
return false;
}
dxtFormat = System.Text.Encoding.ASCII.GetString( mFileData, 84, 4 );
if( dxtFormat.Contains("DXT1") )
textureFormat = TextureFormat.DXT1;
else if( dxtFormat.Contains("DXT3") || dxtFormat.Contains("DXT5") )
textureFormat = TextureFormat.DXT5;
else
throw new System.Exception($"Invalid DDS DXT format., input format:{dxtFormat}");
height = mFileData[13] * 256 + mFileData[12];
width = mFileData[17] * 256 + mFileData[16];
dxtBytes = new byte[mFileData.Length - DDSHeaderSize];
System.Buffer.BlockCopy(mFileData, DDSHeaderSize, dxtBytes, 0, mFileData.Length - DDSHeaderSize);
mTextureInfo = new Texture2D(width, height, textureFormat, false);
//texture.alphaIsTransparency = true;
mTextureInfo.wrapMode = TextureWrapMode.Repeat;
mTextureInfo.LoadRawTextureData(dxtBytes);
mTextureInfo.Apply();
#if DEBUG
Debug.Log( $"TEXTURE_FOR_GXD({mTextureInfo.format}) Success." );
#endif
mCheckValidState = true;
return true;
}
public bool Load( byte[] tData )//FileStream hFile, bool tCheckCreateTexture, bool tCheckRemoveFileData )
{
if( tData.Length < 128 )
{
return false;
}
int DDSHeaderSize = 128;
int height;
int width;
byte[] dxtBytes;
string dxtFormat;
TextureFormat textureFormat;
mFileData = tData;
int ddsSizeCheck = mFileData[4];
if (ddsSizeCheck != 124)
{
Debug.LogErrorFormat($"not DDS DXT texture.{mFileData[4]},{mFileData[3]}");
return false;
}
dxtFormat = System.Text.Encoding.ASCII.GetString( mFileData, 84, 4 );
if( dxtFormat.Contains("DXT1") )
textureFormat = TextureFormat.DXT1;
else if( dxtFormat.Contains("DXT3") || dxtFormat.Contains("DXT5") )
textureFormat = TextureFormat.DXT5;
else
throw new System.Exception($"Invalid DDS DXT format., input format:{dxtFormat}");
height = mFileData[13] * 256 + mFileData[12];
width = mFileData[17] * 256 + mFileData[16];
dxtBytes = new byte[mFileData.Length - DDSHeaderSize];
System.Buffer.BlockCopy(mFileData, DDSHeaderSize, dxtBytes, 0, mFileData.Length - DDSHeaderSize);
mTextureInfo = new Texture2D(width, height, textureFormat, false);
//texture.alphaIsTransparency = true;
mTextureInfo.wrapMode = TextureWrapMode.Repeat;
mTextureInfo.LoadRawTextureData(dxtBytes);
mTextureInfo.Apply();
#if DEBUG
Debug.Log( $"TEXTURE_FOR_GXD({mTextureInfo.format}) Success." );
#endif
mCheckValidState = true;
return true;
}
public bool Skip( FileStream hFile ){ return true; }
public void Create( bool tCheckRemoveFileData ){}
public void Delete(){}
}
class SKIN_FOR_GXD
{
//private SKINVERTEX_FOR_GXD mVertexBufferForBillboard[4];
private bool mCheckChangeNormalState;
//private D3DXVECTOR3 mScaleValue;
private SKINSIZE_FOR_GXD mSize;
//private D3DXMATRIX[] mScaleKeyMatrix;
public bool mCheckValidState;
public SKINEFFECT_FOR_GXD mEffect;
public int mVertexNum;
public int mUVNum;
public int mWeightNum;
public int mTrisNum;
public Vector3[] mVertex;
public Vector3[] mNormal;
public Vector2[] mUV;
public Vector3[] mWeight;
public int[] mTris;
public SKINVERTEX_FOR_GXD[] mVertexBuffer;
public SKINWEIGHT_FOR_GXD[] mWeightBuffer;
public TRIS_FOR_GXD[] mTrisBuffer;
public ushort[] mIndexBuffer;
public float[] mMotionVertex;
public float[] mMotionNormal;
public List<TEXTURE_FOR_GXD> mTexture = new List<TEXTURE_FOR_GXD>();
public SKIN_FOR_GXD(){}
public void Init(){ mCheckValidState = false; }
public void Free(){ mCheckValidState = false; mTexture[0] = mTexture[1] = null; }
public void Load( byte[] tData, ref int tPosition, bool tCheckCreateTexture )
{
AGAIN:
if( tData.Length - tPosition < 16 )
{
return;
}
int tCheckFile = BitConverter.ToInt32( tData, tPosition );
int tOriginalSize = BitConverter.ToInt32( tData, tPosition + 4 );
int tCompressSize = BitConverter.ToInt32( tData, tPosition + 8 );
Debug.Log( $"{tOriginalSize},{tCompressSize},{tPosition}" );
if( tCheckFile == 0 )
{
tPosition = tPosition + 4;
goto AGAIN;
}
if( tCheckCreateTexture && ( tCheckFile + 8 == tOriginalSize ) )
{
goto LOADTEXURE;
}
tPosition = tPosition + 12;
ZLIB_FOR_GXD tUncompress = Decompress( tData, ref tPosition, tOriginalSize, tCompressSize );
mEffect = StructFromByte<SKINEFFECT_FOR_GXD>( tUncompress.mOriginalData );//get mEffect at position 0 = length 120
mVertexNum = BitConverter.ToInt32( tUncompress.mOriginalData, 120 ); //get mWeightNum at byte position 120
mUVNum = BitConverter.ToInt32( tUncompress.mOriginalData, 124 ); //get mWeightNum at byte position 124
mWeightNum = BitConverter.ToInt32( tUncompress.mOriginalData, 128 ); //get mWeightNum at byte position 128
mTrisNum = BitConverter.ToInt32( tUncompress.mOriginalData, 132 ); //get mTrisNum at byte position 132
mSize = StructFromBytePosition<SKINSIZE_FOR_GXD>( tUncompress.mOriginalData, 136 );//get mEffect at position 0 > length 120
int mSkinV = 120 + 16 + 40;
int mSkinM = mSkinM = mSkinV + ( mVertexNum * GetStructSize<SKINVERTEX_FOR_GXD>() );
int mSkinT = mSkinM + ( mVertexNum * GetStructSize<SKINVERTEX_FOR_GXD>() );
mVertexBuffer = StructFromByte<SKINVERTEX_FOR_GXD>( tUncompress.mOriginalData, mSkinV, mVertexNum );
mWeightBuffer = StructFromByte<SKINWEIGHT_FOR_GXD>( tUncompress.mOriginalData, mSkinM, mWeightNum );
mTrisBuffer = StructFromByte<TRIS_FOR_GXD>( tUncompress.mOriginalData, mSkinT, mTrisNum );
//Debug.Log("vertex:"+sobject.mVertexNum+",tris:"+sobject.mTrisNum);
//mMotionVertex = new float[mWeightNum];
mVertex = new Vector3[mVertexNum];
mNormal = new Vector3[mVertexNum];
mUV = new Vector2[mVertexNum];
mTris = new int[( mTrisNum * 3 )];
for( int i = 0; i < mVertexNum; i++ )
{
mVertex[i] = new Vector3( mVertexBuffer[i].mV[0], mVertexBuffer[i].mV[1], mVertexBuffer[i].mV[2] );
mNormal[i] = new Vector3( mVertexBuffer[i].mN[0], mVertexBuffer[i].mN[1], mVertexBuffer[i].mN[2] );
mUV[i] = new Vector2( mVertexBuffer[i].mT[0], mVertexBuffer[i].mT[1] );
}
for( int i = 0; i < mTrisNum; i++ )
{
for( int j = 0; j < 3; j++)
{
mTris[( i * 3 + j )] = mTrisBuffer[i].a[j];
}
}
LOADTEXURE:
mTexture.Add( new TEXTURE_FOR_GXD() );
mTexture.Add( new TEXTURE_FOR_GXD() );
mTexture[0].Init();
if( !mTexture[0].Load( tData, ref tPosition ) )
{
//mTexture[0] //fail = set shared material
}
if( !mTexture[1].Load( tData, ref tPosition ) )
{
//mTexture[0] //fail = set shared material
}
mCheckValidState = true;
}
public Mesh mesh = new Mesh();
SkinnedMeshRenderer smr;
public void Draw( int tDrawSort, TEXTURE_FOR_GXD tTexture, GameObject gameOBJ )
{
if( !mCheckValidState )
{
return;
}
Material material;
if( tDrawSort == 0 )
{
material = new Material(Shader.Find("Unlit/Transparent Cutout"));
material.mainTexture = tTexture.mTextureInfo;
//if( mesh == null )
{
mesh.name = "Mesh";
mesh.vertices = mVertex;
mesh.normals = mNormal;
mesh.uv = mUV;
mesh.triangles = mTris;
mesh.RecalculateBounds();
;
}
smr = gameOBJ.GetComponent<SkinnedMeshRenderer>();
if( smr == null )
{
smr = gameOBJ.AddComponent<SkinnedMeshRenderer>();
}
smr.sharedMesh = mesh;
smr.material = material;
}
else
{
}
}
}
class SOBJECT_FOR_GXD : MonoBehaviour
{
public bool mCheckValidState;
public int mSkinNum;
public List<SKIN_FOR_GXD> mSkin = new List<SKIN_FOR_GXD>();
public SOBJECT_FOR_GXD(){}
public void Init(){ mCheckValidState = false; mSkin = null; }
public void Free()
{
mCheckValidState = false;
if( mSkinNum > 0 )
{
for( int i = 0; i < mSkinNum; i++ )
{
mSkin[i].Free();
mSkin[i] = null;
}
}
}
public bool CreateWithBlankSkin( int tSkinNum ){ return true; }
public bool Save( string tFileName ){ return true; }
public bool Load( string tFileName )//, bool tCheckCreateTexture, bool tCheckRemoveFileData)
{
if( !File.Exists(tFileName) )
{
Debug.LogErrorFormat( $"<color=red>File Not Found :</color> {tFileName}" );
return false;
}
int tPosition = 0;
byte[] tData = File.ReadAllBytes(tFileName);
mSkinNum = BitConverter.ToInt32( tData, 0 );
tPosition = tFileName.Contains("SOBJECT") ? 4 : 0;
for( int i = 0; i < mSkinNum; i++ )
{
mSkin.Add( new SKIN_FOR_GXD() );
mSkin[i].Init();
mSkin[i].Load( tData, ref tPosition, true );
}
mCheckValidState = true;
return true;
}
public void CreateTexture( bool tCheckRemoveFileData ){}
public void DeleteTexture(){}
//void Draw( int tDrawSort, float tFrame, float tCoord[3], float tAngle[3], float tPostTimeForEffect, TEXTURE_FOR_GXD *tTexture, BOOL tCheckDrawCameraSpecularEffect, MOTION_FOR_GXD *tMotion, float tRangeForCulling, BOOL tCheckShadow, void *tWorld, BOOL tCheckCalculateNormal, float tValidShadowLength );
//void DrawForSelect( int tSelectSkinIndex, float tFrame, float tCoord[3], float tAngle[3], MOTION_FOR_GXD *tMotion, float tRangeForCulling );
//void GetSkinCoord( int tSelectSkinIndex, float tFrame, float tCoord[3], float tAngle[3], MOTION_FOR_GXD *tMotion, float tSkinCoord[3] );
public bool SetScale( float x, float y, float z ){ return true; }
public void Draw( GameObject gameOBJ )
{
if( !mCheckValidState )
{
return;
}
GameObject mMODEL = new GameObject("MODEL");
mMODEL.transform.parent = gameOBJ.transform;
for( int i = 0; i < mSkinNum; i++ )
{
if( mSkin[i].mCheckValidState )
{
GameObject go = new GameObject( name : "mSkin" + i );
go.transform.parent = mMODEL.transform;
if( mSkin[i].mTexture[0].mUseSharedMaterial )
{
mSkin[i].Draw( 0, mSkin[0].mTexture[0], go );
}
else
{
foreach( var item in mSkin[i].mTexture )
{
if( item != null )
{
mSkin[i].Draw( 0, mSkin[i].mTexture[0], go );
mSkin[i].Draw( 1, mSkin[i].mTexture[1], go );
}
}
}
}
}
}
}
public class MOBJECT_FOR_GXD
{
//private D3DXVECTOR3 mScaleValue; /** Scaling ���� */
//private float GetMaxScaleValue_(); /** Scaling ����(Scale_X, Scale_Y, Scale_Z) �� ���� ū ���� ��ȯ�ϴ� �Լ�. */
public bool mCheckValidState;
public ushort m_wMajorVersion;
public ushort m_wMinorVersion;
public int mMeshNum;
//public MESH_FOR_GXD *mMesh;
//public MESHSIZE_FOR_GXD *mSize;
public MOBJECT_FOR_GXD(){}
public void Init(){}
public void Free(){}
public bool CreateWithBlankMesh( int tMeshNum ){ return true; }
public bool Save( string tFileName ){ return true; }
public bool Save( FileStream hFile ){ return true; }
public bool Load( string tFileName, bool tCheckCreateTexture, bool tCheckRemoveFileData )
{
return true;
}
public bool Load( string tFileName, bool tCheckCreateTexture, bool tCheckRemoveFileData , ushort pLoadIndexes , ushort wLoadCount){ return true; }
public bool Load( FileStream hFile, bool tCheckCreateTexture, bool tCheckRemoveFileData ){ return true; }
//public void Draw( int tDrawSort, float tFrame, float[] tCoord, float[] tAngle float tPostTimeForEffect, TEXTURE_FOR_GXD *tTexture, bool tCheckDrawCameraSpecularEffect, byte tBlendValue ){}
//--------------------------------------------------------------------------------------------------------------------
// MeshForGXD���� �ѹ��� ���� ������ �̿��ϴ� MObject�� ���� ���� �Լ�
// 2010.12.09 : �輺��
//public void MultiDraw( int tDrawSort, LPMOBJECTINFO_FOR_MULTIDRAW MultiDrawInfo, TEXTURE_FOR_GXD *tTexture, bool tCheckDrawCameraSpecularEffect ){}
//--------------------------------------------------------------------------------------------------------------------
public void DrawForShadow( float tFrame, float[] tCoord, float[] tAngle ){}
public void DrawForSelect( int tSelectMeshIndex, float tFrame, float[] tCoord, float[] tAngle ){}
public bool GetMeshSize( float tFrame, float[] tCoord, float[] tAngle ){ return true; }
public bool TestCameraInMObject( float tFrame, float[] tCoord, float[] tAngle, float[] tCameraLook, float[] tCameraEye ){ return true; }
public bool SetScale(float x, float y, float z){ return true; } /** Scaling ����(mScaleValue) ���� �Լ�. */
//public bool GetMeshSizeAfterScale(int tMeshIndex, int tFrameNum, MESHSIZE_FOR_GXD *tResultSize){ return true; } /** Scaling ó���� �ϱ� ���� Mesh Size�� ��ȯ�ϴ� �Լ�. */
//public bool GetMeshSizeBeforeScale(int tMeshIndex, int tFrameNum, MESHSIZE_FOR_GXD *tResultSize); /** Scaling ó���� �� ���� Mesh Size�� ��ȯ�ϴ� �Լ�. */
public Vector3 GetScaleValue(){ return new Vector3(); } /** ���� ������ Scale ���� ��ȯ�ϴ� �Լ�. */
}
[ExecuteInEditMode]
public class WORLD_FOR_GXD : MonoBehaviour
{
string mFileName;
bool mCheckValidState;
int mLoadSort;
int mTextureNum;
List<TEXTURE_FOR_GXD> mTexture;
//IDirect3DTexture9 *mWaterWaveTexture;
TEXTURE_FOR_GXD mShadowTexture;
//int mG3WMeshNum;
//G3WMESH_FOR_GXD *mG3WMesh;
int mWorldTrisNum;
public WORLDTRIS_FOR_GXD[] mWorldTris;
int mMObjectNum;
//MOBJECT_FOR_GXD *mMObject;
//char *mMObjectFileName;
//int mMObjectInfoNum;
//MOBJECTINFO_FOR_GXD *mMObjectInfo;
//int mPSystemNum;
//PSYSTEM_FOR_GXD *mPSystem;
//char *mPSystemFileName;
//int mPObjectInfoNum;
//POBJECTINFO_FOR_GXD *mPObjectInfo;
int mTotalQuadtreeNodeNum;
int mMaxQuadtreeNodeLeafNum;
QUADTREENODE_FOR_GXD[] mQuadtree;
//int *mTextureTrisPostIndex;
////int mSaveDrawQuadtreeNodeNum;
//int *mSaveDrawQuadtreeNodeIndex;
//int *mSaveDrawWorldTrisFlag;
public MeshFilter meshFilter;
public bool ReloadMaterial;
public int ReloadMaterialNum;
private void Update() {
if(ReloadMaterial)
{
ReloadMaterial = false;
GetComponent<Renderer>().material.mainTexture = mMaterial[ReloadMaterialNum].mainTexture;
}
}
public bool LoadWG( string tFileName, bool tCheckCreateTexture, bool tCheckRemoveFileData, GameObject gameOBJ )
{
mFileName = string.Empty + tFileName;
mLoadSort = 0;
mGameObject = gameOBJ;
StartCoroutine(LoadWG());
//ZLIB2_FOR_GXD
//0 = Model
//1 = Texture Count
//2++ = Texture.DDS
//Last = Texture Config?
return true;
}
public bool LoadWM( string tFileName, GameObject gameOBJ )
{
mFileName = string.Empty + tFileName;
mLoadSort = 1;
mGameObject = gameOBJ;
StartCoroutine(LoadWM());
return true;
}
public bool LoadWO( string tFileName, bool tCheckCreateTexture, bool tCheckRemoveFileData ){ return true; }
IEnumerator LoadWG( )
{
meshFilter = mGameObject.AddComponent<MeshFilter>();
meshFilter.mesh = mesh = new Mesh();
skinnedMeshRenderer = mGameObject.AddComponent<SkinnedMeshRenderer>();
//step1 load model
float fire_start_time = Time.time;
int tPosition = 8;
byte[] tData = File.ReadAllBytes( mFileName );
int tOriginalSize = BitConverter.ToInt32( tData, 0 );
int tCompressSize = BitConverter.ToInt32( tData, 4 );
ZLIB_FOR_GXD tUncompress = Decompress( tData, ref tPosition, tOriginalSize, tCompressSize );
mWorldTrisNum = BitConverter.ToInt32( tUncompress.mOriginalData, 0 );
mWorldTris = StructFromByte<WORLDTRIS_FOR_GXD>( tUncompress.mOriginalData, 4, mWorldTrisNum );
mesh.name = "Zone " + 1 + " Mesh";
mesh.Clear();
//mWorldTris[0].mVertex = new WORLDVERTEX_FOR_GXD[3];
//mWorldTris[0].mVertex[0].mV = new float[3];
mWorldTrisNum *= 3;
int verticiesCount = mWorldTrisNum;
if ( verticiesCount >= 65536)
{
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
}
Debug.Log($"Triangles: {mWorldTrisNum / 3} Vertices: {mWorldTrisNum}");
int[] triangles = new int[mWorldTrisNum];
Vector3[] vertices = new Vector3[mWorldTrisNum];
Vector3[] normals = new Vector3[mWorldTrisNum];
Vector2[] uv = new Vector2[mWorldTrisNum];
Vector2[] uv2 = new Vector2[mWorldTrisNum];
//string[] saveTextureSlot = new string[mWorldTrisNum/3];
//Vector3 size = new Vector3( 1, 0, 1 );
GC.Collect();
for (int i = 0; i < mWorldTrisNum/3; i++)
{
//saveTextureSlot[i] = string.Empty + mWorldTris[i].mTextureIndex.ToString();
//Debug.Log($"Texture: {mWorldTris[i].mTextureIndex}");
for (int j = 0; j < 3; j++)
{
triangles[(i * 3 + j)] = (i * 3 + j);
vertices[(i * 3 + j)] = new Vector3( mWorldTris[i].mVertex[j].mV[0], mWorldTris[i].mVertex[j].mV[1], mWorldTris[i].mVertex[j].mV[2] );
normals[(i * 3 + j)] = new Vector3( mWorldTris[i].mVertex[j].mN[0], mWorldTris[i].mVertex[j].mN[1], mWorldTris[i].mVertex[j].mN[2] );
uv[(i * 3 + j)] = new Vector2( mWorldTris[i].mVertex[j].mT1[0], mWorldTris[i].mVertex[j].mT1[1] );
uv2[(i * 3 + j)] = new Vector2( mWorldTris[i].mVertex[j].mT2[0], mWorldTris[i].mVertex[j].mT2[1] );
}
/*GameObject go = new GameObject($"mPlaneInfo"+i);
go.transform.parent = gameObject.transform;
go.transform.localPosition = new Vector3( mWorldTris[i].mPlaneInfo[0], mWorldTris[i].mPlaneInfo[1], mWorldTris[i].mPlaneInfo[2] );
BoxCollider box = go.AddComponent<BoxCollider>();
box.size = size;
GameObject go2 = new GameObject($"mSphereInfo"+i);
go2.transform.parent = gameObject.transform;
go2.transform.localPosition = new Vector3( mWorldTris[i].mSphereInfo[0], mWorldTris[i].mSphereInfo[1], mWorldTris[i].mSphereInfo[2] );
BoxCollider box2 = go2.AddComponent<BoxCollider>();
box2.size = size;*/
}
//File.WriteAllLines("./textureList.txt", saveTextureSlot);
mesh.vertices = vertices;
mesh.normals = normals;
mesh.uv = uv;
mesh.uv2 = uv2;
mesh.triangles = triangles;
mesh.RecalculateBounds();
;
skinnedMeshRenderer.sharedMesh = mesh;
//step2 load texture
fire_start_time = Time.time;
int tLoadTextureCount = BitConverter.ToInt32( tData, tPosition );
Debug.Log( $"TextureCount{tLoadTextureCount}" );
tLoadTextureCount -= 1;
tPosition = tPosition + 4;
//byte[] tData = File.ReadAllBytes( mFileName );
mTexture = new List<TEXTURE_FOR_GXD>();
mMaterial = new List<Material>();
TEXTURE_FOR_GXD tTexture;
int tIsTexture;
int tPostOriginalSize;
tIsTexture = BitConverter.ToInt32( tData, tPosition + 0 );
do
{
if( tLoadTextureCount < 1 )
{
break;
}
if( tIsTexture == 0 )
{
tPostOriginalSize = BitConverter.ToInt32( tData, tPosition + 0 );
tOriginalSize = BitConverter.ToInt32( tData, tPosition + 4 );
tCompressSize = BitConverter.ToInt32( tData, tPosition + 8 );
if( tPostOriginalSize + 8 != tOriginalSize )
{
tPosition = tPosition + 4;
continue;
}
tPosition = tPosition + 12;
Debug.Log( $"CompressSize:{tCompressSize},OriginalSize:{tOriginalSize}" );
tUncompress = Decompress( tData, ref tPosition, tOriginalSize, tCompressSize );
File.WriteAllBytes( $"tPosition{(tPosition-tCompressSize)}.dds", tUncompress.mOriginalData );
tTexture = new TEXTURE_FOR_GXD();
if( tTexture.Load( tUncompress.mOriginalData ) )
{
Material mt = new Material( Shader.Find("Unlit/GXDEFFECT") );
mt.mainTexture = tTexture.mTextureInfo;
mMaterial.Add( mt );
}
tLoadTextureCount--;
}
} while( tPosition < tData.Length );
Debug.Log( $"LoadWG() elapsed time: {(Time.time - fire_start_time):F5}");
yield break;
}
public GameObject mGameObject;
Mesh mesh;
SkinnedMeshRenderer skinnedMeshRenderer;
public List<Material> mMaterial;
IEnumerator LoadWM()
{
mGameObject.AddComponent<MeshFilter>();
mGameObject.GetComponent<MeshFilter>().mesh = mesh = new Mesh();
skinnedMeshRenderer = mGameObject.AddComponent<SkinnedMeshRenderer>();
float fire_start_time = Time.time;
int tPosition = 8;
byte[] tData = File.ReadAllBytes( mFileName );
int tOriginalSize = BitConverter.ToInt32( tData, 0 );
int tCompressSize = BitConverter.ToInt32( tData, 4 );
ZLIB_FOR_GXD tUncompress = Decompress( tData, ref tPosition, tOriginalSize, tCompressSize );
mWorldTrisNum = BitConverter.ToInt32( tUncompress.mOriginalData, 0 );
mWorldTris = StructFromByte<WORLDTRIS_FOR_GXD>( tUncompress.mOriginalData, 4, mWorldTrisNum );
mesh.name = "Zone " + 1 + " Mesh";
mesh.Clear();
//mWorldTris[0].mVertex = new WORLDVERTEX_FOR_GXD[3];
//mWorldTris[0].mVertex[0].mV = new float[3];
mWorldTrisNum *= 3;
int verticiesCount = mWorldTrisNum;
if ( verticiesCount >= 65536)
{
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
}
Debug.Log($"Triangles: {mWorldTrisNum / 3} Vertices: {mWorldTrisNum}");
int[] triangles = new int[mWorldTrisNum];
Vector3[] vertices = new Vector3[mWorldTrisNum];
Vector3[] normals = new Vector3[mWorldTrisNum];
Vector2[] uv = new Vector2[mWorldTrisNum];
Vector2[] uv2 = new Vector2[mWorldTrisNum];
//string[] saveTextureSlot = new string[mWorldTrisNum/3];
//Vector3 size = new Vector3( 1, 0, 1 );
GC.Collect();
for (int i = 0; i < mWorldTrisNum/3; i++)
{
//saveTextureSlot[i] = string.Empty + mWorldTris[i].mTextureIndex.ToString();
//Debug.Log($"Texture: {mWorldTris[i].mTextureIndex}");
for (int j = 0; j < 3; j++)
{
triangles[(i * 3 + j)] = (i * 3 + j);
vertices[(i * 3 + j)] = new Vector3( mWorldTris[i].mVertex[j].mV[0], mWorldTris[i].mVertex[j].mV[1], mWorldTris[i].mVertex[j].mV[2] );
normals[(i * 3 + j)] = new Vector3( mWorldTris[i].mVertex[j].mN[0], mWorldTris[i].mVertex[j].mN[1], mWorldTris[i].mVertex[j].mN[2] );
uv[(i * 3 + j)] = new Vector2( mWorldTris[i].mVertex[j].mT1[0], mWorldTris[i].mVertex[j].mT1[1] );
uv2[(i * 3 + j)] = new Vector2( mWorldTris[i].mVertex[j].mT2[0], mWorldTris[i].mVertex[j].mT2[1] );
}
/*GameObject go = new GameObject($"mPlaneInfo"+i);
go.transform.parent = gameObject.transform;
go.transform.localPosition = new Vector3( mWorldTris[i].mPlaneInfo[0], mWorldTris[i].mPlaneInfo[1], mWorldTris[i].mPlaneInfo[2] );
BoxCollider box = go.AddComponent<BoxCollider>();
box.size = size;
GameObject go2 = new GameObject($"mSphereInfo"+i);
go2.transform.parent = gameObject.transform;
go2.transform.localPosition = new Vector3( mWorldTris[i].mSphereInfo[0], mWorldTris[i].mSphereInfo[1], mWorldTris[i].mSphereInfo[2] );
BoxCollider box2 = go2.AddComponent<BoxCollider>();
box2.size = size;*/
}
//File.WriteAllLines("./textureList.txt", saveTextureSlot);
mesh.vertices = vertices;
mesh.normals = normals;
mesh.uv = uv;
mesh.uv2 = uv2;
mesh.triangles = triangles;
mesh.RecalculateBounds();
;
skinnedMeshRenderer.sharedMesh = mesh;
Debug.Log($"{tData.Length-tPosition}");
Debug.Log( $"LoadWM() elapsed time: {(Time.time - fire_start_time):F5}");
yield break;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ZLIB_FOR_GXD
{
public int mOriginalSize;
public int mCompressSize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] mCompressData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] mOriginalData;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ZLIB2_FOR_GXD
{
public int mOriginalSize;
public int mCompressSize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] mCompressData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] mOriginalData;
public int mOffset;
public int mTextureCountForWorld;
}
namespace Zlib
{
public static class Zlib
{
public static ZLIB_FOR_GXD Decompress( byte[] bytes, ref int tPosition, int tOriginalSize, int tCompressSize )
{
ZLIB_FOR_GXD t = new ZLIB_FOR_GXD();
//int tOriginalSize = BitConverter.ToInt32( bytes, tPosition + 0 );// read original size
//int tCompressSize = BitConverter.ToInt32( bytes, tPosition + 4 );// read compress size
byte[] data = new byte[ 8 + 8 ]; //int(compressSize) + int(originalSize) + byte[](compressData)
#if DEBUG
Debug.Log( $"CompressSize:{tCompressSize},OriginalSize:{tOriginalSize}" );
#endif
Array.Copy( bytes, tPosition, data, 0, data.Length );
System.Runtime.InteropServices.GCHandle handle = System.Runtime.InteropServices.GCHandle.Alloc( data, System.Runtime.InteropServices.GCHandleType.Pinned );
try
{
t = (ZLIB_FOR_GXD)System.Runtime.InteropServices.Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ZLIB_FOR_GXD));
}
finally
{
handle.Free();
}
t.mOriginalSize = tOriginalSize;
t.mCompressSize = tCompressSize;
t.mCompressData = new byte[ t.mCompressSize ];
t.mOriginalData = new byte[ t.mOriginalSize ];
Array.Copy( bytes, tPosition, t.mCompressData, 0, t.mCompressSize );
tPosition = tPosition + tCompressSize;
Debug.Log($"{tPosition}");
Decompress(ref t);
return t;
}
static void Decompress( ref ZLIB_FOR_GXD input )
{
MemoryStream inputStream = new MemoryStream(input.mCompressData);
MemoryStream outputStream = new MemoryStream();
//inputStream.Read( input.mOriginalData, 0, input.mOriginalSize );
inputStream.Position = 2;
DeflateStream decompressionStream = new DeflateStream(inputStream, CompressionMode.Decompress);
decompressionStream.Read( input.mOriginalData, 0, input.mOriginalData.Length );
}
public static List<ZLIB2_FOR_GXD> GXD_LOADER( string tFileName )
{
byte[] data = File.ReadAllBytes(tFileName);
int tOffset = 0;
int tOriginalSize = 0;
int tCompressSize = 0;
int tLoadCount = 0;
List<ZLIB2_FOR_GXD> tZlib = new List<ZLIB2_FOR_GXD>();
ZLIB2_FOR_GXD temp;
do
{
for( ;tOffset != data.Length - 4; tOffset++ )
{
if( tOffset >= data.Length )
break;
if( data[tOffset] == 0x78 && data[tOffset+1] == 0xDA && data[tOffset+2] != 0x00 && data[tOffset+3] != 0x00 )
break;
if( data[tOffset] == 0x78 && data[tOffset+1] == 0x9C && data[tOffset+2] != 0x00 && data[tOffset+3] != 0x00 )
break;
}
if( tOffset >= data.Length )
{
tOffset = 0;
goto RESULT;
}
tOriginalSize = BitConverter.ToInt32( data, tOffset - 8 );
tCompressSize = BitConverter.ToInt32( data, tOffset - 4 );
if( tOriginalSize < tCompressSize )
{
goto END2;
}
if( tLoadCount == 1 && tFileName.Contains(".WG") )
{
temp = new ZLIB2_FOR_GXD();
temp.mTextureCountForWorld = BitConverter.ToInt32( data, tOffset - 20 );
temp.mTextureCountForWorld = temp.mTextureCountForWorld < 1 ? BitConverter.ToInt32( data, tOffset - 16 ) : temp.mTextureCountForWorld;
temp.mTextureCountForWorld = temp.mTextureCountForWorld < 1 ? BitConverter.ToInt32( data, tOffset - 12 ) : temp.mTextureCountForWorld;
temp.mTextureCountForWorld = temp.mTextureCountForWorld < 1 ? BitConverter.ToInt32( data, tOffset - 8 ) : temp.mTextureCountForWorld;
temp.mOriginalData = BitConverter.GetBytes( temp.mTextureCountForWorld );
tZlib.Add(temp);
Debug.Log($"TextureCount:{temp.mTextureCountForWorld}");
}
temp = new ZLIB2_FOR_GXD();
temp.mOffset = tOffset;
temp.mOriginalSize = tOriginalSize;
temp.mCompressSize = tCompressSize;
tZlib.Add(temp);
Debug.Log($"{temp.mOffset},{temp.mOriginalSize},{temp.mCompressSize}");
tOffset += temp.mCompressSize;
tLoadCount++;
}while( tOffset < data.Length );
tOffset = 0;
goto RESULT;
END2://remain data - some config for file/model
tOffset = tZlib[tZlib.Count-1].mOffset + tZlib[tZlib.Count-1].mCompressSize;
ZLIB2_FOR_GXD temp2 = new ZLIB2_FOR_GXD();
temp2.mOffset = tOffset;
temp2.mOriginalSize = data.Length - (tZlib[tZlib.Count-1].mOffset + tZlib[tZlib.Count-1].mCompressSize);
temp2.mOriginalData = new byte[temp2.mOriginalSize];
Array.Copy( data, temp2.mOffset, temp2.mOriginalData, 0, temp2.mOriginalSize );
tZlib.Add(temp2);
RESULT:
Debug.Log($"FileCount:{tZlib.Count},Remain Offset:{tOffset},Remain Size:{(tOffset==0?0:data.Length-tOffset)}");
for( int i = 0; i < tZlib.Count; i++ )
{
if( i != 1 && i != tZlib.Count - 1 )
tZlib[i] = Decompress2( data, tZlib[i].mOffset, tZlib[i].mOriginalSize, tZlib[i].mCompressSize );
WriteFile(tZlib[i].mOriginalData,i);
}
return tZlib;
}
static void WriteFile(byte[] data, int i )
{
string tFileName = string.Empty;
if( data.Length > 124 && data[4] == 124 && System.Text.Encoding.ASCII.GetString( data, 84, 3 ).Contains("DXT") )
tFileName = i.ToString() + ".DDS";
else tFileName = i.ToString() + ".HEX";
if( !Directory.Exists("output") )
{
Directory.CreateDirectory("output");
}
File.WriteAllBytes( $"output/{tFileName}", data );
}
public static ZLIB2_FOR_GXD Decompress2( byte[] bytes, int tOffset, int tOriginalSize, int tCompressSize )
{
ZLIB2_FOR_GXD t = new ZLIB2_FOR_GXD();
byte[] data = new byte[ 4 + 8 + 8 ];
Array.Copy( bytes, tOffset - 8, data, 0, data.Length );
System.Runtime.InteropServices.GCHandle handle = System.Runtime.InteropServices.GCHandle.Alloc( data, System.Runtime.InteropServices.GCHandleType.Pinned );
try
{
t = (ZLIB2_FOR_GXD)System.Runtime.InteropServices.Marshal.PtrToStructure( handle.AddrOfPinnedObject(), typeof(ZLIB2_FOR_GXD) );
}
finally
{
handle.Free();
}
t.mOriginalSize = tOriginalSize;
t.mCompressSize = tCompressSize;
t.mCompressData = new byte[ t.mCompressSize ];
t.mOriginalData = new byte[ t.mOriginalSize ];
Array.Copy( bytes, tOffset, t.mCompressData, 0, t.mCompressSize );
Decompress2(ref t);
return t;
}
static void Decompress2( ref ZLIB2_FOR_GXD input )
{
MemoryStream inputStream = new MemoryStream(input.mCompressData);
MemoryStream outputStream = new MemoryStream();
inputStream.Position = 2;
System.IO.Compression.DeflateStream decompressionStream = new System.IO.Compression.DeflateStream(inputStream, System.IO.Compression.CompressionMode.Decompress);
decompressionStream.Read( input.mOriginalData, 0, input.mOriginalData.Length );
}
public static int GetStructSize<T>()
{
return (int)System.Runtime.InteropServices.Marshal.SizeOf<T>();
}
public static T StructFromByte<T>(byte[] bytes) where T : struct
{
T stuff;
System.Runtime.InteropServices.GCHandle handle = System.Runtime.InteropServices.GCHandle.Alloc(bytes, System.Runtime.InteropServices.GCHandleType.Pinned);
try
{
stuff = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
return stuff;
}
public static T[] StructFromByte<T>(byte[] bytes, int position, int length) where T : struct
{
T[] stuff = new T[length];
int sizeData = GetStructSize<T>();
byte[] data = new byte[sizeData];
for( int i = 0; i < length; i++ )
{
Array.Copy( bytes, position + (i * sizeData), data, 0, data.Length );
System.Runtime.InteropServices.GCHandle handle = System.Runtime.InteropServices.GCHandle.Alloc( data, System.Runtime.InteropServices.GCHandleType.Pinned );
try
{
stuff[i] = (T)System.Runtime.InteropServices.Marshal.PtrToStructure( handle.AddrOfPinnedObject(), typeof(T) );
}
finally
{
handle.Free();
}
}
return stuff;
}
public static T StructFromBytePosition<T>(byte[] bytes, int position) where T : struct
{
T stuff;
int sizeData = GetStructSize<T>();
byte[] data = new byte[sizeData];
Array.Copy( bytes, position, data, 0, data.Length );
System.Runtime.InteropServices.GCHandle handle = System.Runtime.InteropServices.GCHandle.Alloc( data, System.Runtime.InteropServices.GCHandleType.Pinned);
try
{
stuff = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
return stuff;
}
}
}
[ExecuteInEditMode]
public class UNITY_FOR_GXD : UnityEditor.EditorWindow
{
[UnityEditor.MenuItem("Assets/12Sky2")]
static void Apply()
{
string path = UnityEditor.EditorUtility.OpenFilePanel("Choose .SOBJECT", "", "SOBJECT");
if (path.Length != 0)
{
GameObject gameobject = new GameObject("Model");
SOBJECT_FOR_GXD sobject = new SOBJECT_FOR_GXD();
sobject.Load(path);
sobject.Draw(gameobject);
}
}
}