Add project configuration and scene controller

- Created a new project configuration file `project.json` with metadata, camera settings, scene details, and lighting configurations.
- Implemented a new scene controller in `scena-controller copy.js` to manage 3D scene rendering, model loading, and user interactions.
- Integrated various loaders for STL and GLB models, along with functionality for dynamic material updates and model visibility toggling.
- Enhanced camera controls using TrackballControls for improved user navigation within the 3D environment.
This commit is contained in:
2026-01-21 16:10:18 +01:00
parent 7dca231004
commit 234cd7d415
28 changed files with 1699 additions and 208 deletions

View File

@@ -0,0 +1,12 @@
{
"permissions": {
"allow": [
"mcp__chrome-devtools__list_pages",
"mcp__chrome-devtools__navigate_page",
"mcp__chrome-devtools__take_snapshot",
"mcp__chrome-devtools__take_screenshot",
"mcp__chrome-devtools__evaluate_script",
"mcp__chrome-devtools__drag"
]
}
}

View File

@@ -7,71 +7,91 @@
"label_en": "Lateral bands",
"fields": [
{
"field_type": "select",
"data_type": "model",
"material": "metal",
"color": "#FFFFFF",
"field_type": "group",
"label": "DX",
"label_en": "",
"options": [
{
"label": "Nessuno",
"label_en": "None",
"value": ""
},
"label_en": "Right",
"id": 100,
"parent_id": 99,
"fields": [
{
"field_type": "checkbox",
"data_type": "model",
"label_en": "Band 14",
"label": "Banda 14",
"value": "2_banda 14"
"value": "2_banda 14",
"material": "metal",
"color": "#FFFFFF",
"parent_id": 100,
"id": "input-101"
},
{
"field_type": "checkbox",
"data_type": "model",
"label_en": "Band 15",
"label": "Banda 15",
"value": "2_banda 15"
},
"value": "2_banda 15",
"material": "metal",
"color": "#FFFFFF",
"parent_id": 100,
"id": "input-102"
},
{
"field_type": "checkbox",
"data_type": "model",
"label_en": "Band 16",
"label": "Banda 16",
"value": "2_banda 16"
}
],
"parent_id": 1,
"id": "input-1"
"value": "2_banda 16",
"material": "metal",
"color": "#FFFFFF",
"parent_id": 100,
"id": "input-103"
}
]
},
{
"field_type": "select",
"data_type": "model",
"material": "metal",
"color": "#FFFFFF",
{
"field_type": "group",
"label": "SX",
"label_en": "",
"options": [
{
"label": "Nessuno",
"label_en": "None",
"value": ""
},
"label_en": "Left",
"id": 101,
"parent_id": 99,
"fields": [
{
"field_type": "checkbox",
"data_type": "model",
"label_en": "Band 24",
"label": "Banda 24",
"value": "2_banda 24"
"value": "2_banda 24",
"material": "metal",
"color": "#FFFFFF",
"parent_id": 101,
"id": "input-104"
},
{
"field_type": "checkbox",
"data_type": "model",
"label_en": "Band 25",
"label": "Banda 25",
"value": "2_banda 25"
},
"value": "2_banda 25",
"material": "metal",
"color": "#FFFFFF",
"parent_id": 101,
"id": "input-105"
},
{
"field_type": "checkbox",
"data_type": "model",
"label_en": "Band 26",
"label": "Banda 26",
"value": "2_banda 26"
}
],
"parent_id": 1,
"id": "input-2"
}
"value": "2_banda 26",
"material": "metal",
"color": "#FFFFFF",
"parent_id": 101,
"id": "input-106"
}
]
}
],
"id": 1
"id": 99
},
{
"label": "TADS",
@@ -114,8 +134,8 @@
"data_type": "model",
"material": "metal",
"color": "#FFFFFF",
"label": "Numero di Tads",
"label_en": "Number of Tads",
"label": "Tipologia Viti",
"label_en": "Type of Screws",
"options": [
{
"label": "Nessuno",
@@ -223,6 +243,7 @@
"label_en": "TADS Tandem",
"material": "metal",
"color": "#FFFFFF",
"reset_field": "input-4",
"options": [
{
"label": "Nessuno",
@@ -306,6 +327,8 @@
"data_type": "model",
"label": "Modulo DX",
"label_en": "Right Module",
"depends_on": {"id":"input-14", "value":"11_modulo dx", "hide": true},
"material": "metal",
"value": "10_modulo dx",
"color": "#FFFFFF",
@@ -316,6 +339,7 @@
"data_type": "model",
"label": "Modulo SX",
"label_en": "Left Module",
"depends_on": {"id":"input-15", "value":"11_modulo sx", "hide": true},
"material": "metal",
"value": "10_modulo sx",
"color": "#FFFFFF",
@@ -333,6 +357,8 @@
"data_type": "model",
"label": "Modulo DX",
"label_en": "Right Module",
"depends_on": {"id":"input-12", "value":"10_modulo dx", "hide": true},
"material": "metal",
"value": "11_modulo dx",
"color": "#FFFFFF",
@@ -343,6 +369,7 @@
"data_type": "model",
"label": "Modulo SX",
"label_en": "Left Module",
"depends_on": {"id":"input-13", "value":"10_modulo sx", "hide": true},
"material": "metal",
"value": "11_modulo sx",
"color": "#FFFFFF",
@@ -360,8 +387,14 @@
"data_type": "model",
"label": "Modulo DX",
"label_en": "Right Module",
"depends_on": {"id":"input-18", "value":"13_modulo x intrudere dx", "hide": true},
"material": "metal",
"value": "12_modulo dx",
"other_models": [{
"color": "#f073c4",
"material": "plastic",
"model": "12_molla dx"
}],
"color": "#FFFFFF",
"parent_id": 11,
"id": "input-16"
@@ -370,8 +403,14 @@
"data_type": "model",
"label": "Modulo SX",
"label_en": "Left Module",
"material": "metal",
"depends_on": {"id":"input-19", "value":"13_modulo x intrudere sx", "hide": true},
"value": "12_modulo sx",
"other_models": [{
"color": "#f073c4",
"material": "plastic",
"model": "12_molla sx"
}],
"material": "metal",
"color": "#FFFFFF",
"parent_id": 11,
"id": "input-17"
@@ -387,6 +426,16 @@
"data_type": "model",
"label": "Modulo DX",
"label_en": "Right Module",
"depends_on": {"id":"input-16", "value":"12_modulo dx", "hide": true},
"other_models": [{
"color": "#f073c4",
"material": "plastic",
"model": "13_molla dx"
},{
"color": "#34eb3d",
"material": "plastic",
"model": "13_denti dx"
}],
"material": "metal",
"value": "13_modulo x intrudere dx",
"color": "#FFFFFF",
@@ -397,6 +446,16 @@
"data_type": "model",
"label": "Modulo SX",
"label_en": "Left Module",
"depends_on": {"id":"input-17", "value":"12_modulo sx", "hide": true},
"other_models": [{
"color": "#f073c4",
"material": "plastic",
"model": "13_molla sx"
},{
"color": "#34eb3d",
"material": "plastic",
"model": "13_denti sx"
}],
"material": "metal",
"value": "13_modulo x intrudere sx",
"color": "#FFFFFF",
@@ -412,8 +471,9 @@
{
"field_type": "checkbox",
"data_type": "model",
"label": "Attacchi per Mask",
"label_en": "Mask Hooks",
"label": "Attacchi per Aligners",
"label_en": "Aligners Hooks",
"hide_elements": ["input-21","input-22", "input-25"],
"material": "metal",
"value": "14_attacchi x mask",
"color": "#FFFFFF",
@@ -424,6 +484,7 @@
"data_type": "model",
"label": "Attacco doppia canula DX",
"label_en": "Double Cannula Hook Right",
"hide_elements": ["input-20"],
"material": "metal",
"value": "14_attacco doppia canula dx",
"color": "#FFFFFF",
@@ -434,6 +495,7 @@
"data_type": "model",
"label": "Attacco doppia canula SX",
"label_en": "Double Cannula Hook Left",
"hide_elements": ["input-20"],
"material": "metal",
"value": "14_attacco doppia canula sx",
"color": "#FFFFFF",
@@ -464,6 +526,7 @@
"data_type": "model",
"label": "Gradino",
"label_en": "Step",
"hide_elements": ["input-20"],
"material": "metal",
"value": "14_gradino",
"color": "#FFFFFF",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

467
src/assets/project.json Normal file
View File

@@ -0,0 +1,467 @@
{
"metadata": {},
"project": {
"shadows": true,
"shadowType": 1,
"toneMapping": 0,
"toneMappingExposure": 1
},
"camera": {
"metadata": {
"version": 4.7,
"type": "Object",
"generator": "Object3D.toJSON"
},
"object": {
"uuid": "395a500c-0494-41ec-b6d0-c8bbe4349725",
"type": "PerspectiveCamera",
"name": "Camera",
"layers": 1,
"matrix": [
0.11049213351682519,
2.7755575615628914e-17,
0.9938769986426388,
0,
0.4629545750185746,
0.8848864948632306,
-0.051467977209491755,
0,
-0.8794683336540725,
0.4658067101370114,
0.09777299673766349,
0,
-205.25558887415772,
82.23047074745682,
17.26020551692521,
1
],
"up": [
0,
1,
0
],
"fov": 50,
"zoom": 1,
"near": 0.01,
"far": 1000,
"focus": 10,
"aspect": 1.7745302713987474,
"filmGauge": 35,
"filmOffset": 0
}
},
"controls": {
"center": [
-50,
0,
0
]
},
"scene": {
"metadata": {
"version": 4.7,
"type": "Object",
"generator": "Object3D.toJSON"
},
"object": {
"uuid": "a2253e4f-b675-48b1-8c2c-76d897bcac25",
"type": "Scene",
"name": "Scene",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
],
"up": [
0,
1,
0
],
"children": [
{
"uuid": "2ef7dca1-f570-417b-b55a-46c017f98630",
"type": "Scene",
"name": "Scene",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
],
"up": [
0,
1,
0
],
"children": [
{
"uuid": "f106381a-534c-497e-acbd-a3b2ad121b9a",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
3.0997198829600077,
-97.44223652603492,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 0.8,
"shadow": {
"camera": {
"uuid": "38eaf299-1e78-4fc7-adce-080811a9fe47",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "0e530621-c1bb-48c8-87e3-224a85a2e9c1"
},
{
"uuid": "0b4faf09-07b3-4ab2-80a7-955bf83b8815",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
50,
0,
0,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 1,
"shadow": {
"camera": {
"uuid": "3487b036-5d5a-4331-b589-3b9c0472d0af",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "77316e30-bf2c-49ae-bbbd-1a40c413140c"
},
{
"uuid": "4ef0f77a-df7b-42f8-809d-35028cfc71bc",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
-50,
0,
0,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 1,
"shadow": {
"camera": {
"uuid": "0d0ac848-ef38-4ddc-9d4b-bd1a3fa259e6",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "9a8f9881-3997-4b11-9a5d-ab5dbaf0de11"
},
{
"uuid": "54bbb245-78cb-4ab9-bd57-0f02711f8a03",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
-38.28056498637591,
4.399184106340684,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 0.6,
"shadow": {
"camera": {
"uuid": "ba78f102-e863-4df9-a295-f56af374dbe9",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "ac43e49a-3301-4a12-9d90-0ce724dff367"
},
{
"uuid": "5f633583-57db-4472-be10-2dce0a75d139",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
15.833769711930671,
37.90623637377939,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 0.5,
"shadow": {
"camera": {
"uuid": "9e8a1c42-2f57-4648-9db1-40e59ac6b6e0",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "44ee6450-dc88-46e5-90e7-781de0a69288"
}
],
"backgroundRotation": [
0,
0,
0,
"XYZ"
],
"environmentRotation": [
0,
0,
0,
"XYZ"
]
},
{
"uuid": "09cd262e-79bd-4975-b449-1b813209f26d",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
25.33505179809299,
-6.19180174206452,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 0.6,
"shadow": {
"camera": {
"uuid": "192b16bb-49e2-4be6-8a88-5058304606a6",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "06277cc9-87d0-49d9-8716-5f745df7ee03"
}
],
"backgroundBlurriness": 0.2,
"backgroundIntensity": 0.93,
"backgroundRotation": [
0,
0,
0,
"XYZ"
],
"environmentRotation": [
0,
0,
0,
"XYZ"
]
}
},
"scripts": {},
"history": {
"undos": [],
"redos": []
},
"environment": null
}

View File

@@ -11,131 +11,262 @@
"layers": 1,
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
"up": [0,1,0],
"children": [
{
"uuid": "f106381a-534c-497e-acbd-a3b2ad121b9a",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,3.0997198829600077,-97.44223652603492,1],
"up": [0,1,0],
"color": 16777215,
"intensity": 0.8,
"shadow": {
"camera": {
"uuid": "38eaf299-1e78-4fc7-adce-080811a9fe47",
"type": "OrthographicCamera",
"layers": 1,
"up": [0,1,0],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
}
},
{
"uuid": "0b4faf09-07b3-4ab2-80a7-955bf83b8815",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,50,0,0,1],
"up": [0,1,0],
"color": 16777215,
"intensity": 1,
"shadow": {
"camera": {
"uuid": "3487b036-5d5a-4331-b589-3b9c0472d0af",
"type": "OrthographicCamera",
"layers": 1,
"up": [0,1,0],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
}
},
{
"uuid": "4ef0f77a-df7b-42f8-809d-35028cfc71bc",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-50,0,0,1],
"up": [0,1,0],
"color": 16777215,
"intensity": 1,
"shadow": {
"camera": {
"uuid": "0d0ac848-ef38-4ddc-9d4b-bd1a3fa259e6",
"type": "OrthographicCamera",
"layers": 1,
"up": [0,1,0],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
}
},
{
"uuid": "54bbb245-78cb-4ab9-bd57-0f02711f8a03",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,-38.28056498637591,4.399184106340684,1],
"up": [0,1,0],
"color": 16777215,
"intensity": 0.6,
"shadow": {
"camera": {
"uuid": "ba78f102-e863-4df9-a295-f56af374dbe9",
"type": "OrthographicCamera",
"layers": 1,
"up": [0,1,0],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
}
},
{
"uuid": "5f633583-57db-4472-be10-2dce0a75d139",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,15.833769711930671,37.90623637377939,1],
"up": [0,1,0],
"color": 16777215,
"intensity": 0.5,
"shadow": {
"camera": {
"uuid": "9e8a1c42-2f57-4648-9db1-40e59ac6b6e0",
"type": "OrthographicCamera",
"layers": 1,
"up": [0,1,0],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
}
}]
"children": [
{
"uuid": "f106381a-534c-497e-acbd-a3b2ad121b9a",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
3.0997198829600077,
-97.44223652603492,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 0.8,
"shadow": {
"camera": {
"uuid": "38eaf299-1e78-4fc7-adce-080811a9fe47",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "0e530621-c1bb-48c8-87e3-224a85a2e9c1"
},
{
"uuid": "0b4faf09-07b3-4ab2-80a7-955bf83b8815",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
50,
0,
0,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 1,
"shadow": {
"camera": {
"uuid": "3487b036-5d5a-4331-b589-3b9c0472d0af",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "77316e30-bf2c-49ae-bbbd-1a40c413140c"
},
{
"uuid": "4ef0f77a-df7b-42f8-809d-35028cfc71bc",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
-50,
0,
0,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 1,
"shadow": {
"camera": {
"uuid": "0d0ac848-ef38-4ddc-9d4b-bd1a3fa259e6",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "9a8f9881-3997-4b11-9a5d-ab5dbaf0de11"
},
{
"uuid": "54bbb245-78cb-4ab9-bd57-0f02711f8a03",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
-38.28056498637591,
4.399184106340684,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 0.6,
"shadow": {
"camera": {
"uuid": "ba78f102-e863-4df9-a295-f56af374dbe9",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "ac43e49a-3301-4a12-9d90-0ce724dff367"
},
{
"uuid": "5f633583-57db-4472-be10-2dce0a75d139",
"type": "DirectionalLight",
"name": "DirectionalLight",
"layers": 1,
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
15.833769711930671,
37.90623637377939,
1
],
"up": [
0,
1,
0
],
"color": 16777215,
"intensity": 0.5,
"shadow": {
"camera": {
"uuid": "9e8a1c42-2f57-4648-9db1-40e59ac6b6e0",
"type": "OrthographicCamera",
"layers": 1,
"up": [
0,
1,
0
],
"zoom": 1,
"left": -5,
"right": 5,
"top": 5,
"bottom": -5,
"near": 0.5,
"far": 500
}
},
"target": "44ee6450-dc88-46e5-90e7-781de0a69288"
}
]
}
}

View File

@@ -166,6 +166,31 @@
</div>
</div>
<div class="modal" id="clinicoPazienteModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Inserisci Dati</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="nomeClinico" class="form-label">Nome Clinico</label>
<input type="text" class="form-control" id="nomeClinico" placeholder="Inserisci il nome del clinico">
</div>
<div class="mb-3">
<label for="nomePaziente" class="form-label">Nome Paziente</label>
<input type="text" class="form-control" id="nomePaziente" placeholder="Inserisci il nome del paziente">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
<button type="button" class="btn btn-primary" id="salvaDati">Salva</button>
</div>
</div>
</div>
</div>
<div class="modal" id="linguaModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">

View File

@@ -15,7 +15,7 @@ let controller = this;
let prescrizione;
let def_config;
let lang = navigator.language.split('-')[0] != 'it' ? 'en' : 'it';
const hidden_fields = {};
let API = 'http://localhost/api/';
let CRM_URL = 'http://localhost/prescrizioni/';
let CFG_URL = 'http://localhost/config-predefinite/';
@@ -182,6 +182,21 @@ export const init = async (_scene, _cameraControls) => {
}else{
generaModalProdotti(); //riattivare
/** eliminare prima di andare in produzione */
$("#salvaDati").on('click', () => {
$("#clinicoPazienteModal").modal('hide');
let clinico = $("#nomeClinico").val();
let paziente = $("#nomePaziente").val();
let html = clinico ? '<div>'+_t('clinico')+': <strong>'+clinico+'</strong></div>' : '';
html += '<div>'+_t('paziente')+': <strong>'+paziente+'</strong></div>';
$(".dettagli-prescrizione").html(html);
});
$("#clinicoPazienteModal").modal('show');
/* ***** */
$(".btn-salva").addClass('d-none');
$(".btn-torna-prescrizione").addClass('d-none');
}
@@ -281,15 +296,12 @@ const attivaEvento = (field) => {
if(field.field_type == 'select'){
label = $("#"+field.id+" option:selected").text();
//console.log("LABEL",label)
}
if(field.data_type == 'model'){
updateConfig(field, val, label);
//console.log("model",field);
}else{
config[field.id] = {field: field, value: val, label: label};
Object.keys(config).forEach((k) => {
@@ -302,15 +314,80 @@ const attivaEvento = (field) => {
ui.generaListaConfig(config,menu_data)
}
if(field.check_depends){
if(field.check_depends && field?.depends_on?.hide == null){
document.querySelectorAll(`[data-dep-id="${field.id}"]`).forEach((el) => {
if (el.getAttribute('data-dep-value') !== val) {
el.style.display = 'none';
} else {
el.style.display = '';
}
});
let firstVisibleOption = document.querySelector(`[data-dep-id="${field.id}"]:not([style*="display: none"])`);
if (firstVisibleOption) {
let emptyOption = firstVisibleOption.parentNode.querySelector('option[value=""]');
if (emptyOption) {
emptyOption.selected = true;
} else {
firstVisibleOption.selected = true;
}
firstVisibleOption.parentElement.dispatchEvent(new Event('change'));
}
}else if(field.check_depends && field.depends_on.hide){
document.querySelectorAll(`[data-dep-id]`).forEach((el) => {
if(el.type === 'checkbox') {
if(el.getAttribute('data-dep-id') === field.id) {
if(!el.checked && val.length > 0) {
el.parentElement.style.display = 'none';
} else {
el.parentElement.style.display = '';
}
}
}
});
//document.querySelector(`#${field.depends_on.id}`).parentElement.style.display = 'none';
}
if(field.reset_field){
//console.log("resetto", field.reset_field)
$("#"+field.reset_field).val('');
$("#"+field.reset_field).trigger('change');
}
if(field.hide_elements != null){
field.hide_elements.forEach((el_id) => {
if(hidden_fields[el_id] == null)
hidden_fields[el_id] = 0;
if(val.length > 0)
hidden_fields[el_id]++;
else{
hidden_fields[el_id]--;
if(hidden_fields[el_id] < 0)
hidden_fields[el_id] = 0;
}
})
}
for(let k in hidden_fields){
if(hidden_fields[k] > 0){
$("#"+k).parent().parent().hide();
}else{
$("#"+k).parent().parent().show();
}
}
})
}

View File

@@ -93,14 +93,14 @@ export const generaMenu = (data) => {
field_list.forEach((field) => {
if (field.depends_on) {
let dependentField = field_list.find(f => f.id === field.depends_on);
let dependentField = field_list.find(f => f.id === field.depends_on || f.id === field.depends_on.id);
if (dependentField) {
dependentField.check_depends = true;
}
}
});
console.log("field_list", field_list);
return field_list;
}
@@ -215,15 +215,21 @@ export const generaCheckbox = (field) => {
field.id = 'input-'+gen_id;
gen_id++;
}
let depends_str = '';
if(field.depends_on != null){
depends_str = ` data-dep-id="${field.depends_on.id}" data-dep-value="${field.depends_on.value}"`
}
let inline = field.inline ? 'd-inline-block' : '';
let html = '<div class="form-group '+inline+'">\
<div class="form-check">\
<input class="form-check-input" type="checkbox" value="'+field.value+'" id="'+field.id +'">\
<label class="form-check-label" for="'+field.id +'">\
'+_t(field,'label')+'\
</label>\
</div>\
</div>';
let html = `<div class="form-group ${inline}">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="${field.value}" id="${field.id}"${depends_str}>
<label class="form-check-label" for="${field.id}">
${_t(field,'label')}
</label>
</div>
</div>`;
field_list.push(field);
return html;

View File

@@ -0,0 +1,707 @@
import * as THREE from 'three'
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls';
import * as interfaccia from './interfaccia';
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
import { DecalGeometry } from 'three/examples/jsm/geometries/DecalGeometry.js';
import WebGPU from 'three/examples/jsm/capabilities/WebGPU';
import WebGL from 'three/examples/jsm/capabilities/WebGL';
import * as JSZip from 'jszip';
import * as JSZipUtils from 'jszip-utils';
import 'jszip-utils';
import { degToRad } from 'three/src/math/MathUtils';
/**
* Sizes
*/
const sizes = {}
// Scene
let scene = new THREE.Scene()
let mainGroup = new THREE.Group();
let camera;
let cameraControls;
const clock = new THREE.Clock();
let actions = [];
let mixers = [];
let end = false;
let doRender = false;
let renderer = null;
let frustumSize = 1600; // Aumentato per vedere meglio i modelli (era 1100)
$(".loading").css('visibility','visible');
window.addEventListener('resize', () =>
{
// Save sizes
updateWindowSize();
if(camera != null){
// Update camera
// Aggiorna le dimensioni del frustum della camera
var aspect = sizes.width / sizes.height;
// Imposta questo al valore che preferisci
camera.left = -frustumSize * aspect / 2;
camera.right = frustumSize * aspect / 2;
camera.top = frustumSize / 2;
camera.bottom = -frustumSize / 2;
// Aggiorna la matrice di proiezione della camera
camera.updateProjectionMatrix();
}
// Update renderer
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(sizes.width, sizes.height)// renderer.setSize(sizes.width, sizes.height, true)
doRender = true;
})
window.addEventListener('load', ()=>{ init(); });
const updateWindowSize = () => {
let canvas = document.querySelector('.canvas-container');
sizes.width = canvas.clientWidth
sizes.height = canvas.clientHeight
//console.log("canvas size", sizes)
}
export const matValues = (nome) => {
let roughness = parseFloat($("#roughness-"+nome).val());
let metalness = parseFloat($("#metalness-"+nome).val());
if(isNaN(roughness)) roughness = 0;
if(isNaN(metalness)) metalness = 0;
let obj = scene.getObjectByName(nome);
if(obj.isMesh){
obj.material.roughness = roughness;
obj.material.metalness = metalness;
obj.material.needsUpdate = true;
doRender = true;
}
};
const loadJsonModel = (name, path, callback = null) => {
const loader = new THREE.ObjectLoader();
let loadBar = $(".load-bar");
JSZipUtils.getBinaryContent('./assets/'+name+'.zip', {
progress: (update) => {
//console.log(e.percent + "% loaded");
$(loadBar).text(parseInt(update.percent) + '%');
},
callback: (err, data) => {
if(err) {
throw err; // or handle err
}
$(".loading").text("Inizializzazione scena...");
// loadStatus.nativeElement.innerHTML = 'Caricamento...';
//clearInterval(timer);
JSZip.loadAsync(data).then((zip) => {
let sceneFile = zip.file(name+'.json');
sceneFile.async('string', (update) => {
//console.log(update);
$(loadBar).text(parseInt(update.percent) + '%');
}).then((objectJson) => {
loader.parse(JSON.parse(objectJson), (parsedObj)=>{
if(callback != null){
callback(parsedObj);
}
});
});
});
}});
}
export const loadSTLModel = async (name, path, color, material, callback = null) => {
return new Promise(async (resolve, reject) => {
const loader = new STLLoader();
interfaccia.showLoader();
let geometry;
loader.loadAsync(path+name+".stl", (progress) => {
interfaccia.aggiornaLoader(progress);
}).then((obj) => {
let mesh = addModelToScene(obj, name, color, material);
interfaccia.resetLoader();
resolve(mesh);
}).catch((err) => {
interfaccia.resetLoader();
resolve(null)
console.log(err);
});
});
}
export const loadGLBModel = async (name, path, color, material, callback = null) => {
return new Promise(async (resolve, reject) => {
const loader = new GLTFLoader();
interfaccia.showLoader();
let geometry;
loader.loadAsync(path+name+".glb", (progress) => {
interfaccia.aggiornaLoader(progress);
}).then((obj) => {
let mesh = addModelToScene(obj.scene.children[0], name, color, material);
interfaccia.resetLoader();
resolve(mesh);
}).catch((err) => {
interfaccia.resetLoader();
resolve(null)
console.log(err);
});
//if(callback != null) callback();
});
}
export const addModelToScene = (obj, name, color, material_type) => {
let mesh = null;
let roughness = 1;
let metalness = 0;
if(material_type == 'metal'){
metalness = 0.3;
roughness = 0.20;
}
const material = new THREE.MeshStandardMaterial({color: color, roughness: roughness, metalness: metalness}); //'#a0a0a0'
if(obj.isMesh){
mesh = obj;
mesh.material.color = new THREE.Color(color);
mesh.material.roughness = roughness;
mesh.material.metalness = metalness;
mesh.material.needsUpdate = true;
}else{
mesh = new THREE.Mesh(obj, material);
}
mesh.scale.multiplyScalar(15);
mesh.name = name;
mesh.castShadow = false;
mesh.receiveShadow = false;
mainGroup.add(mesh)
//console.log(mesh)
//scene.add(mesh);
//console.log(scene)
doRender = true;
return mesh;
}
export const mostraArcata = async (model) => {
const url = new URL(location.href);
const params = url.searchParams;
let debug = params.get('debug');
let el = scene.getObjectByName("modello-"+model);
$(".color-"+model).addClass('d-none');
if(el){
if(el.visible){
el.visible = false;
}else{
el.visible = true;
if(debug == 'true'){
$(".color-"+model).removeClass('d-none');
}
}
doRender = true;
}
else{
let obj = await loadGLBModel("modello-"+model, './assets/glb/', '#ffffff');
obj.userData = {"type":"arcata"};
obj.material.roughness = 0.26;
obj.material.metalness = 0;
if(debug == 'true'){
$(".color-"+model).removeClass('d-none');
}
}
}
const randomColor = () => {
var color = '#';
var caratteri = '0123456789ABCDEF';
for (var i = 0; i < 6; i++) {
color += caratteri[Math.floor(Math.random() * 16)];
}
return color;
}
export const loadModels = async (config) => {
let activeObjs = [];
console.log("Config:", config);
return new Promise(async (resolve, reject)=>{
for(let key in config){
let el = config[key];
if(el.field.data_type == 'model' && el.value != ""){
let obj = scene.getObjectByName(el.value);
el.colore = el.colore == null ? el.field.color: el.colore
console.log("Loading model:", el.value, el.colore, el.field.material);
if(obj != null)
activeObjs.push(obj);
else{
obj = await loadGLBModel(el.value, './assets/glb/', el.colore, el.field.material);
if(obj != null)
activeObjs.push(obj);
else{
el.model_not_found = true;
}
}
if(el.field.accessory != null && el.field.accessory != ""){
let acc = scene.getObjectByName(el.field.accessory);
if(acc != null)
activeObjs.push(acc);
else{
acc = await loadGLBModel(el.field.accessory, './assets/glb/', el.colore, el.field.material);
if(acc != null)
activeObjs.push(acc);
else{
el.accessory_not_found = true;
}
}
}
}
}
console.log("Active objs:", activeObjs);
mainGroup.traverse((el) => {
if(el.isMesh && el.userData.type != 'arcata') el.visible = false;
});
activeObjs.forEach((obj) => {
obj.visible = true;
});
doRender = true;
resolve();
})
}
export const init = async () => {
//let scena = await (await fetch("./assets/scene.json")).json();
const loader = new THREE.ObjectLoader();
scene = await loader.loadAsync("./assets/scene.json");
let pointLight, ambientLight;
updateWindowSize();
renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('.webgl'),
antialias: true,
alpha: true,
useLegacyLights: false
})
mainGroup.rotateX(degToRad(-90));
scene.add(mainGroup);
/*
scene.traverse((obj) => {
if(obj.isLight && Math.abs(obj.position.x) == 50){
obj.shadow.mapSize.width = 1024; // default
obj.shadow.mapSize.height = 1024; // default
obj.shadow.camera.near = 330; // default
obj.shadow.camera.far = 1000; // default
obj.shadow.camera.right = 500;
obj.shadow.camera.left = -500;
obj.shadow.camera.top = 500;
obj.shadow.camera.bottom = -500;
obj.shadow.radius = 2000;
obj.shadow.blurSamples = 2500;
obj.position.y = 0;
obj.castShadow = true;
//const helper = new THREE.CameraHelper( obj.shadow.camera );
//scene.add( helper );
}
})
renderer.shadowMap.autoUpdate = false;
renderer.shadowMap.needsUpdate = true; //chiamare ogni volta che viene aggiunto un elemento
*/
let view = {
left: 0,
bottom: 0,
width: 1,
height: 1,
background: new THREE.Color( 0.5, 0.5, 0.7 ),
eye: [0,0,2800],// [ 0, 300, 1800 ],
up: [ 0, 1, 0 ],
fov: 50,
frustum: 120,
container: '.view1',
active: true,
main: true,
updateCamera: function ( camera, scene, mouseX ) {
}
}
let aspect = sizes.width / sizes.height;
//camera = new THREE.PerspectiveCamera(50, sizes.width / sizes.height, 0.1, 10000);
camera = new THREE.OrthographicCamera( frustumSize * aspect / - 2, frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 0.1, 10000 );
camera.position.fromArray( view.eye );
camera.up.fromArray( view.up );
scene.add(camera);
var pointLight2 = new THREE.PointLight( 0xffffff, 0.8 ); // 0xff6666
camera.add( pointLight2 );
/*
ambientLight = new THREE.AmbientLight( 0xffffff, 0.3 );
scene.add( ambientLight );
pointLight = new THREE.PointLight( 0x7c7b7b, 0.5 ); // 0xff0000
pointLight.position.z = 2500;
scene.add( pointLight );
var pointLight3 = new THREE.PointLight( 0x7c7b7b, 0.5 ); // 0x0000ff
pointLight3.position.x = - 1000;
pointLight3.position.z = 1000;
scene.add( pointLight3 );
let pointLight4 = new THREE.DirectionalLight( 0x7c7b7b, 0.8 ); // 0xff0000
pointLight4.position.y = 0;
scene.add( pointLight4 );
*/
window.scene = scene;
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(sizes.width, sizes.height)
renderer.toneMapping = THREE.CineonToneMapping;
renderer.toneMappingExposure = 0.5;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.shadowMap.enabled = true;
renderer.physicallyCorrectLights = false;
cameraControls = new TrackballControls( camera, renderer.domElement );
cameraControls.minDistance = 1;
cameraControls.maxDistance = Infinity;
// TrackballControls permette rotazione infinita in tutte le direzioni
cameraControls.rotateSpeed = 2.5; // Aumentata sensibilità rotazione
cameraControls.zoomSpeed = 1.2;
cameraControls.panSpeed = 0.8;
// No damping per TrackballControls (usa staticMoving)
cameraControls.staticMoving = false;
cameraControls.dynamicDampingFactor = 0.2;
// Salva il metodo update originale per modificarlo
const originalUpdate = cameraControls.update.bind(cameraControls);
// Override del metodo update per bloccare la rotazione Z
cameraControls.update = function() {
// Chiama l'update originale
originalUpdate();
// Resetta la rotazione Z della camera mantenendola sempre a zero
const up = new THREE.Vector3(0, 1, 0);
const right = new THREE.Vector3();
// Calcola il vettore right come perpendicolare a forward e up
const forward = new THREE.Vector3();
forward.subVectors(this.target, camera.position).normalize();
right.crossVectors(forward, up).normalize();
// Ricalcola up come perpendicolare a forward e right per mantenere l'orientamento
up.crossVectors(right, forward).normalize();
// Imposta l'up della camera
camera.up.copy(up);
};
window.camera = camera;
window.cc = cameraControls;
// Update camera
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()
// Update renderer
//renderer.setPixelRatio(sizes.width / sizes.height);
renderer.setSize(sizes.width, sizes.height, true)
doRender = true;
loop();
}
const textToMesh = async (text) => {
const loader = new FontLoader();
const font = await loader.loadAsync('assets/fonts/Agency_FB_Bold.json');
let geometry = new TextGeometry( text, {
font: font,
size: 80,
height: 5,
/*
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 8,
bevelOffset: 0,
bevelSegments: 5*/
} );
geometry.center();
let material = new THREE.MeshBasicMaterial( { color: 0xFF0000 } );
let mesh = new THREE.Mesh( geometry, material );
mesh.position.z = 0;
mesh.position.y = 0;
mesh.position.x = 0;
//scene.add(mesh);
return mesh;
}
async function applyTextToMesh(mesh, text, font, size, color) {
// Crea un nuovo elemento canvas
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
// Imposta il font e il colore del testo
context.font = `${size}px ${font}`;
context.fillStyle = color;
// Disegna il testo sul canvas
context.fillText(text, 0, size);
const loader = new THREE.TextureLoader();
// Carica la texture dall'immagine base64
const texture = await loader.loadAsync(canvas.toDataURL("image/jpeg"));
console.log(canvas.toDataURL("image/jpeg"))
// Crea una nuova texture dal canvas
console.log("asd",texture);
mesh.material.map = texture;
mesh.material.needsUpdate = true;
// Crea un nuovo materiale utilizzando la texture
//const material = new THREE.MeshBasicMaterial({ map: texture });
// Applica il materiale alla mesh
//mesh.material = material;
mesh.geometry.computeVertexNormals();
}
/**
* Loop
*/
const loop = () =>
{
// TrackballControls.update() deve essere chiamato ad ogni frame
cameraControls.update();
// Render sempre per vedere gli aggiornamenti dei controlli
renderer.render( scene, camera );
if(doRender){
// Render aggiuntivo se richiesto da altre parti del codice
}
doRender = false;
window.requestAnimationFrame(loop)
}
export const cambiaColore = (objName, color) => {
let obj = scene.getObjectByName(objName);
if(obj == null) return;
obj.material.color = new THREE.Color(color);
obj.material.needsUpdate = true;
doRender = true;
}
export const toggleModel = (objName) => {
let obj = scene.getObjectByName(objName);
console.log(obj.material)
obj.material.transparent = !obj.material.transparent;
if(obj.material.transparent)obj.material.opacity = 0.1;
obj.material.needsUpdate = true;
doRender = true;
}
window.esporta = () => {
var output = scene.toJSON();
output = JSON.stringify( output, 1, '\t' );
output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
saveString(output, "scena.json");
}
function save( blob, filename ) {
var link = document.createElement( 'a' );
link.style.display = 'none';
document.body.appendChild( link );
link.href = URL.createObjectURL( blob );
link.download = filename;
link.click();
// URL.revokeObjectURL( url ); breaks Firefox...
}
function saveString( text, filename ) {
save( new Blob( [ text ], { type: 'text/plain' } ), filename );
}
const toggleMobileMenu = () => {
$(".navbar-collapse").removeClass('show');
}
window.rotateTo = (side) => {
toggleMobileMenu();
$('.pos-btn').removeClass('active');
// Calcola la posizione della camera in base alla vista richiesta
const distance = camera.position.distanceTo(cameraControls.target);
let newPosition = new THREE.Vector3();
switch ( side ) {
case 'front':
// Vista frontale: camera davanti all'oggetto
newPosition.set(0, 0, distance);
break;
case 'back':
// Vista posteriore: camera dietro all'oggetto
newPosition.set(0, 0, -distance);
break;
case 'up':
// Vista dall'alto: camera sopra l'oggetto
newPosition.set(0, distance, 0);
break;
case 'down':
// Vista dal basso: camera sotto l'oggetto
newPosition.set(0, -distance, 0);
break;
case 'right':
// Vista destra: camera a destra dell'oggetto
newPosition.set(distance, 0, 0);
break;
case 'left':
// Vista sinistra: camera a sinistra dell'oggetto
newPosition.set(-distance, 0, 0);
break;
}
// Anima la transizione con GSAP
if(window.gsap) {
gsap.to(camera.position, {
duration: 0.8,
x: newPosition.x,
y: newPosition.y,
z: newPosition.z,
onUpdate: () => {
camera.lookAt(cameraControls.target);
}
});
} else {
camera.position.copy(newPosition);
camera.lookAt(cameraControls.target);
}
$('.move-'+side).addClass('active');
}

View File

@@ -206,8 +206,8 @@ export const addModelToScene = (obj, name, color, material_type) => {
let metalness = 0;
if(material_type == 'metal'){
metalness = 0.9;
roughness = 0.28;
metalness = 0.86 ;
roughness = 0.3;
}
const material = new THREE.MeshStandardMaterial({color: color, roughness: roughness, metalness: metalness}); //'#a0a0a0'
@@ -259,9 +259,9 @@ export const mostraArcata = async (model) => {
doRender = true;
}
else{
let obj = await loadGLBModel("modello-"+model, './assets/glb/', '#ffffff');
let obj = await loadGLBModel("modello-"+model, './assets/glb/', '#efc971');
obj.userData = {"type":"arcata"};
obj.material.roughness = 0.26;
obj.material.roughness = 0.40;
obj.material.metalness = 0;
if(debug == 'true'){
@@ -285,7 +285,7 @@ const randomColor = () => {
export const loadModels = async (config) => {
let activeObjs = [];
console.log("Config:", config);
//console.log("Config:", config);
return new Promise(async (resolve, reject)=>{
for(let key in config){
@@ -294,7 +294,7 @@ export const loadModels = async (config) => {
if(el.field.data_type == 'model' && el.value != ""){
let obj = scene.getObjectByName(el.value);
el.colore = el.colore == null ? el.field.color: el.colore
console.log("Loading model:", el.value, el.colore, el.field.material);
//console.log("Loading model:", el.value, el.colore, el.field.material);
if(obj != null)
activeObjs.push(obj);
else{
@@ -308,19 +308,22 @@ export const loadModels = async (config) => {
}
if(el.field.accessory != null && el.field.accessory != ""){
let acc = scene.getObjectByName(el.field.accessory);
if(acc != null)
activeObjs.push(acc);
else{
acc = await loadGLBModel(el.field.accessory, './assets/glb/', el.colore, el.field.material);
if(acc != null)
if(el.field.other_models != null){
for(let om of el.field.other_models){
let acc = scene.getObjectByName(om.model);
if(acc != null)
activeObjs.push(acc);
else{
el.accessory_not_found = true;
}
else{
acc = await loadGLBModel(om.model, './assets/glb/', om.color, om.material);
if(acc != null)
activeObjs.push(acc);
else{
el.accessory_not_found = true;
}
}
}
}
}

View File

@@ -250,14 +250,14 @@ def stl_to_gltf(path_to_stl, out_path, is_binary):
print("Done! Exported to %s" %out_path)
def batch_conversion(binary_stl_path, out_path, is_binary):
#print(os.listdir(binary_stl_path))
for f in os.listdir(binary_stl_path):
new_file_name = f.replace('.stl','.glb')
destination = out_path+'/'+new_file_name
source = binary_stl_path+'/'+f
if source.endswith('.stl') and not source.startswith('.'):
if source.endswith('.stl') and not f.startswith('.'):
stl_to_gltf(source, destination, is_binary)
print('Convert: '+f+ ' ---> '+new_file_name)
@@ -267,8 +267,8 @@ if __name__ == '__main__':
import sys
if len(sys.argv) < 3:
print("use it like python3 stl_to_gltf.py /path/to/stl /path/to/gltf/folder -b -batch")
print("or python3 stl_to_gltf.py /path/to/stl /path/to/glb/file -b")
print("use it like python3 converter.py /path/to/stl /path/to/gltf/folder -b -batch")
print("or python3 converter.py /path/to/stl /path/to/glb/file -b")
sys.exit(1)
path_to_stl = sys.argv[1]