Page 1 of 2

Custom world implementation: Need assistance.

Posted: Fri Dec 27, 2019 6:50 pm
by Jeoshua
Currently I am working on a replacement world map, replete with a custom vegetation and river map. The height map is almost there, I just have to adjust the actual heights two something that the game can handle and smooth out the values. I got this part.

Through several experiments, I found that the game can handle surface water perfectly fine, complete with changes in elevation, by just having the tile be declared as a water texture. Setting ocean height in my TerrainSampler implementation to a high value showed that easily. By default, the game will check if the height is below an artificially set sea level, if it is that low then set it to sea level, and in TerrainTexturing it will set all values below or at sea level to ocean tiles.

In my implementation I skip the first check and get "water hills", which is useful to know the game can handle "sloped surface water" but frustrating since I cannot find any way to override the texturing process to declare "this is water" and "this is land" manually. The texturing system seems to be intended to allow for separate instances, but is set in the game as "readonly".

What I have:
An 5000x2500 RGB 16-bit custom terrain image
- Red: Height
- Green: Vegetation Density
- Blue: Water Mask

What I Want:
To be able to use this water mask to tell the game to make a tile be water.
To have this work as a mod.

I know that this can work in the game. I could directly change the terrain texturing system to do what I want, but I'm pretty sure I couldn't compile it that into a dfmod, could I?

Re: Custom world implementation: Need assistance.

Posted: Fri Dec 27, 2019 8:49 pm
by BadLuckBurt
Jeoshua wrote: Fri Dec 27, 2019 6:50 pm Currently I am working on a replacement world map, replete with a custom vegetation and river map. The height map is almost there, I just have to adjust the actual heights two something that the game can handle and smooth out the values. I got this part.

Through several experiments, I found that the game can handle surface water perfectly fine, complete with changes in elevation, by just having the tile be declared as a water texture. Setting ocean height in my TerrainSampler implementation to a high value showed that easily. By default, the game will check if the height is below an artificially set sea level, if it is that low then set it to sea level, and in TerrainTexturing it will set all values below or at sea level to ocean tiles.

In my implementation I skip the first check and get "water hills", which is useful to know the game can handle "sloped surface water" but frustrating since I cannot find any way to override the texturing process to declare "this is water" and "this is land" manually. The texturing system seems to be intended to allow for separate instances, but is set in the game as "readonly".

What I have:
An 5000x2500 RGB 16-bit custom terrain image
- Red: Height
- Green: Vegetation Density
- Blue: Water Mask

What I Want:
To be able to use this water mask to tell the game to make a tile be water.
To have this work as a mod.

I know that this can work in the game. I could directly change the terrain texturing system to do what I want, but I'm pretty sure I couldn't compile it that into a dfmod, could I?
You can overwrite the default instance of TerrainTexturing.cs if you create your own. Hazelnut was kind of enough to add it to my terrain sampler experiment, you can check the code here: https://github.com/BadLuckBurt/BLBTerra ... Terrain.cs.

It's the last line before Mod.IsReady = true

Code: Select all

        blbTerrainSampler = new BLBTerrainSampler(noiseSettings);
        DaggerfallUnity.Instance.TerrainSampler = blbTerrainSampler;
        DaggerfallUnity.Instance.TerrainTexturing = new BLBTerrainTexturing();
My BLBTerrainTexturing class is just a copy of the existing TerrainTexturing.cs, you'll probably need your own but I hope this helps you get started.

Good luck!

Re: Custom world implementation: Need assistance.

Posted: Fri Dec 27, 2019 9:14 pm
by Jeoshua
I had assumed that since that value is readonly I couldn't replace it. Shows what I know, I guess. So I assume I have to replace the whole class. I wonder if I can use inheritance to limit what I actually have to rewrite.

Re: Custom world implementation: Need assistance.

Posted: Fri Dec 27, 2019 9:28 pm
by BadLuckBurt
Jeoshua wrote: Fri Dec 27, 2019 9:14 pm I had assumed that since that value is readonly I couldn't replace it. Shows what I know, I guess. So I assume I have to replace the whole class. I wonder if I can use inheritance to limit what I actually have to rewrite.
If it wasn't for Hazelnut, I wouldn't have known what to do either. I just copied the entire class for both the sampler and texturing and changed what I needed to create a proof of concept. But your approach is different from mine so perhaps wait until Hazelnut and / or Interkarma have a chance to reply or give inheritance a shot if you feel like pushing forward. The structs might give you some trouble and my knowledge of C# is too limited to advise on that.

Re: Custom world implementation: Need assistance.

Posted: Fri Dec 27, 2019 11:35 pm
by Jeoshua
Basically I just have to replace one procedure to make it check the texture file for a value instead of the height sample being equal to a static value. It will be slightly slower but hopefully not by much since the file should already be in memory.

Re: Custom world implementation: Need assistance.

Posted: Sat Dec 28, 2019 9:29 pm
by Jeoshua
Well, the inheritance works, I think, but the code to inject it doesn't. I think I understand what it's supposed to do, by swapping the script that the game object points to. Doesn't matter if the code is immutable then, since the GameObject isn't.

When was the last time you tried to run this? I get an error on compile:

Code: Select all

error CS16061: Type `Daggerfall Workshop.DaggerfallUnity' does not contain a definition for `TerrainTexturing' and no extension method `TerrainTexturing' could be found. Are you missing an assembly reference?
And, when checking out Daggerfall.cs, indeed, there is no such entry. The only reference to the terrain texturing system I can find is in StreamingWorld.cs, and that's the readonly member.

Re: Custom world implementation: Need assistance.

Posted: Sat Dec 28, 2019 9:47 pm
by BadLuckBurt
Jeoshua wrote: Sat Dec 28, 2019 9:29 pm Well, the inheritance works, I think, but the code to inject it doesn't. I think I understand what it's supposed to do, by swapping the script that the game object points to. Doesn't matter if the code is immutable then, since the GameObject isn't.

When was the last time you tried to run this? I get an error on compile:

Code: Select all

error CS16061: Type `Daggerfall Workshop.DaggerfallUnity' does not contain a definition for `TerrainTexturing' and no extension method `TerrainTexturing' could be found. Are you missing an assembly reference?
And, when checking out Daggerfall.cs, indeed, there is no such entry. The only reference to the terrain texturing system I can find is in StreamingWorld.cs, and that's the readonly member.
I built the mod and ran it today actually but as I said, I copied the entire class so I'm not inheriting anything but instead replace the default TerrainTexturing instance with my own. I'm going to look up an answer Meritamas passed on from a PM convo he had with Interkarma about roads.

- edit

Checked the PM and that was about the terrain sampler itself but it probably holds true for the terrain texturing class as well.

Do you have any particular reason for not wanting to copy the class like I did? Terrain texturing isn't likely to change in the near future unless someone specifically decides to work on that.

I'm not familiar with your entire setup but if I understand correctly, you have an RGB color image to assign terrain textures?

-edit 2

I checked my own class and it's inheriting from ITerrainTexturing, not TerrainTexturing. ITerrainTexturing is an interface which defines the methods and structs that are expected for a custom TerrainTexturing class. I will add that Hazelnut took care of this part for me so he can probably clear things up after the holidays have passed.

Re: Custom world implementation: Need assistance.

Posted: Sat Dec 28, 2019 10:00 pm
by Jeoshua
Well yes and no. I have a Texture2d image in which one channel is height, another is water, and a third is vegetation/wetness. The idea is to use the values from the blue channel to declare "this is a water tile". The way the game works by default there is no way to do this, as water is height based only (or set in locations which is out of scope here), and this is set in the TerrainTexturing class.

I just wanted to limit my effort in replacing the whole class, and by C# semantics it should work, but the stopping point I'm reaching is before that. The idea of replacing the TerrainTexturing class is sound, except DaggerfallUnity.TerrainTexturing does not seem to exist for me. I'm using the latest source code from Git as of the day before Christmas.

Re: Custom world implementation: Need assistance.

Posted: Sat Dec 28, 2019 10:03 pm
by BadLuckBurt
Jeoshua wrote: Sat Dec 28, 2019 10:00 pm Well yes and no. I have a Texture2d image in which one channel is height, another is water, and a third is vegetation/wetness. The idea is to use the values from the blue channel to declare "this is a water tile". The way the game works by default there is no way to do this, as water is height based only (or set in locations which is out of scope here), and this is set in the TerrainTexturing class.

I just wanted to limit my effort in replacing the whole class, and by C# semantics it should work, but the stopping point I'm reaching is before that. The idea of replacing the TerrainTexturing class is sound, except DaggerfallUnity.TerrainTexturing does not seem to exist for me. I'm using the latest source code from Git as of the day before Christmas.
I think you need to use DaggerfallUnity.Instance.TerrainTexturing:

Code: Select all

DaggerfallUnity.Instance.TerrainTexturing = new BLBTerrainTexturing();
If you have a repository I could take a look at I might be able to say more but without seeing the code, it's kinda hard to tell, especially with my limited understanding of C# but if you want to replace the whole class, that's exactly what my mod is doing.

Re: Custom world implementation: Need assistance.

Posted: Sat Dec 28, 2019 10:29 pm
by Jeoshua
I mistyped. My code is exactly like that, barring a different TerrainTexturing replacement.

Code: Select all

Daggerfallunity.Instance.TerrainTexturing = new HiResTerrainTexturing() 
I have tried using inheritance and just a straight replacement copy, neither one gets past the error that the thing doesn't exist for the compiler. DaggerfallUnity.Instance returns a reference to the DaggerfallUnity class, which for me does not contain anything named TerrainTexturing.