Fluid Engine Development 创建 PIC, FLIP, Level Set 演示 Demo

Fluid Engine Development 看了很久,应该要做 Demo 来演示算法了

项目 level_set_liquid_sim 里面有运行 Level Set 的模拟,输出三角面的示例代码

项目 hybrid_liquid_sim 里面有运行 PIC FLIP APIC 的模拟,但是只输出位置信息的示例代码,比如他保存成 xyz 格式

项目 particles2obj 可以把位置信息文件 xyz 转成三角面文件 obj

项目 sandbox 提供了自己创建求解器的模板,但是现在暂时应该用不到,现在想输出他的求解器的图像

然后他这个 Marching Cube 的算法里面写了对于边界的处理,原仓库的代码里面特意设置了不创建底部的面的标志,我不知道为什么要这么做

void triangulateAndSave(const ScalarGrid3Ptr& sdf, const std::string& rootDir,
                        int frameCnt) {
   
    TriangleMesh3 mesh;
    // int flag = kDirectionAll & ~kDirectionDown;
    int flag = kDirectionAll;
    marchingCubes(sdf->constDataAccessor(), sdf->gridSpacing(),
                  sdf->dataOrigin(), &mesh, 0.0, flag);
    saveTriangleMesh(mesh, rootDir, frameCnt);
}

用 Blender 渲染的话,为了做光线追踪,液体网格应该封闭才能达成正确的光线反射,现在这个不创建底面直接就没有那个正确的效果了

一开始我还不知道有这个标记,于是等那个溃坝的模拟,一帧五分钟,等了五十帧,之后才开始做,这个时候才开始发现模型没有底面……浪费了很多时间

Blender 渲染的时候记得要在 Preference-System-Cycles Render Device 选 CUDA,明显渲染会快很多,可能十多倍都有可能

然后记得构建 VS 工程要构建成 Release,开启了代码优化,计算速度会快很多,两三倍吧

因为 PIC FLIP 那边的没有保存三角面的,所以简单拼接一下就可以了

在 example 里新建一个文件夹,里面是新项目的 main.cpp 和 CMakeList.txt。这个项目我命名为 comparsion

项目的 CMakeList

#
# Copyright (c) 2018 Doyub Kim
#
# I am making my contributions/submissions to this project solely in my personal
# capacity and am not conveying any rights to any intellectual property of any
# third parties.
#

# Target name
set(target comparsion)

# Includes
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

# Sources
file(GLOB sources
    ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)

# Build executable
add_executable(${target}
    ${sources})

# Project options
set_target_properties(${target}
    PROPERTIES
    ${DEFAULT_PROJECT_OPTIONS}
)

# Compile options
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    add_definitions(-D_USE_MATH_DEFINES) # for M_PI
endif ()

target_compile_options(${target}
    PRIVATE

    PUBLIC
    ${DEFAULT_COMPILE_OPTIONS}

    INTERFACE
)

# Link libraries
target_link_libraries(${target}
    PRIVATE
    ${DEFAULT_LINKER_OPTIONS}
    jet
    pystring)

要在根目录的 CMakeList 里加上新项目

add_subdirectory(src/examples/comparsion)

main.cpp

// Copyright (c) 2018 Doyub Kim
//
// I am making my contributions/submissions to this project solely in my
// personal capacity and am not conveying any rights to any intellectual
// property of any third parties.

#include <jet/jet.h>
#include <pystring/pystring.h>

#ifdef JET_WINDOWS
#include <direct.h>
#else
#include <sys/stat.h>
#endif

#include <example_utils/clara_utils.h>
#include <clara.hpp>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#define APP_NAME "comparsion"

using namespace jet;

void saveTriangleMesh(const TriangleMesh3& mesh, const std::string& rootDir,
                      int frameCnt) {
   
    char basename[256];
    snprintf(basename, sizeof(basename), "frame_%06d.obj", frameCnt);
    std::string filename = pystring::os::path::join(rootDir, basename);
    std::ofstream file(filename.c_str());
    if (file) {
   
        printf("Writing %s...\n", filename.c_str());
        mesh.writeObj(&file);
        file.close();
    }
}

void triangulateAndSave(const ScalarGrid3Ptr& sdf, const std::string& rootDir,
                        int frameCnt) {
   
    TriangleMesh3 mesh;
    // int flag = kDirectionAll & ~kDirectionDown;
    int flag = kDirectionAll;
    marchingCubes(sdf->constDataAccessor(), sdf->gridSpacing(),
                  sdf->dataOrigin(), &mesh, 0.0, flag);
    saveTriangleMesh(mesh, rootDir, frameCnt);
}

void printInfo(const PicSolver3Ptr& solver) {
   
    auto grids = solver->gridSystemData();
    Size3 resolution = grids->resolution();
    BoundingBox3D domain = grids->boundingBox();
    Vector3D gridSpacing = grids->gridSpacing();

    printf("Resolution: %zu x %zu x %zu\n", resolution.x, resolution.y,
           resolution.z);
    printf("Domain: [%f, %f, %f] x [%f, %f, %f]\n", domain.lowerCorner.x,
           domain.lowerCorner.y, domain.lowerCorner.z, domain.upperCorner.x,
           domain.upperCorner.y, domain.upperCorner.z);
    printf("Grid spacing: [%f, %f, %f]\n", gridSpacing.x, gridSpacing.y,
           gridSpacing.z);
}

void runSimulation(const std::string& rootDir, const PicSolver3Ptr& solver,
                   int numberOfFrames, double fps) {
   
    auto sdf = solver->signedDistanceField();

    for (Frame frame(0, 1.0 / fps); frame.index < numberOfFrames; ++frame) {
   
        solver->update(frame);

        triangulateAndSave(sdf, rootDir, frame.index);
    }
}

// Water-drop example (FLIP)
void runExample1(const std::string& rootDir, size_t resolutionX,
                 int numberOfFrames, double fps) {
   
    // Build solver
    auto solver =
        FlipSolver3::builder()
            .withResolution({
   resolutionX, 2 * resolutionX, resolutionX})
            .withDomainSizeX(1.0)
            .makeShared();

    auto grids = solver->gridSystemData();
    auto particles = solver->particleSystemData();

    Vector3D gridSpacing = grids->gridSpacing();
    double dx = gridSpacing.x;
    BoundingBox3D domain = grids->boundingBox();

    // Build emitter
    auto plane = Plane3::builder()
                     .withNormal({
   0, 1, 0})
                     .withPoint({
   0, 0.25 * domain.height(), 0})
                     .makeShared();

    auto sphere = Sphere3::builder()
                  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值