Closed davids91 closed 1 year ago
This one is not so obvious as a crash, I don't see anything that would behave specially for threshold 0, and I personally used other values like 0.5 (although not a lot). Are you sure your density function is continuous around 0.1 and 0.01 ? The meshes look not so great on the 0 screenshot too, to me.
The way to investigate this would be to reduce the reproducible case with as few blocks and subdivisions as possible, and hardcoded values.
The function is exactly like this, but it should be continous, albeit the gradient might be a bit egzotic..
My comment about the density having to be continuous was probably misleading or false, I don't think it actually has to be. However, the gradient has to "make sense", otherwise the normals will be "wrong" (but only the normals should be impacted). Note that for estimating the gradient, the algorithm looks for densities quite far away (the dx,dy,dz are one full voxel grid step instead of being epsilons), and it will look outside of the block.
From a quick look, I think that in your case it means it will return 0 instead of noise values (for x/y/z being -1 and size+1 but also 0, which will impact more than the normals), so that could explain a different behavior with a threshold of 0.
Typically, for a block to be a proper "slice" of the world, you have to allow density queries outside of the block (and return values consistent with neighboring blocks).
To make it easier to investigate (for you or me when I get more time), you could try reducing the case to extracting a single block, and to describe what seems to be wrong.
I notice that your NoiseContainer seems to serve a similar purpose to the internal PreCachingVoxelSource, so you could try to just provide your density function instead. But then you lose some control and the caching policy might not suit you (that's probably the part where refactoring is needed).
And just now I notice that on your screenshots some point seems to be way out of range. So that definitely seems like a bug. It could also be reduced to a simpler case, given some time.
Unfortunately my usecase doesn't permit to provide only a function, as I plan to set / erase values by hand. I am pretty sure I can reduce this to a single block though.
If you could, it would make it more likely that I find a time slot to investigate soner rather than later.
For your use case, it looks like it would get messy with the current interface: if you use one noise container per block , you need to update several such containers when you edit a voxel (because they have to overlap). Probably cleaner if you could provide the caching yourself, but that's the refactor thing
So I couldn't reproduce with one block, because it will not show with a simple triangle, but I did it with a 3x3x3 matrix:
threshold 0:
threshold 0.5:
threshold 1.0:
threshold 1.1:
threshold 1.3:
threshold 1.6:
I do hope the wireframe is not too distracting, but I can render this without it even. Does this help?
It sounds much simpler than the previous one. Could you share the code?
ah sure! Although it's pretty simple:
use transvoxel::density::ScalarField;
impl ScalarField<f32, f32> for MyStruct {
fn get_density(&self, x: f32, y: f32, z: f32) -> f32 {
let ix = x.round() as i32;
let iy = y.round() as i32;
let iz = z.round() as i32;
if (ix < 0 || ix >= 3)
|| (iy < 0 || iy >= 3)
|| (iz < 0 || iz >= 3)
{
return 0.;
}
1.
}
}
for some other extremes here is the field with threshold 6
and -0.5
:
and -2
:
the circle ( at approx (-5,5,-5 ) is emitting red light, that is why the surface looks strange. The structure of the mesh can be clearly seen though. Here's a shot from another angle in threshold -2
:
Oops there was something still hardcoded with threshold 0:
impl Density for f32 {
type F = f32;
fn inside(&self) -> bool {
self > &0f32
}
It's now fixed in version 0.6.0 Thanks for reporting and helping pinpoint the issue!
Thank you for your help!
Extracted field with surface value threshold![image](https://user-images.githubusercontent.com/4211067/231941706-33ae8998-3d17-42d5-947c-5d6d60e87e3f.png)
0.0
Same field extracted with surface value threshold![image](https://user-images.githubusercontent.com/4211067/231941615-76614192-85fd-49bf-b1a9-b0d6c9dc16be.png)
0.01
Same field extracted with surface value threshold![image](https://user-images.githubusercontent.com/4211067/231942189-9c4eb6e5-5a38-437e-870f-0b34fa4fe98d.png)
0.1
Have tried using any other value, but it only works with
0.0
. The greater the value, the greater the mess The images describe it better than I ever could :)