doyubkim / fluid-engine-dev

Fluid simulation engine for computer graphics applications
https://fluidenginedevelopment.org/
MIT License
1.88k stars 263 forks source link

[Questions] LevelSetLiquidSolver3 #231

Closed PavelBlend closed 5 years ago

PavelBlend commented 5 years ago

In the PIC solver, particles act as a fluid. And what is the liquid in the solver LevelSetLiquidSolver3? How can I save fluid data (positions, velocities, forces) in a LevelSet solver? And how can you create a mesh, based on the LevelSet solver?

doyubkim commented 5 years ago

LevelSetLiquidSolver3 uses voxel grids to track fluid surface. More specifically, it uses SDF (or level set field) that is stored in a grid and moves it around via fluid velocity field which is also defined on grids.

In order to get the mesh, you need to call marchingCubes to solver.signedDistanceField.

PavelBlend commented 5 years ago

I have all obj files have a size of 0 bytes. What am I doing wrong? level_set_test.zip

doyubkim commented 5 years ago

You also need to add emitter.addSignedDistanceTarget(solver.signedDistanceField) after solver.emitter = emitter. This let emitter to know which grid (among many grids in the solver) to emit volume in which form (SDF in this case). You also want to set margin greater than 0.2. Below is part of the code I fixed:

# create emitter
mesh_obj = pyjet.TriangleMesh3()
mesh_obj.readObj(filename='emitter.obj')
emitter_mesh = pyjet.ImplicitTriangleMesh3(
    mesh=mesh_obj,
    resolutionX=solver.resolution.x,
    margin=0.2
)
emitter = pyjet.VolumeGridEmitter3(
    sourceRegion=emitter_mesh,
    isOneShot=True
)
solver.emitter = emitter
emitter.addSignedDistanceTarget(solver.signedDistanceField)

# create collider
mesh_obj = pyjet.TriangleMesh3()
mesh_obj.readObj(filename='collider.obj')
collider_mesh = pyjet.ImplicitTriangleMesh3(
    mesh=mesh_obj,
    resolutionX=solver.resolution.x,
    margin=0.2
)
collider = pyjet.RigidBodyCollider3(
    surface=collider_mesh
)
solver.collider = collider
PavelBlend commented 4 years ago

I'm having trouble again with level set solver. I create a mesh this way:

    surface_mesh = pyjet.marchingCubes(
        solver.signedDistanceField,
        solver.gridSpacing,
        (0, 0, 0),
        0.0, 0, 0
    )

But I get the wrong mesh size: 01

How to fix it?

doyubkim commented 4 years ago

Is Fluid mesh the result of marching cubes? Looks like the overall scale got doubled after the marching cubes. Can you share other parts of the code (like emitter creation) so ghat I can try reproducing it?

PavelBlend commented 4 years ago

Is Fluid mesh the result of marching cubes?

yes

Can you share other parts of the code (like emitter creation)

triangle_mesh = pyjet.TriangleMesh3(
        points=[[v.co.x, v.co.z, v.co.y] for v in mesh.vertices],
        pointIndices=[[p.vertices[0], p.vertices[2], p.vertices[1]] for p in mesh.polygons]
    )
imp_triangle_mesh = pyjet.ImplicitTriangleMesh3(
        mesh=triangle_mesh,
        resolutionX=int(round(
            solver.resolution.x * obj.dimensions[0] / domain_object.dimensions[0],
            0
        )),
        margin=0.2
    )
...
emitter = pyjet.VolumeGridEmitter3(implicit_triangle_mesh, True)
emitter.addSignedDistanceTarget(solver.signedDistanceField)
transform = pyjet.Transform3(
        translation=(pos[0], pos[2], pos[1]),
        orientation=(-rot[0], rot[1], rot[3], rot[2])
    )
emitter.sourceRegion.transform = transform
PavelBlend commented 4 years ago

I tried to create a simple example but could not reproduce the error. This error only occurs in the blender. And I noticed that the mesh size depends on the resolution of the simulation. Here is an example with different resolutions: 01 How to fix this behavior?

doyubkim commented 4 years ago

Looks like grid size is not changing when the resolution is changing. Seems like it's fixed. Can you double check?

PavelBlend commented 4 years ago

Where should the grid size be indicated? Like this?:

    grid_size = 0.04
    solver = pyjet.LevelSetLiquidSolver3(
        resolution=(50, 50, 50),
        gridSpacing=grid_size,
        gridOrigin=(0, 0, 0),
        domainSizeX=2.0
    )
doyubkim commented 4 years ago

Yes, exactly. Let me know if that doesn't work.

PavelBlend commented 4 years ago

The grid size I set.

I check the grid size in this way:

print(solver.gridSpacing)

And the correct value is always displayed in the console. But the mesh size is not correct.

I added the code to the github: https://github.com/PavelBlend/blender_jet_fluids_addon/tree/level-set-solver

Maybe you find a mistake.

The level set simulation starts here: https://github.com/PavelBlend/blender_jet_fluids_addon/blob/level-set-solver/jet_fluids/bake_fluid.py#L86

Grid size calculation is here: https://github.com/PavelBlend/blender_jet_fluids_addon/blob/level-set-solver/jet_fluids/bake.py#L147

doyubkim commented 4 years ago

Thanks for the info! Let me take a look. Might take some time though.

PavelBlend commented 4 years ago

I found my mistake. I multiply the coordinate of the mesh vertex by a factor: https://github.com/PavelBlend/blender_jet_fluids_addon/blob/level-set-solver/jet_fluids/bake_mesh.py#L71

Since simulation resolution and mesh resolution may vary. But I forgot about it. I apologize. The error was on my part.

PavelBlend commented 4 years ago

I have one more problem.

I am trying to change the Level Set Solver this way:

solver.levelSetSolver = pyjet.FmmLevelSetSolver3()

And I get an error:

TypeError: pyjet.FmmLevelSetSolver3: No constructor defined!

Am I doing everything right? And why does this error occur?

doyubkim commented 4 years ago

Glad you found the problem!

Missing constructor seems to be the binding problem. Let me create a separate issue to track it.