Jump to content

GR2 -> FBX Exporter [+ Source]


Recommended Posts

Thank you for the updates.
the BindPose error is gone as far as i can see
the functionality of the gui is really nice
but the bones position error is still there

and a small thing would be that when i try to add the model for animation it doubles the directory items:

https://metin2.download/picture/nMo0r55xnF1mZ932Vkkm1Qk5AS0ZA9wc/.gif

Edited by Metin2 Dev
Core X - External 2 Internal
Link to comment
Share on other sites

15 hours ago, GeoGeo123 said:

Thank you for the updates.
the BindPose error is gone as far as i can see
the functionality of the gui is really nice
but the bones position error is still there

and a small thing would be that when i try to add the model for animation it doubles the directory items:

https://metin2.download/picture/nMo0r55xnF1mZ932Vkkm1Qk5AS0ZA9wc/.gif

Double inserting file in Gui is fixed, pls send me the file where you get bone errors, I will find a way  for fixing.

Edited by Metin2 Dev
Core X - External 2 Internal

giphy.gif

Best regards, Arlinamid

Link to comment
Share on other sites

On 3/21/2022 at 8:04 AM, arlinamid said:

Double inserting file in Gui is fixed, pls send me the file where you get bone errors, I will find a way  for fixing.

Regarding the bone errors.. my granny converter library already addresses this kind of issue. However it was not exposed as an extra option until now.. **Update** Now, it only requires to enable an option which can be set straightforwardly.

You could implement a checkbox for the option in your GUI.

I just updated my library to provide the option for this which can be set straightforwardly. I also updated the example.

Just review my recent commit:

This is the hidden content, please

Edited by Anohros
  • Metin2 Dev 46
  • Not Good 2
  • Sad 1
  • Good 12
  • Love 4
  • Love 13
Link to comment
Share on other sites

@AnohrosYesterday, goes around this anim issue, and I arrive to UE4 source, i think it has  some fixes. I found this check it pls. 

This is the hidden content, please

In this file has void CorrectAnimTrackInterpolation  could be these fixing ?

  • Metin2 Dev 33
  • kekw 1
  • Eyes 1
  • Not Good 1
  • Cry 1
  • Think 2
  • Good 7
  • Love 1
  • Love 11

giphy.gif

Best regards, Arlinamid

Link to comment
Share on other sites

On 3/20/2022 at 4:24 PM, GeoGeo123 said:

Thank you for the updates.
the BindPose error is gone as far as i can see
the functionality of the gui is really nice
but the bones position error is still there

and a small thing would be that when i try to add the model for animation it doubles the directory items:

https://metin2.download/picture/nMo0r55xnF1mZ932Vkkm1Qk5AS0ZA9wc/.gif

@GeoGeo123 Could you provide the file path "d:/ymir work/.." to the affected animation or send me the file? I think the armor is not required to check the issue.

@ arlinamid The correction script from Unreal Engine could be useful 🙂 I know, my option mentioned above just enables a work around - it is a old way I handled the conversion.

Another issue I'am aware of but not addressed yet: The file "d:/ymir work/pc2/warrior/intro/selected.gr2" is currently not supported with the default animation importer, but works with the old animation importer.

At least it's only a few not supported animations. You can count it on one hand. For my purpose it is just fine to use the old animation importer.

Edited by Metin2 Dev
Core X - External 2 Internal
Link to comment
Share on other sites

  • Management
On 3/22/2022 at 7:59 PM, Anohros said:

Regarding the bone errors.. my granny converter library already addresses this kind of issue. However it was not exposed as an extra option until now.. **Update** Now, it only requires to enable an option which can be set straightforwardly.

You could implement a checkbox for the option in your GUI.

I just updated my library to provide the option for this which can be set straightforwardly. I also updated the example.

Just review my recent commit:

This is the hidden content, please

Without those changes: https://metin2.download/picture/KEsNS2jtTUTXw32WZKAw6YfAegY24ig8/.gif

With those changes: https://metin2.download/picture/fofDIklu9ykjoR2cBqPu1i3a3n8W9765/.gif

Code used (with it false that weird flying bug doesn't happen):

    GCL::Importer::GrannyImportOptions options;
    options.importAnimationDeboor = true;
    GrannyImporter* importer = new GrannyImporter(options);

I attempted to apply that update to see if it would solve the left shoulder issue, but apparently it didn't.

To fix it manually just need to mirror Bone_shoulder_03 on XY axis and adjust the position manually.

Edited by Metin2 Dev
Core X - External 2 Internal
  • Love 1

raw

raw

Link to comment
Share on other sites

Hello,  I'm still working on this project, and today I found a strange things.

I'm imported saved fbx file to 3ds max and Unity. With Unity I get these:

.gif

Everything fine animation look pretty.

With 3ds Max I get these

.gif

It has animation mistake, so we need some error correction,  I try to find  way to get error correction

  • Love 2

giphy.gif

Best regards, Arlinamid

Link to comment
Share on other sites

  • 3 months later...
  • 5 months later...
  • Active+ Member

Not sure if it's a error or not (since i've found the same problem with other similar tools) but while exporting sura model, the bones of 2 of the fingers in the left hand always export bigger than the other fingers

15b420741b0bed64a15466e8deaece4d.png

The only way i found to kinda fix this was using grnreader or noesis and exporting to smd (if it was exported to fbx the problem also occurs)

Edited by Metin2 Dev
Core X - External 2 Internal
Link to comment
Share on other sites

  • Former Staff
On 1/26/2023 at 1:55 PM, idok2 said:

My question is, how did u import the map? I want it too sooo soo badly 😕

using System;
using System.IO;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;

public class MapLoaderView : MonoBehaviour
{
    public Terrain Terrain;

    private const int TerrainTileSize = 131;
    private const int TerrainTileSquare = TerrainTileSize * TerrainTileSize;
    private const int SplatSize = TerrainTileSize - 2;
    private const int SplatSquare = SplatSize * SplatSize;
    // Start is called before the first frame update
    void Start()
    {
        var mapWidth = 4;
        var mapHeight = 5;
        
        float[,] data = new float[Terrain.terrainData.heightmapResolution, Terrain.terrainData.heightmapResolution];
        Terrain.terrainData.SetHeights(0, 0, data);
        
        NativeArray<int> xOffset = new NativeArray<int>(mapWidth * mapHeight, Allocator.TempJob);
        NativeArray<int> yOffset = new NativeArray<int>(mapWidth * mapHeight, Allocator.TempJob);
        NativeArray<float> jobData = new NativeArray<float>(SplatSquare * mapHeight * mapWidth, Allocator.TempJob);
        NativeArray<UInt16> mapData = new NativeArray<UInt16>(TerrainTileSquare * mapHeight * mapWidth, Allocator.TempJob);
        
        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            var file = File.ReadAllBytes($"Assets/_M2/Features/Maps/Original/metin2_map_c1/00{tileX}00{tileY}/height.raw");
            var tileOffset = ((tileX * TerrainTileSquare * mapHeight) + (tileY * TerrainTileSquare));
            for (var offset = 0; offset < file.Length / 2; offset++)
            {
                var mapDataOffset = tileOffset + offset;
                mapData[mapDataOffset] = BitConverter.ToUInt16(file, offset * 2);
            }
            
            xOffset[tileX * mapHeight + tileY] = tileX;
            yOffset[tileX * mapHeight + tileY] = tileY;
        }
        
        TerrainJob terrainJob = new TerrainJob
        {
            xOffsetData = xOffset,
            yOffsetData = yOffset,
            data = jobData,
            mapWidth = mapWidth,
            mapHeight = mapHeight,
            mapData = mapData,
        };
        JobHandle handle = terrainJob.Schedule(mapWidth * mapHeight, 1);
        handle.Complete();

        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            for (var pixelX = 0; pixelX < SplatSize; pixelX++)
            for (var pixelY = 0; pixelY < SplatSize; pixelY++)
            {
                var dataOffset = ((tileX * SplatSquare * mapHeight) + (((mapHeight - 1) - tileY) * SplatSquare));
                data[tileY * SplatSize + pixelY, tileX * SplatSize + pixelX] = terrainJob.data[dataOffset + pixelX * SplatSize + pixelY];
            }
        }

        Terrain.terrainData.SetHeights(0, 0, data);

        xOffset.Dispose();
        yOffset.Dispose();
        jobData.Dispose();
        mapData.Dispose();

        int size = 258;
        int[,] texData = new int[size * mapWidth, size * mapHeight];
        
        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            LoadTextures($"Assets/_M2/Features/Maps/Original/metin2_map_c1/00{tileX}00{tileY}/tile.raw", tileX, (mapHeight - 1) - tileY, ref texData);
        }
        
        LoadFullTextures(texData, Terrain.terrainData, size * mapWidth, size * mapHeight);
        bool[,] holes = new bool[Terrain.terrainData.holesResolution, Terrain.terrainData.holesResolution];
        for (var pixelX = 0; pixelX < Terrain.terrainData.holesResolution; pixelX++)
        for (var pixelY = 0; pixelY < Terrain.terrainData.holesResolution; pixelY++)
        {
            var solid = pixelX + 1 < mapHeight * SplatSize && pixelY + 1 < mapWidth * SplatSize;
            holes[pixelX, pixelY] = solid;
        }
        Terrain.terrainData.SetHoles(0, 0, holes);
    }

    public struct TerrainJob : IJobParallelFor
    {
        [NativeDisableParallelForRestriction]
        public NativeArray<float> data;
        [ReadOnly]
        public NativeArray<int> xOffsetData;
        [ReadOnly]
        public NativeArray<int> yOffsetData;
        [ReadOnly] 
        public NativeArray<UInt16> mapData;
        [ReadOnly]
        public int mapWidth;
        [ReadOnly]
        public int mapHeight;
        
        public void Execute(int i)
        {
            var xShift = xOffsetData[i];
            var yShift = yOffsetData[i];

            var dataOffset = ((xShift * TerrainTileSquare * mapHeight) + (yShift * TerrainTileSquare));

            var targetDataOffset = ((xShift * SplatSquare * mapHeight) + (yShift * SplatSquare));
            
            for (int pixelY = 0; pixelY < TerrainTileSize; pixelY++)
            {
                for (int pixelX = 0; pixelX < TerrainTileSize; pixelX++)
                {
                    float v = (float)mapData[dataOffset + (pixelX * TerrainTileSize) + pixelY] / 0xFFFF;
                    if (pixelX >= 1 && pixelY >= 1 && pixelX <= SplatSize && pixelY <= SplatSize)
                    {
                        var realY = pixelY - 1;
                        var realX = pixelX - 1;
                        data[targetDataOffset + realY * SplatSize + ((SplatSize - 1) - realX)] = v;
                    }
                }
            }
        }
    }
    
    public struct Native2DArray<T> : System.IDisposable where T: struct
    {
        private int sizeX;
        private int sizeY;
        private NativeArray<T> flatArray;
        
        public Native2DArray(int sizeX, int sizeY, Allocator allocator)
        {
            this.sizeX = sizeX;
            this.sizeY = sizeY;
            flatArray = new NativeArray<T>(sizeX * sizeY, allocator);
        }
 
        public T this[int x, int y]
        {
            get { return flatArray[x + y * sizeX]; }
            set { flatArray[x + y * sizeX] = value; }
        }
 
        public void Dispose()
        {
            flatArray.Dispose();
        }

        public int Length => this.sizeX * this.sizeY;
    }

    void LoadTerrain(string aFileName, TerrainData aTerrain, int shiftX, int shiftY)
    {
        int size = 131;
        
        float[,] data = new float[size - 2, size - 2];
        using (var file = System.IO.File.OpenRead(aFileName))
        using (var reader = new System.IO.BinaryReader(file))
        {
            for (int y = size - 1; y >= 0; y--)
            {
                for (int x = 0; x < size; x++)
                {
                    float v = (float)reader.ReadUInt16() / 0xFFFF;
                    if (x >= 1 && y >= 1 && x <= size - 2 && y <= size - 2)
                    {
                        data[y - 1, x - 1] = v;
                    }
                }
            }
        }
    }

    void LoadTextures(string tileFileName, int shiftX, int shiftY, ref int[,] fullTexData)
    {
        int size = 258;

        using (var texFile = System.IO.File.OpenRead(tileFileName))
        using (var texReader = new System.IO.BinaryReader(texFile))
        {
            for (int y = size - 1; y >= 0; y--)
            {
                for (int x = 0; x < size; x++)
                {
                    int tex = texReader.ReadByte();
                    fullTexData[size * shiftX + x, size * shiftY + y] = tex - 1;
                }
            }
        }
    }
    
    void LoadFullTextures(int[,] fullTexData, TerrainData aTerrain, int width, int height)
    {
        float[,,] texData = aTerrain.GetAlphamaps(0, 0, width, height);
        {
            for (int y = height - 1; y >= 0; y--)
            {
                for (int x = 0; x < width; x++)
                {
                    {
                        var count = 0;
                        float[] texWeights = new float[aTerrain.terrainLayers.Length];
                        // BOTTOM
                        if (x - 1 >= 0 && y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y - 1]] += 1 / 9f;
                        }

                        if (y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x, y - 1]] += 1;
                        }

                        if (x + 1 < width && y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y - 1]] += 1;
                        }
                        
                        // CENTER
                        if (x - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y]] += 1;
                        }

                        if (true)
                        {
                            count++;
                            texWeights[fullTexData[x, y]] += 1;
                        }

                        if (x + 1 < width)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y]] += 1;
                        }
                        
                        // TOP
                        if (x - 1 >= 0 && y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y]] += 1;
                        }

                        if (y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x, y]] += 1;
                        }

                        if (x + 1 < width && y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y]] += 1;
                        }

                        for (var iTex = 0; iTex < aTerrain.terrainLayers.Length; iTex++)
                        {
                            texData[y, x, iTex] = texWeights[iTex] / (float)count;
                        }
                    }
                }
            }
        }

        aTerrain.SetAlphamaps(0, 0, texData);
    }

    bool IsBitSet(byte b, int pos)
    {
        return (b & (1 << pos)) != 0;
    }

    // Update is called once per frame
    void Update()
    {
    }
}
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;

public static class NativeArrayExtension
{
    public static byte[] ToRawBytes<T>(this NativeArray<T> arr) where T : struct
    {
        var slice = new NativeSlice<T>(arr).SliceConvert<byte>();
        var bytes = new byte[slice.Length];
        slice.CopyTo(bytes);
        return bytes;
    }

    public static void CopyFromRawBytes<T>(this NativeArray<T> arr, byte[] bytes) where T : struct
    {
        var byteArr = new NativeArray<byte>(bytes, Allocator.Temp);
        var slice = new NativeSlice<byte>(byteArr).SliceConvert<T>();

        UnityEngine.Debug.Assert(arr.Length == slice.Length);
        slice.CopyTo(arr);
    }

    public static NativeArray<T> FromRawBytes<T>(byte[] bytes, Allocator allocator) where T : struct
    {
        int structSize = UnsafeUtility.SizeOf<T>();

        UnityEngine.Debug.Assert(bytes.Length % structSize == 0);

        int length = bytes.Length / UnsafeUtility.SizeOf<T>();
        var arr = new NativeArray<T>(length, allocator);
        arr.CopyFromRawBytes(bytes);
        return arr;
    }
}

This would be the map loader I have used

  • Good 1
  • Love 1
Link to comment
Share on other sites

On 2/4/2023 at 11:03 PM, .InyaProduction said:
using System;
using System.IO;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;

public class MapLoaderView : MonoBehaviour
{
    public Terrain Terrain;

    private const int TerrainTileSize = 131;
    private const int TerrainTileSquare = TerrainTileSize * TerrainTileSize;
    private const int SplatSize = TerrainTileSize - 2;
    private const int SplatSquare = SplatSize * SplatSize;
    // Start is called before the first frame update
    void Start()
    {
        var mapWidth = 4;
        var mapHeight = 5;
        
        float[,] data = new float[Terrain.terrainData.heightmapResolution, Terrain.terrainData.heightmapResolution];
        Terrain.terrainData.SetHeights(0, 0, data);
        
        NativeArray<int> xOffset = new NativeArray<int>(mapWidth * mapHeight, Allocator.TempJob);
        NativeArray<int> yOffset = new NativeArray<int>(mapWidth * mapHeight, Allocator.TempJob);
        NativeArray<float> jobData = new NativeArray<float>(SplatSquare * mapHeight * mapWidth, Allocator.TempJob);
        NativeArray<UInt16> mapData = new NativeArray<UInt16>(TerrainTileSquare * mapHeight * mapWidth, Allocator.TempJob);
        
        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            var file = File.ReadAllBytes($"Assets/_M2/Features/Maps/Original/metin2_map_c1/00{tileX}00{tileY}/height.raw");
            var tileOffset = ((tileX * TerrainTileSquare * mapHeight) + (tileY * TerrainTileSquare));
            for (var offset = 0; offset < file.Length / 2; offset++)
            {
                var mapDataOffset = tileOffset + offset;
                mapData[mapDataOffset] = BitConverter.ToUInt16(file, offset * 2);
            }
            
            xOffset[tileX * mapHeight + tileY] = tileX;
            yOffset[tileX * mapHeight + tileY] = tileY;
        }
        
        TerrainJob terrainJob = new TerrainJob
        {
            xOffsetData = xOffset,
            yOffsetData = yOffset,
            data = jobData,
            mapWidth = mapWidth,
            mapHeight = mapHeight,
            mapData = mapData,
        };
        JobHandle handle = terrainJob.Schedule(mapWidth * mapHeight, 1);
        handle.Complete();

        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            for (var pixelX = 0; pixelX < SplatSize; pixelX++)
            for (var pixelY = 0; pixelY < SplatSize; pixelY++)
            {
                var dataOffset = ((tileX * SplatSquare * mapHeight) + (((mapHeight - 1) - tileY) * SplatSquare));
                data[tileY * SplatSize + pixelY, tileX * SplatSize + pixelX] = terrainJob.data[dataOffset + pixelX * SplatSize + pixelY];
            }
        }

        Terrain.terrainData.SetHeights(0, 0, data);

        xOffset.Dispose();
        yOffset.Dispose();
        jobData.Dispose();
        mapData.Dispose();

        int size = 258;
        int[,] texData = new int[size * mapWidth, size * mapHeight];
        
        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            LoadTextures($"Assets/_M2/Features/Maps/Original/metin2_map_c1/00{tileX}00{tileY}/tile.raw", tileX, (mapHeight - 1) - tileY, ref texData);
        }
        
        LoadFullTextures(texData, Terrain.terrainData, size * mapWidth, size * mapHeight);
        bool[,] holes = new bool[Terrain.terrainData.holesResolution, Terrain.terrainData.holesResolution];
        for (var pixelX = 0; pixelX < Terrain.terrainData.holesResolution; pixelX++)
        for (var pixelY = 0; pixelY < Terrain.terrainData.holesResolution; pixelY++)
        {
            var solid = pixelX + 1 < mapHeight * SplatSize && pixelY + 1 < mapWidth * SplatSize;
            holes[pixelX, pixelY] = solid;
        }
        Terrain.terrainData.SetHoles(0, 0, holes);
    }

    public struct TerrainJob : IJobParallelFor
    {
        [NativeDisableParallelForRestriction]
        public NativeArray<float> data;
        [ReadOnly]
        public NativeArray<int> xOffsetData;
        [ReadOnly]
        public NativeArray<int> yOffsetData;
        [ReadOnly] 
        public NativeArray<UInt16> mapData;
        [ReadOnly]
        public int mapWidth;
        [ReadOnly]
        public int mapHeight;
        
        public void Execute(int i)
        {
            var xShift = xOffsetData[i];
            var yShift = yOffsetData[i];

            var dataOffset = ((xShift * TerrainTileSquare * mapHeight) + (yShift * TerrainTileSquare));

            var targetDataOffset = ((xShift * SplatSquare * mapHeight) + (yShift * SplatSquare));
            
            for (int pixelY = 0; pixelY < TerrainTileSize; pixelY++)
            {
                for (int pixelX = 0; pixelX < TerrainTileSize; pixelX++)
                {
                    float v = (float)mapData[dataOffset + (pixelX * TerrainTileSize) + pixelY] / 0xFFFF;
                    if (pixelX >= 1 && pixelY >= 1 && pixelX <= SplatSize && pixelY <= SplatSize)
                    {
                        var realY = pixelY - 1;
                        var realX = pixelX - 1;
                        data[targetDataOffset + realY * SplatSize + ((SplatSize - 1) - realX)] = v;
                    }
                }
            }
        }
    }
    
    public struct Native2DArray<T> : System.IDisposable where T: struct
    {
        private int sizeX;
        private int sizeY;
        private NativeArray<T> flatArray;
        
        public Native2DArray(int sizeX, int sizeY, Allocator allocator)
        {
            this.sizeX = sizeX;
            this.sizeY = sizeY;
            flatArray = new NativeArray<T>(sizeX * sizeY, allocator);
        }
 
        public T this[int x, int y]
        {
            get { return flatArray[x + y * sizeX]; }
            set { flatArray[x + y * sizeX] = value; }
        }
 
        public void Dispose()
        {
            flatArray.Dispose();
        }

        public int Length => this.sizeX * this.sizeY;
    }

    void LoadTerrain(string aFileName, TerrainData aTerrain, int shiftX, int shiftY)
    {
        int size = 131;
        
        float[,] data = new float[size - 2, size - 2];
        using (var file = System.IO.File.OpenRead(aFileName))
        using (var reader = new System.IO.BinaryReader(file))
        {
            for (int y = size - 1; y >= 0; y--)
            {
                for (int x = 0; x < size; x++)
                {
                    float v = (float)reader.ReadUInt16() / 0xFFFF;
                    if (x >= 1 && y >= 1 && x <= size - 2 && y <= size - 2)
                    {
                        data[y - 1, x - 1] = v;
                    }
                }
            }
        }
    }

    void LoadTextures(string tileFileName, int shiftX, int shiftY, ref int[,] fullTexData)
    {
        int size = 258;

        using (var texFile = System.IO.File.OpenRead(tileFileName))
        using (var texReader = new System.IO.BinaryReader(texFile))
        {
            for (int y = size - 1; y >= 0; y--)
            {
                for (int x = 0; x < size; x++)
                {
                    int tex = texReader.ReadByte();
                    fullTexData[size * shiftX + x, size * shiftY + y] = tex - 1;
                }
            }
        }
    }
    
    void LoadFullTextures(int[,] fullTexData, TerrainData aTerrain, int width, int height)
    {
        float[,,] texData = aTerrain.GetAlphamaps(0, 0, width, height);
        {
            for (int y = height - 1; y >= 0; y--)
            {
                for (int x = 0; x < width; x++)
                {
                    {
                        var count = 0;
                        float[] texWeights = new float[aTerrain.terrainLayers.Length];
                        // BOTTOM
                        if (x - 1 >= 0 && y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y - 1]] += 1 / 9f;
                        }

                        if (y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x, y - 1]] += 1;
                        }

                        if (x + 1 < width && y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y - 1]] += 1;
                        }
                        
                        // CENTER
                        if (x - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y]] += 1;
                        }

                        if (true)
                        {
                            count++;
                            texWeights[fullTexData[x, y]] += 1;
                        }

                        if (x + 1 < width)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y]] += 1;
                        }
                        
                        // TOP
                        if (x - 1 >= 0 && y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y]] += 1;
                        }

                        if (y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x, y]] += 1;
                        }

                        if (x + 1 < width && y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y]] += 1;
                        }

                        for (var iTex = 0; iTex < aTerrain.terrainLayers.Length; iTex++)
                        {
                            texData[y, x, iTex] = texWeights[iTex] / (float)count;
                        }
                    }
                }
            }
        }

        aTerrain.SetAlphamaps(0, 0, texData);
    }

    bool IsBitSet(byte b, int pos)
    {
        return (b & (1 << pos)) != 0;
    }

    // Update is called once per frame
    void Update()
    {
    }
}
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;

public static class NativeArrayExtension
{
    public static byte[] ToRawBytes<T>(this NativeArray<T> arr) where T : struct
    {
        var slice = new NativeSlice<T>(arr).SliceConvert<byte>();
        var bytes = new byte[slice.Length];
        slice.CopyTo(bytes);
        return bytes;
    }

    public static void CopyFromRawBytes<T>(this NativeArray<T> arr, byte[] bytes) where T : struct
    {
        var byteArr = new NativeArray<byte>(bytes, Allocator.Temp);
        var slice = new NativeSlice<byte>(byteArr).SliceConvert<T>();

        UnityEngine.Debug.Assert(arr.Length == slice.Length);
        slice.CopyTo(arr);
    }

    public static NativeArray<T> FromRawBytes<T>(byte[] bytes, Allocator allocator) where T : struct
    {
        int structSize = UnsafeUtility.SizeOf<T>();

        UnityEngine.Debug.Assert(bytes.Length % structSize == 0);

        int length = bytes.Length / UnsafeUtility.SizeOf<T>();
        var arr = new NativeArray<T>(length, allocator);
        arr.CopyFromRawBytes(bytes);
        return arr;
    }
}

This would be the map loader I have used

OMG! Thank you a lot. I am just getting started so i sorry, but i have 2 errors. 

https://metin2.download/picture/RgYGUN28Xh9l3QoY12ysqxyRlG6uVigA/.png

Before you asking, no i don't want to develop a game like metin 2 without knowledge. I just want to learn Unity this way. I just want to play around with things 😄 . And i like messing around with Metin2 things.

Edited by Metin2 Dev
Core X - External 2 Internal
Link to comment
Share on other sites

On 2/6/2023 at 11:28 AM, idok2 said:

OMG! Thank you a lot. I am just getting started so i sorry, but i have 2 errors. 

https://metin2.download/picture/RgYGUN28Xh9l3QoY12ysqxyRlG6uVigA/.png

Before you asking, no i don't want to develop a game like metin 2 without knowledge. I just want to learn Unity this way. I just want to play around with things 😄 . And i like messing around with Metin2 things.

A wild guess..

does the map width and height match with your map?

I refer to this part from the source:

var mapWidth = 4;
var mapHeight = 5;

Width is the number of tiles in the x axis and height in y axis.

Link to comment
Share on other sites

  • 2 months later...

Can someone compile an old fbx version build?
I'm using 3ds max 2010 because I have a potato laptop, and the latest fbx import plugin available to that version is 2012.2 which only supports fbx version up to 7.2 (I think) while fbx produces by gr2 to fbx exporter is 7.7

Or can someone recommend me a software that can downgrade fbx version? No noesis please because it always messes up something to model.

Thanks in advance.

Link to comment
Share on other sites

  • 2 weeks later...
On 5/3/2023 at 6:06 AM, ocarinas said:

Can someone compile an old fbx version build?
I'm using 3ds max 2010 because I have a potato laptop, and the latest fbx import plugin available to that version is 2012.2 which only supports fbx version up to 7.2 (I think) while fbx produces by gr2 to fbx exporter is 7.7

Or can someone recommend me a software that can downgrade fbx version? No noesis please because it always messes up something to model.

Thanks in advance.

It is right now not possible to set the fbx format version on the builds available here.

Though the current version of the fbx sdk supports to export to older versions of the fbx format. Basically, we do not need to downgrade the version of the fbx sdk and only have to pass the specific older version of the fbx format itself on export.

Edited by Anohros
Link to comment
Share on other sites

  • 2 months later...
  • 3 months later...
On 2/6/2023 at 1:28 PM, idok2 said:

OMG! Thank you a lot. I am just getting started so i sorry, but i have 2 errors. 

https://metin2.download/picture/RgYGUN28Xh9l3QoY12ysqxyRlG6uVigA/.png

Before you asking, no i don't want to develop a game like metin 2 without knowledge. I just want to learn Unity this way. I just want to play around with things 😄 . And i like messing around with Metin2 things.

i'm getting this error too

@ .InyaProduction

Link to comment
Share on other sites

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.