Click here to Skip to main content
15,882,113 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I am struggling with deciphering the heightmap in a Unity game written in C# using VBA with a view to being able to then develop a terrain generator for the game.

I'm reading a binary game file into a byte array and at a variable point in the file, (it is made of a variable number of variable length chunks - each with a header) is the height map, comprising 513 x 513 4 byte values.
I can find the start of the heightmap without difficulty by looking for it's header string.
The values for each height 'pixel' are 4 bytes long and seem to be held in low order byte -> high order byte with a maximum value in the high order byte seeming to be &h3F - any value higher than that and the terrain height is interpreted and displayed as minimum by the game.

The game that generates the data file is written c#, (by someone else - I have no c# skills) using Unity3d as the engine.

Can anyone enlighten me, please?

What I have tried:

I have tried extracting the 1052676 bytes of height data and writing it to a binary file with 'Put' which I then close and reopen to 'Get' the data into a 513x513 array of type long. That doesn't work. Whilst I don't get an error message, I don't get any data either. I've tried searching for c#/VB data formats but have not been able to find a solution. I've tried reading the VBA help and have scratched my way through VBA for dummies, without success.
I am able to effect height changes in the terrain programmatically, but manipluating the byte values as a set of four separate numbers is cumbersome and the effects of changes to the 4th byte are surprising.
Posted
Updated 2-Jan-19 21:04pm
v2
Comments
[no name] 1-Jan-19 13:00pm    
You change the map; then see how it affects the game. That's how you reverse engineer at least in this case.

Because you seem to be mapping "bytes to longs" without showing / knowing "why".
Member 14100511 2-Jan-19 17:32pm    
Unhelpful Greg. However do you think I figured out what was height data, what colour data, what asset data?
I am doing it because I want to write a random terrain generator for the game - a feature which the original dev's did not provide - and it'll be a heck of a lot easier if I have an array of integers than an array of bytes.
Maciej Los 2-Jan-19 8:31am    
Working with images in VBA is a nightmare! VBA is not for such of things! It was written to support MS Office programs to manipulate objects and data automation. I'd strogly recommend to abandon this idea ASAP.
Member 14100511 2-Jan-19 17:33pm    
I'm not working in VBA to process images Maciej.
I'm working in VBA to produce a 513x513 array of numbers which I will insert into the game file which will then be read by the game engine. I'm just hoping someone out there knows how Unity/C# stores heightmap data.
It's 4 bytes, yes, and my first thought was it's a standard long integer, but in the game engine changes to the 1st byte seem insignificant, the 2nd byte minor, the 3rd byte noticeable but the 4th byte!
Values from 0 - &h39 and values above &h3f all result in a zero height in the game map, values in between seem to generate orders of magnitude of height change - and not simple powers of two.
My assumption has been that the data is stored in a standard MS format and it's just my lack of knowledge of MS coding platform internals that is holding me back, but maybe it isn't. I am perplexed.
Peter_in_2780 2-Jan-19 21:05pm    
Have you considered that the values might be floats, stored little-endian? Take a look through that lens, see if it makes any sense.

1 solution

Okay, so What I have is (((b4*256)+b3)*256+b2)*256+b1 with a minimum value of &h00000000 and a maximum of &hFFFF803F. Any value above that stops the terrain editor working

VB
Private Sub CmdMakeTerrain_Click()

pixelheightchange = maxheight / 513
maxheight = 1062273023
r1 = maxheight / 16777216
b4 = CByte(Int(r1))
midheight = maxheight - (Int(r1) * 16777216)
r2 = midheight / 65536
b3 = CByte(Int(r2))
midheight2 = midheight - (Int(r2) * 65536)
r3 = midheight2 / 256
b2 = CByte(Int(r3))
'midheight3 = midheight2 - (Int(r3) * 256)
'r4 = midheight3 / 256
b1 = (r3 - Int(r3)) * 256

End Sub


I'll not bore people with the obvious reverse process.

Thanks all for your help.
 
Share this answer
 
v3
Comments
Maciej Los 3-Jan-19 5:57am    
Good job.
I'm voting 5 for encouragement.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900