Skip to content

Commit 53841f9

Browse files
committed
🐙 Add support for inflate tooth root.
1 parent 90c00ac commit 53841f9

File tree

14 files changed

+181
-37
lines changed

14 files changed

+181
-37
lines changed

examples/web/threejs/editor/js/Sidebar.Object.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,46 @@ function SidebarObject( editor ) {
686686
}
687687
});
688688

689+
const wasmOpInflateToothRoot = new UIButton( strings.getKey( 'sidebar/object/wasmOpInflateToothRoot') ).setMarginLeft( '7px' ).onClick( function () {
690+
if ( !editor.selected ) return;
691+
692+
const currentUUID = editor.selected.uuid;
693+
if ( currentUUID ) {
694+
const { verticesPtr, jsVertices, indicesPtr, jsIndices } = createMemoryViewFromGeometry( editor, editor.selected.geometry );
695+
696+
try {
697+
const mesh = editor.MeshSDK.Mesh.fromTrianglesMemoryView( jsVertices, jsIndices, true );
698+
699+
///
700+
const threeWorldDir = new THREE.Vector3();
701+
editor.camera.getWorldDirection( threeWorldDir );
702+
const upDir = new editor.MeshSDK.Vector3f(
703+
-threeWorldDir.x,
704+
-threeWorldDir.y,
705+
-threeWorldDir.z,
706+
)
707+
708+
const inflateSettings = {
709+
pressure: 20,
710+
iterations: 1,
711+
preSmooth: true,
712+
gradualPressureGrowth: true
713+
};
714+
// const inflateSettings = new editor.MeshSDK.InflateSettings();
715+
// inflateSettings.pressure = 50;
716+
const result = editor.MeshSDK.inflateToothRootImpl( mesh, inflateSettings );
717+
///
718+
719+
720+
showMesh( mesh, result.meshMV.vertices, result.meshMV.indices );
721+
showMesh( mesh, result.rootMeshMV.vertices, result.rootMeshMV.indices );
722+
} catch ( error ) {
723+
console.error( 'Error creating from ThreeJS Mesh:', error.message );
724+
editor.MeshSDK._free( verticesPtr );
725+
editor.MeshSDK._free( indicesPtr );
726+
}
727+
}
728+
});
689729

690730
wasmOpsRow.add( new UIText( strings.getKey( 'sidebar/object/wasm' ) ).setClass( 'Label' ) );
691731

@@ -713,13 +753,17 @@ function SidebarObject( editor ) {
713753
wasmOpsRowGypsum.add( wasmOpBuildMandibleBottom );
714754
wasmOpsRowGypsum.add( wasmOpFindSilhouetteEdges );
715755

756+
const wasmOpsRowToothRoot = new UIRow();
757+
wasmOpsRowToothRoot.add( wasmOpInflateToothRoot );
758+
716759
container.add( wasmOpsRow );
717760
container.add( wasmOpsRowLoad );
718761
container.add( wasmOpsRowHole );
719762
container.add( wasmOpsRowSelector );
720763
container.add( wasmOpsRowFixUndercuts );
721764
container.add( wasmOpsRowThicken );
722765
container.add( wasmOpsRowGypsum );
766+
container.add( wasmOpsRowToothRoot );
723767

724768
// fov
725769

examples/web/threejs/editor/js/Strings.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ function Strings( config ) {
540540
'sidebar/object/wasmOpBuildMandibleBottom': 'Mandible Bottom',
541541
'sidebar/object/wasmOpBuildMaxillaBottom': 'Maxilla Bottom',
542542
'sidebar/object/wasmOpFindSilhouetteEdges': 'Find Maxilla Silhuette Edges',
543+
'sidebar/object/wasmOpInflateToothRoot': 'Inflate Tooth Root',
543544
'sidebar/object/fov': 'Fov',
544545
'sidebar/object/left': 'Left',
545546
'sidebar/object/right': 'Right',
@@ -1358,6 +1359,7 @@ function Strings( config ) {
13581359
'sidebar/object/wasmOpBuildMandibleBottom': '下颌底座',
13591360
'sidebar/object/wasmOpBuildMaxillaBottom': '上颌底座',
13601361
'sidebar/object/wasmOpFindSilhouetteEdges': '上颌底座投影拟合',
1362+
'sidebar/object/wasmOpInflateToothRoot': '填充牙根',
13611363
'sidebar/object/fov': '视角',
13621364
'sidebar/object/left': '左',
13631365
'sidebar/object/right': '右',

examples/web/threejs/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/web/threejs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "three-meshsdk-editor",
3-
"version": "0.7.3",
3+
"version": "0.7.4",
44
"description": "3Mesh - ThreeJS Mesh Editor utilizing the `MeshSDK`.",
55
"keywords": [
66
"threejs",

source/MRJavaScript/MROffset.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ namespace MRJS {
2929

3030
val thickenMeshImplFilled( const Mesh& mesh, float offset, GeneralOffsetParameters &params )
3131
{
32-
// Return the mesh wrapped in an object that indicates success
3332
val returnObj = val::object();
3433

3534
Mesh meshCopy;

source/MRJavaScript/MRPositionVertsSmoothly.cpp

Lines changed: 99 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,110 @@
77
#include <MRMesh/MRVector3.h>
88
#include <MRMesh/MRBitSet.h>
99
#include <MRMesh/MRId.h>
10+
#include <MRMesh/MRFillHoleNicely.h>
11+
#include <MRMesh/MRRegionBoundary.h>
1012
#include <MRMesh/MRPositionVertsSmoothly.h>
1113

14+
#include "MRPositionVertsSmoothly.h"
15+
#include "MRUtils.h"
16+
1217
using namespace emscripten;
1318
using namespace MR;
1419

20+
namespace MRJS
21+
{
22+
23+
val inflateToothRootImpl( Mesh& mesh, const InflateSettings& inflateSettings )
24+
{
25+
val returnObj = val::object();
26+
27+
28+
///
29+
auto holeEdges = mesh.topology.findHoleRepresentiveEdges();
30+
EdgeId maxAreaHole;
31+
float maxHoleAreaSq = 0.0f;
32+
for ( const auto& e : holeEdges )
33+
{
34+
float areaSq = mesh.holeDirArea( e ).lengthSq();
35+
if ( areaSq > maxHoleAreaSq )
36+
{
37+
maxHoleAreaSq = areaSq;
38+
maxAreaHole = e;
39+
}
40+
}
41+
///
42+
43+
44+
FillHoleNicelySettings fillHoleParams;
45+
fillHoleParams.maxEdgeSplits = 1000000; // just a big number not to stop subdivision by this criteria
46+
fillHoleParams.maxEdgeLen = mesh.averageEdgeLength(); // stop subdivision by this criteria
47+
for ( const auto& e : holeEdges )
48+
{
49+
fillHoleParams.smoothCurvature = ( e != maxAreaHole ); // The maximum aperture is not smoothed in order to facilitate subsequent expansion
50+
auto newFaces = fillHoleNicely( mesh, e, fillHoleParams );
51+
52+
if ( e == maxAreaHole )
53+
{
54+
// Find the newly generated internal vertices
55+
auto newVerts = getInnerVerts( mesh.topology, newFaces );
56+
inflate( mesh, newVerts, inflateSettings );
57+
58+
59+
Mesh newFacesMesh;
60+
auto newInflatedFaces = getInnerFaces( mesh.topology, newVerts );
61+
newFacesMesh.addMeshPart( {mesh, &newInflatedFaces} );
62+
val newFacesMeshData = MRJS::exportMeshMemoryView( newFacesMesh );
63+
returnObj.set( "rootMesh", newFacesMesh );
64+
returnObj.set( "rootMeshMV", newFacesMeshData );
65+
}
66+
}
67+
68+
69+
val meshData = MRJS::exportMeshMemoryView( mesh );
70+
71+
returnObj.set( "success", true );
72+
returnObj.set( "mesh", mesh );
73+
returnObj.set( "meshMV", meshData );
74+
75+
return returnObj;
76+
}
77+
78+
} // namespace MRJS
79+
80+
1581
EMSCRIPTEN_BINDINGS( PositionVertsSmoothlyModule )
1682
{
17-
class_<SpacingSettings>( "SpacingSettings" )
18-
.property( "region", &SpacingSettings::region, allow_raw_pointers() )
19-
.property( "dist", &SpacingSettings::dist )
20-
.property( "numIters", &SpacingSettings::numIters )
21-
.property( "stabilizer", &SpacingSettings::stabilizer )
22-
.property( "maxSumNegW", &SpacingSettings::maxSumNegW )
23-
.property( "isInverted", &SpacingSettings::isInverted );
24-
25-
value_object<InflateSettings>("InflateSettings")
26-
.field("pressure", &InflateSettings::pressure)
27-
.field("iterations", &InflateSettings::iterations)
28-
.field("preSmooth", &InflateSettings::preSmooth)
29-
.field( "gradualPressureGrowth", &InflateSettings::gradualPressureGrowth );
30-
31-
32-
function("positionVertsSmoothly", select_overload<void( Mesh&, const VertBitSet&, EdgeWeights, VertexMass, const VertBitSet * )>( &positionVertsSmoothly ), allow_raw_pointers() );
33-
function("positionVertsSmoothlyWithTopology", select_overload<void( const MeshTopology&, VertCoords&, const VertBitSet&, EdgeWeights, VertexMass, const VertBitSet * )>( &positionVertsSmoothly ), allow_raw_pointers() );
34-
function("positionVertsSmoothlySharpBd", select_overload<void( Mesh&, const VertBitSet&, const Vector<Vector3f, VertId>*, const VertScalars* )>( &positionVertsSmoothlySharpBd ), allow_raw_pointers() );
35-
function("positionVertsSmoothlySharpBdWithTopology", select_overload<void( const MeshTopology&, VertCoords&, const VertBitSet&, const Vector<Vector3f, VertId>* , const VertScalars* )>( &positionVertsSmoothlySharpBd ), allow_raw_pointers());
36-
function("positionVertsWithSpacing", select_overload<void( Mesh&, const SpacingSettings& )>( &positionVertsWithSpacing ));
37-
function("positionVertsWithSpacingWithTopology", select_overload<void( const MeshTopology&, VertCoords&, const SpacingSettings& )>( &positionVertsWithSpacing ));
38-
function("inflate", select_overload<void( Mesh&, const VertBitSet&, const InflateSettings&)>( &inflate ));
39-
function("inflateWithTopology", select_overload<void( const MeshTopology&, VertCoords&, const VertBitSet&, const InflateSettings& )>( &inflate ));
40-
function("inflate1WithTopology", select_overload<void( const MeshTopology&, VertCoords&, const VertBitSet&, float )>( &inflate1 ));
83+
class_<SpacingSettings>( "SpacingSettings" )
84+
.constructor<>()
85+
.property( "region", &SpacingSettings::region, allow_raw_pointers() )
86+
.property( "dist", &SpacingSettings::dist )
87+
.property( "numIters", &SpacingSettings::numIters )
88+
.property( "stabilizer", &SpacingSettings::stabilizer )
89+
.property( "maxSumNegW", &SpacingSettings::maxSumNegW )
90+
.property( "isInverted", &SpacingSettings::isInverted );
91+
92+
value_object<InflateSettings>( "InflateSettings" )
93+
.field( "pressure", &InflateSettings::pressure )
94+
.field( "iterations", &InflateSettings::iterations )
95+
.field( "preSmooth", &InflateSettings::preSmooth )
96+
.field( "gradualPressureGrowth", &InflateSettings::gradualPressureGrowth );
97+
98+
99+
///
100+
function( "positionVertsSmoothly", select_overload<void( Mesh&, const VertBitSet&, EdgeWeights, VertexMass, const VertBitSet* )>( &positionVertsSmoothly ), allow_raw_pointers() );
101+
function( "positionVertsSmoothlyWithTopology", select_overload<void( const MeshTopology&, VertCoords&, const VertBitSet&, EdgeWeights, VertexMass, const VertBitSet* )>( &positionVertsSmoothly ), allow_raw_pointers() );
102+
103+
function( "positionVertsSmoothlySharpBd", select_overload<void( Mesh&, const VertBitSet&, const Vector<Vector3f, VertId>*, const VertScalars* )>( &positionVertsSmoothlySharpBd ), allow_raw_pointers() );
104+
function( "positionVertsSmoothlySharpBdWithTopology", select_overload<void( const MeshTopology&, VertCoords&, const VertBitSet&, const Vector<Vector3f, VertId>*, const VertScalars* )>( &positionVertsSmoothlySharpBd ), allow_raw_pointers() );
105+
106+
function( "positionVertsWithSpacing", select_overload<void( Mesh&, const SpacingSettings& )>( &positionVertsWithSpacing ) );
107+
function( "positionVertsWithSpacingWithTopology", select_overload<void( const MeshTopology&, VertCoords&, const SpacingSettings& )>( &positionVertsWithSpacing ) );
108+
109+
function( "inflate", select_overload<void( Mesh&, const VertBitSet&, const InflateSettings& )>( &inflate ) );
110+
function( "inflateWithTopology", select_overload<void( const MeshTopology&, VertCoords&, const VertBitSet&, const InflateSettings& )>( &inflate ) );
111+
function( "inflate1WithTopology", select_overload<void( const MeshTopology&, VertCoords&, const VertBitSet&, float )>( &inflate1 ) );
112+
///
113+
114+
115+
function( "inflateToothRootImpl", &MRJS::inflateToothRootImpl );
41116
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <MRPch/MRWasm.h>
2+
3+
#include <MRMesh/MRMeshFwd.h>
4+
#include <MRMesh/MRMesh.h>
5+
#include <MRMesh/MRMeshTopology.h>
6+
#include <MRMesh/MRVector.h>
7+
#include <MRMesh/MRVector3.h>
8+
#include <MRMesh/MRBitSet.h>
9+
#include <MRMesh/MRId.h>
10+
#include <MRMesh/MRPositionVertsSmoothly.h>
11+
12+
using namespace emscripten;
13+
using namespace MR;
14+
15+
namespace MRJS
16+
{
17+
18+
val inflateToothRootImpl( Mesh& mesh, const InflateSettings& inflateSettings );
19+
20+
} // namespace MRJS

source/MRJavaScript/MRUtils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ std::shared_ptr<GeometryBuffer> exportGeometryBuffer( const Mesh& meshToExport )
362362
{
363363
return GeometryBuffer::fromMesh(meshToExport);
364364
}
365+
365366
val exportMeshMemoryView( const Mesh& meshToExport )
366367
{
367368
///

source/MRJavaScript/MRUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ struct GeometryBuffer
8484
size_t pointCount = points_.size();
8585
size_t vertexElementCount = pointCount * 3;
8686
const float* pointDataPtr = reinterpret_cast< const float* >( points_.data() );
87-
// FIXME
87+
// FIXME!!!
8888
val pointsArray = val( typed_memory_view( vertexElementCount, pointDataPtr ) );
8989

9090
// === Export triangle data ===

wasm/meshsdk/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)