三边形
实时网状断裂和切切为 三.js
三平纳塔是一个库,可以让你在浏览器中直接实时地断裂并切出3D meshes. 无论是建造一个破坏物理游戏,一个交互式的艺术作品,还是科学的可视化,三平纳塔都提供了你所需要的工具,以美地打破事物.
特征
- 瓦罗诺伊断裂 - 有3D和2.5D模式的自然外观断裂模式
- 基于影响的分裂 - 将碎片集中在撞击点周围,以进行现实的销毁
- 折叠 - 碎裂可能再次被碎裂以逐步销毁(外部处理的生成跟踪)
- 飞机切片 - 在当地或世界空间任意用飞机相撞
- 双重材料 - 外部表面和内部断裂面分离材料
- 自定义种子点 - 全面控制有定制的沃罗诺伊种子的断裂图案
- 紫外线绘图 - 内部面相自动紫外线生成,可配置比例并抵消
现场直播
安装
npm install @dgreenheck/three-pinata
需要三.js 0.158.0作为同伴依赖.
快速启动
import * as THREE from "three";
import { DestructibleMesh, FractureOptions } from "@dgreenheck/three-pinata";
// Setup scene
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000,
);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create materials
const outerMaterial = new THREE.MeshStandardMaterial({ color: 0x4a90e2 });
const innerMaterial = new THREE.MeshStandardMaterial({ color: 0xff6b6b });
// Create destructible mesh with both materials
const geometry = new THREE.SphereGeometry(1, 32, 32);
const mesh = new DestructibleMesh(geometry, outerMaterial, innerMaterial);
scene.add(mesh);
// Fracture the mesh
const options = new FractureOptions({
fractureMethod: "voronoi",
fragmentCount: 50,
voronoiOptions: {
mode: "3D",
},
});
const fragments = mesh.fracture(options, (fragment) => {
// Setup each fragment (material already set automatically)
scene.add(fragment);
});
// Hide original mesh
mesh.visible = false;
// Render
renderer.render(scene, camera);
API 参考
类
DestructibleMesh
扩展 THREE.Mesh 具有内置断裂和切分能力.
构造器 :
new DestructibleMesh(
geometry?: THREE.BufferGeometry,
outerMaterial?: THREE.Material,
innerMaterial?: THREE.Material
)
参数:
geometry- 网状的几何outerMaterial- 原始外表面材料innerMaterial- 用于新形成的内部断裂/切片面的材料(可选的,默认为外层材料)
方法:
fracture(options, onFragment?, onComplete?)
将网状断裂成碎片.
- 参数:
options: FractureOptions- 断裂配置onFragment?: (fragment: DestructibleMesh, index: number) => void- 每片可选回调onComplete?: () => void- 断裂完成时可选回调
- 回返情况:
DestructibleMesh[]- 一堆碎块
slice(sliceNormal, sliceOrigin, options?, onSlice?, onComplete?)
沿着平面(局部空间)切片网.
- 参数:
sliceNormal: THREE.Vector3- 切片平面正常(局部空间)sliceOrigin: THREE.Vector3- 点在平面上(局部空间)options?: SliceOptions- 切片配置onSlice?: (piece: DestructibleMesh, index: number) => void有选择的回叫每个作品onComplete?: () => void- 切片完成后可选回调
- 回返情况:
DestructibleMesh[]- 一堆碎块
sliceWorld(worldNormal, worldOrigin, options?, onSlice?, onComplete?)
沿着平面(世界空间)剪接网.
- 参数:
worldNormal: THREE.Vector3- 切片平面正常(世界空间)worldOrigin: THREE.Vector3- 点在平面上(世界空间)options?: SliceOptions- 切片配置onSlice?: (piece: DestructibleMesh, index: number) => void有选择的回叫每个作品onComplete?: () => void- 切片完成后可选回调
- 回返情况:
DestructibleMesh[]- 一堆碎块
dispose()
处置网状几何和材料以释放记忆.
- 参数: 无
- 回返情况:
void
选项
FractureOptions
分解操作的配置 。 既支持沃罗诺伊也支持简单的平面分解.
构造器 :
new FractureOptions({
fractureMethod?: "voronoi" | "simple";
fragmentCount?: number;
voronoiOptions?: VoronoiOptions;
fracturePlanes?: { x: boolean; y: boolean; z: boolean };
textureScale?: THREE.Vector2;
textureOffset?: THREE.Vector2;
seed?: number;
})
属性 :
fractureMethod: "voronoi" | "simple"- 使用断裂法(默认:"voronoi")"voronoi": 自然外观断裂,采用Voronii断裂法(需要voronoi options)"simple": 简单平面分解(快速,质量较低)
fragmentCount: number- 要创建的碎片数( 默认: 50) 。 请注意,在分解出非凸起膜时,实际碎片计数可能更高.voronoiOptions?: VoronoiOptions- Voronii特定选项(当断裂方法是"voronoi"时需要)fracturePlanes: { x: boolean; y: boolean; z: boolean }- 简单的断裂:沿途由哪轴断裂(默认:全部为真)textureScale: THREE.Vector2- 内部面相的紫外尺度(默认:1,1)textureOffset: THREE.Vector2- 内部面相的紫外线抵消(默认:0,0)seed?: number- 可复制的随机种子
VoronoiOptions
Voronoi特定断裂配置(在断裂选项中使用).
接口 :
{
mode: "3D" | "2.5D";
seedPoints?: THREE.Vector3[];
impactPoint?: THREE.Vector3;
impactRadius?: number;
projectionAxis?: "x" | "y" | "z" | "auto";
projectionNormal?: THREE.Vector3;
useApproximation?: boolean;
approximationNeighborCount?: number;
}
属性 :
mode: "3D" | "2.5D"- 沃罗诺伊断裂模式(需要)"3D": 完整 3D Voranoi 切换 - 最现实, 慢"2.5D": 2D Voronoi 通过网状投影 - 更快,对平面物体有利
seedPoints?: THREE.Vector3[]- 为当地空间的Voranoi细胞自定义种子点(如果不提供,则自动生成)impactPoint?: THREE.Vector3- 局部空间的撞击位置,以集中碎片impactRadius?: number- 撞击点周围的半径为碎片密度projectionAxis?: "x" | "y" | "z" | "auto"- 对于2.5D模式:投影轴(默认为"自动")projectionNormal?: THREE.Vector3- 2.5D模式:可选投影平面正常useApproximation?: boolean- 使用 K 近邻 近似值进行性能( 默认: 假)- 警告: 启用时可能导致碎片重叠
approximationNeighborCount?: number- 使用近似值时应考虑的邻居(默认:12)
SliceOptions
切换操作配置 .
构造器 :
new SliceOptions();
属性 :
textureScale: THREE.Vector2- 内部面相的紫外尺度(默认:1,1)textureOffset: THREE.Vector2- 内部面相的紫外线抵消(默认:0,0)
用法实例
基本构造
import { DestructibleMesh, FractureOptions } from "@dgreenheck/three-pinata";
const outerMaterial = new THREE.MeshStandardMaterial({ color: 0x4a90e2 });
const innerMaterial = new THREE.MeshStandardMaterial({ color: 0xff6b6b });
const mesh = new DestructibleMesh(geometry, outerMaterial, innerMaterial);
scene.add(mesh);
const options = new FractureOptions({
fractureMethod: "voronoi",
fragmentCount: 16,
voronoiOptions: {
mode: "3D",
},
});
const fragments = mesh.fracture(options);
fragments.forEach((fragment) => scene.add(fragment));
mesh.visible = false;
与撞击点相断
const options = new FractureOptions({
fractureMethod: "voronoi",
fragmentCount: 16,
voronoiOptions: {
mode: "3D",
impactPoint: new THREE.Vector3(0, 1, 0), // Local space
impactRadius: 0.5, // Smaller = more concentrated
},
});
const fragments = mesh.fracture(options);
折叠
裂口可再被分解为相继被破坏. 使用外部处理生成跟踪 userData数字 :
// Configuration
const maxGeneration = 3;
const fragmentCounts = {
1: 32, // First fracture: 32 fragments
2: 16, // Second fracture: 16 fragments
3: 8, // Third fracture: 8 fragments
};
// Initial fracture
const mesh = new DestructibleMesh(geometry, outerMaterial, innerMaterial);
mesh.userData.generation = 0; // Track generation externally
const options1 = new FractureOptions({
fractureMethod: "voronoi",
fragmentCount: fragmentCounts[1],
voronoiOptions: {
mode: "3D",
},
});
const fragments = mesh.fracture(options1, (fragment) => {
// Track generation in each fragment
fragment.userData.generation = 1;
scene.add(fragment);
});
// Later, refracture a fragment when clicked
function onFragmentClick(fragment: DestructibleMesh) {
const currentGeneration = fragment.userData.generation || 0;
// Check generation limit (external refracture control)
if (currentGeneration >= maxGeneration) {
return; // Max generation reached
}
// Determine fragment count for next generation
const nextGeneration = currentGeneration + 1;
const fragmentCount = fragmentCounts[nextGeneration];
const options = new FractureOptions({
fractureMethod: "voronoi",
fragmentCount: fragmentCount,
voronoiOptions: {
mode: "3D",
},
});
const newFragments = fragment.fracture(options, (newFragment) => {
// Track generation externally
newFragment.userData.generation = nextGeneration;
scene.add(newFragment);
});
// Clean up old fragment
scene.remove(fragment);
fragment.geometry.dispose();
}
这种外部方法使你完全控制了折射行为,使你能够执行诸如:
- 逐渐减弱(每代有羽毛碎片)
- 以能为基础的再生(仅在撞击力超过阈值的情况下)
- 基于材料的限度(玻璃折射量大于木材)
- 基于性能的节流( FPS 下降时停止折叠)
简单分解
const options = new FractureOptions({
fractureMethod: "simple",
fragmentCount: 50,
fracturePlanes: { x: true, y: true, z: true },
});
const fragments = mesh.fracture(options);
切开
// Create mesh with outer and inner materials
const mesh = new DestructibleMesh(geometry, outerMaterial, innerMaterial);
const sliceNormal = new THREE.Vector3(0, 1, 0); // Horizontal cut
const sliceOrigin = new THREE.Vector3(0, 0, 0); // At origin
const options = new SliceOptions();
const pieces = mesh.slice(sliceNormal, sliceOrigin, options);
// Materials are already set automatically
pieces.forEach((piece) => scene.add(piece));
mesh.visible = false;
使用回调
const mesh = new DestructibleMesh(geometry, outerMaterial, innerMaterial);
const fragments = mesh.fracture(
options,
(fragment, index) => {
// Called for each fragment (materials already set)
fragment.castShadow = true;
// Add physics, apply forces, etc.
physics.add(fragment, { type: "dynamic" });
},
() => {
// Called when complete
console.log("Fracturing complete!");
},
);
双重材料
裂痕支撑了两种材料——一种用于原地表,一种用于内出裂面.
建议的办法: 将两种材料传递给构造器:
const outerMaterial = new THREE.MeshStandardMaterial({ color: 0xff6644 });
const innerMaterial = new THREE.MeshStandardMaterial({ color: 0xdddddd });
// Materials are automatically inherited by fragments
const mesh = new DestructibleMesh(geometry, outerMaterial, innerMaterial);
const fragments = mesh.fracture(options, (fragment) => {
// Material array [outer, inner] is already set automatically
scene.add(fragment);
});
备选案文: 手动设定每个碎片的材料:
const mesh = new DestructibleMesh(geometry, outerMaterial);
const fragments = mesh.fracture(options, (fragment) => {
// Manually assign material array: [outer, inner]
fragment.material = [outerMaterial, innerMaterial];
scene.add(fragment);
});
碎片几何包括两个材料组:
- 组 0 (材料Index 0):原始外表面面相
- 第1组 (材料Index 1):新产生的内部断裂面
重要要求
Manifold/ 紧水网
图书馆要求 多重( 防水) meshes - 三维模型,形成一个完全封闭的,固态的体积,没有孔或自相交接几何.
有效网点:
- 球形、立方体、圆柱形、圆锥形
- 封闭字符模型
- 适当建模无缺口的物体
无效的 meshes :
- 平面或单面表面
- 有洞或脸部缺失
- 无限用气瓶或盒
- 重叠几何
如何在 Blender 中检查/修复 :
- 在编辑模式中选择网格
Mesh > Clean Up > Make Manifold- 使用“ 3D 打印工具箱” 附加以检查问题
为什么这很重要:
- 分解算法需要确定"内"对"外"
- 非狂眼膜造成模糊不清 导致脸孔和视觉文物的缺失
- 物理相撞器会与非磁性相撞的碎片发生不可预测的行为
物理整合
库只处理几何. 对于现实的破坏,与物理引擎融合如: 猛兽。 。 。 .
基础物理模式
import RAPIER from "@dimforge/rapier3d";
// Initialize physics world
await RAPIER.init();
const world = new RAPIER.World({ x: 0, y: -9.81, z: 0 });
// Add physics to fragments
const fragments = mesh.fracture(options, (fragment) => {
// Create rigid body
const rigidBodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
fragment.position.x,
fragment.position.y,
fragment.position.z,
);
const rigidBody = world.createRigidBody(rigidBodyDesc);
// Create convex hull collider
const vertices = fragment.geometry.getAttribute("position").array;
const colliderDesc = RAPIER.ColliderDesc.convexHull(vertices)
.setRestitution(0.3)
.setFriction(0.5);
world.createCollider(colliderDesc, rigidBody);
});
// Update physics each frame
function animate() {
world.step();
// Sync Three.js objects with physics...
}
关于全面执行情况,见:
demo/src/physics/PhysicsWorld.ts- 完整的物理包装demo/src/physics/PhysicsBody.ts- 物理人体包装器demo/src/scenes/SmashingScene.ts- 现实世界的例子
性能提示
- 碎片计数:10-50 碎片是最佳的. 100+ 可能导致慢设备滞后
- 2.5D对3D: 在可能的情况下使用 2.5D 模式 - 明显更快
- 断裂前: 提前断裂并保存碎片以立即销毁
- 大约: 对于高分数(>50),启用
useApproximation(可能造成重叠) - 物理学:更多的碎片=更多的物理体. 破碎的碎片在安顿下来之后
限制
- 管理要求: Meshes 必须是紧取水(没有孔或自相接几何)
- 内存:每个片段都是一个新的几何. 为许多可毁物体制定相应的计划
- 所需物理学: 库只处理几何 - 您必须添加物理集成
大楼
npm run build:lib
生成 :
three-pinata.es.js- ES模块three-pinata.umd.js- UMD模块- 类型声明
运行演示
npm install
npm run dev
开放http://localhost:5173/ (中文(简体) )
许可证
本项目根据以下规定获得许可证: MIT 许可证。 。 。 .
承认
支助
对于错误或特性请求,请在 问题跟踪器。 。 。 .
捐款
欢迎捐款! 请提交一份拉出请求.