Merge branch 'master' into custom_blocky_mesh
# Conflicts: # util/array_slice.hmaster
commit
f5001fdc07
10
README.md
10
README.md
|
@ -11,11 +11,11 @@ Features
|
|||
---------------------------
|
||||
|
||||
- Realtime editable, 3D based terrain (Unlike a heightmap based terrain, this allows for overhangs, tunnels, and user creation/destruction)
|
||||
- Full collision support
|
||||
- Physics based collision and raycast support
|
||||
- Infinite terrains made by paging sections in and out
|
||||
- Voxel data is streamed from a variety of sources, which includes the ability to write your own
|
||||
- Voxel data is streamed from a variety of sources, which includes the ability to write your own generators
|
||||
- Minecraft-style blocky voxel terrain, with multiple materials and baked ambient occlusion
|
||||
- Smooth terrain using Dual Marching Cubes
|
||||
- Smooth terrain using Transvoxel
|
||||
- Levels of detail for smooth terrain
|
||||
- Voxel storage using 8-bit channels for any general purpose
|
||||
|
||||
|
@ -32,7 +32,7 @@ What This Module Doesn't Provide
|
|||
How To Install And Use
|
||||
-------------------------
|
||||
|
||||
Voxel Tools is a custom C++ module for Godot 3.1+. It must be compiled into the engine to work.
|
||||
Voxel Tools is a custom C++ module for Godot 3.1+. It must be compiled into the engine to work. [Prebuilt binaries](http://tokisan.com/godot-binaries) are available.
|
||||
|
||||
Please see the [Getting Started Guide](doc/01_get-started.md) for instructions, or [Zylann's demos](https://github.com/Zylann/voxelgame) and [TinmanJuggernaut's demo](https://github.com/tinmanjuggernaut/voxelgame) for working examples.
|
||||
|
||||
|
@ -44,5 +44,5 @@ These are some ideas that may or may not be implemented in the future:
|
|||
|
||||
* LOD (in development)
|
||||
* Support general voxel use (not just terrains)
|
||||
* Transvoxel and other meshing algorithms
|
||||
* Other meshing algorithms (e.g. dual contouring)
|
||||
* GPU Offloading (Maybe when Godot 4+ supports compute shaders)
|
||||
|
|
17
config.py
17
config.py
|
@ -1,5 +1,4 @@
|
|||
|
||||
|
||||
def can_build(env, platform):
|
||||
return True
|
||||
|
||||
|
@ -20,21 +19,27 @@ def get_doc_classes():
|
|||
"VoxelLodTerrain",
|
||||
|
||||
"VoxelStream",
|
||||
"VoxelStreamTest",
|
||||
"VoxelStreamImage",
|
||||
"VoxelStreamNoise",
|
||||
"VoxelStreamFile",
|
||||
"VoxelStreamBlockFiles",
|
||||
"VoxelStreamRegionFiles",
|
||||
|
||||
"VoxelGenerator",
|
||||
"VoxelGeneratorHeightmap",
|
||||
"VoxelGeneratorImage",
|
||||
"VoxelGeneratorNoise",
|
||||
"VoxelGeneratorNoise2D",
|
||||
"VoxelGeneratorTest",
|
||||
|
||||
"VoxelBoxMover",
|
||||
"VoxelIsoSurfaceTool",
|
||||
"VoxelTool",
|
||||
"VoxelRaycastResult",
|
||||
|
||||
"VoxelMesher",
|
||||
"VoxelMesherBlocky",
|
||||
"VoxelMesherTransvoxel",
|
||||
"VoxelMesherDMC"
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
|
||||
def get_doc_path():
|
||||
|
|
|
@ -2,18 +2,21 @@
|
|||
|
||||
Voxel Tools for Godot is a C++ module that must be compiled into the engine. It requires version 3.1+. The following guide will give you a build of Godot that supports Voxel Tools and show you how to use it.
|
||||
|
||||
[Prebuilt binaries](http://tokisan.com/godot-binaries) are also available.
|
||||
|
||||
## Tutorials
|
||||
|
||||
* [Building Godot With Voxel Tools](02_build-voxel-tools.md)
|
||||
* [Creating A Voxel Terrain](03_create-terrain.md)
|
||||
* [Texturing & Materials](04_materials.md)
|
||||
* [Collision](05_collision.md)
|
||||
* [Custom Data Streams](06_custom-streams.md)
|
||||
* [Custom Data Generators](06_custom-generator.md)
|
||||
* [Performance Tips](07_performance-tips.md)
|
||||
|
||||
## API
|
||||
* [Overview](08_api-overview.md)
|
||||
* [API Class List](api/Class_List.md)
|
||||
* [Region files specification](specs/region_format.md)
|
||||
|
||||
|
||||
## External Reference
|
||||
|
@ -21,5 +24,5 @@ Find more information about related topics here.
|
|||
|
||||
* [Custom C++ modules in Godot](https://godot.readthedocs.io/en/latest/development/cpp/custom_modules_in_cpp.html)
|
||||
* [Dual Marching Cubes algorithm](https://www.volume-gfx.com/volume-rendering/dual-marching-cubes/)
|
||||
|
||||
* [Transvoxel algorithm](https://transvoxel.org/)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ These steps will walk you through creating a custom build of Godot with the Voxe
|
|||
|
||||
## Build Godot From Source
|
||||
1. Download and compile the [Godot source](https://github.com/godotengine/godot) by following [the official guide](https://docs.godotengine.org/en/latest/development/compiling/index.html). If you want to regularly update your build (recommended), clone the repository with Git instead of downloading a zip file.
|
||||
1. Generally you want the master branch to match with the master branch of Voxel Tools. However as of Godot 3.1, a stable branch is being maintained.
|
||||
1. Make sure to select the appropriate branches. Generally the master branch of Voxel Tools will build with the master branch and other recent branches of Godot. If there is a versioned Voxel Tools branch (e.g. 3.1), that is intended to match the corresponding version of Godot.
|
||||
1. Build Godot before adding this or any other modules and make sure it produces an executable.
|
||||
1. Run the newly built executable found in `godot/bin`. Look under Help/About and confirm that the version string indicates you are running a development version (e.g. 3.2dev.custom_build.ee5ba3e).
|
||||
|
||||
|
@ -12,8 +12,8 @@ These steps will walk you through creating a custom build of Godot with the Voxe
|
|||
## Add Voxel Tools
|
||||
|
||||
1. Download or clone the repository for [Voxel Tools](https://github.com/Zylann/godot_voxel). Use Git to clone the repository if you want to make it easy to update your builds (recommended).
|
||||
1. Generally you want the master branch to get the latest features and fixes. If you desired, you can use the branch that corresponds with Godot's stable branch (e.g. godot3.1).
|
||||
1. Place the Voxel Tools directory inside your Godot source, in the `godot/modules` directory.
|
||||
1. Make sure to select the branch that corresponds with Godot's branch.
|
||||
1. Place the Voxel Tools directory inside your Godot source tree, in the `godot/modules` directory.
|
||||
1. Rename the Voxel Tools folder to `voxel`. When correct, the files (e.g. README.md) will be located in `godot/modules/voxel`. **This is important!**
|
||||
1. Rebuild Godot and make sure it produces an executable.
|
||||
1. Test that your build has Voxel support:
|
||||
|
@ -31,7 +31,7 @@ If you cloned Godot and Voxel Tools, you can use git to update your local code.
|
|||
1. Rebuild Godot.
|
||||
|
||||
**Note:**
|
||||
Since you are pulling from two development branches, it's probable that on occasion your build won't compile, your project won't open, or your Voxel Tools won't work properly or even crash Godot. To minimize downtime, save your successful builds. Move them out of the build folder and rename them with the version number (e.g. godot-3.2-ee5ba3e.exe). This way, you can continue to use previously working builds until the Godot or Voxel developers fix whatever is broken. It is generally desired by all that code published to repositories will at least build, but stuff happens.
|
||||
Since you are pulling from two development branches, it's probable that on occasion your build won't compile, your project won't open, or your Voxel Tools won't work properly or even crash Godot. To minimize downtime, save your successful builds. Move them out of the build folder and rename them with the version number (e.g. godot-3.2+ee5ba3e.exe). This way, you can continue to use previously working builds until the Godot or Voxel developers fix whatever is broken. It is generally desired by all that code published to repositories will at least build, but stuff happens.
|
||||
|
||||
|
||||
---
|
||||
|
|
|
@ -2,17 +2,21 @@
|
|||
# Creating A Voxel Terrain
|
||||
Now that your Godot Engine has voxel support built in, you can either download one of the demos ([Zylann's demos](https://github.com/Zylann/voxelgame) or [TinmanJuggernaut's fps_demo](https://github.com/tinmanjuggernaut/voxelgame)) and start playing with them, or start creating your own terrain.
|
||||
|
||||
Watch this 20 minute video tutorial, or work through the text tutorial below for quick answers.
|
||||
|
||||
[![How To Make Voxel Terrains In Godot](http://i3.ytimg.com/vi/zfzmcbR1H_0/maxresdefault.jpg)](https://www.youtube.com/watch?v=zfzmcbR1H_0)
|
||||
|
||||
|
||||
## Create A Terrain In The Editor: VoxelTerrain + Heightmap
|
||||
1. Create a new project and a new 3D scene, with a Spatial type root node.
|
||||
1. Add a Camera and elevate it by setting the transform: Translation Y = 75 and Rotation X = -25. The terrain starts generating around (0,0,0), but creates high hills, and may be invisible from underneath. We will be looking down from above.
|
||||
1. Import a black and white heightmap texture such as [this one](https://github.com/Zylann/voxelgame/blob/master/project/blocky_terrain/noise_distorted.png) from the demo. Make sure that the file is imported as an Image and NOT a Texture on the Import panel. You'll likely have to re-import and restart.
|
||||
1. Add a `VoxelTerrain` node and adjust the following settings:
|
||||
1. Stream: New VoxelStreamImage. Then click VoxelStreamImage again.
|
||||
1. Image: Load. Select your imported noise texture.
|
||||
1. Decide on the type of terrain you want:
|
||||
* Blocky: Set Channel = "Type" (or 0), and leave Smooth Meshing Enabled unchecked (lower down).
|
||||
* Smooth: Set Channel = "SDF" (or 1), and enable Smooth Meshing Enabled.
|
||||
1. Voxel Library: add a New VoxelLibrary
|
||||
1. Stream: New VoxelGeneratorImage. Then click VoxelGeneratorImage again.
|
||||
1. Select the type of terrain you want:
|
||||
* Blocky: Set Channel = "Type".
|
||||
* Smooth: Set Channel = "SDF".
|
||||
1. Image: Load. Select your imported noise image.
|
||||
1. Set the Viewer Path, Assign, select your camera or player (the parent of your camera).
|
||||
1. Play your scene and you should see a terrain.
|
||||
|
||||
|
@ -22,7 +26,7 @@ Now that your Godot Engine has voxel support built in, you can either download o
|
|||
|
||||
|
||||
## Create A Terrain In The Editor: VoxelLODTerrain + 3D Noise
|
||||
Here we'll look at `VoxelLODTerrain` with a noise data stream.
|
||||
Here we'll look at `VoxelLODTerrain` with a noise data generator.
|
||||
|
||||
1. Create a new project and a new 3D scene, with a Spatial type root node.
|
||||
1. Add a Camera and adjust the following settings:
|
||||
|
@ -30,7 +34,7 @@ Here we'll look at `VoxelLODTerrain` with a noise data stream.
|
|||
1. Rotation X = -25.
|
||||
1. Far: 2048 (or up to the maximum of 8192, which I use).
|
||||
1. Add a `VoxelLODTerrain` node and adjust the following settings:
|
||||
1. Stream: New VoxelStreamNoise. Then click VoxelStreamNoise again.
|
||||
1. Stream: New VoxelGeneratorNoise. Then click VoxelGeneratorNoise again.
|
||||
1. Noise: New OpenSimplexNoise. Then click OpenSimplexNoise again. Leave the settings at the default, but here's where they are.
|
||||
1. Set the Viewer Path, Assign, select your camera or player (the parent of your camera).
|
||||
1. Play your scene and you should see a terrain.
|
||||
|
@ -70,14 +74,14 @@ const HEIGHT_MAP = preload("res://blocky_terrain/noise_distorted.png")
|
|||
var terrain = VoxelTerrain.new()
|
||||
|
||||
func _ready():
|
||||
terrain.voxel_library = VoxelLibrary.new()
|
||||
terrain.stream = VoxelStreamImage.new()
|
||||
terrain.stream = VoxelGeneratorImage.new()
|
||||
terrain.stream.image = HEIGHT_MAP
|
||||
terrain.view_distance = 256
|
||||
terrain.viewer_path = "/root/Spatial/Player" # Change to the path of your camera or player node
|
||||
add_child(terrain) # Add the terrain to the tree so Godot will render it
|
||||
```
|
||||
|
||||
For a full example, see my [demo code](https://github.com/tinmanjuggernaut/voxelgame/blob/master/project/fps_demo/scripts/CodeTerrain.gd).
|
||||
|
||||
---
|
||||
* [Next Page](04_materials.md)
|
||||
|
|
|
@ -6,24 +6,24 @@ Here are some notes for better results.
|
|||
|
||||
## Recommended Reading
|
||||
|
||||
* [SpatialMatieral](https://docs.godotengine.org/en/3.1/tutorials/3d/spatial_material.html) - demonstrates many of the shader options available in Godot.
|
||||
* [Shading Index](https://docs.godotengine.org/en/3.1/tutorials/shading/index.html) - tutorials and the shader language API
|
||||
* [SpatialMaterial](https://docs.godotengine.org/en/latest/tutorials/3d/spatial_material.html) - demonstrates many of the shader options available in Godot.
|
||||
* [Shading Index](https://docs.godotengine.org/en/latest/tutorials/shading/index.html) - tutorials and the shader language API
|
||||
* Shader API Reference - some of the most frequently accessed references
|
||||
* [Shading Language](https://docs.godotengine.org/en/3.1/tutorials/shading/shading_reference/shading_language.html)
|
||||
* [SpatialShader](https://docs.godotengine.org/en/3.1/tutorials/shading/shading_reference/spatial_shader.html)
|
||||
* [Shading Language](https://docs.godotengine.org/en/latest/tutorials/shading/shading_reference/shading_language.html)
|
||||
* [SpatialShader](https://docs.godotengine.org/en/latest/tutorials/shading/shading_reference/spatial_shader.html)
|
||||
|
||||
|
||||
## Triplanar Mapping
|
||||
|
||||
Projecting a flat, 2D image texture onto a rounded terrain is like wrapping a piece of paper wrapped around a sphere. It often warps the texture in undesirable ways. Triplanar mapping is a wrapping method that provides a reasonable result for spheres and terrains.
|
||||
|
||||
The method involves projecting the texture onto only part of object that faces the X-axis directly. Then projecting it on the sides that face the Y-axis directly. Then again for the Z-axis. The edges of these projections are then blended together with a specified sharpness.
|
||||
The method involves projecting the texture on to the part of object that directly faces the X-axis. Then projecting it on the sides that directly face the Y-axis. Then again for the Z-axis. The edges of these projections are then blended together with a specified sharpness.
|
||||
|
||||
Look at how the brick textures are blended together on the top right sphere.
|
||||
|
||||
![Triplanar mapping image](https://docs.godotengine.org/en/3.1/_images/spatial_material25.png)
|
||||
|
||||
Read about [triplanar mapping in Godot](https://docs.godotengine.org/en/3.1/tutorials/3d/spatial_material.html?highlight=triplanar%20#triplanar-mapping).
|
||||
Read about [triplanar mapping in Godot](https://docs.godotengine.org/en/latest/tutorials/3d/spatial_material.html?highlight=triplanar%20#triplanar-mapping).
|
||||
|
||||
The algorithm to implement this is a little complicated, which gets far worse if you also wish to add normal maps and others. However there is a very easy way to do this in the section below.
|
||||
|
||||
|
@ -35,18 +35,23 @@ Rather than writing your own shader from scratch, especially with triplanar mapp
|
|||
1. Add an albedo texture, and if desired, normal map, ambient occlusion, etc.
|
||||
1. Under UV1, turn on triplanar mapping and adjust triplanar sharpness as desired.
|
||||
1. Scale and style the material as desired.
|
||||
1. Optionally [convert the material to a shader](#convert-to-shader-code).
|
||||
|
||||
If you want to start without a texture and just want to use a color, try turning down roughness, or adding some metalic to give the surface some reflectivity. This will allow light to reflect off the curves of the terrain in the distance. Otherwise you'll just see an undifferentiated mass of color.
|
||||
If you want to start without a texture and just want to use a color, try turning down roughness, or adding some metalic to give the surface some reflectivity. This will allow light to reflect off of the curves of the terrain in the distance. Otherwise you'll just see an undifferentiated mass of color.
|
||||
|
||||
## Enable Built-In Ambient Occlusion
|
||||
VoxelTerrain adds Ambient Occlusion to the vertex colors on blocky terrains. You can add this to your material by enabling the `Vertex Color/Use As Albedo` flag in your material. Below is what that looks like on an otherwise plain white material. AO can also be added to any terrain using the AO feature built in to materials.
|
||||
|
||||
<img src="https://github.com/tinmanjuggernaut/voxelgame/raw/master/screenshots/blocky-vertex-color.jpg" width="800" />
|
||||
|
||||
|
||||
## How To View Live Changes To Materials
|
||||
You can't see the terrain in the viewport, so there are two options to view your material live while making changes:
|
||||
## How To View Live Changes To Materials Or When Placing Objects
|
||||
You can't view the terrain in the editor, so there are two options to view your material live while making changes:
|
||||
* Add a sphere or cube with the same material, then adjust the material in the editor. This option is OK, but the UV scale is usually different than the terrain, so it's not ideal.
|
||||
* Run your scene, focus the camera on the terrain, reduce the game window and move it to the side, then move the editor window to the other side. With both the editor and game displayed simultaneously, you can adjust the material in the inspector panel and it will update live. All edits to a SpatialMaterial or the shader parameters of your ShaderMaterial will update live. Editing your shader code will not update live. (Though it may be possible to trigger the engine to recompile your shader code.)
|
||||
* Run your scene, focus the camera on the terrain, reduce the game window and move it to the side, then move the editor window to the other side. With both the editor and game displayed simultaneously, you can adjust the material in the inspector panel and it will update live.
|
||||
|
||||
All edits to a SpatialMaterial or the shader parameters of your ShaderMaterial will update live. Editing your shader code will not update live. (Though it may be possible to trigger the engine to recompile your shader code.) You can also use this method to place objects.
|
||||
|
||||
|
||||
## Convert To Shader Code
|
||||
|
||||
|
@ -60,6 +65,7 @@ Your material now has shader code that produces the same material your SpatialMa
|
|||
|
||||
Note, you can't edit the shader code and see live changes. You must stop and restart your scene. However you can change shader parameters live.
|
||||
|
||||
|
||||
## Advanced Shading
|
||||
|
||||
One of the best ways to learn about shaders is to pick apart and experiment with other's shader code.
|
||||
|
|
|
@ -4,7 +4,7 @@ Physics based collision is enabled by default. It provides both raycasting and c
|
|||
|
||||
You can turn it on or off by setting the `generate_collisions` option on any of the terrain nodes. Or you can enable or disable it in code.
|
||||
|
||||
The collision is built along with the mesh. So any blocks that have already been built will not be affected by the setting unless they are regenerated.
|
||||
The collision is built along with the mesh. So any blocks that have already been built will not be affected by this setting unless they are regenerated.
|
||||
|
||||
|
||||
## Debugging
|
||||
|
@ -63,5 +63,5 @@ if terrain.raycast(...):
|
|||
|
||||
|
||||
---
|
||||
* [Next Page](06_custom-streams.md)
|
||||
* [Next Page](06_custom-generator.md)
|
||||
* [Doc Index](01_get-started.md)
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
# Create Your Own Voxel Data Stream
|
||||
You can provide your own stream of voxel data by extending VoxelStream either in GDScript or C++.
|
||||
# Generate Your Own Voxel Data
|
||||
You can provide your own voxel generator by extending VoxelGenerator in either GDScript or C++.
|
||||
|
||||
Note: Your stream must be thread safe.
|
||||
Note: Your generator must be thread safe.
|
||||
|
||||
Create MyStream.gd with the following contents:
|
||||
|
||||
```
|
||||
extends VoxelStream
|
||||
|
||||
func emerge_block(buffer:VoxelBuffer, origin:Vector3, lod:int) -> void:
|
||||
extends VoxelGenerator
|
||||
|
||||
export var channel:int = VoxelBuffer.CHANNEL_TYPE
|
||||
|
||||
func get_used_channels_mask () -> int:
|
||||
return 1<<channel
|
||||
|
||||
func generate_block(buffer:VoxelBuffer, origin:Vector3, lod:int) -> void:
|
||||
if lod != 0: return
|
||||
if origin.y < 0: buffer.fill(1, 0)
|
||||
if origin.x==origin.z and origin.y < 1: buffer.fill(1,0)
|
||||
if origin.y < 0: buffer.fill(1, channel)
|
||||
if origin.x==origin.z and origin.y < 1: buffer.fill(1,channel)
|
||||
```
|
||||
|
||||
In your terrain generation script, add this:
|
||||
|
@ -22,7 +27,6 @@ var terrain = VoxelTerrain.new()
|
|||
|
||||
func _ready():
|
||||
terrain.stream = MyStream.new()
|
||||
terrain.voxel_library = VoxelLibrary.new()
|
||||
terrain.view_distance = 256
|
||||
terrain.viewer_path = "/root/Spatial/Player" # Set this path to your player/camera
|
||||
add_child(terrain)
|
||||
|
@ -30,9 +34,9 @@ func _ready():
|
|||
|
||||
<img src="images/custom-stream.jpg" width="800" />
|
||||
|
||||
Though `VoxelBuffer.fill()` is probably not what you want to use, the above is a quick example. Emerge_block generally gives you a block of 16x16x16 cubes to fill all at once, so you probably want to use `VoxelBuffer.set_voxel()` to specify each one.
|
||||
Though `VoxelBuffer.fill()` is probably not what you want to use, the above is a quick example. Generate_block generally gives you a block of 16x16x16 cubes to fill all at once, so you'll want to use `VoxelBuffer.set_voxel()` to specify each one. You can change the channel to `VoxelBuffer.CHANNEL_SDF` to get smooth voxels.
|
||||
|
||||
In the fps_demo, there is a [custom gdscript stream](https://github.com/tinmanjuggernaut/voxelgame/blob/master/project/fps_demo/scripts/MyStream.gd) that makes a sine wave. This was copied from the [C++ version](../streams/voxel_stream_test.cpp), which runs a lot faster.
|
||||
In the fps_demo, there is a [custom gdscript stream](https://github.com/tinmanjuggernaut/voxelgame/blob/master/project/fps_demo/scripts/MyStream.gd) that makes a sine wave. This was copied from the [C++ version](../generators/voxel_generator_waves.cpp), which runs a lot faster.
|
||||
|
||||
<img src="images/custom-stream-sine.jpg" width="800" />
|
||||
|
|
@ -4,11 +4,15 @@
|
|||
|
||||
* Excessive noise height will kill your performance, use with care. A height range of 300 can run at 300-400fps on a GTX1060, but a range of 6-10,000 might run at 30-40fps. Hopefully this will be addressed when occlusion culling and other features are available in Godot 4.
|
||||
|
||||
* Lower shadow distance. I might use 200-400 on a GTX1060, but maybe 20 or disabled on an integrated card.
|
||||
* Lower shadow distance on your directional light. I might use 200-400 on a GTX1060, but maybe 20 or disable shadows altogether on an integrated card.
|
||||
|
||||
* Use only one directional light. A second cost me a 12% performance hit.
|
||||
|
||||
* VoxelLodTerrain has a `collision_lod_count` that limits the creation of collision shapes for distant LODs. Try setting it to 2-3 or higher.
|
||||
|
||||
* Optimize and simplify your shaders. In the fps_demo, there are two grass-rock shaders. The second version randomizes the tiling of texture maps so there is no obvious repeating pattern. It only requires two extra texture lookups, but it pretty much halves my frame rate from around 300 to 150 or less.
|
||||
|
||||
|
||||
* Use Linux. On my system, my demo runs with a 30-100% higher frame rate under linux.
|
||||
|
||||
|
||||
---
|
||||
|
|
|
@ -38,7 +38,7 @@ Note that the engine and your graphics card do not work with voxels. They are co
|
|||
|
||||
**Smooth [Terrain]** - One of many isosurface extraction algorithms that attempts to represent voxel data with smoother surfaces and is a better fit for organic shapes. Rather than using a full cube to describe the surface, a cube with one or more planes at potentially any angle is used to provide a far more accurate representation of the source data. As an example if you took a Lego block and sanded down the sharp corners to better represent the airplane curves, or sanded down the tops of the bar chart to better represent the bell curve. However you can only sand down to flat planes, no curves within the cubes.
|
||||
|
||||
Voxel Tools supports Dual Marching Cubes, Transvoxel (WIP) and is structured to support other algorithms in the future. Some are faster, use less memory, provide manifold meshes (cleaner meshes), and/or provide more accurate representations of the voxel data.
|
||||
Voxel Tools supports Dual Marching Cubes, Transvoxel, and is structured to support other algorithms in the future. Various algorithms are faster, use less memory, provide manifold (cleaner) meshes, allow for sharp edges, and/or provide more accurate representations of the voxel data.
|
||||
|
||||
**LOD - Level of Detail** - As the camera gets further away, detail decreases to improve performance.
|
||||
|
||||
|
@ -57,7 +57,7 @@ Note: Terrains use their VoxelStream and VoxelMeshers from multiple threads. Acc
|
|||
### VoxelTerrain
|
||||
An infinite, paged terrain made of voxel blocks, all with the same level of detail. Voxels are polygonized around the viewer by distance in a large cubic space.
|
||||
|
||||
* Voxel data is streamed using a VoxelStream (e.g. noise image, 3D noise texture, etc).
|
||||
* Voxel data is streamed using a VoxelGenerator (e.g. noise image, 3D noise texture, etc).
|
||||
* Stores a terrain in a VoxelMap.
|
||||
* Supports blocky and smooth terrains.
|
||||
* Handles the main Godot \_process() call to update the terrain, load and unload voxel blocks, and generate the mesh and collision.
|
||||
|
@ -67,7 +67,7 @@ An infinite, paged terrain made of voxel blocks, all with the same level of deta
|
|||
### VoxelLodTerrain
|
||||
An infinite, paged terrain made of voxel blocks with a variable level of detail. Designed for high view distances. Voxels are polygonized around the viewer by distance in a very large sphere.
|
||||
|
||||
* Data is streamed using a VoxelStream, which must support LOD.
|
||||
* Data is streamed using a VoxelGenerator, which must support LOD.
|
||||
* Stores a terrain in a VoxelMap.
|
||||
* Handles the main Godot \_process() call to update the terrain, load and unload voxel blocks, and generate the mesh and collision.
|
||||
* Supports only smooth terrains.
|
||||
|
@ -79,29 +79,31 @@ An infinite, paged terrain made of voxel blocks with a variable level of detail.
|
|||
|
||||
These classes provide the source voxel data.
|
||||
|
||||
### VoxelStream
|
||||
### VoxelGenerator
|
||||
Base class to provide infinite, paged voxel data as blocks. Doesn't provide data itself, but can be extended with GDScript.
|
||||
|
||||
If you choose to implement your own stream that does not offer LOD, it is recommended to `assert(lod == 0)`. It will be executed in a separate thread, so access the main thread with care.
|
||||
If you choose to implement your own generator that does not offer LOD, it is recommended to `assert(lod == 0)`. It will be executed in a separate thread, so access the main thread with care.
|
||||
|
||||
The classes below provide voxel data.
|
||||
|
||||
### VoxelStreamTest
|
||||
Provides a flat plane or 2D sine waves.
|
||||
### VoxelGeneratorFlat
|
||||
Generates a flat world.
|
||||
|
||||
* Blocky only.
|
||||
### VoxelGeneratorWaves
|
||||
Generates regular waves.
|
||||
|
||||
### VoxelStreamImage
|
||||
### VoxelGeneratorImage
|
||||
Creates a heightmap based on a user provided, black and white image.
|
||||
|
||||
This class expects the image to be imported as an Image. By default, image files are imported as a Texture, which are stored in video RAM and are not accessible to the engine. On the Import tab, you need to change the import method of your image to Image and may need to restart Godot before VoxelStreamImage will recognize your file.
|
||||
|
||||
* Blocky or smooth.
|
||||
For smooth terrain, it is recommended to use more than 8-bit precision images, using either EXR or HDR formats. Formats loaded as 8-bit such as PNG or JPG are supported but will look blocky at close range.
|
||||
|
||||
### VoxelStreamNoise
|
||||
Generates 3D noise via OpenSimplexNoise.
|
||||
### VoxelGeneratorNoise
|
||||
Generates organic-looking terrain using a 3D noise algorithm. This one can have caves and overhangs but loads slower.
|
||||
|
||||
* Smooth only.
|
||||
### VoxelGeneratorNoise2D
|
||||
Generates organic-looking terrain using a 3D noise algorithm. This one doesn't have overhangs but loads faster.
|
||||
|
||||
|
||||
## Mesher Classes
|
||||
|
@ -111,7 +113,7 @@ These classes use full cubes or an isosurface extraction algorithm to represent
|
|||
Note: Their initial use case was for terrains, so the input data must be padded by a certain amount of voxels to work (get_minimum_padding() gives you that number. It's usually 1 or 2).
|
||||
|
||||
### VoxelMesher
|
||||
Abstract base class to build a polygonal terrain mesh from a given VoxelBuffer. Unlike VoxelStream, this class cannot be implemented with a script. You must extend it with a C++ class to implement another meshing algorithm.
|
||||
Abstract base class to build a polygonal terrain mesh from a given VoxelBuffer. Unlike VoxelGenerator, this class cannot be implemented with a script. You must extend it with a C++ class to implement another meshing algorithm.
|
||||
|
||||
### VoxelMesherBlocky
|
||||
Builds a mesh using full cubes only. Looks like Minecraft.
|
||||
|
@ -132,9 +134,7 @@ Builds a smooth mesh using the Dual Marching Cubes algorithm.
|
|||
### VoxelMesherTransvoxel
|
||||
Builds a smooth mesh using the Transvoxel algorithm.
|
||||
|
||||
* Development is on hold for now. Use DMC.
|
||||
* Partial implementation, which may or may not be broken.
|
||||
|
||||
* This is now the default smooth mesher.
|
||||
|
||||
|
||||
## Storage Classes
|
||||
|
@ -150,7 +150,7 @@ Where Terrains store their voxels, as an infinite, 3D, sparse grid. It can be th
|
|||
Note: There are two grid coordinate systems. One addresses voxels individually, the other addresses blocks. It was initially required to allow streaming of the world, because loading voxels individually would have been very expensive. So instead I load chunks (like Minecraft), and those chunks lie in a grid having a step 16 times larger (because each block contains 16\*16\*16 voxels). When LOD is considered, there are even multiple block grids, but each having a scale higher by powers of two.
|
||||
|
||||
|
||||
### VoxelBlock (Unregistered)
|
||||
### VoxelBlock (not exposed)
|
||||
Internal structure for holding a reference to mesh visuals, collision, and a block of voxel data. Not available to GDScript, but supports both the above and below classes.
|
||||
|
||||
* Stores 3D grid position and LOD index.
|
||||
|
@ -167,26 +167,26 @@ The underlying storage for voxels. Also used to pass voxels between functions.
|
|||
|
||||
## Supporting Classes
|
||||
|
||||
### VoxelIsoSurfaceTool
|
||||
Provides functions to add or remove smooth terrain. Currently supported shapes are sphere, plane, cube, heightmap.
|
||||
### VoxelTool
|
||||
Provides functions to add or remove smooth terrain. The interface provides for points, lines, circles, spheres, boxes, and custom shapes, though not all are implemented.
|
||||
|
||||
* You can generate a 2D heightmap and ask the tool to "rasterize" that portion of the world in a VoxelBuffer, which is what you will have to fill when implementing a custom VoxelStream.
|
||||
* You can generate a 2D heightmap and ask the tool to "rasterize" that portion of the world in a VoxelBuffer, which is what you will have to fill when implementing a custom VoxelGenerator.
|
||||
|
||||
* Since Godot does not support 3D images, a custom shape could be added using an existing VoxelBuffer as input. This is not yet implemented.
|
||||
* Since Godot does not support 3D textures, a custom shape could be added using an existing VoxelBuffer as input. This is not yet implemented.
|
||||
|
||||
|
||||
### VoxelBoxMover
|
||||
Provides Axis Aligned Bounding Box based collision. (blocky only)
|
||||
### VoxelBoxMover (blocky)
|
||||
Provides Axis Aligned Bounding Box based collision.
|
||||
|
||||
|
||||
### Voxel
|
||||
A basic voxel unit. Creating Voxels with VoxelLibrary is recommended. (blocky only)
|
||||
### Voxel (blocky)
|
||||
A basic voxel unit. Creating Voxels with VoxelLibrary is recommended.
|
||||
|
||||
* Stores ID, name, material, transparency and type
|
||||
|
||||
|
||||
### VoxelLibrary
|
||||
A factory for creating Voxels. (blocky only)
|
||||
### VoxelLibrary (blocky)
|
||||
A collection of voxel types, which is used for blocky only, similar to Minecraft or GridMap.
|
||||
|
||||
---
|
||||
* [API Class List](api/Class_List.md)
|
||||
|
|
|
@ -5,7 +5,12 @@ These classes are exposed to GDScript. This information is also available within
|
|||
* [Voxel.md](Voxel.md)
|
||||
* [VoxelBoxMover.md](VoxelBoxMover.md)
|
||||
* [VoxelBuffer.md](VoxelBuffer.md)
|
||||
* [VoxelIsoSurfaceTool.md](VoxelIsoSurfaceTool.md)
|
||||
* [VoxelGenerator.md](VoxelGenerator.md)
|
||||
* [VoxelGeneratorHeightmap.md](VoxelGeneratorHeightmap.md)
|
||||
* [VoxelGeneratorImage.md](VoxelGeneratorImage.md)
|
||||
* [VoxelGeneratorNoise.md](VoxelGeneratorNoise.md)
|
||||
* [VoxelGeneratorNoise2D.md](VoxelGeneratorNoise2D.md)
|
||||
* [VoxelGeneratorTest.md](VoxelGeneratorTest.md)
|
||||
* [VoxelLibrary.md](VoxelLibrary.md)
|
||||
* [VoxelLodTerrain.md](VoxelLodTerrain.md)
|
||||
* [VoxelMap.md](VoxelMap.md)
|
||||
|
@ -13,15 +18,14 @@ These classes are exposed to GDScript. This information is also available within
|
|||
* [VoxelMesherBlocky.md](VoxelMesherBlocky.md)
|
||||
* [VoxelMesherDMC.md](VoxelMesherDMC.md)
|
||||
* [VoxelMesherTransvoxel.md](VoxelMesherTransvoxel.md)
|
||||
* [VoxelRaycastResult.md](VoxelRaycastResult.md)
|
||||
* [VoxelStream.md](VoxelStream.md)
|
||||
* [VoxelStreamBlockFiles.md](VoxelStreamBlockFiles.md)
|
||||
* [VoxelStreamFile.md](VoxelStreamFile.md)
|
||||
* [VoxelStreamImage.md](VoxelStreamImage.md)
|
||||
* [VoxelStreamNoise.md](VoxelStreamNoise.md)
|
||||
* [VoxelStreamRegionFiles.md](VoxelStreamRegionFiles.md)
|
||||
* [VoxelStreamTest.md](VoxelStreamTest.md)
|
||||
* [VoxelTerrain.md](VoxelTerrain.md)
|
||||
* [VoxelTool.md](VoxelTool.md)
|
||||
|
||||
---
|
||||
* [Doc Index](../01_get-started.md)
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: Resource
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -11,56 +11,47 @@ _Godot version: 3.2_
|
|||
|
||||
## Constants:
|
||||
|
||||
#### » GeometryType.GEOMETRY_NONE = 0
|
||||
#### » GeometryType.GEOMETRY_NONE = 0
|
||||
|
||||
|
||||
#### » GeometryType.GEOMETRY_CUBE = 1
|
||||
#### » GeometryType.GEOMETRY_CUBE = 1
|
||||
|
||||
|
||||
#### » GeometryType.GEOMETRY_MAX = 2
|
||||
|
||||
|
||||
#### » ChannelMode.CHANNEL_TYPE = 0
|
||||
|
||||
|
||||
#### » ChannelMode.CHANNEL_ISOLEVEL = 1
|
||||
|
||||
|
||||
#### » ChannelMode.CHANNEL_DATA = 2
|
||||
#### » GeometryType.GEOMETRY_MAX = 2
|
||||
|
||||
|
||||
|
||||
## Properties:
|
||||
|
||||
#### » Color color
|
||||
#### » Color color
|
||||
|
||||
`set_color (value)` setter
|
||||
|
||||
`get_color ()` getter
|
||||
|
||||
|
||||
#### » int Voxel.GeometryType.geometry_type
|
||||
#### » int Voxel.GeometryType.geometry_type
|
||||
|
||||
`set_geometry_type (value)` setter
|
||||
|
||||
`get_geometry_type ()` getter
|
||||
|
||||
|
||||
#### » int material_id
|
||||
#### » int material_id
|
||||
|
||||
`set_material_id (value)` setter
|
||||
|
||||
`get_material_id ()` getter
|
||||
|
||||
|
||||
#### » bool transparent
|
||||
#### » bool transparent
|
||||
|
||||
`set_transparent (value)` setter
|
||||
|
||||
`is_transparent ()` getter
|
||||
|
||||
|
||||
#### » String voxel_name
|
||||
#### » String voxel_name
|
||||
|
||||
`set_voxel_name (value)` setter
|
||||
|
||||
|
@ -70,22 +61,22 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » int get_id ( ) const
|
||||
#### » int get_id ( ) const
|
||||
|
||||
|
||||
#### » Voxel set_color ( Color color )
|
||||
#### » Voxel set_color ( Color color )
|
||||
|
||||
|
||||
#### » Voxel set_id ( int id )
|
||||
#### » Voxel set_id ( int id )
|
||||
|
||||
|
||||
#### » Voxel set_material_id ( int id )
|
||||
#### » Voxel set_material_id ( int id )
|
||||
|
||||
|
||||
#### » Voxel set_transparent ( bool transparent=true )
|
||||
#### » Voxel set_transparent ( bool transparent=true )
|
||||
|
||||
|
||||
#### » Voxel set_voxel_name ( String name )
|
||||
#### » Voxel set_voxel_name ( String name )
|
||||
|
||||
|
||||
|
||||
|
@ -96,4 +87,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: Reference
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -17,7 +17,7 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » Vector3 get_motion ( Vector3 pos, Vector3 motion, AABB aabb, Node terrain )
|
||||
#### » Vector3 get_motion ( Vector3 pos, Vector3 motion, AABB aabb, Node terrain )
|
||||
|
||||
|
||||
|
||||
|
@ -28,4 +28,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: Reference
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -11,31 +11,46 @@ _Godot version: 3.2_
|
|||
|
||||
## Constants:
|
||||
|
||||
#### » ChannelId.CHANNEL_TYPE = 0
|
||||
#### » ChannelId.CHANNEL_TYPE = 0
|
||||
|
||||
|
||||
#### » ChannelId.CHANNEL_ISOLEVEL = 1
|
||||
#### » ChannelId.CHANNEL_SDF = 1
|
||||
|
||||
|
||||
#### » ChannelId.CHANNEL_DATA2 = 2
|
||||
#### » ChannelId.CHANNEL_DATA2 = 2
|
||||
|
||||
|
||||
#### » ChannelId.CHANNEL_DATA3 = 3
|
||||
#### » ChannelId.CHANNEL_DATA3 = 3
|
||||
|
||||
|
||||
#### » ChannelId.CHANNEL_DATA4 = 4
|
||||
#### » ChannelId.CHANNEL_DATA4 = 4
|
||||
|
||||
|
||||
#### » ChannelId.CHANNEL_DATA5 = 5
|
||||
#### » ChannelId.CHANNEL_DATA5 = 5
|
||||
|
||||
|
||||
#### » ChannelId.CHANNEL_DATA6 = 6
|
||||
#### » ChannelId.CHANNEL_DATA6 = 6
|
||||
|
||||
|
||||
#### » ChannelId.CHANNEL_DATA7 = 7
|
||||
#### » ChannelId.CHANNEL_DATA7 = 7
|
||||
|
||||
|
||||
#### » ChannelId.MAX_CHANNELS = 8
|
||||
#### » ChannelId.MAX_CHANNELS = 8
|
||||
|
||||
|
||||
#### » Depth.DEPTH_8_BIT = 0
|
||||
|
||||
|
||||
#### » Depth.DEPTH_16_BIT = 1
|
||||
|
||||
|
||||
#### » Depth.DEPTH_32_BIT = 2
|
||||
|
||||
|
||||
#### » Depth.DEPTH_64_BIT = 3
|
||||
|
||||
|
||||
#### » Depth.DEPTH_COUNT = 4
|
||||
|
||||
|
||||
|
||||
|
@ -44,58 +59,70 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » void clear ( )
|
||||
#### » void clear ( )
|
||||
|
||||
|
||||
#### » void copy_from ( VoxelBuffer other, int channel=0 )
|
||||
#### » void copy_channel_from ( VoxelBuffer other, int channel )
|
||||
|
||||
|
||||
#### » void copy_from_area ( VoxelBuffer other, Vector3 src_min, Vector3 src_max, Vector3 dst_min, int channel=0 )
|
||||
#### » void copy_channel_from_area ( VoxelBuffer other, Vector3 src_min, Vector3 src_max, Vector3 dst_min, int channel )
|
||||
|
||||
|
||||
#### » void create ( int sx, int sy, int sz )
|
||||
#### » void create ( int sx, int sy, int sz )
|
||||
|
||||
|
||||
#### » void fill ( int value, int channel=0 )
|
||||
#### » void downscale_to ( VoxelBuffer dst, Vector3 src_min, Vector3 src_max, Vector3 dst_min ) const
|
||||
|
||||
|
||||
#### » void fill_area ( int value, Vector3 min, Vector3 max, int channel=0 )
|
||||
#### » void fill ( int value, int channel=0 )
|
||||
|
||||
|
||||
#### » void fill_f ( float value, int channel=0 )
|
||||
#### » void fill_area ( int value, Vector3 min, Vector3 max, int channel=0 )
|
||||
|
||||
|
||||
#### » Vector3 get_size ( ) const
|
||||
#### » void fill_f ( float value, int channel=0 )
|
||||
|
||||
|
||||
#### » int get_size_x ( ) const
|
||||
#### » int get_channel_depth ( int channel ) const
|
||||
|
||||
|
||||
#### » int get_size_y ( ) const
|
||||
#### » Vector3 get_size ( ) const
|
||||
|
||||
|
||||
#### » int get_size_z ( ) const
|
||||
#### » int get_size_x ( ) const
|
||||
|
||||
|
||||
#### » int get_voxel ( int x, int y, int z, int channel=0 ) const
|
||||
#### » int get_size_y ( ) const
|
||||
|
||||
|
||||
#### » float get_voxel_f ( int x, int y, int z, int channel=0 ) const
|
||||
#### » int get_size_z ( ) const
|
||||
|
||||
|
||||
#### » bool is_uniform ( int channel ) const
|
||||
#### » int get_voxel ( int x, int y, int z, int channel=0 ) const
|
||||
|
||||
|
||||
#### » void optimize ( )
|
||||
#### » float get_voxel_f ( int x, int y, int z, int channel=0 ) const
|
||||
|
||||
|
||||
#### » void set_voxel ( int value, int x, int y, int z, int channel=0 )
|
||||
#### » VoxelTool get_voxel_tool ( )
|
||||
|
||||
|
||||
#### » void set_voxel_f ( float value, int x, int y, int z, int channel=0 )
|
||||
#### » bool is_uniform ( int channel ) const
|
||||
|
||||
|
||||
#### » void set_voxel_v ( int value, Vector3 pos, int channel=0 )
|
||||
#### » void optimize ( )
|
||||
|
||||
|
||||
#### » void set_channel_depth ( int channel, int depth )
|
||||
|
||||
|
||||
#### » void set_voxel ( int value, int x, int y, int z, int channel=0 )
|
||||
|
||||
|
||||
#### » void set_voxel_f ( float value, int x, int y, int z, int channel=0 )
|
||||
|
||||
|
||||
#### » void set_voxel_v ( int value, Vector3 pos, int channel=0 )
|
||||
|
||||
|
||||
|
||||
|
@ -106,4 +133,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# Class: VoxelGenerator
|
||||
|
||||
Inherits: VoxelStream
|
||||
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
||||
|
||||
|
||||
## Constants:
|
||||
|
||||
|
||||
## Properties:
|
||||
|
||||
|
||||
## Methods:
|
||||
|
||||
#### » void generate_block ( VoxelBuffer out_buffer, Vector3 origin_in_voxels, int lod )
|
||||
|
||||
|
||||
|
||||
## Signals:
|
||||
|
||||
|
||||
---
|
||||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Feb 16, 2020_
|
|
@ -0,0 +1,55 @@
|
|||
# Class: VoxelGeneratorHeightmap
|
||||
|
||||
Inherits: VoxelGenerator
|
||||
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
||||
|
||||
|
||||
## Constants:
|
||||
|
||||
|
||||
## Properties:
|
||||
|
||||
#### » float height_range
|
||||
|
||||
`set_height_range (value)` setter
|
||||
|
||||
`get_height_range ()` getter
|
||||
|
||||
|
||||
#### » float height_start
|
||||
|
||||
`set_height_start (value)` setter
|
||||
|
||||
`get_height_start ()` getter
|
||||
|
||||
|
||||
#### » float iso_scale
|
||||
|
||||
`set_iso_scale (value)` setter
|
||||
|
||||
`get_iso_scale ()` getter
|
||||
|
||||
|
||||
|
||||
## Methods:
|
||||
|
||||
#### » int get_channel ( ) const
|
||||
|
||||
|
||||
#### » void set_channel ( int channel )
|
||||
|
||||
|
||||
|
||||
## Signals:
|
||||
|
||||
|
||||
---
|
||||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Feb 16, 2020_
|
|
@ -1,8 +1,8 @@
|
|||
# Class: VoxelStreamImage
|
||||
# Class: VoxelGeneratorImage
|
||||
|
||||
Inherits: VoxelStream
|
||||
Inherits: VoxelGeneratorHeightmap
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -14,14 +14,21 @@ _Godot version: 3.2_
|
|||
|
||||
## Properties:
|
||||
|
||||
#### » int VoxelBuffer.ChannelId.channel
|
||||
#### » bool blur_enabled
|
||||
|
||||
`set_blur_enabled (value)` setter
|
||||
|
||||
`is_blur_enabled ()` getter
|
||||
|
||||
|
||||
#### » int VoxelBuffer.ChannelId.channel
|
||||
|
||||
`set_channel (value)` setter
|
||||
|
||||
`get_channel ()` getter
|
||||
|
||||
|
||||
#### » Image image
|
||||
#### » Image image
|
||||
|
||||
`set_image (value)` setter
|
||||
|
||||
|
@ -39,4 +46,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
|
@ -1,8 +1,8 @@
|
|||
# Class: VoxelStreamNoise
|
||||
# Class: VoxelGeneratorNoise
|
||||
|
||||
Inherits: VoxelStream
|
||||
Inherits: VoxelGenerator
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -14,21 +14,28 @@ _Godot version: 3.2_
|
|||
|
||||
## Properties:
|
||||
|
||||
#### » float height_range
|
||||
#### » int VoxelBuffer.ChannelId.channel
|
||||
|
||||
`set_channel (value)` setter
|
||||
|
||||
`get_channel ()` getter
|
||||
|
||||
|
||||
#### » float height_range
|
||||
|
||||
`set_height_range (value)` setter
|
||||
|
||||
`get_height_range ()` getter
|
||||
|
||||
|
||||
#### » float height_start
|
||||
#### » float height_start
|
||||
|
||||
`set_height_start (value)` setter
|
||||
|
||||
`get_height_start ()` getter
|
||||
|
||||
|
||||
#### » OpenSimplexNoise noise
|
||||
#### » OpenSimplexNoise noise
|
||||
|
||||
`set_noise (value)` setter
|
||||
|
||||
|
@ -46,4 +53,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
|
@ -0,0 +1,49 @@
|
|||
# Class: VoxelGeneratorNoise2D
|
||||
|
||||
Inherits: VoxelGeneratorHeightmap
|
||||
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
||||
|
||||
|
||||
## Constants:
|
||||
|
||||
|
||||
## Properties:
|
||||
|
||||
#### » int VoxelBuffer.ChannelId.channel
|
||||
|
||||
`set_channel (value)` setter
|
||||
|
||||
`get_channel ()` getter
|
||||
|
||||
|
||||
#### » Curve curve
|
||||
|
||||
`set_curve (value)` setter
|
||||
|
||||
`get_curve ()` getter
|
||||
|
||||
|
||||
#### » OpenSimplexNoise noise
|
||||
|
||||
`set_noise (value)` setter
|
||||
|
||||
`get_noise ()` getter
|
||||
|
||||
|
||||
|
||||
## Methods:
|
||||
|
||||
|
||||
## Signals:
|
||||
|
||||
|
||||
---
|
||||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Feb 16, 2020_
|
|
@ -1,8 +1,8 @@
|
|||
# Class: VoxelStreamTest
|
||||
# Class: VoxelGeneratorTest
|
||||
|
||||
Inherits: VoxelStream
|
||||
Inherits: VoxelGenerator
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -11,37 +11,44 @@ _Godot version: 3.2_
|
|||
|
||||
## Constants:
|
||||
|
||||
#### » Mode.MODE_FLAT = 0
|
||||
#### » Mode.MODE_FLAT = 0
|
||||
|
||||
|
||||
#### » Mode.MODE_WAVES = 1
|
||||
#### » Mode.MODE_WAVES = 1
|
||||
|
||||
|
||||
|
||||
## Properties:
|
||||
|
||||
#### » int VoxelStreamTest.Mode.mode
|
||||
#### » int VoxelBuffer.ChannelId.channel
|
||||
|
||||
`set_channel (value)` setter
|
||||
|
||||
`get_channel ()` getter
|
||||
|
||||
|
||||
#### » int VoxelGeneratorTest.Mode.mode
|
||||
|
||||
`set_mode (value)` setter
|
||||
|
||||
`get_mode ()` getter
|
||||
|
||||
|
||||
#### » Vector3 pattern_offset
|
||||
#### » Vector3 pattern_offset
|
||||
|
||||
`set_pattern_offset (value)` setter
|
||||
|
||||
`get_pattern_offset ()` getter
|
||||
|
||||
|
||||
#### » Vector3 pattern_size
|
||||
#### » Vector3 pattern_size
|
||||
|
||||
`set_pattern_size (value)` setter
|
||||
|
||||
`get_pattern_size ()` getter
|
||||
|
||||
|
||||
#### » int voxel_type
|
||||
#### » int voxel_type
|
||||
|
||||
`set_voxel_type (value)` setter
|
||||
|
||||
|
@ -59,4 +66,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
|
@ -1,67 +0,0 @@
|
|||
# Class: VoxelIsoSurfaceTool
|
||||
|
||||
Inherits: Reference
|
||||
|
||||
_Godot version: 3.2_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
||||
|
||||
|
||||
## Constants:
|
||||
|
||||
#### » Operation.OP_ADD = 0
|
||||
|
||||
|
||||
#### » Operation.OP_SUBTRACT = 1
|
||||
|
||||
|
||||
#### » Operation.OP_SET = 2
|
||||
|
||||
|
||||
|
||||
## Properties:
|
||||
|
||||
|
||||
## Methods:
|
||||
|
||||
#### » void do_cube ( Transform transform, Vector3 extents, int op=0 )
|
||||
|
||||
|
||||
#### » void do_heightmap ( Image heightmap, Vector3 offset, float vertical_scale, int op=0 )
|
||||
|
||||
|
||||
#### » void do_plane ( Plane plane, int op=0 )
|
||||
|
||||
|
||||
#### » void do_sphere ( Vector3 center, float radius, int op=0 )
|
||||
|
||||
|
||||
#### » VoxelBuffer get_buffer ( ) const
|
||||
|
||||
|
||||
#### » float get_iso_scale ( ) const
|
||||
|
||||
|
||||
#### » Vector3 get_offset ( ) const
|
||||
|
||||
|
||||
#### » void set_buffer ( VoxelBuffer voxel_buffer )
|
||||
|
||||
|
||||
#### » void set_iso_scale ( float iso_scale )
|
||||
|
||||
|
||||
#### » void set_offset ( Vector3 offset )
|
||||
|
||||
|
||||
|
||||
## Signals:
|
||||
|
||||
|
||||
---
|
||||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: Resource
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -11,23 +11,33 @@ _Godot version: 3.2_
|
|||
|
||||
## Constants:
|
||||
|
||||
#### » MAX_VOXEL_TYPES = 65536
|
||||
|
||||
|
||||
|
||||
## Properties:
|
||||
|
||||
#### » int atlas_size
|
||||
#### » int atlas_size
|
||||
|
||||
`set_atlas_size (value)` setter
|
||||
|
||||
`get_atlas_size ()` getter
|
||||
|
||||
|
||||
#### » int voxel_count
|
||||
|
||||
`set_voxel_count (value)` setter
|
||||
|
||||
`get_voxel_count ()` getter
|
||||
|
||||
|
||||
|
||||
## Methods:
|
||||
|
||||
#### » Voxel create_voxel ( int id, String name )
|
||||
#### » Voxel create_voxel ( int id, String name )
|
||||
|
||||
|
||||
#### » Voxel get_voxel ( int id )
|
||||
#### » Voxel get_voxel ( int id )
|
||||
|
||||
|
||||
|
||||
|
@ -38,4 +48,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: Spatial
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -14,56 +14,56 @@ _Godot version: 3.2_
|
|||
|
||||
## Properties:
|
||||
|
||||
#### » int collision_lod_count
|
||||
#### » int collision_lod_count
|
||||
|
||||
`set_collision_lod_count (value)` setter
|
||||
|
||||
`get_collision_lod_count ()` getter
|
||||
|
||||
|
||||
#### » bool generate_collisions
|
||||
#### » bool generate_collisions
|
||||
|
||||
`set_generate_collisions (value)` setter
|
||||
|
||||
`get_generate_collisions ()` getter
|
||||
|
||||
|
||||
#### » int lod_count
|
||||
#### » int lod_count
|
||||
|
||||
`set_lod_count (value)` setter
|
||||
|
||||
`get_lod_count ()` getter
|
||||
|
||||
|
||||
#### » float lod_split_scale
|
||||
#### » float lod_split_scale
|
||||
|
||||
`set_lod_split_scale (value)` setter
|
||||
|
||||
`get_lod_split_scale ()` getter
|
||||
|
||||
|
||||
#### » Material material
|
||||
#### » Material material
|
||||
|
||||
`set_material (value)` setter
|
||||
|
||||
`get_material ()` getter
|
||||
|
||||
|
||||
#### » VoxelStream stream
|
||||
#### » VoxelStream stream
|
||||
|
||||
`set_stream (value)` setter
|
||||
|
||||
`get_stream ()` getter
|
||||
|
||||
|
||||
#### » int view_distance
|
||||
#### » int view_distance
|
||||
|
||||
`set_view_distance (value)` setter
|
||||
|
||||
`get_view_distance ()` getter
|
||||
|
||||
|
||||
#### » NodePath viewer_path
|
||||
#### » NodePath viewer_path
|
||||
|
||||
`set_viewer_path (value)` setter
|
||||
|
||||
|
@ -73,16 +73,34 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » Dictionary get_block_info ( Vector3 block_pos, int lod ) const
|
||||
#### » Dictionary debug_get_block_info ( Vector3 block_pos, int lod ) const
|
||||
|
||||
|
||||
#### » int get_block_region_extent ( ) const
|
||||
#### » Array debug_get_octrees ( ) const
|
||||
|
||||
|
||||
#### » Dictionary get_statistics ( ) const
|
||||
#### » Array debug_print_sdf_top_down ( Vector3 center, Vector3 extents ) const
|
||||
|
||||
|
||||
#### » Vector3 voxel_to_block_position ( Vector3 lod_index, int arg1 ) const
|
||||
#### » Array debug_raycast_block ( Vector3 origin, Vector3 dir ) const
|
||||
|
||||
|
||||
#### » void debug_save_all_modified_blocks ( )
|
||||
|
||||
|
||||
#### » int get_block_region_extent ( ) const
|
||||
|
||||
|
||||
#### » int get_block_size ( ) const
|
||||
|
||||
|
||||
#### » Dictionary get_statistics ( ) const
|
||||
|
||||
|
||||
#### » VoxelTool get_voxel_tool ( )
|
||||
|
||||
|
||||
#### » Vector3 voxel_to_block_position ( Vector3 lod_index, int arg1 ) const
|
||||
|
||||
|
||||
|
||||
|
@ -93,4 +111,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: Reference
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -17,46 +17,46 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » Vector3 block_to_voxel ( Vector3 block_pos ) const
|
||||
#### » Vector3 block_to_voxel ( Vector3 block_pos ) const
|
||||
|
||||
|
||||
#### » int get_block_size ( ) const
|
||||
#### » int get_block_size ( ) const
|
||||
|
||||
|
||||
#### » void get_buffer_copy ( Vector3 min_pos, VoxelBuffer out_buffer, int channel=0 )
|
||||
#### » void get_buffer_copy ( Vector3 min_pos, VoxelBuffer out_buffer, int channel=0 )
|
||||
|
||||
|
||||
#### » int get_default_voxel ( int channel=0 )
|
||||
#### » int get_default_voxel ( int channel=0 )
|
||||
|
||||
|
||||
#### » int get_voxel ( int x, int y, int z, int c=0 )
|
||||
#### » int get_voxel ( int x, int y, int z, int c=0 )
|
||||
|
||||
|
||||
#### » float get_voxel_f ( int x, int y, int z, int c=1 )
|
||||
#### » float get_voxel_f ( int x, int y, int z, int c=1 )
|
||||
|
||||
|
||||
#### » int get_voxel_v ( Vector3 pos, int c=0 )
|
||||
#### » int get_voxel_v ( Vector3 pos, int c=0 )
|
||||
|
||||
|
||||
#### » bool has_block ( int x, int y, int z )
|
||||
#### » bool has_block ( int x, int y, int z )
|
||||
|
||||
|
||||
#### » void set_block_buffer ( Vector3 block_pos, VoxelBuffer buffer )
|
||||
#### » void set_block_buffer ( Vector3 block_pos, VoxelBuffer buffer )
|
||||
|
||||
|
||||
#### » void set_default_voxel ( int value, int channel=0 )
|
||||
#### » void set_default_voxel ( int value, int channel=0 )
|
||||
|
||||
|
||||
#### » void set_voxel ( int value, int x, int y, int z, int c=0 )
|
||||
#### » void set_voxel ( int value, int x, int y, int z, int c=0 )
|
||||
|
||||
|
||||
#### » void set_voxel_f ( float value, int x, int y, int z, int c=1 )
|
||||
#### » void set_voxel_f ( float value, int x, int y, int z, int c=1 )
|
||||
|
||||
|
||||
#### » void set_voxel_v ( int value, Vector3 pos, int c=0 )
|
||||
#### » void set_voxel_v ( int value, Vector3 pos, int c=0 )
|
||||
|
||||
|
||||
#### » Vector3 voxel_to_block ( Vector3 voxel_pos ) const
|
||||
#### » Vector3 voxel_to_block ( Vector3 voxel_pos ) const
|
||||
|
||||
|
||||
|
||||
|
@ -67,4 +67,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: Reference
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -17,7 +17,13 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » Mesh build_mesh ( VoxelBuffer voxel_buffer )
|
||||
#### » Mesh build_mesh ( VoxelBuffer voxel_buffer )
|
||||
|
||||
|
||||
#### » int get_maximum_padding ( ) const
|
||||
|
||||
|
||||
#### » int get_minimum_padding ( ) const
|
||||
|
||||
|
||||
|
||||
|
@ -28,4 +34,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: VoxelMesher
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -17,22 +17,22 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » VoxelLibrary get_library ( ) const
|
||||
#### » VoxelLibrary get_library ( ) const
|
||||
|
||||
|
||||
#### » float get_occlusion_darkness ( ) const
|
||||
#### » float get_occlusion_darkness ( ) const
|
||||
|
||||
|
||||
#### » bool get_occlusion_enabled ( ) const
|
||||
#### » bool get_occlusion_enabled ( ) const
|
||||
|
||||
|
||||
#### » void set_library ( VoxelLibrary voxel_library )
|
||||
#### » void set_library ( VoxelLibrary voxel_library )
|
||||
|
||||
|
||||
#### » void set_occlusion_darkness ( float value )
|
||||
#### » void set_occlusion_darkness ( float value )
|
||||
|
||||
|
||||
#### » void set_occlusion_enabled ( bool enable )
|
||||
#### » void set_occlusion_enabled ( bool enable )
|
||||
|
||||
|
||||
|
||||
|
@ -43,4 +43,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: VoxelMesher
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -11,31 +11,31 @@ _Godot version: 3.2_
|
|||
|
||||
## Constants:
|
||||
|
||||
#### » MeshMode.MESH_NORMAL = 0
|
||||
#### » MeshMode.MESH_NORMAL = 0
|
||||
|
||||
|
||||
#### » MeshMode.MESH_WIREFRAME = 1
|
||||
#### » MeshMode.MESH_WIREFRAME = 1
|
||||
|
||||
|
||||
#### » MeshMode.MESH_DEBUG_OCTREE = 2
|
||||
#### » MeshMode.MESH_DEBUG_OCTREE = 2
|
||||
|
||||
|
||||
#### » MeshMode.MESH_DEBUG_DUAL_GRID = 3
|
||||
#### » MeshMode.MESH_DEBUG_DUAL_GRID = 3
|
||||
|
||||
|
||||
#### » SimplifyMode.SIMPLIFY_OCTREE_BOTTOM_UP = 0
|
||||
#### » SimplifyMode.SIMPLIFY_OCTREE_BOTTOM_UP = 0
|
||||
|
||||
|
||||
#### » SimplifyMode.SIMPLIFY_OCTREE_TOP_DOWN = 1
|
||||
#### » SimplifyMode.SIMPLIFY_OCTREE_TOP_DOWN = 1
|
||||
|
||||
|
||||
#### » SimplifyMode.SIMPLIFY_NONE = 2
|
||||
#### » SimplifyMode.SIMPLIFY_NONE = 2
|
||||
|
||||
|
||||
#### » SeamMode.SEAM_NONE = 0
|
||||
#### » SeamMode.SEAM_NONE = 0
|
||||
|
||||
|
||||
#### » SeamMode.SEAM_MARCHING_SQUARE_SKIRTS = 1
|
||||
#### » SeamMode.SEAM_MARCHING_SQUARE_SKIRTS = 1
|
||||
|
||||
|
||||
|
||||
|
@ -44,31 +44,31 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » float get_geometric_error ( ) const
|
||||
#### » float get_geometric_error ( ) const
|
||||
|
||||
|
||||
#### » int get_mesh_mode ( ) const
|
||||
#### » int get_mesh_mode ( ) const
|
||||
|
||||
|
||||
#### » int get_seam_mode ( ) const
|
||||
#### » int get_seam_mode ( ) const
|
||||
|
||||
|
||||
#### » int get_simplify_mode ( ) const
|
||||
#### » int get_simplify_mode ( ) const
|
||||
|
||||
|
||||
#### » Dictionary get_statistics ( ) const
|
||||
#### » Dictionary get_statistics ( ) const
|
||||
|
||||
|
||||
#### » void set_geometric_error ( float error )
|
||||
#### » void set_geometric_error ( float error )
|
||||
|
||||
|
||||
#### » void set_mesh_mode ( int mode )
|
||||
#### » void set_mesh_mode ( int mode )
|
||||
|
||||
|
||||
#### » void set_seam_mode ( int mode )
|
||||
#### » void set_seam_mode ( int mode )
|
||||
|
||||
|
||||
#### » void set_simplify_mode ( int mode )
|
||||
#### » void set_simplify_mode ( int mode )
|
||||
|
||||
|
||||
|
||||
|
@ -79,4 +79,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: VoxelMesher
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -17,6 +17,9 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » ArrayMesh build_transition_mesh ( VoxelBuffer voxel_buffer, int direction )
|
||||
|
||||
|
||||
|
||||
## Signals:
|
||||
|
||||
|
@ -25,4 +28,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# Class: VoxelRaycastResult
|
||||
|
||||
Inherits: Reference
|
||||
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
||||
|
||||
|
||||
## Constants:
|
||||
|
||||
|
||||
## Properties:
|
||||
|
||||
#### » Vector3 position
|
||||
|
||||
` (value)` setter
|
||||
|
||||
`get_position ()` getter
|
||||
|
||||
|
||||
#### » Vector3 previous_position
|
||||
|
||||
` (value)` setter
|
||||
|
||||
`get_previous_position ()` getter
|
||||
|
||||
|
||||
|
||||
## Methods:
|
||||
|
||||
|
||||
## Signals:
|
||||
|
||||
|
||||
---
|
||||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Feb 16, 2020_
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: Resource
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -17,10 +17,13 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » void emerge_block ( VoxelBuffer out_buffer, Vector3 origin_in_voxels, int lod )
|
||||
#### » void emerge_block ( VoxelBuffer out_buffer, Vector3 origin_in_voxels, int lod )
|
||||
|
||||
|
||||
#### » void immerge_block ( VoxelBuffer buffer, Vector3 origin_in_voxels, int lod )
|
||||
#### » int get_used_channels_mask ( ) const
|
||||
|
||||
|
||||
#### » void immerge_block ( VoxelBuffer buffer, Vector3 origin_in_voxels, int lod )
|
||||
|
||||
|
||||
|
||||
|
@ -31,4 +34,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: VoxelStreamFile
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -14,7 +14,7 @@ _Godot version: 3.2_
|
|||
|
||||
## Properties:
|
||||
|
||||
#### » String directory
|
||||
#### » String directory
|
||||
|
||||
`set_directory (value)` setter
|
||||
|
||||
|
@ -32,4 +32,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: VoxelStream
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -14,14 +14,14 @@ _Godot version: 3.2_
|
|||
|
||||
## Properties:
|
||||
|
||||
#### » VoxelStream fallback_stream
|
||||
#### » VoxelStream fallback_stream
|
||||
|
||||
`set_fallback_stream (value)` setter
|
||||
|
||||
`get_fallback_stream ()` getter
|
||||
|
||||
|
||||
#### » bool save_fallback_output
|
||||
#### » bool save_fallback_output
|
||||
|
||||
`set_save_fallback_output (value)` setter
|
||||
|
||||
|
@ -31,7 +31,7 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » Vector3 get_block_size ( ) const
|
||||
#### » Vector3 get_block_size ( ) const
|
||||
|
||||
|
||||
|
||||
|
@ -42,4 +42,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: VoxelStreamFile
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -14,35 +14,35 @@ _Godot version: 3.2_
|
|||
|
||||
## Properties:
|
||||
|
||||
#### » int block_size_po2
|
||||
#### » int block_size_po2
|
||||
|
||||
`set_block_size_po2 (value)` setter
|
||||
|
||||
`get_region_size_po2 ()` getter
|
||||
|
||||
|
||||
#### » String directory
|
||||
#### » String directory
|
||||
|
||||
`set_directory (value)` setter
|
||||
|
||||
`get_directory ()` getter
|
||||
|
||||
|
||||
#### » int lod_count
|
||||
#### » int lod_count
|
||||
|
||||
`set_lod_count (value)` setter
|
||||
|
||||
`get_lod_count ()` getter
|
||||
|
||||
|
||||
#### » int region_size_po2
|
||||
#### » int region_size_po2
|
||||
|
||||
`set_region_size_po2 (value)` setter
|
||||
|
||||
`get_region_size_po2 ()` getter
|
||||
|
||||
|
||||
#### » int sector_size
|
||||
#### » int sector_size
|
||||
|
||||
`set_sector_size (value)` setter
|
||||
|
||||
|
@ -52,13 +52,13 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » void convert_files ( Dictionary new_settings )
|
||||
#### » void convert_files ( Dictionary new_settings )
|
||||
|
||||
|
||||
#### » int get_block_size_po2 ( ) const
|
||||
#### » int get_block_size_po2 ( ) const
|
||||
|
||||
|
||||
#### » Vector3 get_region_size ( ) const
|
||||
#### » Vector3 get_region_size ( ) const
|
||||
|
||||
|
||||
|
||||
|
@ -69,4 +69,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Inherits: Spatial
|
||||
|
||||
_Godot version: 3.2_
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
@ -14,42 +14,35 @@ _Godot version: 3.2_
|
|||
|
||||
## Properties:
|
||||
|
||||
#### » bool generate_collisions
|
||||
#### » bool generate_collisions
|
||||
|
||||
`set_generate_collisions (value)` setter
|
||||
|
||||
`get_generate_collisions ()` getter
|
||||
|
||||
|
||||
#### » bool smooth_meshing_enabled
|
||||
|
||||
`set_smooth_meshing_enabled (value)` setter
|
||||
|
||||
`is_smooth_meshing_enabled ()` getter
|
||||
|
||||
|
||||
#### » VoxelStream stream
|
||||
#### » VoxelStream stream
|
||||
|
||||
`set_stream (value)` setter
|
||||
|
||||
`get_stream ()` getter
|
||||
|
||||
|
||||
#### » int view_distance
|
||||
#### » int view_distance
|
||||
|
||||
`set_view_distance (value)` setter
|
||||
|
||||
`get_view_distance ()` getter
|
||||
|
||||
|
||||
#### » NodePath viewer_path
|
||||
#### » NodePath viewer_path
|
||||
|
||||
`set_viewer_path (value)` setter
|
||||
|
||||
`get_viewer_path ()` getter
|
||||
|
||||
|
||||
#### » VoxelLibrary voxel_library
|
||||
#### » VoxelLibrary voxel_library
|
||||
|
||||
`set_voxel_library (value)` setter
|
||||
|
||||
|
@ -59,31 +52,22 @@ _Godot version: 3.2_
|
|||
|
||||
## Methods:
|
||||
|
||||
#### » Vector3 block_to_voxel ( Vector3 block_pos )
|
||||
#### » Vector3 block_to_voxel ( Vector3 block_pos )
|
||||
|
||||
|
||||
#### » Material get_material ( int id ) const
|
||||
#### » Material get_material ( int id ) const
|
||||
|
||||
|
||||
#### » Dictionary get_statistics ( ) const
|
||||
#### » Dictionary get_statistics ( ) const
|
||||
|
||||
|
||||
#### » VoxelMap get_storage ( )
|
||||
#### » VoxelTool get_voxel_tool ( )
|
||||
|
||||
|
||||
#### » void make_area_dirty ( AABB aabb )
|
||||
#### » void set_material ( int id, Material material )
|
||||
|
||||
|
||||
#### » void make_voxel_dirty ( Vector3 pos )
|
||||
|
||||
|
||||
#### » Variant raycast ( Vector3 origin, Vector3 direction, float max_distance=100 )
|
||||
|
||||
|
||||
#### » void set_material ( int id, Material material )
|
||||
|
||||
|
||||
#### » Vector3 voxel_to_block ( Vector3 voxel_pos )
|
||||
#### » Vector3 voxel_to_block ( Vector3 voxel_pos )
|
||||
|
||||
|
||||
|
||||
|
@ -94,4 +78,4 @@ _Godot version: 3.2_
|
|||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Aug 26, 2019_
|
||||
_Generated on Feb 16, 2020_
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
# Class: VoxelTool
|
||||
|
||||
Inherits: Reference
|
||||
|
||||
_Godot version: 3.2.1_
|
||||
|
||||
|
||||
## Online Tutorials:
|
||||
|
||||
|
||||
|
||||
## Constants:
|
||||
|
||||
#### » Mode.MODE_ADD = 0
|
||||
|
||||
|
||||
#### » Mode.MODE_REMOVE = 1
|
||||
|
||||
|
||||
#### » Mode.MODE_SET = 2
|
||||
|
||||
|
||||
|
||||
## Properties:
|
||||
|
||||
#### » int channel
|
||||
|
||||
`set_channel (value)` setter
|
||||
|
||||
`get_channel ()` getter
|
||||
|
||||
|
||||
#### » int eraser_value
|
||||
|
||||
`set_eraser_value (value)` setter
|
||||
|
||||
`get_eraser_value ()` getter
|
||||
|
||||
|
||||
#### » int VoxelTool.Mode.mode
|
||||
|
||||
`set_mode (value)` setter
|
||||
|
||||
`get_mode ()` getter
|
||||
|
||||
|
||||
#### » int value
|
||||
|
||||
`set_value (value)` setter
|
||||
|
||||
`get_value ()` getter
|
||||
|
||||
|
||||
|
||||
## Methods:
|
||||
|
||||
#### » void do_point ( Vector3 pos )
|
||||
|
||||
|
||||
#### » void do_sphere ( Vector3 center, float radius )
|
||||
|
||||
|
||||
#### » int get_voxel ( Vector3 pos )
|
||||
|
||||
|
||||
#### » float get_voxel_f ( Vector3 pos )
|
||||
|
||||
|
||||
#### » VoxelRaycastResult raycast ( Vector3 origin, Vector3 direction, float max_distance=10.0 )
|
||||
|
||||
|
||||
#### » void set_voxel ( Vector3 pos, int v )
|
||||
|
||||
|
||||
#### » void set_voxel_f ( Vector3 pos, float v )
|
||||
|
||||
|
||||
|
||||
## Signals:
|
||||
|
||||
|
||||
---
|
||||
* [Class List](Class_List.md)
|
||||
* [Doc Index](../01_get-started.md)
|
||||
|
||||
_Generated on Feb 16, 2020_
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="Voxel" inherits="Resource" category="Core" version="3.2">
|
||||
<class name="Voxel" inherits="Resource" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -73,11 +73,5 @@
|
|||
</constant>
|
||||
<constant name="GEOMETRY_MAX" value="2" enum="GeometryType">
|
||||
</constant>
|
||||
<constant name="CHANNEL_TYPE" value="0" enum="ChannelMode">
|
||||
</constant>
|
||||
<constant name="CHANNEL_ISOLEVEL" value="1" enum="ChannelMode">
|
||||
</constant>
|
||||
<constant name="CHANNEL_DATA" value="2" enum="ChannelMode">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelBoxMover" inherits="Reference" category="Core" version="3.2">
|
||||
<class name="VoxelBoxMover" inherits="Reference" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelBuffer" inherits="Reference" category="Core" version="3.2">
|
||||
<class name="VoxelBuffer" inherits="Reference" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -13,17 +13,17 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="copy_from">
|
||||
<method name="copy_channel_from">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="other" type="VoxelBuffer">
|
||||
</argument>
|
||||
<argument index="1" name="channel" type="int" default="0">
|
||||
<argument index="1" name="channel" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="copy_from_area">
|
||||
<method name="copy_channel_from_area">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="other" type="VoxelBuffer">
|
||||
|
@ -34,7 +34,7 @@
|
|||
</argument>
|
||||
<argument index="3" name="dst_min" type="Vector3">
|
||||
</argument>
|
||||
<argument index="4" name="channel" type="int" default="0">
|
||||
<argument index="4" name="channel" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
|
@ -51,6 +51,20 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="downscale_to" qualifiers="const">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="dst" type="VoxelBuffer">
|
||||
</argument>
|
||||
<argument index="1" name="src_min" type="Vector3">
|
||||
</argument>
|
||||
<argument index="2" name="src_max" type="Vector3">
|
||||
</argument>
|
||||
<argument index="3" name="dst_min" type="Vector3">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="fill">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
@ -85,6 +99,14 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_channel_depth" qualifiers="const">
|
||||
<return type="int" enum="VoxelBuffer.Depth">
|
||||
</return>
|
||||
<argument index="0" name="channel" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_size" qualifiers="const">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
|
@ -137,6 +159,12 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_voxel_tool">
|
||||
<return type="VoxelTool">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_uniform" qualifiers="const">
|
||||
<return type="bool">
|
||||
</return>
|
||||
|
@ -151,6 +179,16 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_channel_depth">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="channel" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="depth" type="int" enum="VoxelBuffer.Depth">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_voxel">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
@ -199,7 +237,7 @@
|
|||
<constants>
|
||||
<constant name="CHANNEL_TYPE" value="0" enum="ChannelId">
|
||||
</constant>
|
||||
<constant name="CHANNEL_ISOLEVEL" value="1" enum="ChannelId">
|
||||
<constant name="CHANNEL_SDF" value="1" enum="ChannelId">
|
||||
</constant>
|
||||
<constant name="CHANNEL_DATA2" value="2" enum="ChannelId">
|
||||
</constant>
|
||||
|
@ -215,5 +253,15 @@
|
|||
</constant>
|
||||
<constant name="MAX_CHANNELS" value="8" enum="ChannelId">
|
||||
</constant>
|
||||
<constant name="DEPTH_8_BIT" value="0" enum="Depth">
|
||||
</constant>
|
||||
<constant name="DEPTH_16_BIT" value="1" enum="Depth">
|
||||
</constant>
|
||||
<constant name="DEPTH_32_BIT" value="2" enum="Depth">
|
||||
</constant>
|
||||
<constant name="DEPTH_64_BIT" value="3" enum="Depth">
|
||||
</constant>
|
||||
<constant name="DEPTH_COUNT" value="4" enum="Depth">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelGenerator" inherits="VoxelStream" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="generate_block">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="out_buffer" type="VoxelBuffer">
|
||||
</argument>
|
||||
<argument index="1" name="origin_in_voxels" type="Vector3">
|
||||
</argument>
|
||||
<argument index="2" name="lod" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelGeneratorHeightmap" inherits="VoxelGenerator" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_channel" qualifiers="const">
|
||||
<return type="int" enum="VoxelBuffer.ChannelId">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_channel">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="channel" type="int" enum="VoxelBuffer.ChannelId">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="height_range" type="float" setter="set_height_range" getter="get_height_range" default="200.0">
|
||||
</member>
|
||||
<member name="height_start" type="float" setter="set_height_start" getter="get_height_start" default="-50.0">
|
||||
</member>
|
||||
<member name="iso_scale" type="float" setter="set_iso_scale" getter="get_iso_scale" default="0.1">
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelStreamImage" inherits="VoxelStream" category="Core" version="3.2">
|
||||
<class name="VoxelGeneratorImage" inherits="VoxelGeneratorHeightmap" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -9,7 +9,9 @@
|
|||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="channel" type="int" setter="set_channel" getter="get_channel" enum="VoxelBuffer.ChannelId" default="0">
|
||||
<member name="blur_enabled" type="bool" setter="set_blur_enabled" getter="is_blur_enabled" default="false">
|
||||
</member>
|
||||
<member name="channel" type="int" setter="set_channel" getter="get_channel" enum="VoxelBuffer.ChannelId" default="1">
|
||||
</member>
|
||||
<member name="image" type="Image" setter="set_image" getter="get_image">
|
||||
</member>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelStreamNoise" inherits="VoxelStream" category="Core" version="3.2">
|
||||
<class name="VoxelGeneratorNoise" inherits="VoxelGenerator" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -9,6 +9,8 @@
|
|||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="channel" type="int" setter="set_channel" getter="get_channel" enum="VoxelBuffer.ChannelId" default="1">
|
||||
</member>
|
||||
<member name="height_range" type="float" setter="set_height_range" getter="get_height_range" default="300.0">
|
||||
</member>
|
||||
<member name="height_start" type="float" setter="set_height_start" getter="get_height_start" default="0.0">
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelGeneratorNoise2D" inherits="VoxelGeneratorHeightmap" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="channel" type="int" setter="set_channel" getter="get_channel" enum="VoxelBuffer.ChannelId" default="1">
|
||||
</member>
|
||||
<member name="curve" type="Curve" setter="set_curve" getter="get_curve">
|
||||
</member>
|
||||
<member name="noise" type="OpenSimplexNoise" setter="set_noise" getter="get_noise">
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelStreamTest" inherits="VoxelStream" category="Core" version="3.2">
|
||||
<class name="VoxelGeneratorTest" inherits="VoxelGenerator" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -9,7 +9,9 @@
|
|||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="VoxelStreamTest.Mode" default="1">
|
||||
<member name="channel" type="int" setter="set_channel" getter="get_channel" enum="VoxelBuffer.ChannelId" default="1">
|
||||
</member>
|
||||
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="VoxelGeneratorTest.Mode" default="1">
|
||||
</member>
|
||||
<member name="pattern_offset" type="Vector3" setter="set_pattern_offset" getter="get_pattern_offset" default="Vector3( 0, 0, 0 )">
|
||||
</member>
|
|
@ -1,109 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelIsoSurfaceTool" inherits="Reference" category="Core" version="3.2">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="do_cube">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="transform" type="Transform">
|
||||
</argument>
|
||||
<argument index="1" name="extents" type="Vector3">
|
||||
</argument>
|
||||
<argument index="2" name="op" type="int" enum="VoxelIsoSurfaceTool.Operation" default="0">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="do_heightmap">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="heightmap" type="Image">
|
||||
</argument>
|
||||
<argument index="1" name="offset" type="Vector3">
|
||||
</argument>
|
||||
<argument index="2" name="vertical_scale" type="float">
|
||||
</argument>
|
||||
<argument index="3" name="op" type="int" enum="VoxelIsoSurfaceTool.Operation" default="0">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="do_plane">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="plane" type="Plane">
|
||||
</argument>
|
||||
<argument index="1" name="op" type="int" enum="VoxelIsoSurfaceTool.Operation" default="0">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="do_sphere">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="center" type="Vector3">
|
||||
</argument>
|
||||
<argument index="1" name="radius" type="float">
|
||||
</argument>
|
||||
<argument index="2" name="op" type="int" enum="VoxelIsoSurfaceTool.Operation" default="0">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_buffer" qualifiers="const">
|
||||
<return type="VoxelBuffer">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_iso_scale" qualifiers="const">
|
||||
<return type="float">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_offset" qualifiers="const">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_buffer">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="voxel_buffer" type="VoxelBuffer">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_iso_scale">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="iso_scale" type="float">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_offset">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="offset" type="Vector3">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
<constant name="OP_ADD" value="0" enum="Operation">
|
||||
</constant>
|
||||
<constant name="OP_SUBTRACT" value="1" enum="Operation">
|
||||
</constant>
|
||||
<constant name="OP_SET" value="2" enum="Operation">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelLibrary" inherits="Resource" category="Core" version="3.2">
|
||||
<class name="VoxelLibrary" inherits="Resource" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -29,7 +29,11 @@
|
|||
<members>
|
||||
<member name="atlas_size" type="int" setter="set_atlas_size" getter="get_atlas_size" default="1">
|
||||
</member>
|
||||
<member name="voxel_count" type="int" setter="set_voxel_count" getter="get_voxel_count" default="0">
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="MAX_VOXEL_TYPES" value="65536">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelLodTerrain" inherits="Spatial" category="Core" version="3.2">
|
||||
<class name="VoxelLodTerrain" inherits="Spatial" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -7,7 +7,7 @@
|
|||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_block_info" qualifiers="const">
|
||||
<method name="debug_get_block_info" qualifiers="const">
|
||||
<return type="Dictionary">
|
||||
</return>
|
||||
<argument index="0" name="block_pos" type="Vector3">
|
||||
|
@ -17,18 +17,62 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="debug_get_octrees" qualifiers="const">
|
||||
<return type="Array">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="debug_print_sdf_top_down" qualifiers="const">
|
||||
<return type="Array">
|
||||
</return>
|
||||
<argument index="0" name="center" type="Vector3">
|
||||
</argument>
|
||||
<argument index="1" name="extents" type="Vector3">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="debug_raycast_block" qualifiers="const">
|
||||
<return type="Array">
|
||||
</return>
|
||||
<argument index="0" name="origin" type="Vector3">
|
||||
</argument>
|
||||
<argument index="1" name="dir" type="Vector3">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="debug_save_all_modified_blocks">
|
||||
<return type="void">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_block_region_extent" qualifiers="const">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_block_size" qualifiers="const">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_statistics" qualifiers="const">
|
||||
<return type="Dictionary">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_voxel_tool">
|
||||
<return type="VoxelTool">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="voxel_to_block_position" qualifiers="const">
|
||||
<return type="Vector3">
|
||||
</return>
|
||||
|
@ -45,7 +89,7 @@
|
|||
</member>
|
||||
<member name="generate_collisions" type="bool" setter="set_generate_collisions" getter="get_generate_collisions" default="true">
|
||||
</member>
|
||||
<member name="lod_count" type="int" setter="set_lod_count" getter="get_lod_count" default="8">
|
||||
<member name="lod_count" type="int" setter="set_lod_count" getter="get_lod_count" default="4">
|
||||
</member>
|
||||
<member name="lod_split_scale" type="float" setter="set_lod_split_scale" getter="get_lod_split_scale" default="3.0">
|
||||
</member>
|
||||
|
@ -53,7 +97,7 @@
|
|||
</member>
|
||||
<member name="stream" type="VoxelStream" setter="set_stream" getter="get_stream">
|
||||
</member>
|
||||
<member name="view_distance" type="int" setter="set_view_distance" getter="get_view_distance" default="0">
|
||||
<member name="view_distance" type="int" setter="set_view_distance" getter="get_view_distance" default="512">
|
||||
</member>
|
||||
<member name="viewer_path" type="NodePath" setter="set_viewer_path" getter="get_viewer_path" default="NodePath("")">
|
||||
</member>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelMap" inherits="Reference" category="Core" version="3.2">
|
||||
<class name="VoxelMap" inherits="Reference" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelMesher" inherits="Reference" category="Core" version="3.2">
|
||||
<class name="VoxelMesher" inherits="Reference" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -15,6 +15,18 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_maximum_padding" qualifiers="const">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_minimum_padding" qualifiers="const">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelMesherBlocky" inherits="VoxelMesher" category="Core" version="3.2">
|
||||
<class name="VoxelMesherBlocky" inherits="VoxelMesher" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelMesherDMC" inherits="VoxelMesher" category="Core" version="3.2">
|
||||
<class name="VoxelMesherDMC" inherits="VoxelMesher" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelMesherTransvoxel" inherits="VoxelMesher" category="Core" version="3.2">
|
||||
<class name="VoxelMesherTransvoxel" inherits="VoxelMesher" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -7,6 +7,16 @@
|
|||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="build_transition_mesh">
|
||||
<return type="ArrayMesh">
|
||||
</return>
|
||||
<argument index="0" name="voxel_buffer" type="VoxelBuffer">
|
||||
</argument>
|
||||
<argument index="1" name="direction" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelRaycastResult" inherits="Reference" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="position" type="Vector3" setter="" getter="get_position" default="Vector3( 0, 0, 0 )">
|
||||
</member>
|
||||
<member name="previous_position" type="Vector3" setter="" getter="get_previous_position" default="Vector3( 0, 0, 0 )">
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelStream" inherits="Resource" category="Core" version="3.2">
|
||||
<class name="VoxelStream" inherits="Resource" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -19,6 +19,12 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_used_channels_mask" qualifiers="const">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="immerge_block">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelStreamBlockFiles" inherits="VoxelStreamFile" category="Core" version="3.2">
|
||||
<class name="VoxelStreamBlockFiles" inherits="VoxelStreamFile" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelStreamFile" inherits="VoxelStream" category="Core" version="3.2">
|
||||
<class name="VoxelStreamFile" inherits="VoxelStream" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelStreamRegionFiles" inherits="VoxelStreamFile" category="Core" version="3.2">
|
||||
<class name="VoxelStreamRegionFiles" inherits="VoxelStreamFile" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelTerrain" inherits="Spatial" category="Core" version="3.2">
|
||||
<class name="VoxelTerrain" inherits="Spatial" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
|
@ -29,40 +29,12 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_storage">
|
||||
<return type="VoxelMap">
|
||||
<method name="get_voxel_tool">
|
||||
<return type="VoxelTool">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="make_area_dirty">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="aabb" type="AABB">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="make_voxel_dirty">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="pos" type="Vector3">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="raycast">
|
||||
<return type="Variant">
|
||||
</return>
|
||||
<argument index="0" name="origin" type="Vector3">
|
||||
</argument>
|
||||
<argument index="1" name="direction" type="Vector3">
|
||||
</argument>
|
||||
<argument index="2" name="max_distance" type="float" default="100">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_material">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
@ -85,8 +57,6 @@
|
|||
<members>
|
||||
<member name="generate_collisions" type="bool" setter="set_generate_collisions" getter="get_generate_collisions" default="true">
|
||||
</member>
|
||||
<member name="smooth_meshing_enabled" type="bool" setter="set_smooth_meshing_enabled" getter="is_smooth_meshing_enabled" default="false">
|
||||
</member>
|
||||
<member name="stream" type="VoxelStream" setter="set_stream" getter="get_stream">
|
||||
</member>
|
||||
<member name="view_distance" type="int" setter="set_view_distance" getter="get_view_distance" default="128">
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VoxelTool" inherits="Reference" version="3.2.1">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="do_point">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="pos" type="Vector3">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="do_sphere">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="center" type="Vector3">
|
||||
</argument>
|
||||
<argument index="1" name="radius" type="float">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_voxel">
|
||||
<return type="int">
|
||||
</return>
|
||||
<argument index="0" name="pos" type="Vector3">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_voxel_f">
|
||||
<return type="float">
|
||||
</return>
|
||||
<argument index="0" name="pos" type="Vector3">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="raycast">
|
||||
<return type="VoxelRaycastResult">
|
||||
</return>
|
||||
<argument index="0" name="origin" type="Vector3">
|
||||
</argument>
|
||||
<argument index="1" name="direction" type="Vector3">
|
||||
</argument>
|
||||
<argument index="2" name="max_distance" type="float" default="10.0">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_voxel">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="pos" type="Vector3">
|
||||
</argument>
|
||||
<argument index="1" name="v" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_voxel_f">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="pos" type="Vector3">
|
||||
</argument>
|
||||
<argument index="1" name="v" type="float">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="channel" type="int" setter="set_channel" getter="get_channel" default="0">
|
||||
</member>
|
||||
<member name="eraser_value" type="int" setter="set_eraser_value" getter="get_eraser_value" default="0">
|
||||
</member>
|
||||
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="VoxelTool.Mode" default="0">
|
||||
</member>
|
||||
<member name="value" type="int" setter="set_value" getter="get_value" default="0">
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="MODE_ADD" value="0" enum="Mode">
|
||||
</constant>
|
||||
<constant name="MODE_REMOVE" value="1" enum="Mode">
|
||||
</constant>
|
||||
<constant name="MODE_SET" value="2" enum="Mode">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
|
@ -0,0 +1,158 @@
|
|||
Region format
|
||||
==================
|
||||
|
||||
Version: 2
|
||||
|
||||
Regions allows to save large 3D voxel volumes in a format suitable for frequent streaming in all directions.
|
||||
This format is inspired by https://www.seedofandromeda.com/blogs/1-creating-a-region-file-system-for-a-voxel-game
|
||||
It is implemented by `VoxelStreamRegionFiles`, which can be found in https://github.com/Zylann/godot_voxel/blob/master/streams/voxel_stream_region_files.cpp
|
||||
|
||||
|
||||
Coordinate spaces
|
||||
-------------------
|
||||
|
||||
This format uses 3 different coordinate spaces. Each one can be converted to another by using a multiplier.
|
||||
|
||||
- Voxel coordinates: actual position of voxels in space
|
||||
- Block coordinates: position of a block of voxels with a defined size B. For example, common block size is 16x16x16 voxels. Block coordinates can be converted into voxel coordinates by multiplying it by B, giving the origin voxel within that block.
|
||||
- Region coordinates: position of a region of blocks with a defined size R. A region coordinate can be converted into block coordinates by multiplying it by R, giving the origin block within that region.
|
||||
|
||||
Powers of two may be used as multipliers.
|
||||
|
||||
|
||||
File structure
|
||||
----------------
|
||||
|
||||
A region save is organized in multiple files, and is contained within a root directory containing them.
|
||||
Under that directory, is located two things:
|
||||
|
||||
- A `meta.vxrm` file
|
||||
- A `regions` directory
|
||||
|
||||
Under the region directory, there must be a sub-directory, for each layer of level of detail (LOD). Those folders must be named `lodX`, where `X` is the LOD index, starting from `0`.
|
||||
|
||||
LOD folders then contain region files for that LOD.
|
||||
Each region file is named using the following convention: `r.X.Y.Z.vxr`, where X, Y and Z are coordinates of the region, in the region coordinate space.
|
||||
|
||||
- `world/`
|
||||
- `meta.vxrm`
|
||||
- `regions/`
|
||||
- `lod0/`
|
||||
- `r.0.0.0.vxr`
|
||||
- `r.1.6.0.vxr`
|
||||
- `r.32.-2.-6.vxr`
|
||||
- ...
|
||||
- `lod1/`
|
||||
- ...
|
||||
- `lod2/`
|
||||
- ...
|
||||
- ...
|
||||
|
||||
|
||||
Meta file
|
||||
------------
|
||||
|
||||
The meta file under the root directory contains global information about all voxel data. It is currently using JSON, but may not be edited by hand.
|
||||
|
||||
It must contain the following fields:
|
||||
|
||||
- `version`: integer telling the version of that format. It must be `2`. Older versions may be migrated.
|
||||
- `block_size_po2`: size of blocks in voxels, as an integer power of two (4 for 16, 5 for 32 etc). Blocks are always cubic.
|
||||
- `lod_count`: how many LOD levels there are. There will be as many LOD folders. It must be greater than 0.
|
||||
- `region_size_po2`: size of regions in blocks, as an integer power of two (4 for 16, 5 for 32 etc). Regions are always cubic.
|
||||
- `sector_size`: size of a sector within a region file, as a strictly positive integer. See region format for more information.
|
||||
- `channel_depths`: array of 8 integers, representing the bit depth of each voxel channel:
|
||||
- `0`: 8 bits
|
||||
- `1`: 16 bits
|
||||
- `2`: 32 bits
|
||||
- `3`: 64 bits
|
||||
- See block format for more information.
|
||||
|
||||
|
||||
Region file
|
||||
-------------
|
||||
|
||||
Region files are binary, little-endian. They are composed of a prologue, header, and sector data.
|
||||
|
||||
```
|
||||
Prologue:
|
||||
- "VXR_"
|
||||
- version: uint8_t
|
||||
Header:
|
||||
- blocks: uint32_t[region_size ^ 3]
|
||||
SectorData:
|
||||
- ...
|
||||
```
|
||||
|
||||
### Prologue
|
||||
|
||||
It starts with four 8-bit characters: `VXR_`, followed by one byte representing the version of the format in binary form. The version must be `2`. Version `1` has the same data layout so it can be read the same. Other versions cannot be read.
|
||||
|
||||
### Header
|
||||
|
||||
The header is a sequence of 32-bit integers. Each integer represents information about where a block is in the file, and how big it is. The count of that sequence is the number of blocks a region can contain, and is the same in all regions. The index of elements in that sequence is calculated from 3D block positions, in ZXY order. The index for a block can be obtained with the formula `y + block_size * (x + block_size * z)`.
|
||||
Each integer contains two informations:
|
||||
- The first byte is the number of sectors the block is spanning. Obtained as `n & 0xff`.
|
||||
- The 3 other bytes are the index to the first sector. Obtained as `n >> 8`.
|
||||
|
||||
### Sectors
|
||||
|
||||
The rest of the file is occupied by sectors.
|
||||
Sectors are fixed-size chunks of data. Their size is determined from the meta file described earlier.
|
||||
Blocks are stored in those sectors. A block can span one or more sectors.
|
||||
The file is partitionned in this way to allow frequently writing blocks of variable size without having to often shift consecutive contents.
|
||||
|
||||
When we need to load a block, the address where block information starts will be the following:
|
||||
```
|
||||
header_size + first_sector_index * sector_size
|
||||
```
|
||||
|
||||
Once we have the address of the block, the first 4 bytes at this address will contain the size of the written data.
|
||||
Note: those 4 bytes are included in the total block size when the number of occupied sectors is determined.
|
||||
|
||||
```
|
||||
RegionBlockData
|
||||
- buffer_size: uint32_t
|
||||
- buffer
|
||||
```
|
||||
|
||||
The obtained buffer can be read using the block format.
|
||||
|
||||
|
||||
Block format
|
||||
--------------
|
||||
|
||||
A block is serialized as compressed data.
|
||||
|
||||
```
|
||||
BlockData
|
||||
- decompressed_data_size: uint32_t
|
||||
- compressed_data
|
||||
```
|
||||
|
||||
`compressed_data` must be decompressed using the LZ4 algorithm (without header), into a buffer big enough to contain `decompressed_data_size` bytes.
|
||||
|
||||
The obtained data then contains the actual block. It is saved as it comes, assuming the format specified in the meta file is respected.
|
||||
Block data consists in 8 channels one after the other, each with the following structure:
|
||||
|
||||
```
|
||||
Channel
|
||||
- compression: uint8_t
|
||||
- data
|
||||
```
|
||||
|
||||
`compression` is the same as the `VoxelBuffer::Compression` enum.
|
||||
Depending on the value of `compression`, `data` will be different.
|
||||
|
||||
If compression is `COMPRESSION_NONE` (0), the data will be an array of N bytes, where N is the number of voxels inside a block, multiplied by the number of bytes in the depth setting of the current channel (defined in the meta file seen earlier). For example, a block of size 16 and a channel of 32-bit depth will have `16*16*16*4` bytes to load from the file into this channel.
|
||||
The 3D indexing of that data is also in order `ZXY`.
|
||||
|
||||
If compression is `COMPRESSION_UNIFORM` (1), the data will be a single voxel value, which means all voxels in the block have that same value. Unused channels will always use this mode. The value can span a variable number of bytes depending on the depth of the current channel:
|
||||
- 1 byte if 8-bit
|
||||
- 2 bytes if 16-bits
|
||||
- 4 bytes if 32-bits
|
||||
- 8 bytes if 64-bits
|
||||
|
||||
Other compression values are invalid.
|
||||
|
||||
After all channels information, block data ends with a sequence of 4 bytes, which once read into a `uint32_t` integer must match the value `0x900df00d`. If that condition isn't fulfilled, the block must be assumed corrupted.
|
|
@ -118,7 +118,7 @@ def find_godot(godot, bindir):
|
|||
else:
|
||||
filemask = 'godot.*.[36][24]'
|
||||
|
||||
binfiles = glob.glob(bindir+filemask)
|
||||
binfiles = glob.glob(os.path.join(bindir,filemask))
|
||||
if len(binfiles) > 0:
|
||||
return binfiles[0]
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
#include "voxel_generator_flat.h"
|
||||
|
||||
VoxelGeneratorFlat::VoxelGeneratorFlat() {
|
||||
}
|
||||
|
||||
void VoxelGeneratorFlat::set_channel(VoxelBuffer::ChannelId channel) {
|
||||
ERR_FAIL_INDEX(channel, VoxelBuffer::MAX_CHANNELS);
|
||||
if (_channel != channel) {
|
||||
_channel = channel;
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
VoxelBuffer::ChannelId VoxelGeneratorFlat::get_channel() const {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
int VoxelGeneratorFlat::get_used_channels_mask() const {
|
||||
return (1 << _channel);
|
||||
}
|
||||
|
||||
void VoxelGeneratorFlat::set_voxel_type(int t) {
|
||||
_voxel_type = t;
|
||||
}
|
||||
|
||||
int VoxelGeneratorFlat::get_voxel_type() const {
|
||||
return _voxel_type;
|
||||
}
|
||||
|
||||
void VoxelGeneratorFlat::set_height(float h) {
|
||||
_height = h;
|
||||
}
|
||||
|
||||
void VoxelGeneratorFlat::generate_block(VoxelBlockRequest &input) {
|
||||
ERR_FAIL_COND(input.voxel_buffer.is_null());
|
||||
|
||||
VoxelBuffer &out_buffer = **input.voxel_buffer;
|
||||
const Vector3i origin = input.origin_in_voxels;
|
||||
const int channel = _channel;
|
||||
const Vector3i bs = out_buffer.get_size();
|
||||
const bool use_sdf = channel == VoxelBuffer::CHANNEL_SDF;
|
||||
const float margin = 1 << input.lod;
|
||||
const int lod = input.lod;
|
||||
|
||||
if (origin.y > _height + margin) {
|
||||
// The bottom of the block is above the highest ground can go (default is air)
|
||||
return;
|
||||
}
|
||||
if (origin.y + (bs.y << lod) < _height - margin) {
|
||||
// The top of the block is below the lowest ground can go
|
||||
out_buffer.clear_channel(_channel, use_sdf ? 0 : _voxel_type);
|
||||
return;
|
||||
}
|
||||
|
||||
const int stride = 1 << lod;
|
||||
|
||||
if (use_sdf) {
|
||||
|
||||
int gz = origin.z;
|
||||
for (int z = 0; z < bs.z; ++z, gz += stride) {
|
||||
|
||||
int gx = origin.x;
|
||||
for (int x = 0; x < bs.x; ++x, gx += stride) {
|
||||
|
||||
int gy = origin.y;
|
||||
for (int y = 0; y < bs.y; ++y, gy += stride) {
|
||||
float sdf = _iso_scale * (gy - _height);
|
||||
out_buffer.set_voxel_f(sdf, x, y, z, channel);
|
||||
}
|
||||
|
||||
} // for x
|
||||
} // for z
|
||||
|
||||
} else {
|
||||
// Blocky
|
||||
|
||||
int gz = origin.z;
|
||||
for (int z = 0; z < bs.z; ++z, gz += stride) {
|
||||
|
||||
int gx = origin.x;
|
||||
for (int x = 0; x < bs.x; ++x, gx += stride) {
|
||||
|
||||
float h = _height - origin.y;
|
||||
int ih = int(h);
|
||||
if (ih > 0) {
|
||||
if (ih > bs.y) {
|
||||
ih = bs.y;
|
||||
}
|
||||
out_buffer.fill_area(_voxel_type, Vector3i(x, 0, z), Vector3i(x + 1, ih, z + 1), channel);
|
||||
}
|
||||
|
||||
} // for x
|
||||
} // for z
|
||||
} // use_sdf
|
||||
}
|
||||
|
||||
void VoxelGeneratorFlat::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_channel", "channel"), &VoxelGeneratorFlat::set_channel);
|
||||
ClassDB::bind_method(D_METHOD("get_channel"), &VoxelGeneratorFlat::get_channel);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_voxel_type", "id"), &VoxelGeneratorFlat::set_voxel_type);
|
||||
ClassDB::bind_method(D_METHOD("get_voxel_type"), &VoxelGeneratorFlat::get_voxel_type);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_height", "h"), &VoxelGeneratorFlat::set_height);
|
||||
ClassDB::bind_method(D_METHOD("get_height"), &VoxelGeneratorFlat::get_height);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "channel", PROPERTY_HINT_ENUM, VoxelBuffer::CHANNEL_ID_HINT_STRING), "set_channel", "get_channel");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height"), "set_height", "get_height");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "voxel_type", PROPERTY_HINT_RANGE, "0,65536,1"), "set_voxel_type", "get_voxel_type");
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef VOXEL_GENERATOR_FLAT_H
|
||||
#define VOXEL_GENERATOR_FLAT_H
|
||||
|
||||
#include "voxel_generator.h"
|
||||
|
||||
class VoxelGeneratorFlat : public VoxelGenerator {
|
||||
GDCLASS(VoxelGeneratorFlat, VoxelGenerator)
|
||||
|
||||
public:
|
||||
VoxelGeneratorFlat();
|
||||
|
||||
void set_channel(VoxelBuffer::ChannelId channel);
|
||||
VoxelBuffer::ChannelId get_channel() const;
|
||||
int get_used_channels_mask() const override;
|
||||
|
||||
void generate_block(VoxelBlockRequest &input) override;
|
||||
|
||||
void set_voxel_type(int t);
|
||||
int get_voxel_type() const;
|
||||
|
||||
void set_height(float h);
|
||||
float get_height() const { return _height; }
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
private:
|
||||
VoxelBuffer::ChannelId _channel = VoxelBuffer::CHANNEL_SDF;
|
||||
int _voxel_type = 1;
|
||||
float _height = 0;
|
||||
float _iso_scale = 0.1;
|
||||
};
|
||||
|
||||
#endif // VOXEL_GENERATOR_FLAT_H
|
|
@ -7,13 +7,20 @@ VoxelGeneratorHeightmap::VoxelGeneratorHeightmap() {
|
|||
|
||||
void VoxelGeneratorHeightmap::set_channel(VoxelBuffer::ChannelId channel) {
|
||||
ERR_FAIL_INDEX(channel, VoxelBuffer::MAX_CHANNELS);
|
||||
_channel = channel;
|
||||
if (_channel != channel) {
|
||||
_channel = channel;
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
VoxelBuffer::ChannelId VoxelGeneratorHeightmap::get_channel() const {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
int VoxelGeneratorHeightmap::get_used_channels_mask() const {
|
||||
return (1 << _channel);
|
||||
}
|
||||
|
||||
void VoxelGeneratorHeightmap::set_height_start(float start) {
|
||||
_range.start = start;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ public:
|
|||
|
||||
void set_channel(VoxelBuffer::ChannelId channel);
|
||||
VoxelBuffer::ChannelId get_channel() const;
|
||||
int get_used_channels_mask() const override;
|
||||
|
||||
void set_height_start(float start);
|
||||
float get_height_start() const;
|
||||
|
@ -97,7 +98,7 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
VoxelBuffer::ChannelId _channel = VoxelBuffer::CHANNEL_TYPE;
|
||||
VoxelBuffer::ChannelId _channel = VoxelBuffer::CHANNEL_SDF;
|
||||
int _matter_type = 1;
|
||||
Range _range;
|
||||
float _iso_scale = 0.1;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
// Provides infinite tiling heightmap based on an image
|
||||
class VoxelGeneratorImage : public VoxelGeneratorHeightmap {
|
||||
GDCLASS(VoxelGeneratorImage, VoxelGeneratorHeightmap)
|
||||
|
||||
public:
|
||||
VoxelGeneratorImage();
|
||||
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
#include "voxel_generator_noise.h"
|
||||
|
||||
void VoxelGeneratorNoise::set_noise(Ref<OpenSimplexNoise> noise) {
|
||||
_noise = noise;
|
||||
}
|
||||
|
||||
void VoxelGeneratorNoise::set_channel(VoxelBuffer::ChannelId channel) {
|
||||
ERR_FAIL_INDEX(channel, VoxelBuffer::MAX_CHANNELS);
|
||||
_channel = channel;
|
||||
if (_channel != channel) {
|
||||
_channel = channel;
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
VoxelBuffer::ChannelId VoxelGeneratorNoise::get_channel() const {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
void VoxelGeneratorNoise::set_noise(Ref<OpenSimplexNoise> noise) {
|
||||
_noise = noise;
|
||||
int VoxelGeneratorNoise::get_used_channels_mask() const {
|
||||
return (1 << _channel);
|
||||
}
|
||||
|
||||
Ref<OpenSimplexNoise> VoxelGeneratorNoise::get_noise() const {
|
||||
|
@ -161,6 +168,9 @@ void VoxelGeneratorNoise::generate_block(VoxelBlockRequest &input) {
|
|||
|
||||
void VoxelGeneratorNoise::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_channel", "channel"), &VoxelGeneratorNoise::set_channel);
|
||||
ClassDB::bind_method(D_METHOD("get_channel"), &VoxelGeneratorNoise::get_channel);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &VoxelGeneratorNoise::set_noise);
|
||||
ClassDB::bind_method(D_METHOD("get_noise"), &VoxelGeneratorNoise::get_noise);
|
||||
|
||||
|
@ -170,11 +180,8 @@ void VoxelGeneratorNoise::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_height_range", "hrange"), &VoxelGeneratorNoise::set_height_range);
|
||||
ClassDB::bind_method(D_METHOD("get_height_range"), &VoxelGeneratorNoise::get_height_range);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_channel", "channel"), &VoxelGeneratorNoise::set_channel);
|
||||
ClassDB::bind_method(D_METHOD("get_channel"), &VoxelGeneratorNoise::get_channel);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "channel", PROPERTY_HINT_ENUM, VoxelBuffer::CHANNEL_ID_HINT_STRING), "set_channel", "get_channel");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_start"), "set_height_start", "get_height_start");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_range"), "set_height_range", "get_height_range");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "channel", PROPERTY_HINT_ENUM, VoxelBuffer::CHANNEL_ID_HINT_STRING), "set_channel", "get_channel");
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ class VoxelGeneratorNoise : public VoxelGenerator {
|
|||
public:
|
||||
void set_channel(VoxelBuffer::ChannelId channel);
|
||||
VoxelBuffer::ChannelId get_channel() const;
|
||||
int get_used_channels_mask() const override;
|
||||
|
||||
void set_noise(Ref<OpenSimplexNoise> noise);
|
||||
Ref<OpenSimplexNoise> get_noise() const;
|
||||
|
@ -27,7 +28,7 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
private:
|
||||
VoxelBuffer::ChannelId _channel = VoxelBuffer::CHANNEL_TYPE;
|
||||
VoxelBuffer::ChannelId _channel = VoxelBuffer::CHANNEL_SDF;
|
||||
Ref<OpenSimplexNoise> _noise;
|
||||
FloatBuffer3D _noise_buffer;
|
||||
float _height_start = 0;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
class VoxelGeneratorNoise2D : public VoxelGeneratorHeightmap {
|
||||
GDCLASS(VoxelGeneratorNoise2D, VoxelGeneratorHeightmap)
|
||||
|
||||
public:
|
||||
VoxelGeneratorNoise2D();
|
||||
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
#include "voxel_generator_test.h"
|
||||
|
||||
VARIANT_ENUM_CAST(VoxelGeneratorTest::Mode)
|
||||
|
||||
VoxelGeneratorTest::VoxelGeneratorTest() {
|
||||
_mode = MODE_WAVES;
|
||||
_voxel_type = 1;
|
||||
_pattern_size = Vector3i(10, 10, 10);
|
||||
}
|
||||
|
||||
void VoxelGeneratorTest::set_mode(Mode mode) {
|
||||
ERR_FAIL_INDEX(mode, MODE_COUNT)
|
||||
_mode = mode;
|
||||
}
|
||||
|
||||
void VoxelGeneratorTest::set_voxel_type(int t) {
|
||||
_voxel_type = t;
|
||||
}
|
||||
|
||||
int VoxelGeneratorTest::get_voxel_type() const {
|
||||
return _voxel_type;
|
||||
}
|
||||
|
||||
void VoxelGeneratorTest::set_pattern_size(Vector3i size) {
|
||||
ERR_FAIL_COND(size.x < 1 || size.y < 1 || size.z < 1);
|
||||
_pattern_size = size;
|
||||
}
|
||||
|
||||
void VoxelGeneratorTest::set_pattern_offset(Vector3i offset) {
|
||||
_pattern_offset = offset;
|
||||
}
|
||||
|
||||
void VoxelGeneratorTest::generate_block(VoxelBlockRequest &input) {
|
||||
ERR_FAIL_COND(input.voxel_buffer.is_null());
|
||||
|
||||
if (input.lod != 0) {
|
||||
// TODO Handle higher lods
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_mode) {
|
||||
|
||||
case MODE_FLAT:
|
||||
generate_block_flat(**input.voxel_buffer, input.origin_in_voxels, input.lod);
|
||||
break;
|
||||
|
||||
case MODE_WAVES:
|
||||
generate_block_waves(**input.voxel_buffer, input.origin_in_voxels, input.lod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelGeneratorTest::generate_block_flat(VoxelBuffer &out_buffer, Vector3i origin, int lod) {
|
||||
|
||||
// TODO Don't expect a block pos, but a voxel pos!
|
||||
Vector3i size = out_buffer.get_size();
|
||||
|
||||
int rh = _pattern_offset.y - origin.y;
|
||||
if (rh > size.y)
|
||||
rh = size.y;
|
||||
|
||||
for (int rz = 0; rz < size.z; ++rz) {
|
||||
for (int rx = 0; rx < size.x; ++rx) {
|
||||
for (int ry = 0; ry < rh; ++ry) {
|
||||
out_buffer.set_voxel(_voxel_type, rx, ry, rz, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelGeneratorTest::generate_block_waves(VoxelBuffer &out_buffer, Vector3i origin, int lod) {
|
||||
|
||||
// TODO Don't expect a block pos, but a voxel pos!
|
||||
Vector3i size = out_buffer.get_size();
|
||||
//origin += _pattern_offset;
|
||||
|
||||
float amplitude = static_cast<float>(_pattern_size.y);
|
||||
float period_x = 1.f / static_cast<float>(_pattern_size.x);
|
||||
float period_z = 1.f / static_cast<float>(_pattern_size.z);
|
||||
|
||||
//out_buffer.fill(0, 1); // TRANSVOXEL TEST
|
||||
|
||||
if (origin.y + size.y < Math::floor(_pattern_offset.y - 1.5 * amplitude)) {
|
||||
// Everything is ground
|
||||
out_buffer.fill(_voxel_type);
|
||||
|
||||
} else if (origin.y > Math::ceil(_pattern_offset.y + 1.5 * amplitude)) {
|
||||
// Everything is air
|
||||
return;
|
||||
|
||||
} else {
|
||||
for (int rz = 0; rz < size.z; ++rz) {
|
||||
for (int rx = 0; rx < size.x; ++rx) {
|
||||
|
||||
float x = origin.x + rx;
|
||||
float z = origin.z + rz;
|
||||
|
||||
int h = _pattern_offset.y + amplitude * (Math::cos(x * period_x) + Math::sin(z * period_z));
|
||||
int rh = h - origin.y;
|
||||
if (rh > size.y)
|
||||
rh = size.y;
|
||||
|
||||
for (int ry = 0; ry < rh; ++ry) {
|
||||
out_buffer.set_voxel(_voxel_type, rx, ry, rz, 0);
|
||||
//out_buffer.set_voxel(255, rx, ry, rz, 1); // TRANSVOXEL TEST
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelGeneratorTest::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &VoxelGeneratorTest::set_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_mode"), &VoxelGeneratorTest::get_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_voxel_type", "id"), &VoxelGeneratorTest::set_voxel_type);
|
||||
ClassDB::bind_method(D_METHOD("get_voxel_type"), &VoxelGeneratorTest::get_voxel_type);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_pattern_size", "size"), &VoxelGeneratorTest::_set_pattern_size);
|
||||
ClassDB::bind_method(D_METHOD("get_pattern_size"), &VoxelGeneratorTest::_get_pattern_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_pattern_offset", "offset"), &VoxelGeneratorTest::_set_pattern_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_pattern_offset"), &VoxelGeneratorTest::_get_pattern_offset);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Flat,Waves"), "set_mode", "get_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "voxel_type", PROPERTY_HINT_RANGE, "0,255,1"), "set_voxel_type", "get_voxel_type");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "pattern_size"), "set_pattern_size", "get_pattern_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "pattern_offset"), "set_pattern_offset", "get_pattern_offset");
|
||||
|
||||
BIND_ENUM_CONSTANT(MODE_FLAT);
|
||||
BIND_ENUM_CONSTANT(MODE_WAVES);
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
#ifndef VOXEL_GENERATOR_TEST_H
|
||||
#define VOXEL_GENERATOR_TEST_H
|
||||
|
||||
#include "voxel_generator.h"
|
||||
|
||||
class VoxelGeneratorTest : public VoxelGenerator {
|
||||
GDCLASS(VoxelGeneratorTest, VoxelGenerator)
|
||||
|
||||
public:
|
||||
enum Mode {
|
||||
MODE_FLAT,
|
||||
MODE_WAVES,
|
||||
MODE_COUNT
|
||||
};
|
||||
|
||||
VoxelGeneratorTest();
|
||||
|
||||
void generate_block(VoxelBlockRequest &input) override;
|
||||
|
||||
void set_mode(Mode mode);
|
||||
Mode get_mode() const { return _mode; }
|
||||
|
||||
void set_voxel_type(int t);
|
||||
int get_voxel_type() const;
|
||||
|
||||
Vector3i get_pattern_size() const { return _pattern_size; }
|
||||
void set_pattern_size(Vector3i size);
|
||||
|
||||
Vector3i get_pattern_offset() const { return _pattern_offset; }
|
||||
void set_pattern_offset(Vector3i offset);
|
||||
|
||||
protected:
|
||||
void generate_block_flat(VoxelBuffer &out_buffer, Vector3i origin, int lod);
|
||||
void generate_block_waves(VoxelBuffer &out_buffer, Vector3i origin, int lod);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
Vector3 _get_pattern_size() const { return get_pattern_size().to_vec3(); }
|
||||
void _set_pattern_size(Vector3 size) { set_pattern_size(Vector3i(size)); }
|
||||
|
||||
Vector3 _get_pattern_offset() const { return get_pattern_offset().to_vec3(); }
|
||||
void _set_pattern_offset(Vector3 offset) { set_pattern_offset(Vector3i(offset)); }
|
||||
|
||||
private:
|
||||
Mode _mode;
|
||||
int _voxel_type;
|
||||
Vector3i _pattern_offset;
|
||||
Vector3i _pattern_size;
|
||||
};
|
||||
|
||||
#endif // VOXEL_GENERATOR_TEST_H
|
|
@ -0,0 +1,45 @@
|
|||
#include "voxel_generator_waves.h"
|
||||
#include "../util/utility.h"
|
||||
#include <cmath>
|
||||
|
||||
VoxelGeneratorWaves::VoxelGeneratorWaves() {
|
||||
_pattern_size = Vector2(30, 30);
|
||||
set_height_range(30);
|
||||
}
|
||||
|
||||
void VoxelGeneratorWaves::generate_block(VoxelBlockRequest &input) {
|
||||
|
||||
VoxelBuffer &out_buffer = **input.voxel_buffer;
|
||||
const Vector2 freq(
|
||||
Math_PI / static_cast<float>(_pattern_size.x),
|
||||
Math_PI / static_cast<float>(_pattern_size.y));
|
||||
const Vector2 offset = _pattern_offset;
|
||||
|
||||
VoxelGeneratorHeightmap::generate(out_buffer,
|
||||
[freq, offset](int x, int z) {
|
||||
return 0.5 + 0.25 * (Math::cos((x + offset.x) * freq.x) + Math::sin((z + offset.y) * freq.y));
|
||||
},
|
||||
input.origin_in_voxels, input.lod);
|
||||
}
|
||||
|
||||
void VoxelGeneratorWaves::set_pattern_size(Vector2 size) {
|
||||
size.x = max(size.x, 0.1f);
|
||||
size.y = max(size.y, 0.1f);
|
||||
_pattern_size = size;
|
||||
}
|
||||
|
||||
void VoxelGeneratorWaves::set_pattern_offset(Vector2 offset) {
|
||||
_pattern_offset = offset;
|
||||
}
|
||||
|
||||
void VoxelGeneratorWaves::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_pattern_size", "size"), &VoxelGeneratorWaves::set_pattern_size);
|
||||
ClassDB::bind_method(D_METHOD("get_pattern_size"), &VoxelGeneratorWaves::get_pattern_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_pattern_offset", "offset"), &VoxelGeneratorWaves::set_pattern_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_pattern_offset"), &VoxelGeneratorWaves::get_pattern_offset);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pattern_size"), "set_pattern_size", "get_pattern_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pattern_offset"), "set_pattern_offset", "get_pattern_offset");
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef VOXEL_GENERATOR_WAVES_H
|
||||
#define VOXEL_GENERATOR_WAVES_H
|
||||
|
||||
#include "voxel_generator_heightmap.h"
|
||||
|
||||
class VoxelGeneratorWaves : public VoxelGeneratorHeightmap {
|
||||
GDCLASS(VoxelGeneratorWaves, VoxelGeneratorHeightmap)
|
||||
|
||||
public:
|
||||
VoxelGeneratorWaves();
|
||||
|
||||
void set_channel(VoxelBuffer::ChannelId channel);
|
||||
VoxelBuffer::ChannelId get_channel() const;
|
||||
|
||||
void generate_block(VoxelBlockRequest &input) override;
|
||||
|
||||
Vector2 get_pattern_size() const { return _pattern_size; }
|
||||
void set_pattern_size(Vector2 size);
|
||||
|
||||
Vector2 get_pattern_offset() const { return _pattern_offset; }
|
||||
void set_pattern_offset(Vector2 offset);
|
||||
|
||||
private:
|
||||
static void _bind_methods();
|
||||
|
||||
Vector2 _pattern_size;
|
||||
Vector2 _pattern_offset;
|
||||
};
|
||||
|
||||
#endif // VOXEL_GENERATOR_WAVES_H
|
|
@ -103,13 +103,25 @@ struct Vector3i {
|
|||
|
||||
// Clamps between min and max, where max is excluded
|
||||
void clamp_to(const Vector3i min, const Vector3i max) {
|
||||
if (x < min.x) x = min.x;
|
||||
if (y < min.y) y = min.y;
|
||||
if (z < min.z) z = min.z;
|
||||
if (x < min.x) {
|
||||
x = min.x;
|
||||
}
|
||||
if (y < min.y) {
|
||||
y = min.y;
|
||||
}
|
||||
if (z < min.z) {
|
||||
z = min.z;
|
||||
}
|
||||
|
||||
if (x >= max.x) x = max.x - 1;
|
||||
if (y >= max.y) y = max.y - 1;
|
||||
if (z >= max.z) z = max.z - 1;
|
||||
if (x >= max.x) {
|
||||
x = max.x - 1;
|
||||
}
|
||||
if (y >= max.y) {
|
||||
y = max.y - 1;
|
||||
}
|
||||
if (z >= max.z) {
|
||||
z = max.z - 1;
|
||||
}
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool is_contained_in(const Vector3i &min, const Vector3i &max) {
|
||||
|
|
|
@ -384,10 +384,23 @@ void VoxelMesherBlocky::build(VoxelMesher::Output &output, const VoxelMesher::In
|
|||
// That means we can use raw pointers to voxel data inside instead of using the higher-level getters,
|
||||
// and then save a lot of time.
|
||||
|
||||
ERR_FAIL_COND(voxels.get_channel_compression(channel) != VoxelBuffer::COMPRESSION_NONE);
|
||||
if (voxels.get_channel_compression(channel) == VoxelBuffer::COMPRESSION_UNIFORM) {
|
||||
// All voxels have the same type.
|
||||
// If it's all air, nothing to do. If it's all cubes, nothing to do either.
|
||||
// TODO Handle edge case of uniform block with non-cubic voxels!
|
||||
// If the type of voxel still produces geometry in this situation (which is an absurd use case but not an error),
|
||||
// decompress into a backing array to still allow the use of the same algorithm.
|
||||
return;
|
||||
|
||||
} else if (voxels.get_channel_compression(channel) != VoxelBuffer::COMPRESSION_NONE) {
|
||||
// No other form of compression is allowed
|
||||
ERR_PRINT("VoxelMesherBlocky received unsupported voxel compression");
|
||||
return;
|
||||
}
|
||||
|
||||
ArraySlice<uint8_t> raw_channel;
|
||||
if (!voxels.get_channel_raw(channel, raw_channel)) {
|
||||
// _
|
||||
/* _
|
||||
// | \
|
||||
// /\ \\
|
||||
// / /|\\\
|
||||
|
@ -396,10 +409,9 @@ void VoxelMesherBlocky::build(VoxelMesher::Output &output, const VoxelMesher::In
|
|||
// | | )
|
||||
// \ | |
|
||||
// \ /
|
||||
//
|
||||
// No data to read, the channel is probably uniform
|
||||
// TODO This is an invalid behavior IF sending a full block of uniformly opaque cubes,
|
||||
// however not likely for terrains because with neighbor padding, such a case means no face would be generated anyways
|
||||
*/
|
||||
// Case supposedly handled before...
|
||||
ERR_PRINT("Something wrong happened");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ inline uint8_t get_border_mask(const Vector3i &pos, const Vector3i &block_size)
|
|||
// 16: -Z
|
||||
// 32: +Z
|
||||
|
||||
for (int i = 0; i < Vector3i::AXIS_COUNT; i++) {
|
||||
for (unsigned int i = 0; i < Vector3i::AXIS_COUNT; i++) {
|
||||
// Close to negative face.
|
||||
if (pos[i] == 0) {
|
||||
mask |= (1 << (i * 2));
|
||||
|
@ -908,20 +908,20 @@ void VoxelMesherTransvoxel::build_transition(const VoxelBuffer &p_voxels, unsign
|
|||
void VoxelMesherTransvoxel::reset_reuse_cells(Vector3i block_size) {
|
||||
_block_size = block_size;
|
||||
unsigned int deck_area = block_size.x * block_size.y;
|
||||
for (int i = 0; i < _cache.size(); ++i) {
|
||||
for (unsigned int i = 0; i < _cache.size(); ++i) {
|
||||
std::vector<ReuseCell> &deck = _cache[i];
|
||||
deck.resize(deck_area);
|
||||
for (int j = 0; j < deck.size(); ++j) {
|
||||
for (size_t j = 0; j < deck.size(); ++j) {
|
||||
deck[j].vertices.fill(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelMesherTransvoxel::reset_reuse_cells_2d(Vector3i block_size) {
|
||||
for (int i = 0; i < _cache_2d.size(); ++i) {
|
||||
for (unsigned int i = 0; i < _cache_2d.size(); ++i) {
|
||||
std::vector<ReuseTransitionCell> &row = _cache_2d[i];
|
||||
row.resize(block_size.x);
|
||||
for (int j = 0; j < row.size(); ++j) {
|
||||
for (size_t j = 0; j < row.size(); ++j) {
|
||||
row[j].vertices.fill(-1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#include "register_types.h"
|
||||
#include "edition/voxel_tool.h"
|
||||
#include "generators/voxel_generator_flat.h"
|
||||
#include "generators/voxel_generator_heightmap.h"
|
||||
#include "generators/voxel_generator_image.h"
|
||||
#include "generators/voxel_generator_noise.h"
|
||||
#include "generators/voxel_generator_noise_2d.h"
|
||||
#include "generators/voxel_generator_test.h"
|
||||
#include "generators/voxel_generator_waves.h"
|
||||
#include "meshers/blocky/voxel_library.h"
|
||||
#include "meshers/blocky/voxel_mesher_blocky.h"
|
||||
#include "meshers/dmc/voxel_mesher_dmc.h"
|
||||
|
@ -42,7 +43,8 @@ void register_voxel_types() {
|
|||
|
||||
// Generators
|
||||
ClassDB::register_class<VoxelGenerator>();
|
||||
ClassDB::register_class<VoxelGeneratorTest>();
|
||||
ClassDB::register_class<VoxelGeneratorFlat>();
|
||||
ClassDB::register_class<VoxelGeneratorWaves>();
|
||||
ClassDB::register_class<VoxelGeneratorHeightmap>();
|
||||
ClassDB::register_class<VoxelGeneratorImage>();
|
||||
ClassDB::register_class<VoxelGeneratorNoise2D>();
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
#include "file_utils.h"
|
||||
|
||||
const char *to_string(VoxelFileResult res) {
|
||||
switch (res) {
|
||||
case VOXEL_FILE_OK:
|
||||
return "OK";
|
||||
case VOXEL_FILE_CANT_OPEN:
|
||||
return "Can't open";
|
||||
case VOXEL_FILE_UNEXPECTED_EOF:
|
||||
return "Unexpected end of file";
|
||||
case VOXEL_FILE_INVALID_MAGIC:
|
||||
return "Invalid magic";
|
||||
case VOXEL_FILE_INVALID_VERSION:
|
||||
return "Invalid version";
|
||||
case VOXEL_FILE_INVALID_DATA:
|
||||
return "Invalid data";
|
||||
default:
|
||||
CRASH_NOW();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VoxelFileResult check_magic_and_version(FileAccess *f, uint8_t expected_version, const char *expected_magic, uint8_t &out_version) {
|
||||
|
||||
uint8_t magic[5] = { '\0' };
|
||||
int count = f->get_buffer(magic, 4);
|
||||
if (count != 4) {
|
||||
return VOXEL_FILE_UNEXPECTED_EOF;
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (magic[i] != expected_magic[i]) {
|
||||
return VOXEL_FILE_INVALID_MAGIC;
|
||||
}
|
||||
}
|
||||
|
||||
out_version = f->get_8();
|
||||
if (out_version != expected_version) {
|
||||
return VOXEL_FILE_INVALID_VERSION;
|
||||
}
|
||||
|
||||
return VOXEL_FILE_OK;
|
||||
}
|
||||
|
||||
Error check_directory_created(const String &directory_path) {
|
||||
|
||||
DirAccess *d = DirAccess::create_for_path(directory_path);
|
||||
|
||||
if (d == nullptr) {
|
||||
ERR_PRINT("Could not access to filesystem");
|
||||
return ERR_FILE_CANT_OPEN;
|
||||
}
|
||||
|
||||
if (!d->exists(directory_path)) {
|
||||
// Create if not exist
|
||||
Error err = d->make_dir_recursive(directory_path);
|
||||
if (err != OK) {
|
||||
ERR_PRINT("Could not create directory");
|
||||
memdelete(d);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
memdelete(d);
|
||||
return OK;
|
||||
}
|
|
@ -33,51 +33,17 @@ inline void store_vec3u32(FileAccess *f, const Vector3i v) {
|
|||
f->store_32(v.z);
|
||||
}
|
||||
|
||||
inline Error check_magic_and_version(FileAccess *f, uint8_t expected_version, const char *expected_magic, uint8_t &out_version) {
|
||||
enum VoxelFileResult {
|
||||
VOXEL_FILE_OK = 0,
|
||||
VOXEL_FILE_CANT_OPEN,
|
||||
VOXEL_FILE_UNEXPECTED_EOF,
|
||||
VOXEL_FILE_INVALID_MAGIC,
|
||||
VOXEL_FILE_INVALID_VERSION,
|
||||
VOXEL_FILE_INVALID_DATA
|
||||
};
|
||||
|
||||
uint8_t magic[5] = { '\0' };
|
||||
int count = f->get_buffer(magic, 4);
|
||||
if (count != 4) {
|
||||
ERR_PRINT("Unexpected end of file");
|
||||
return ERR_FILE_CORRUPT;
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (magic[i] != expected_magic[i]) {
|
||||
ERR_PRINT("Invalid magic");
|
||||
return ERR_FILE_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
||||
out_version = f->get_8();
|
||||
if (out_version != expected_version) {
|
||||
ERR_PRINT("Invalid version");
|
||||
return ERR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
inline Error check_directory_created(const String &directory_path) {
|
||||
|
||||
DirAccess *d = DirAccess::create_for_path(directory_path);
|
||||
|
||||
if (d == nullptr) {
|
||||
ERR_PRINT("Could not access to filesystem");
|
||||
return ERR_FILE_CANT_OPEN;
|
||||
}
|
||||
|
||||
if (!d->exists(directory_path)) {
|
||||
// Create if not exist
|
||||
Error err = d->make_dir_recursive(directory_path);
|
||||
if (err != OK) {
|
||||
ERR_PRINT("Could not create directory");
|
||||
memdelete(d);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
memdelete(d);
|
||||
return OK;
|
||||
}
|
||||
const char *to_string(VoxelFileResult res);
|
||||
VoxelFileResult check_magic_and_version(FileAccess *f, uint8_t expected_version, const char *expected_magic, uint8_t &out_version);
|
||||
Error check_directory_created(const String &directory_path);
|
||||
|
||||
#endif // FILE_UTILS_H
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <core/os/file_access.h>
|
||||
|
||||
namespace {
|
||||
// TODO Introduce versionning
|
||||
const unsigned int BLOCK_TRAILING_MAGIC = 0x900df00d;
|
||||
const int BLOCK_TRAILING_MAGIC_SIZE = 4;
|
||||
} // namespace
|
||||
|
@ -61,11 +62,22 @@ const std::vector<uint8_t> &VoxelBlockSerializer::serialize(VoxelBuffer &voxel_b
|
|||
} break;
|
||||
|
||||
case VoxelBuffer::COMPRESSION_UNIFORM: {
|
||||
int v = voxel_buffer.get_voxel(Vector3i(), channel_index);
|
||||
f->store_8((uint8_t)v);
|
||||
// TODO Support for larger depths
|
||||
if (VoxelBuffer::get_depth_bit_count(voxel_buffer.get_channel_depth(channel_index)) > 8) {
|
||||
ERR_PRINT("Uniform compression serialization doesn't support more than 8 bit depth");
|
||||
uint64_t v = voxel_buffer.get_voxel(Vector3i(), channel_index);
|
||||
switch (voxel_buffer.get_channel_depth(channel_index)) {
|
||||
case VoxelBuffer::DEPTH_8_BIT:
|
||||
f->store_8(v);
|
||||
break;
|
||||
case VoxelBuffer::DEPTH_16_BIT:
|
||||
f->store_16(v);
|
||||
break;
|
||||
case VoxelBuffer::DEPTH_32_BIT:
|
||||
f->store_32(v);
|
||||
break;
|
||||
case VoxelBuffer::DEPTH_64_BIT:
|
||||
f->store_64(v);
|
||||
break;
|
||||
default:
|
||||
CRASH_NOW();
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -107,9 +119,26 @@ bool VoxelBlockSerializer::deserialize(const std::vector<uint8_t> &p_data, Voxel
|
|||
|
||||
} break;
|
||||
|
||||
case VoxelBuffer::COMPRESSION_UNIFORM:
|
||||
out_voxel_buffer.clear_channel(channel_index, f->get_8());
|
||||
break;
|
||||
case VoxelBuffer::COMPRESSION_UNIFORM: {
|
||||
uint64_t v;
|
||||
switch (out_voxel_buffer.get_channel_depth(channel_index)) {
|
||||
case VoxelBuffer::DEPTH_8_BIT:
|
||||
v = f->get_8();
|
||||
break;
|
||||
case VoxelBuffer::DEPTH_16_BIT:
|
||||
v = f->get_16();
|
||||
break;
|
||||
case VoxelBuffer::DEPTH_32_BIT:
|
||||
v = f->get_32();
|
||||
break;
|
||||
case VoxelBuffer::DEPTH_64_BIT:
|
||||
v = f->get_64();
|
||||
break;
|
||||
default:
|
||||
CRASH_NOW();
|
||||
}
|
||||
out_voxel_buffer.clear_channel(channel_index, v);
|
||||
} break;
|
||||
|
||||
default:
|
||||
ERR_PRINT("Unhandled compression mode");
|
||||
|
|
|
@ -76,6 +76,27 @@ void VoxelStream::_immerge_block(Ref<VoxelBuffer> buffer, Vector3 origin_in_voxe
|
|||
immerge_block(buffer, Vector3i(origin_in_voxels), lod);
|
||||
}
|
||||
|
||||
int VoxelStream::get_used_channels_mask() const {
|
||||
ScriptInstance *script = get_script_instance();
|
||||
int mask = 0;
|
||||
if (script) {
|
||||
// Call script to get mask
|
||||
Variant::CallError err;
|
||||
//const Variant *args[3] = { &arg1, &arg2, &arg3 };
|
||||
mask = script->call(VoxelStringNames::get_singleton()->get_used_channels_mask, NULL, 0, err);
|
||||
ERR_FAIL_COND_V_MSG(err.error != Variant::CallError::CALL_OK, mask,
|
||||
"voxel_stream.cpp:get_used_channels_mask gave an error: " + String::num(err.error) +
|
||||
" Argument: " + String::num(err.argument) +
|
||||
" Expected type: " + Variant::get_type_name(err.expected));
|
||||
// This had to be explicitely logged due to the usual GD debugger not working with threads
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
int VoxelStream::_get_used_channels_mask() const {
|
||||
return get_used_channels_mask();
|
||||
}
|
||||
|
||||
VoxelStream::Stats VoxelStream::get_statistics() const {
|
||||
return _stats;
|
||||
}
|
||||
|
@ -85,4 +106,5 @@ void VoxelStream::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method(D_METHOD("emerge_block", "out_buffer", "origin_in_voxels", "lod"), &VoxelStream::_emerge_block);
|
||||
ClassDB::bind_method(D_METHOD("immerge_block", "buffer", "origin_in_voxels", "lod"), &VoxelStream::_immerge_block);
|
||||
ClassDB::bind_method(D_METHOD("get_used_channels_mask"), &VoxelStream::_get_used_channels_mask);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ public:
|
|||
// This function is recommended if you save to files, because you can batch their access.
|
||||
virtual void immerge_blocks(Vector<VoxelBlockRequest> &p_blocks);
|
||||
|
||||
virtual int get_used_channels_mask() const;
|
||||
|
||||
virtual bool is_thread_safe() const;
|
||||
virtual bool is_cloneable() const;
|
||||
|
||||
|
@ -43,6 +45,7 @@ protected:
|
|||
|
||||
void _emerge_block(Ref<VoxelBuffer> out_buffer, Vector3 origin_in_voxels, int lod);
|
||||
void _immerge_block(Ref<VoxelBuffer> buffer, Vector3 origin_in_voxels, int lod);
|
||||
int _get_used_channels_mask() const;
|
||||
|
||||
Stats _stats;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "voxel_stream_block_files.h"
|
||||
#include "../util/utility.h"
|
||||
#include "file_utils.h"
|
||||
#include <core/os/dir_access.h>
|
||||
#include <core/os/file_access.h>
|
||||
|
||||
|
@ -17,6 +16,7 @@ VoxelStreamBlockFiles::VoxelStreamBlockFiles() {
|
|||
_meta.block_size_po2 = 4;
|
||||
_meta.lod_count = 1;
|
||||
_meta.version = FORMAT_VERSION;
|
||||
_meta.channel_depths.fill(VoxelBuffer::DEFAULT_CHANNEL_DEPTH);
|
||||
}
|
||||
|
||||
// TODO Have configurable block size
|
||||
|
@ -31,7 +31,7 @@ void VoxelStreamBlockFiles::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i o
|
|||
}
|
||||
|
||||
if (!_meta_loaded) {
|
||||
if (load_meta() != OK) {
|
||||
if (load_meta() != VOXEL_FILE_OK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -62,8 +62,14 @@ void VoxelStreamBlockFiles::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i o
|
|||
{
|
||||
{
|
||||
uint8_t version;
|
||||
Error err = check_magic_and_version(f, FORMAT_VERSION, FORMAT_BLOCK_MAGIC, version);
|
||||
ERR_FAIL_COND(err != OK);
|
||||
VoxelFileResult err = check_magic_and_version(f, FORMAT_VERSION, FORMAT_BLOCK_MAGIC, version);
|
||||
ERR_FAIL_COND_MSG(err != VOXEL_FILE_OK, ::to_string(err));
|
||||
}
|
||||
|
||||
// Configure depths, as they currently are only specified in the meta file.
|
||||
// Files are expected to contain such depths, and use those in the buffer to know how much data to read.
|
||||
for (unsigned int channel_index = 0; channel_index < _meta.channel_depths.size(); ++channel_index) {
|
||||
out_buffer->set_channel_depth(channel_index, _meta.channel_depths[channel_index]);
|
||||
}
|
||||
|
||||
uint32_t size_to_read = f->get_32();
|
||||
|
@ -79,9 +85,32 @@ void VoxelStreamBlockFiles::immerge_block(Ref<VoxelBuffer> buffer, Vector3i orig
|
|||
ERR_FAIL_COND(_directory_path.empty());
|
||||
ERR_FAIL_COND(buffer.is_null());
|
||||
|
||||
if (!_meta_loaded) {
|
||||
// If it's not loaded, always try to load meta file first if it exists already,
|
||||
// because we could want to save blocks without reading any
|
||||
VoxelFileResult res = load_meta();
|
||||
if (res != VOXEL_FILE_OK && res != VOXEL_FILE_CANT_OPEN) {
|
||||
// The file is present but there is a problem with it
|
||||
String meta_path = _directory_path.plus_file(META_FILE_NAME);
|
||||
ERR_PRINT(String("Could not read {0}: {1}").format(varray(meta_path, ::to_string(res))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_meta_saved) {
|
||||
Error err = save_meta();
|
||||
ERR_FAIL_COND(err != OK);
|
||||
// First time we save the meta file, initialize it from the first block format
|
||||
for (unsigned int i = 0; i < _meta.channel_depths.size(); ++i) {
|
||||
_meta.channel_depths[i] = buffer->get_channel_depth(i);
|
||||
}
|
||||
VoxelFileResult res = save_meta();
|
||||
ERR_FAIL_COND(res != VOXEL_FILE_OK);
|
||||
}
|
||||
|
||||
// Check format
|
||||
const Vector3i block_size = Vector3i(1 << _meta.block_size_po2);
|
||||
ERR_FAIL_COND(buffer->get_size() != block_size);
|
||||
for (unsigned int channel_index = 0; channel_index < _meta.channel_depths.size(); ++channel_index) {
|
||||
ERR_FAIL_COND(buffer->get_channel_depth(channel_index) != _meta.channel_depths[channel_index]);
|
||||
}
|
||||
|
||||
Vector3i block_pos = get_block_position(origin_in_voxels) >> lod;
|
||||
|
@ -130,7 +159,7 @@ int VoxelStreamBlockFiles::get_block_size_po2() const {
|
|||
return _meta.block_size_po2;
|
||||
}
|
||||
|
||||
Error VoxelStreamBlockFiles::save_meta() {
|
||||
VoxelFileResult VoxelStreamBlockFiles::save_meta() {
|
||||
|
||||
CRASH_COND(_directory_path.empty());
|
||||
|
||||
|
@ -139,7 +168,7 @@ Error VoxelStreamBlockFiles::save_meta() {
|
|||
Error err = check_directory_created(_directory_path);
|
||||
if (err != OK) {
|
||||
ERR_PRINT("Could not save meta");
|
||||
return err;
|
||||
return VOXEL_FILE_CANT_OPEN;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,7 +177,7 @@ Error VoxelStreamBlockFiles::save_meta() {
|
|||
{
|
||||
Error err;
|
||||
FileAccess *f = open_file(meta_path, FileAccess::WRITE, &err);
|
||||
ERR_FAIL_COND_V(f == nullptr, err);
|
||||
ERR_FAIL_COND_V(f == nullptr, VOXEL_FILE_CANT_OPEN);
|
||||
|
||||
f->store_buffer((uint8_t *)FORMAT_META_MAGIC, 4);
|
||||
f->store_8(FORMAT_VERSION);
|
||||
|
@ -165,30 +194,30 @@ Error VoxelStreamBlockFiles::save_meta() {
|
|||
|
||||
_meta_loaded = true;
|
||||
_meta_saved = true;
|
||||
return OK;
|
||||
return VOXEL_FILE_OK;
|
||||
}
|
||||
|
||||
Error VoxelStreamBlockFiles::load_meta() {
|
||||
VoxelFileResult VoxelStreamBlockFiles::load_meta() {
|
||||
CRASH_COND(_directory_path.empty());
|
||||
|
||||
String meta_path = _directory_path.plus_file(META_FILE_NAME);
|
||||
|
||||
Meta meta;
|
||||
{
|
||||
Error err;
|
||||
FileAccessRef f = open_file(meta_path, FileAccess::READ, &err);
|
||||
Error open_result;
|
||||
FileAccessRef f = open_file(meta_path, FileAccess::READ, &open_result);
|
||||
// Had to add ERR_FILE_CANT_OPEN because that's what Godot actually returns when the file doesn't exist...
|
||||
if (!_meta_saved && (err == ERR_FILE_NOT_FOUND || err == ERR_FILE_CANT_OPEN)) {
|
||||
if (!_meta_saved && (open_result == ERR_FILE_NOT_FOUND || open_result == ERR_FILE_CANT_OPEN)) {
|
||||
// This is a new terrain, save the meta we have and consider it current
|
||||
Error save_err = save_meta();
|
||||
ERR_FAIL_COND_V(save_err != OK, save_err);
|
||||
return OK;
|
||||
VoxelFileResult save_result = save_meta();
|
||||
ERR_FAIL_COND_V(save_result != VOXEL_FILE_OK, save_result);
|
||||
return VOXEL_FILE_OK;
|
||||
}
|
||||
ERR_FAIL_COND_V(!f, err);
|
||||
ERR_FAIL_COND_V(!f, VOXEL_FILE_CANT_OPEN);
|
||||
|
||||
err = check_magic_and_version(f.f, FORMAT_VERSION, FORMAT_META_MAGIC, meta.version);
|
||||
if (err != OK) {
|
||||
return err;
|
||||
VoxelFileResult check_result = check_magic_and_version(f.f, FORMAT_VERSION, FORMAT_META_MAGIC, meta.version);
|
||||
if (check_result != VOXEL_FILE_OK) {
|
||||
return check_result;
|
||||
}
|
||||
|
||||
meta.lod_count = f->get_8();
|
||||
|
@ -196,17 +225,17 @@ Error VoxelStreamBlockFiles::load_meta() {
|
|||
|
||||
for (unsigned int i = 0; i < meta.channel_depths.size(); ++i) {
|
||||
uint8_t depth = f->get_8();
|
||||
ERR_FAIL_COND_V(depth >= VoxelBuffer::DEPTH_COUNT, ERR_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(depth >= VoxelBuffer::DEPTH_COUNT, VOXEL_FILE_INVALID_DATA);
|
||||
meta.channel_depths[i] = (VoxelBuffer::Depth)depth;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(meta.lod_count < 1 || meta.lod_count > 32, ERR_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(meta.block_size_po2 < 1 || meta.block_size_po2 > 8, ERR_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(meta.lod_count < 1 || meta.lod_count > 32, VOXEL_FILE_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(meta.block_size_po2 < 1 || meta.block_size_po2 > 8, VOXEL_FILE_INVALID_DATA);
|
||||
}
|
||||
|
||||
_meta_loaded = true;
|
||||
_meta = meta;
|
||||
return OK;
|
||||
return VOXEL_FILE_OK;
|
||||
}
|
||||
|
||||
String VoxelStreamBlockFiles::get_block_file_path(const Vector3i &block_pos, unsigned int lod) const {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef VOXEL_STREAM_BLOCK_FILES_H
|
||||
#define VOXEL_STREAM_BLOCK_FILES_H
|
||||
|
||||
#include "file_utils.h"
|
||||
#include "voxel_stream_file.h"
|
||||
|
||||
class FileAccess;
|
||||
|
@ -24,8 +25,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
private:
|
||||
Error save_meta();
|
||||
Error load_meta();
|
||||
VoxelFileResult save_meta();
|
||||
VoxelFileResult load_meta();
|
||||
String get_block_file_path(const Vector3i &block_pos, unsigned int lod) const;
|
||||
Vector3i get_block_position(const Vector3i &origin_in_voxels) const;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "voxel_stream_region_files.h"
|
||||
#include "../math/rect3i.h"
|
||||
#include "../util/utility.h"
|
||||
#include "file_utils.h"
|
||||
#include <core/io/json.h>
|
||||
#include <core/os/os.h>
|
||||
#include <algorithm>
|
||||
|
@ -21,10 +20,7 @@ VoxelStreamRegionFiles::VoxelStreamRegionFiles() {
|
|||
_meta.region_size_po2 = 4;
|
||||
_meta.sector_size = 512; // next_power_of_2(_meta.block_size.volume() / 10) // based on compression ratios
|
||||
_meta.lod_count = 1;
|
||||
|
||||
for (unsigned int i = 0; i < _meta.channel_depths.size(); ++i) {
|
||||
_meta.channel_depths[i] = VoxelBuffer::DEFAULT_CHANNEL_DEPTH;
|
||||
}
|
||||
_meta.channel_depths.fill(VoxelBuffer::DEFAULT_CHANNEL_DEPTH);
|
||||
}
|
||||
|
||||
VoxelStreamRegionFiles::~VoxelStreamRegionFiles() {
|
||||
|
@ -104,14 +100,13 @@ VoxelStreamRegionFiles::EmergeResult VoxelStreamRegionFiles::_emerge_block(Ref<V
|
|||
}
|
||||
|
||||
if (!_meta_loaded) {
|
||||
Error err = load_meta();
|
||||
if (err != OK) {
|
||||
// Had to add ERR_FILE_CANT_OPEN because that's what Godot actually returns when the file doesn't exist...
|
||||
if (!_meta_saved && (err == ERR_FILE_NOT_FOUND || err == ERR_FILE_CANT_OPEN)) {
|
||||
VoxelFileResult load_res = load_meta();
|
||||
if (load_res != VOXEL_FILE_OK) {
|
||||
if (!_meta_saved && load_res == VOXEL_FILE_CANT_OPEN) {
|
||||
// TODO Is it a good idea to save on read?
|
||||
// New data folder, save it for first time
|
||||
//print_line("Writing meta file");
|
||||
Error save_err = save_meta();
|
||||
ERR_FAIL_COND_V(save_err != OK, EMERGE_FAILED);
|
||||
VoxelFileResult save_res = save_meta();
|
||||
ERR_FAIL_COND_V(save_res != VOXEL_FILE_OK, EMERGE_FAILED);
|
||||
} else {
|
||||
return EMERGE_FAILED;
|
||||
}
|
||||
|
@ -125,6 +120,12 @@ VoxelStreamRegionFiles::EmergeResult VoxelStreamRegionFiles::_emerge_block(Ref<V
|
|||
ERR_FAIL_COND_V(lod >= _meta.lod_count, EMERGE_FAILED);
|
||||
ERR_FAIL_COND_V(block_size != out_buffer->get_size(), EMERGE_FAILED);
|
||||
|
||||
// Configure depths, as they currently are only specified in the meta file.
|
||||
// Regions are expected to contain such depths, and use those in the buffer to know how much data to read.
|
||||
for (unsigned int channel_index = 0; channel_index < _meta.channel_depths.size(); ++channel_index) {
|
||||
out_buffer->set_channel_depth(channel_index, _meta.channel_depths[channel_index]);
|
||||
}
|
||||
|
||||
Vector3i block_pos = get_block_position_from_voxels(origin_in_voxels) >> lod;
|
||||
Vector3i region_pos = get_region_position_from_blocks(block_pos);
|
||||
|
||||
|
@ -176,23 +177,38 @@ void VoxelStreamRegionFiles::_immerge_block(Ref<VoxelBuffer> voxel_buffer, Vecto
|
|||
|
||||
VOXEL_PROFILE_SCOPE(profile_scope);
|
||||
|
||||
const Vector3i block_size = Vector3i(1 << _meta.block_size_po2);
|
||||
const Vector3i region_size = Vector3i(1 << _meta.region_size_po2);
|
||||
|
||||
ERR_FAIL_COND(_directory_path.empty());
|
||||
ERR_FAIL_COND(voxel_buffer.is_null());
|
||||
ERR_FAIL_COND(voxel_buffer->get_size() != block_size);
|
||||
|
||||
if (!_meta_loaded) {
|
||||
// If it's not loaded, always try to load meta file first if it exists already,
|
||||
// because we could want to save blocks without reading any
|
||||
VoxelFileResult load_res = load_meta();
|
||||
if (load_res != VOXEL_FILE_OK && load_res != VOXEL_FILE_CANT_OPEN) {
|
||||
// The file is present but there is a problem with it
|
||||
String meta_path = _directory_path.plus_file(META_FILE_NAME);
|
||||
ERR_PRINT(String("Could not read {0}: error {1}").format(varray(meta_path, ::to_string(load_res))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_meta_saved) {
|
||||
Error err = save_meta();
|
||||
ERR_FAIL_COND(err != OK);
|
||||
// First time we save the meta file, initialize it from the first block format
|
||||
for (unsigned int i = 0; i < _meta.channel_depths.size(); ++i) {
|
||||
_meta.channel_depths[i] = voxel_buffer->get_channel_depth(i);
|
||||
}
|
||||
VoxelFileResult err = save_meta();
|
||||
ERR_FAIL_COND(err != VOXEL_FILE_OK);
|
||||
}
|
||||
|
||||
// Verify format
|
||||
const Vector3i block_size = Vector3i(1 << _meta.block_size_po2);
|
||||
ERR_FAIL_COND(voxel_buffer->get_size() != block_size);
|
||||
for (unsigned int i = 0; i < VoxelBuffer::MAX_CHANNELS; ++i) {
|
||||
ERR_FAIL_COND(voxel_buffer->get_channel_depth(i) != _meta.channel_depths[i]);
|
||||
}
|
||||
|
||||
const Vector3i region_size = Vector3i(1 << _meta.region_size_po2);
|
||||
Vector3i block_pos = get_block_position_from_voxels(origin_in_voxels) >> lod;
|
||||
Vector3i region_pos = get_region_position_from_blocks(block_pos);
|
||||
Vector3i block_rpos = block_pos.wrap(region_size);
|
||||
|
@ -382,6 +398,7 @@ void VoxelStreamRegionFiles::set_directory(String dirpath) {
|
|||
if (_directory_path != dirpath) {
|
||||
_directory_path = dirpath.strip_edges();
|
||||
_meta_loaded = false;
|
||||
_meta_saved = false;
|
||||
load_meta();
|
||||
_change_notify();
|
||||
}
|
||||
|
@ -428,9 +445,9 @@ static bool depth_from_json_variant(Variant &v, VoxelBuffer::Depth &d) {
|
|||
return true;
|
||||
}
|
||||
|
||||
Error VoxelStreamRegionFiles::save_meta() {
|
||||
VoxelFileResult VoxelStreamRegionFiles::save_meta() {
|
||||
|
||||
ERR_FAIL_COND_V(_directory_path == "", ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V(_directory_path == "", VOXEL_FILE_CANT_OPEN);
|
||||
|
||||
Dictionary d;
|
||||
d["version"] = _meta.version;
|
||||
|
@ -453,7 +470,7 @@ Error VoxelStreamRegionFiles::save_meta() {
|
|||
Error err = check_directory_created(_directory_path);
|
||||
if (err != OK) {
|
||||
ERR_PRINT("Could not save meta");
|
||||
return err;
|
||||
return VOXEL_FILE_CANT_OPEN;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,8 +479,8 @@ Error VoxelStreamRegionFiles::save_meta() {
|
|||
Error err;
|
||||
FileAccessRef f = open_file(meta_path, FileAccess::WRITE, &err);
|
||||
if (!f) {
|
||||
print_error(String("Could not save {0}").format(varray(meta_path)));
|
||||
return err;
|
||||
ERR_PRINT(String("Could not save {0}").format(varray(meta_path)));
|
||||
return VOXEL_FILE_CANT_OPEN;
|
||||
}
|
||||
|
||||
f->store_string(json);
|
||||
|
@ -471,12 +488,12 @@ Error VoxelStreamRegionFiles::save_meta() {
|
|||
_meta_saved = true;
|
||||
_meta_loaded = true;
|
||||
|
||||
return OK;
|
||||
return VOXEL_FILE_OK;
|
||||
}
|
||||
|
||||
static void migrate_region_meta_data(Dictionary &data) {
|
||||
|
||||
if (data["version"] == Variant(FORMAT_VERSION_LEGACY_1)) {
|
||||
if (data["version"] == Variant(real_t(FORMAT_VERSION_LEGACY_1))) {
|
||||
Array depths;
|
||||
depths.resize(VoxelBuffer::MAX_CHANNELS);
|
||||
for (int i = 0; i < depths.size(); ++i) {
|
||||
|
@ -487,9 +504,9 @@ static void migrate_region_meta_data(Dictionary &data) {
|
|||
}
|
||||
}
|
||||
|
||||
Error VoxelStreamRegionFiles::load_meta() {
|
||||
VoxelFileResult VoxelStreamRegionFiles::load_meta() {
|
||||
|
||||
ERR_FAIL_COND_V(_directory_path == "", ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V(_directory_path == "", VOXEL_FILE_CANT_OPEN);
|
||||
|
||||
// Ensure you cleanup previous world before loading another
|
||||
CRASH_COND(_region_cache.size() > 0);
|
||||
|
@ -501,8 +518,7 @@ Error VoxelStreamRegionFiles::load_meta() {
|
|||
Error err;
|
||||
FileAccessRef f = open_file(meta_path, FileAccess::READ, &err);
|
||||
if (!f) {
|
||||
//print_error(String("Could not load {0}").format(varray(meta_path)));
|
||||
return err;
|
||||
return VOXEL_FILE_CANT_OPEN;
|
||||
}
|
||||
json = f->get_as_utf8_string();
|
||||
}
|
||||
|
@ -515,34 +531,34 @@ Error VoxelStreamRegionFiles::load_meta() {
|
|||
int json_err_line;
|
||||
Error json_err = JSON::parse(json, res, json_err_msg, json_err_line);
|
||||
if (json_err != OK) {
|
||||
print_error(String("Error when parsing {0}: line {1}: {2}").format(varray(meta_path, json_err_line, json_err_msg)));
|
||||
return json_err;
|
||||
ERR_PRINT(String("Error when parsing {0}: line {1}: {2}").format(varray(meta_path, json_err_line, json_err_msg)));
|
||||
return VOXEL_FILE_INVALID_DATA;
|
||||
}
|
||||
|
||||
Dictionary d = res;
|
||||
migrate_region_meta_data(d);
|
||||
Meta meta;
|
||||
ERR_FAIL_COND_V(!u8_from_json_variant(d["version"], meta.version), ERR_PARSE_ERROR);
|
||||
ERR_FAIL_COND_V(!u8_from_json_variant(d["block_size_po2"], meta.block_size_po2), ERR_PARSE_ERROR);
|
||||
ERR_FAIL_COND_V(!u8_from_json_variant(d["region_size_po2"], meta.region_size_po2), ERR_PARSE_ERROR);
|
||||
ERR_FAIL_COND_V(!u8_from_json_variant(d["lod_count"], meta.lod_count), ERR_PARSE_ERROR);
|
||||
ERR_FAIL_COND_V(!s32_from_json_variant(d["sector_size"], meta.sector_size), ERR_PARSE_ERROR);
|
||||
ERR_FAIL_COND_V(!u8_from_json_variant(d["version"], meta.version), VOXEL_FILE_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(!u8_from_json_variant(d["block_size_po2"], meta.block_size_po2), VOXEL_FILE_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(!u8_from_json_variant(d["region_size_po2"], meta.region_size_po2), VOXEL_FILE_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(!u8_from_json_variant(d["lod_count"], meta.lod_count), VOXEL_FILE_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(!s32_from_json_variant(d["sector_size"], meta.sector_size), VOXEL_FILE_INVALID_DATA);
|
||||
|
||||
ERR_FAIL_COND_V(meta.version < 0, ERR_PARSE_ERROR);
|
||||
ERR_FAIL_COND_V(meta.version < 0, VOXEL_FILE_INVALID_DATA);
|
||||
|
||||
Array channel_depths_data = d["channel_depths"];
|
||||
ERR_FAIL_COND_V(channel_depths_data.size() != VoxelBuffer::MAX_CHANNELS, ERR_PARSE_ERROR);
|
||||
ERR_FAIL_COND_V(channel_depths_data.size() != VoxelBuffer::MAX_CHANNELS, VOXEL_FILE_INVALID_DATA);
|
||||
for (int i = 0; i < channel_depths_data.size(); ++i) {
|
||||
ERR_FAIL_COND_V(depth_from_json_variant(channel_depths_data[i], meta.channel_depths[i]), ERR_PARSE_ERROR);
|
||||
ERR_FAIL_COND_V(!depth_from_json_variant(channel_depths_data[i], meta.channel_depths[i]), VOXEL_FILE_INVALID_DATA);
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(!check_meta(meta), ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V(!check_meta(meta), VOXEL_FILE_INVALID_DATA);
|
||||
|
||||
_meta = meta;
|
||||
_meta_loaded = true;
|
||||
_meta_saved = true;
|
||||
|
||||
return OK;
|
||||
return VOXEL_FILE_OK;
|
||||
}
|
||||
|
||||
bool VoxelStreamRegionFiles::check_meta(const Meta &meta) {
|
||||
|
@ -657,12 +673,23 @@ VoxelStreamRegionFiles::CachedRegion *VoxelStreamRegionFiles::open_region(const
|
|||
VOXEL_PROFILE_SCOPE(profile_read_existing);
|
||||
|
||||
uint8_t version;
|
||||
if (check_magic_and_version(existing_f, FORMAT_VERSION, FORMAT_REGION_MAGIC, version) != OK) {
|
||||
const VoxelFileResult check_result = check_magic_and_version(existing_f, FORMAT_VERSION, FORMAT_REGION_MAGIC, version);
|
||||
|
||||
if (check_result == VOXEL_FILE_INVALID_VERSION) {
|
||||
if (version != FORMAT_VERSION_LEGACY_1) {
|
||||
memdelete(existing_f);
|
||||
ERR_PRINT(String("Could not open file {0}, invalid version {1}").format(varray(fpath, version)));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} else if (check_result != VOXEL_FILE_OK) {
|
||||
memdelete(existing_f);
|
||||
print_error(String("Could not open file {0}, format or version mismatch").format(varray(fpath)));
|
||||
ERR_PRINT(String("Could not open file {0}, {1}").format(varray(fpath, ::to_string(check_result))));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Versions 1 and 2 are the same
|
||||
|
||||
cache = memnew(CachedRegion);
|
||||
cache->file_exists = true;
|
||||
cache->file_access = existing_f;
|
||||
|
@ -853,7 +880,7 @@ void VoxelStreamRegionFiles::_convert_files(Meta new_meta) {
|
|||
int lod;
|
||||
};
|
||||
|
||||
ERR_FAIL_COND(old_stream->load_meta() != OK);
|
||||
ERR_FAIL_COND(old_stream->load_meta() != VOXEL_FILE_OK);
|
||||
|
||||
std::vector<PositionAndLod> old_region_list;
|
||||
Meta old_meta = old_stream->_meta;
|
||||
|
@ -898,7 +925,7 @@ void VoxelStreamRegionFiles::_convert_files(Meta new_meta) {
|
|||
}
|
||||
|
||||
_meta = new_meta;
|
||||
ERR_FAIL_COND(save_meta() != OK);
|
||||
ERR_FAIL_COND(save_meta() != VOXEL_FILE_OK);
|
||||
|
||||
const Vector3i old_block_size = Vector3i(1 << old_meta.block_size_po2);
|
||||
const Vector3i new_block_size = Vector3i(1 << _meta.block_size_po2);
|
||||
|
@ -1079,7 +1106,7 @@ void VoxelStreamRegionFiles::convert_files(Dictionary d) {
|
|||
|
||||
if (!_meta_loaded) {
|
||||
|
||||
if (load_meta() != OK) {
|
||||
if (load_meta() != VOXEL_FILE_OK) {
|
||||
// New stream, nothing to convert
|
||||
_meta = meta;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define VOXEL_STREAM_REGION_H
|
||||
|
||||
#include "../util/fixed_array.h"
|
||||
#include "file_utils.h"
|
||||
#include "voxel_stream_file.h"
|
||||
|
||||
class FileAccess;
|
||||
|
@ -60,8 +61,8 @@ private:
|
|||
EmergeResult _emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod);
|
||||
void _immerge_block(Ref<VoxelBuffer> voxel_buffer, Vector3i origin_in_voxels, int lod);
|
||||
|
||||
Error save_meta();
|
||||
Error load_meta();
|
||||
VoxelFileResult save_meta();
|
||||
VoxelFileResult load_meta();
|
||||
Vector3i get_block_position_from_voxels(const Vector3i &origin_in_voxels) const;
|
||||
Vector3i get_region_position_from_blocks(const Vector3i &block_position) const;
|
||||
void close_all_regions();
|
||||
|
|
|
@ -104,6 +104,7 @@ void VoxelDataLoader::process_blocks_thread_func(const ArraySlice<InputBlock> in
|
|||
if (ib.data.voxels_to_save.is_null()) {
|
||||
output.type = TYPE_LOAD;
|
||||
output.voxels_loaded = emerge_requests.write[iload].voxel_buffer;
|
||||
CRASH_COND(output.voxels_loaded.is_null());
|
||||
++iload;
|
||||
|
||||
} else {
|
||||
|
|
|
@ -13,7 +13,8 @@ public:
|
|||
};
|
||||
|
||||
enum RequestType {
|
||||
TYPE_SAVE = 0,
|
||||
TYPE_NOT_INITIALIZED = 0, // For error detection
|
||||
TYPE_SAVE,
|
||||
TYPE_LOAD
|
||||
};
|
||||
|
||||
|
|
|
@ -83,6 +83,15 @@ VoxelLodTerrain::~VoxelLodTerrain() {
|
|||
}
|
||||
}
|
||||
|
||||
String VoxelLodTerrain::get_configuration_warning() const {
|
||||
if (_stream.is_valid()) {
|
||||
if (! (_stream->get_used_channels_mask() & (1<<VoxelBuffer::CHANNEL_SDF))) {
|
||||
return TTR("VoxelLodTerrain supports only stream channel \"Sdf\" (smooth).");
|
||||
}
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
Ref<Material> VoxelLodTerrain::get_material() const {
|
||||
return _material;
|
||||
}
|
||||
|
@ -154,6 +163,8 @@ void VoxelLodTerrain::_on_stream_params_changed() {
|
|||
Lod &lod = _lods[i];
|
||||
lod.last_view_distance_blocks = 0;
|
||||
}
|
||||
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
void VoxelLodTerrain::set_block_size_po2(unsigned int p_block_size_po2) {
|
||||
|
@ -280,7 +291,7 @@ void VoxelLodTerrain::stop_updater() {
|
|||
|
||||
_blocks_pending_main_thread_update.clear();
|
||||
|
||||
for (int i = 0; i < _lods.size(); ++i) {
|
||||
for (unsigned int i = 0; i < _lods.size(); ++i) {
|
||||
|
||||
Lod &lod = _lods[i];
|
||||
lod.blocks_pending_update.clear();
|
||||
|
@ -307,7 +318,7 @@ void VoxelLodTerrain::stop_streamer() {
|
|||
_stream_thread = nullptr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _lods.size(); ++i) {
|
||||
for (unsigned int i = 0; i < _lods.size(); ++i) {
|
||||
Lod &lod = _lods[i];
|
||||
lod.blocks_to_load.clear();
|
||||
}
|
||||
|
@ -337,7 +348,7 @@ float VoxelLodTerrain::get_lod_split_scale() const {
|
|||
|
||||
void VoxelLodTerrain::set_lod_count(int p_lod_count) {
|
||||
|
||||
ERR_FAIL_COND(p_lod_count >= VoxelConstants::MAX_LOD);
|
||||
ERR_FAIL_COND(p_lod_count >= (int)VoxelConstants::MAX_LOD);
|
||||
ERR_FAIL_COND(p_lod_count < 1);
|
||||
|
||||
if (get_lod_count() != p_lod_count) {
|
||||
|
@ -347,7 +358,7 @@ void VoxelLodTerrain::set_lod_count(int p_lod_count) {
|
|||
|
||||
void VoxelLodTerrain::_set_lod_count(int p_lod_count) {
|
||||
|
||||
CRASH_COND(p_lod_count >= VoxelConstants::MAX_LOD);
|
||||
CRASH_COND(p_lod_count >= (int)VoxelConstants::MAX_LOD);
|
||||
CRASH_COND(p_lod_count < 1);
|
||||
|
||||
_lod_count = p_lod_count;
|
||||
|
@ -365,7 +376,7 @@ void VoxelLodTerrain::_set_lod_count(int p_lod_count) {
|
|||
void VoxelLodTerrain::reset_maps() {
|
||||
// Clears all blocks and reconfigures maps to account for new LOD count and block sizes
|
||||
|
||||
for (int lod_index = 0; lod_index < _lods.size(); ++lod_index) {
|
||||
for (int lod_index = 0; lod_index < (int)_lods.size(); ++lod_index) {
|
||||
|
||||
Lod &lod = _lods[lod_index];
|
||||
|
||||
|
@ -447,7 +458,7 @@ void VoxelLodTerrain::_notification(int p_what) {
|
|||
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
World *world = *get_world();
|
||||
for (int lod_index = 0; lod_index < _lods.size(); ++lod_index) {
|
||||
for (unsigned int lod_index = 0; lod_index < _lods.size(); ++lod_index) {
|
||||
if (_lods[lod_index].map.is_valid()) {
|
||||
_lods[lod_index].map->for_all_blocks([world](VoxelBlock *block) {
|
||||
block->set_world(world);
|
||||
|
@ -457,7 +468,7 @@ void VoxelLodTerrain::_notification(int p_what) {
|
|||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
for (int lod_index = 0; lod_index < _lods.size(); ++lod_index) {
|
||||
for (unsigned int lod_index = 0; lod_index < _lods.size(); ++lod_index) {
|
||||
if (_lods[lod_index].map.is_valid()) {
|
||||
_lods[lod_index].map->for_all_blocks([](VoxelBlock *block) {
|
||||
block->set_world(nullptr);
|
||||
|
@ -468,7 +479,7 @@ void VoxelLodTerrain::_notification(int p_what) {
|
|||
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
bool visible = is_visible();
|
||||
for (int lod_index = 0; lod_index < _lods.size(); ++lod_index) {
|
||||
for (unsigned int lod_index = 0; lod_index < _lods.size(); ++lod_index) {
|
||||
if (_lods[lod_index].map.is_valid()) {
|
||||
_lods[lod_index].map->for_all_blocks([visible](VoxelBlock *block) {
|
||||
block->set_parent_visible(visible);
|
||||
|
@ -968,18 +979,19 @@ void VoxelLodTerrain::_process() {
|
|||
|
||||
//print_line(String("Loaded {0} blocks").format(varray(output.emerged_blocks.size())));
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
for (int i = 0; i < _lod_count; ++i) {
|
||||
_lods[i].debug_unexpected_block_drops.clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < output.blocks.size(); ++i) {
|
||||
|
||||
VOXEL_PROFILE_SCOPE(profile_process_get_loading_responses_block);
|
||||
|
||||
const VoxelDataLoader::OutputBlock &ob = output.blocks[i];
|
||||
|
||||
if (ob.data.type == VoxelDataLoader::TYPE_SAVE) {
|
||||
// That's a save confirmation event.
|
||||
// Note: in the future, if blocks don't get copied before being sent for saving,
|
||||
// we will need to use block versionning to know when we can reset the `modified` flag properly
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ob.lod >= get_lod_count()) {
|
||||
// That block was requested at a time where LOD was higher... drop it
|
||||
++_stats.dropped_block_loads;
|
||||
|
@ -1007,9 +1019,6 @@ void VoxelLodTerrain::_process() {
|
|||
// print_line(String("Received a block loading drop while we were still expecting it: lod{0} ({1}, {2}, {3})")
|
||||
// .format(varray(ob.lod, ob.position.x, ob.position.y, ob.position.z)));
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
lod.debug_unexpected_block_drops.push_back(ob.position);
|
||||
#endif
|
||||
++_stats.dropped_block_loads;
|
||||
continue;
|
||||
}
|
||||
|
@ -1205,7 +1214,7 @@ void VoxelLodTerrain::_process() {
|
|||
|
||||
{
|
||||
VOXEL_PROFILE_SCOPE(profile_process_receive_mesh_updates_block_update_transitions);
|
||||
for (int dir = 0; dir < mesh_data.transition_surfaces.size(); ++dir) {
|
||||
for (unsigned int dir = 0; dir < mesh_data.transition_surfaces.size(); ++dir) {
|
||||
|
||||
Ref<ArrayMesh> transition_mesh = build_mesh(
|
||||
mesh_data.transition_surfaces[dir],
|
||||
|
@ -1254,7 +1263,7 @@ void VoxelLodTerrain::flush_pending_lod_edits() {
|
|||
// Make sure LOD0 gets updates even if _lod_count is 1
|
||||
Lod &lod0 = _lods[0];
|
||||
for (unsigned int i = 0; i < lod0.blocks_pending_lodding.size(); ++i) {
|
||||
Vector3i bpos = lod0.blocks_pending_lodding[i];
|
||||
const Vector3i bpos = lod0.blocks_pending_lodding[i];
|
||||
VoxelBlock *block = lod0.map->get_block(bpos);
|
||||
block->set_needs_lodding(false);
|
||||
L::schedule_update(block, lod0.blocks_pending_update);
|
||||
|
@ -1270,8 +1279,8 @@ void VoxelLodTerrain::flush_pending_lod_edits() {
|
|||
Lod &dst_lod = _lods[dst_lod_index];
|
||||
|
||||
for (unsigned int i = 0; i < src_lod.blocks_pending_lodding.size(); ++i) {
|
||||
Vector3i src_bpos = src_lod.blocks_pending_lodding[i];
|
||||
Vector3i dst_bpos = src_bpos >> 1;
|
||||
const Vector3i src_bpos = src_lod.blocks_pending_lodding[i];
|
||||
const Vector3i dst_bpos = src_bpos >> 1;
|
||||
|
||||
VoxelBlock *src_block = src_lod.map->get_block(src_bpos);
|
||||
VoxelBlock *dst_block = dst_lod.map->get_block(dst_bpos);
|
||||
|
@ -1294,7 +1303,7 @@ void VoxelLodTerrain::flush_pending_lod_edits() {
|
|||
dst_lod.blocks_pending_lodding.push_back(dst_bpos);
|
||||
}
|
||||
|
||||
Vector3i rel = src_bpos - (dst_bpos << 1);
|
||||
const Vector3i rel = src_bpos - (dst_bpos << 1);
|
||||
|
||||
// Update lower LOD
|
||||
// This must always be done after an edit before it gets saved, otherwise LODs won't match and it will look ugly.
|
||||
|
@ -1422,7 +1431,7 @@ uint8_t VoxelLodTerrain::get_transition_mask(Vector3i block_pos, int lod_index)
|
|||
|
||||
uint8_t transition_mask = 0;
|
||||
|
||||
if (lod_index + 1 >= _lods.size()) {
|
||||
if (lod_index + 1 >= (int)_lods.size()) {
|
||||
return transition_mask;
|
||||
}
|
||||
|
||||
|
@ -1482,7 +1491,7 @@ uint8_t VoxelLodTerrain::get_transition_mask(Vector3i block_pos, int lod_index)
|
|||
// There are always 4 on each side, checking any is enough
|
||||
|
||||
Vector3i upper_neighbor_pos = upper_pos;
|
||||
for (int i = 0; i < Vector3i::AXIS_COUNT; ++i) {
|
||||
for (unsigned int i = 0; i < Vector3i::AXIS_COUNT; ++i) {
|
||||
if (side_normal[i] == -1) {
|
||||
--upper_neighbor_pos[i];
|
||||
} else if (side_normal[i] == 1) {
|
||||
|
@ -1556,30 +1565,8 @@ Array VoxelLodTerrain::debug_raycast_block(Vector3 world_origin, Vector3 world_d
|
|||
return hits;
|
||||
}
|
||||
|
||||
Array VoxelLodTerrain::debug_get_last_unexpected_block_drops() const {
|
||||
|
||||
Array lods;
|
||||
lods.resize(_lod_count);
|
||||
|
||||
for (int i = 0; i < _lod_count; ++i) {
|
||||
const Lod &lod = _lods[i];
|
||||
|
||||
Array drops;
|
||||
drops.resize(lod.debug_unexpected_block_drops.size());
|
||||
|
||||
for (int j = 0; j < lod.debug_unexpected_block_drops.size(); ++j) {
|
||||
drops[j] = lod.debug_unexpected_block_drops[j].to_vec3();
|
||||
}
|
||||
|
||||
lods[i] = drops;
|
||||
}
|
||||
|
||||
return lods;
|
||||
}
|
||||
|
||||
Dictionary VoxelLodTerrain::debug_get_block_info(Vector3 fbpos, int lod_index) const {
|
||||
|
||||
// Gets some info useful for debugging
|
||||
Dictionary d;
|
||||
ERR_FAIL_COND_V(lod_index < 0, d);
|
||||
ERR_FAIL_COND_V(lod_index >= get_lod_count(), d);
|
||||
|
@ -1620,6 +1607,39 @@ Array VoxelLodTerrain::debug_get_octrees() const {
|
|||
return positions;
|
||||
}
|
||||
|
||||
Array VoxelLodTerrain::_b_debug_print_sdf_top_down(Vector3 center, Vector3 extents) const {
|
||||
|
||||
Array image_array;
|
||||
image_array.resize(get_lod_count());
|
||||
|
||||
for (int lod_index = 0; lod_index < get_lod_count(); ++lod_index) {
|
||||
|
||||
const Rect3i world_box = Rect3i::from_center_extents(Vector3i(center) >> lod_index, Vector3i(extents) >> lod_index);
|
||||
|
||||
if (world_box.size.volume() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Ref<VoxelBuffer> buffer_ref;
|
||||
buffer_ref.instance();
|
||||
VoxelBuffer &buffer = **buffer_ref;
|
||||
buffer.create(world_box.size);
|
||||
|
||||
const Lod &lod = _lods[lod_index];
|
||||
|
||||
world_box.for_each_cell([&](const Vector3i &world_pos) {
|
||||
const float v = lod.map->get_voxel_f(world_pos, VoxelBuffer::CHANNEL_SDF);
|
||||
const Vector3i rpos = world_pos - world_box.pos;
|
||||
buffer.set_voxel_f(v, rpos.x, rpos.y, rpos.z, VoxelBuffer::CHANNEL_SDF);
|
||||
});
|
||||
|
||||
Ref<Image> image = buffer.debug_print_sdf_to_image_top_down();
|
||||
image_array[lod_index] = image;
|
||||
}
|
||||
|
||||
return image_array;
|
||||
}
|
||||
|
||||
void VoxelLodTerrain::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_stream", "stream"), &VoxelLodTerrain::set_stream);
|
||||
|
@ -1655,8 +1675,9 @@ void VoxelLodTerrain::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method(D_METHOD("debug_raycast_block", "origin", "dir"), &VoxelLodTerrain::debug_raycast_block);
|
||||
ClassDB::bind_method(D_METHOD("debug_get_block_info", "block_pos", "lod"), &VoxelLodTerrain::debug_get_block_info);
|
||||
ClassDB::bind_method(D_METHOD("debug_get_last_unexpected_block_drops"), &VoxelLodTerrain::debug_get_last_unexpected_block_drops);
|
||||
ClassDB::bind_method(D_METHOD("debug_get_octrees"), &VoxelLodTerrain::debug_get_octrees);
|
||||
ClassDB::bind_method(D_METHOD("debug_save_all_modified_blocks"), &VoxelLodTerrain::_b_save_all_modified_blocks);
|
||||
ClassDB::bind_method(D_METHOD("debug_print_sdf_top_down", "center", "extents"), &VoxelLodTerrain::_b_debug_print_sdf_top_down);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_on_stream_params_changed"), &VoxelLodTerrain::_on_stream_params_changed);
|
||||
|
||||
|
@ -1669,3 +1690,7 @@ void VoxelLodTerrain::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_collisions"), "set_generate_collisions", "get_generate_collisions");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_lod_count"), "set_collision_lod_count", "get_collision_lod_count");
|
||||
}
|
||||
|
||||
void VoxelLodTerrain::_b_save_all_modified_blocks() {
|
||||
save_all_modified_blocks(true);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ public:
|
|||
VoxelLodTerrain();
|
||||
~VoxelLodTerrain();
|
||||
|
||||
String get_configuration_warning() const override;
|
||||
|
||||
Ref<Material> get_material() const;
|
||||
void set_material(Ref<Material> p_material);
|
||||
|
||||
|
@ -76,7 +78,6 @@ public:
|
|||
Dictionary get_statistics() const;
|
||||
|
||||
Array debug_raycast_block(Vector3 world_origin, Vector3 world_direction) const;
|
||||
Array debug_get_last_unexpected_block_drops() const;
|
||||
Dictionary debug_get_block_info(Vector3 fbpos, int lod_index) const;
|
||||
Array debug_get_octrees() const;
|
||||
|
||||
|
@ -115,6 +116,9 @@ private:
|
|||
void process_transition_updates();
|
||||
uint8_t get_transition_mask(Vector3i block_pos, int lod_index) const;
|
||||
|
||||
void _b_save_all_modified_blocks();
|
||||
Array _b_debug_print_sdf_top_down(Vector3 center, Vector3 extents) const;
|
||||
|
||||
struct OctreeItem {
|
||||
LodOctree octree;
|
||||
};
|
||||
|
@ -157,11 +161,6 @@ private:
|
|||
|
||||
// Members for memory caching
|
||||
std::vector<Vector3i> blocks_to_load;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
// TODO Debug, may be removed in the future
|
||||
std::vector<Vector3i> debug_unexpected_block_drops;
|
||||
#endif
|
||||
};
|
||||
|
||||
FixedArray<Lod, VoxelConstants::MAX_LOD> _lods;
|
||||
|
|
|
@ -61,7 +61,7 @@ VoxelBlock *VoxelMap::get_or_create_block_at_voxel_pos(Vector3i pos) {
|
|||
Vector3i bpos = voxel_to_block(pos);
|
||||
VoxelBlock *block = get_block(bpos);
|
||||
|
||||
if (block == NULL) {
|
||||
if (block == nullptr) {
|
||||
|
||||
Ref<VoxelBuffer> buffer(memnew(VoxelBuffer));
|
||||
buffer->create(_block_size, _block_size, _block_size);
|
||||
|
@ -85,7 +85,7 @@ float VoxelMap::get_voxel_f(Vector3i pos, unsigned int c) const {
|
|||
|
||||
Vector3i bpos = voxel_to_block(pos);
|
||||
const VoxelBlock *block = get_block(bpos);
|
||||
if (block == NULL) {
|
||||
if (block == nullptr) {
|
||||
return _default_voxel[c];
|
||||
}
|
||||
Vector3i lpos = to_local(pos);
|
||||
|
|
|
@ -23,11 +23,14 @@ VoxelTerrain::VoxelTerrain() {
|
|||
_view_distance_blocks = 8;
|
||||
_last_view_distance_blocks = 0;
|
||||
|
||||
_stream_thread = NULL;
|
||||
_block_updater = NULL;
|
||||
_stream_thread = nullptr;
|
||||
_block_updater = nullptr;
|
||||
|
||||
_run_in_editor = false;
|
||||
_smooth_meshing_enabled = false;
|
||||
|
||||
Ref<VoxelLibrary> library;
|
||||
library.instance();
|
||||
set_voxel_library(library);
|
||||
}
|
||||
|
||||
VoxelTerrain::~VoxelTerrain() {
|
||||
|
@ -46,6 +49,15 @@ VoxelTerrain::~VoxelTerrain() {
|
|||
}
|
||||
}
|
||||
|
||||
String VoxelTerrain::get_configuration_warning() const {
|
||||
if (_stream.is_valid()) {
|
||||
if (! (_stream->get_used_channels_mask() & ((1<<VoxelBuffer::CHANNEL_TYPE) | (1<<VoxelBuffer::CHANNEL_SDF)))) {
|
||||
return TTR("VoxelTerrain supports only stream channels \"Type\" or \"Sdf\".");
|
||||
}
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
// TODO See if there is a way to specify materials in voxels directly?
|
||||
|
||||
bool VoxelTerrain::_set(const StringName &p_name, const Variant &p_value) {
|
||||
|
@ -162,6 +174,8 @@ void VoxelTerrain::_on_stream_params_changed() {
|
|||
start_updater();
|
||||
}
|
||||
|
||||
update_configuration_warning();
|
||||
|
||||
// The whole map might change, so make all area dirty
|
||||
// TODO Actually, we should regenerate the whole map, not just update all its blocks
|
||||
make_all_view_dirty_deferred();
|
||||
|
@ -206,7 +220,7 @@ int VoxelTerrain::get_view_distance() const {
|
|||
}
|
||||
|
||||
void VoxelTerrain::set_view_distance(int distance_in_voxels) {
|
||||
ERR_FAIL_COND(distance_in_voxels < 0)
|
||||
ERR_FAIL_COND(distance_in_voxels < 0);
|
||||
int d = distance_in_voxels / _map->get_block_size();
|
||||
if (d != _view_distance_blocks) {
|
||||
print_line(String("View distance changed from ") + String::num(_view_distance_blocks) + String(" blocks to ") + String::num(d));
|
||||
|
@ -248,19 +262,6 @@ Ref<Material> VoxelTerrain::get_material(unsigned int id) const {
|
|||
return _materials[id];
|
||||
}
|
||||
|
||||
bool VoxelTerrain::is_smooth_meshing_enabled() const {
|
||||
return _smooth_meshing_enabled;
|
||||
}
|
||||
|
||||
void VoxelTerrain::set_smooth_meshing_enabled(bool enabled) {
|
||||
if (_smooth_meshing_enabled != enabled) {
|
||||
_smooth_meshing_enabled = enabled;
|
||||
stop_updater();
|
||||
start_updater();
|
||||
make_all_view_dirty_deferred();
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelTerrain::make_block_dirty(Vector3i bpos) {
|
||||
// TODO Immediate update viewer distance?
|
||||
|
||||
|
@ -389,7 +390,11 @@ void VoxelTerrain::start_updater() {
|
|||
|
||||
// TODO Thread-safe way to change those parameters
|
||||
VoxelMeshUpdater::MeshingParams params;
|
||||
params.smooth_surface = _smooth_meshing_enabled;
|
||||
|
||||
if (_stream.is_valid()) {
|
||||
params.smooth_surface = _stream->get_used_channels_mask() & (1 << VoxelBuffer::CHANNEL_SDF);
|
||||
}
|
||||
|
||||
params.library = _library;
|
||||
|
||||
_block_updater = memnew(VoxelMeshUpdater(1, params));
|
||||
|
@ -899,14 +904,14 @@ void VoxelTerrain::_process() {
|
|||
// Smooth meshing works on more neighbors, so checking a single block isn't enough to ignore it,
|
||||
// but that will slow down meshing a lot.
|
||||
// TODO This is one reason to separate terrain systems between blocky and smooth (other reason is LOD)
|
||||
if (!_smooth_meshing_enabled) {
|
||||
if (! (_stream->get_used_channels_mask() & (1<<VoxelBuffer::CHANNEL_SDF))) {
|
||||
VoxelBlock *block = _map->get_block(block_pos);
|
||||
if (block == nullptr) {
|
||||
continue;
|
||||
} else {
|
||||
CRASH_COND(block->voxels.is_null());
|
||||
|
||||
int air_type = 0;
|
||||
uint64_t air_type = 0;
|
||||
if (
|
||||
block->voxels->is_uniform(VoxelBuffer::CHANNEL_TYPE) &&
|
||||
block->voxels->is_uniform(VoxelBuffer::CHANNEL_SDF) &&
|
||||
|
@ -1065,7 +1070,15 @@ void VoxelTerrain::_process() {
|
|||
}
|
||||
|
||||
Ref<VoxelTool> VoxelTerrain::get_voxel_tool() {
|
||||
return Ref<VoxelTool>(memnew(VoxelToolTerrain(this, _map)));
|
||||
Ref<VoxelTool> vt = memnew(VoxelToolTerrain(this, _map));
|
||||
if (_stream.is_valid()) {
|
||||
if(_stream->get_used_channels_mask() & (1<<VoxelBuffer::CHANNEL_SDF)) {
|
||||
vt->set_channel(VoxelBuffer::CHANNEL_SDF);
|
||||
} else {
|
||||
vt->set_channel(VoxelBuffer::CHANNEL_TYPE);
|
||||
}
|
||||
}
|
||||
return vt;
|
||||
}
|
||||
|
||||
Vector3 VoxelTerrain::_b_voxel_to_block(Vector3 pos) {
|
||||
|
@ -1096,9 +1109,6 @@ void VoxelTerrain::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_viewer_path"), &VoxelTerrain::get_viewer_path);
|
||||
ClassDB::bind_method(D_METHOD("set_viewer_path", "path"), &VoxelTerrain::set_viewer_path);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_smooth_meshing_enabled"), &VoxelTerrain::is_smooth_meshing_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_smooth_meshing_enabled", "enabled"), &VoxelTerrain::set_smooth_meshing_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("voxel_to_block", "voxel_pos"), &VoxelTerrain::_b_voxel_to_block);
|
||||
ClassDB::bind_method(D_METHOD("block_to_voxel", "block_pos"), &VoxelTerrain::_b_block_to_voxel);
|
||||
|
||||
|
@ -1112,5 +1122,4 @@ void VoxelTerrain::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::INT, "view_distance"), "set_view_distance", "get_view_distance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewer_path"), "set_viewer_path", "get_viewer_path");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_collisions"), "set_generate_collisions", "get_generate_collisions");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_meshing_enabled"), "set_smooth_meshing_enabled", "is_smooth_meshing_enabled");
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ public:
|
|||
VoxelTerrain();
|
||||
~VoxelTerrain();
|
||||
|
||||
String get_configuration_warning() const override;
|
||||
|
||||
void set_stream(Ref<VoxelStream> p_stream);
|
||||
Ref<VoxelStream> get_stream() const;
|
||||
|
||||
|
@ -49,9 +51,6 @@ public:
|
|||
void set_material(unsigned int id, Ref<Material> material);
|
||||
Ref<Material> get_material(unsigned int id) const;
|
||||
|
||||
bool is_smooth_meshing_enabled() const;
|
||||
void set_smooth_meshing_enabled(bool enabled);
|
||||
|
||||
Ref<VoxelMap> get_storage() const { return _map; }
|
||||
Ref<VoxelTool> get_voxel_tool();
|
||||
|
||||
|
@ -103,7 +102,6 @@ private:
|
|||
Vector3 _b_block_to_voxel(Vector3 pos);
|
||||
//void _force_load_blocks_binding(Vector3 center, Vector3 extents) { force_load_blocks(center, extents); }
|
||||
|
||||
private:
|
||||
// Voxel storage
|
||||
Ref<VoxelMap> _map;
|
||||
|
||||
|
@ -132,7 +130,6 @@ private:
|
|||
|
||||
bool _generate_collisions = true;
|
||||
bool _run_in_editor;
|
||||
bool _smooth_meshing_enabled;
|
||||
|
||||
Ref<Material> _materials[VoxelMesherBlocky::MAX_MATERIALS];
|
||||
|
||||
|
|
|
@ -46,14 +46,14 @@ public:
|
|||
|
||||
inline T &operator[](size_t i) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
CRASH_COND(i >= _size)
|
||||
CRASH_COND(i >= _size);
|
||||
#endif
|
||||
return _ptr[i];
|
||||
}
|
||||
|
||||
inline const T &operator[](size_t i) const {
|
||||
#ifdef DEBUG_ENABLED
|
||||
CRASH_COND(i >= _size)
|
||||
CRASH_COND(i >= _size);
|
||||
#endif
|
||||
return _ptr[i];
|
||||
}
|
||||
|
|
|
@ -40,12 +40,12 @@ uint64_t g_depth_max_values[] = {
|
|||
};
|
||||
|
||||
inline uint32_t get_depth_bit_count(VoxelBuffer::Depth d) {
|
||||
CRASH_COND(d < 0 || d >= VoxelBuffer::DEPTH_COUNT)
|
||||
CRASH_COND(d < 0 || d >= VoxelBuffer::DEPTH_COUNT);
|
||||
return g_depth_bit_counts[d];
|
||||
}
|
||||
|
||||
inline uint64_t get_max_value_for_depth(VoxelBuffer::Depth d) {
|
||||
CRASH_COND(d < 0 || d >= VoxelBuffer::DEPTH_COUNT)
|
||||
CRASH_COND(d < 0 || d >= VoxelBuffer::DEPTH_COUNT);
|
||||
return g_depth_max_values[d];
|
||||
}
|
||||
|
||||
|
@ -96,8 +96,8 @@ inline real_t raw_voxel_to_real(uint64_t value, VoxelBuffer::Depth depth) {
|
|||
}
|
||||
case VoxelBuffer::DEPTH_64_BIT: {
|
||||
MarshallDouble m;
|
||||
m.d = value;
|
||||
return m.l;
|
||||
m.l = value;
|
||||
return m.d;
|
||||
}
|
||||
default:
|
||||
CRASH_NOW();
|
||||
|
@ -360,19 +360,19 @@ void VoxelBuffer::fill_area(uint64_t defval, Vector3i min, Vector3i max, unsigne
|
|||
break;
|
||||
|
||||
case DEPTH_16_BIT:
|
||||
for (unsigned int i = 0; i < area_size.y; ++i) {
|
||||
for (int i = 0; i < area_size.y; ++i) {
|
||||
((uint16_t *)channel.data)[dst_ri + i] = defval;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEPTH_32_BIT:
|
||||
for (unsigned int i = 0; i < area_size.y; ++i) {
|
||||
for (int i = 0; i < area_size.y; ++i) {
|
||||
((uint32_t *)channel.data)[dst_ri + i] = defval;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEPTH_64_BIT:
|
||||
for (unsigned int i = 0; i < area_size.y; ++i) {
|
||||
for (int i = 0; i < area_size.y; ++i) {
|
||||
((uint64_t *)channel.data)[dst_ri + i] = defval;
|
||||
}
|
||||
break;
|
||||
|
@ -631,7 +631,7 @@ void VoxelBuffer::downscale_to(VoxelBuffer &dst, Vector3i src_min, Vector3i src_
|
|||
for (pos.x = dst_min.x; pos.x < dst_max.x; ++pos.x) {
|
||||
for (pos.y = dst_min.y; pos.y < dst_max.y; ++pos.y) {
|
||||
|
||||
Vector3i src_pos = src_min + ((pos - dst_min) << 1);
|
||||
const Vector3i src_pos = src_min + ((pos - dst_min) << 1);
|
||||
|
||||
// TODO Remove check once it works
|
||||
CRASH_COND(!validate_pos(src_pos.x, src_pos.y, src_pos.z));
|
||||
|
@ -639,7 +639,7 @@ void VoxelBuffer::downscale_to(VoxelBuffer &dst, Vector3i src_min, Vector3i src_
|
|||
uint64_t v;
|
||||
if (src_channel.data) {
|
||||
// TODO Optimized version?
|
||||
v = get_voxel(pos, channel_index);
|
||||
v = get_voxel(src_pos, channel_index);
|
||||
} else {
|
||||
v = src_channel.defval;
|
||||
}
|
||||
|
@ -721,8 +721,6 @@ uint32_t VoxelBuffer::get_depth_bit_count(Depth d) {
|
|||
return ::get_depth_bit_count(d);
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
Ref<Image> VoxelBuffer::debug_print_sdf_to_image_top_down() {
|
||||
Image *im = memnew(Image);
|
||||
im->create(_size.x, _size.z, false, Image::FORMAT_RGB8);
|
||||
|
@ -745,8 +743,6 @@ Ref<Image> VoxelBuffer::debug_print_sdf_to_image_top_down() {
|
|||
return Ref<Image>(im);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void VoxelBuffer::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("create", "sx", "sy", "sz"), &VoxelBuffer::_b_create);
|
||||
|
|
|
@ -141,13 +141,9 @@ public:
|
|||
// }
|
||||
// }
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
// Debugging
|
||||
Ref<Image> debug_print_sdf_to_image_top_down();
|
||||
|
||||
#endif
|
||||
|
||||
private:
|
||||
void create_channel_noinit(int i, Vector3i size);
|
||||
void create_channel(int i, Vector3i size, uint64_t defval);
|
||||
|
|
|
@ -18,6 +18,7 @@ VoxelStringNames::VoxelStringNames() {
|
|||
emerge_block = StaticCString::create("emerge_block");
|
||||
immerge_block = StaticCString::create("immerge_block");
|
||||
generate_block = StaticCString::create("generate_block");
|
||||
get_used_channels_mask = StaticCString::create("get_used_channels_mask");
|
||||
|
||||
u_transition_mask = StaticCString::create("u_transition_mask");
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ public:
|
|||
StringName emerge_block;
|
||||
StringName immerge_block;
|
||||
StringName generate_block;
|
||||
StringName get_used_channels_mask;
|
||||
|
||||
StringName u_transition_mask;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue