将对象的边缘变形到 3D 模型上

问题描述 投票:0回答:1

我不完全确定从哪里开始解决手头的问题或如何寻找解决方案,一些指示将不胜感激,谢谢:)

我想要实现的是将较小的网格对齐(或变形)到较大的网格上。

例如:

我有较大的网格 - 球体,和较小的网格 - 长方体。

我需要面向球体的长方体面以适合球体的方式变形。

最终的解决方案需要编码,而不是使用 GUI 软件完成,因此需要记住这一点。

正如我之前所说,我不确定这个过程的确切名称,我不是在寻找解决方案,而是寻找正确方向的指针。

3d mesh modeling
1个回答
0
投票

对于这个特定示例,您可以使用符号距离场 (SDF) 来完成此操作。

您可以将盒子和球体描述为数学函数,给定空间中的任何点,您将返回从表面上最近的点到空间中该点的距离。

可以在此处找到 SDF 函数的详细列表。 https://iquilezles.org/articles/distfunctions/

然后,您可以使用行进立方体算法对 SDF 进行细分。在此 YouTube 视频中可以找到很好的解释 https://www.youtube.com/watch?v=M3iI2l0ltbE

然后,为了平滑地为从一个函数到另一个函数的过渡设置动画,我将立方体和球体 SDF 合并,并将球体 SDF 的半径乘以动画时间。因此,在时间 0 时,球体的半径为 0,而在时间 1 时,球体的半径为完整半径。

下面是用 polyform 编写的示例代码,其外观如下:

package main

import (
    "math"

    "github.com/EliCDavis/polyform/formats/gltf"
    "github.com/EliCDavis/polyform/generator"
    "github.com/EliCDavis/polyform/modeling"
    "github.com/EliCDavis/polyform/modeling/marching"
    "github.com/EliCDavis/polyform/modeling/meshops"
    "github.com/EliCDavis/vector/vector3"
)

func main() {

    app := generator.App{
        Name:        "Cube to Sphere",
        Description: "Smoothly blend a cube into a sphere",
        Version:     "1.0.0",
        Generator: &generator.Generator{
            Parameters: &generator.GroupParameter{
                Parameters: []generator.Parameter{
                    &generator.FloatParameter{
                        Name: "Time",
                        CLI: &generator.FloatCliParameterConfig{
                            FlagName: "time",
                            Usage:    "Percentage through the transition from cube to sphere, clamped between 0 and 1",
                        },
                    },
                    &generator.IntParameter{
                        Name:         "Resolution",
                        DefaultValue: 30,
                        CLI: &generator.IntCliParameterConfig{
                            FlagName: "resolution",
                            Usage:    "The resolution of the marching cubes algorithm, roughly translating to number of voxels per unit",
                        },
                    },
                },
            },
            Producers: map[string]generator.Producer{
                "mesh.glb": func(c *generator.Context) (generator.Artifact, error) {
                    time := math.Max(math.Min(c.Parameters.Float64("Time"), 1), 0)

                    box := marching.Box(
                        vector3.Zero[float64](),
                        vector3.New(0.7, 0.5, 0.5), // Box size
                        1,
                    )

                    sphere := marching.Sphere(
                        vector3.Zero[float64](),
                        0.5*time, // Sphere radius
                        1,
                    )

                    field := marching.CombineFields(box, sphere).March(modeling.PositionAttribute, 30, 0)

                    smoothedMesh := field.Transform(
                        meshops.LaplacianSmoothTransformer{Iterations: 10, SmoothingFactor: 0.1},
                        meshops.SmoothNormalsTransformer{},
                    )

                    return generator.GltfArtifact{
                        Scene: gltf.PolyformScene{
                            Models: []gltf.PolyformModel{
                                {
                                    Name: "Mesh",
                                    Mesh: smoothedMesh,
                                },
                            },
                        },
                    }, nil
                },
            },
        },
    }

    err := app.Run()

    if err != nil {
        panic(err)
    }
}

您可以这样运行此应用程序:

go run ./main.go generate --time 0.7

生成的网格看起来像这样

PS:网格图像是服务函数的屏幕截图。它允许您通过托管本地服务器与网络浏览器中的参数进行交互。

go run ./main.go serve
© www.soinside.com 2019 - 2024. All rights reserved.