Merge branch 'release/AddNpmWebDoorViewer_02'

This commit is contained in:
Samuele Locatelli
2024-06-26 16:54:26 +02:00
13 changed files with 1071 additions and 186 deletions
+1 -1
View File
@@ -126,7 +126,7 @@ WebGl3D.Door:release:
- *version-fix
- *ReplicaX
script:
- cd .\IcarusView\WebGl\
- cd .\WebDoorView\src\
- Set-Content -Path "./.npmrc" -Value "email=ceo@steamware.net `nalways-auth=true `n//nexus.steamware.net/repository/npm-hosted/:_authToken=$NPM_TOKEN"
- $JSON_FILE = Get-Content '.\package.json' -raw
- $JSON_FILE_RAW = $JSON_FILE | ConvertFrom-Json
+1 -28
View File
@@ -33,19 +33,11 @@
<div id ="divMenu2" class="p-2">
<div>
<button id="btnHelp" class="btn btn-lg btn-light" onclick="toggleHelp()" title="Hide/Show Menu"><i class="fas fa-question"></i></button>
<!-- <div class="btn-group" role="group" aria-label="Mode">
<button id="btnOrto" class="btn btn-lg btn-light" onclick="setOrtho()" title="Ortho/ISO View"><i class="fas fa-cube"></i></button>
<button id="btnPers" class="btn btn-lg btn-secondary" onclick="setPersp()" title="Perspective View"><i class="fab fa-unity"></i></button>
</div> -->
<div class="btn-group" role="group" aria-label="Animation">
<button id="btnPause" class="btn btn-lg btn-secondary" onclick="toggleAnim()" title="Freeze model"><i class="fas fa-pause"></i></button>
<button id="btnPlay" class="btn btn-lg btn-light" onclick="toggleAnim()" title="Animation Active"><i class="fas fa-play"></i></button>
</div>
<!-- <div class="btn-group" role="group" aria-label="Animation">
<button id="btnRotate" class="btn btn-lg btn-light" onclick="toggleRotate()" title="Toggle Rotate"><i class="fas fa-globe"></i></button>
<button id="btnQuote" class="btn btn-lg btn-light" onclick="toggleQuote()" title="Show Quotation"><i class="fas fa-ruler"></i></button>
<button id="btnGrid" class="btn btn-lg btn-light" onclick="toggleGrid()" title="Toggle Grid"><i class="fas fa-border-all"></i></button>
</div> -->
<button id="btnReset" class="btn btn-lg btn-secondary" onclick="resetCamera()" title="Reset"><i class="fas fa-sync-alt"></i></button>
</div>
<div id = "infoDiv">
@@ -61,67 +53,48 @@
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<b>Rotate</b> CTRL + Drag Mouse-Wheel
</li>
<!-- <li class="list-group-item p-1 d-flex justify-content-between">
<div>
Toggle Show-Cube : <b>C</b>
</div>
<button class="btn btn-sm btn-primary py-0" onclick="toggleCube()">C</button>
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div>
Toggle Show-Frame : <b>F</b>
</div>
<button class="btn btn-sm btn-primary py-0" onclick="toggleFrame()">F</button>
</li> -->
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Iso / Ortho</b></div>
<div>
<i class="fas fa-cube"></i> | key : <b>O</b>
</div>
<!-- <button class="btn btn-sm btn-primary py-1" onclick="setOrtho()"><i class="fas fa-cube"></i></button> -->
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Perspective</b></div>
<div>
<i class="fab fa-unity"></i> | key : <b>P</b>
</div>
<!-- <button class="btn btn-sm btn-primary py-1" onclick="setPersp()"><i class="fab fa-unity"></i></button> -->
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>AutoRotate</b></div>
<div>
<i class="fas fa-globe"></i> | key : <b>R</b>
</div>
<!-- <button class="btn btn-sm btn-primary py-1" onclick="toggleRotate()"><i class="fas fa-globe"></i></button> -->
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Quotes</b></div>
<div>
<i class="fas fa-ruler"></i> | key : <b>Q</b>
</div>
<!-- <button class="btn btn-sm btn-primary py-1" onclick="toggleQuote()"><i class="fas fa-ruler"></i></button> -->
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Grid</b></div>
<div>
<i class="fas fa-border-all"></i> | key : <b>G</b>
</div>
<!-- <button class="btn btn-sm btn-primary py-1" onclick="toggleGrid()"></button> -->
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Reset</b></div>
<div>
<i class="fas fa-sync-alt"></i> | key: <b>SpaceBar</b>
</div>
<!-- <button class="btn btn-sm btn-primary py-1" onclick="resetCamera()"><i class="fas fa-sync-alt"></i></button> -->
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Menu</b></div>
<div>
<i class="fas fa-question"></i> | key : <b>H</b>
</div>
<!-- <button class="btn btn-sm btn-primary py-1" onclick="toggleHelp()"><i class="fas fa-question small"></i></button> -->
</li>
</ul>
</div>
+18 -1
View File
@@ -1,5 +1,22 @@
{
"name": "webgl-door-visualizer",
"dependencies": {
"three": "^0.162.0"
}
},
"publishConfig": {
"registry": "https://nexus.steamware.net/repository/npm-hosted/"
},
"version": ".24062212",
"description": "3D WebDoor visualizer ",
"main": "draw_call.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"3D",
"WebGl",
"WebDoor"
],
"author": "R.E., S.E.L",
"license": "ISC"
}
+297
View File
@@ -0,0 +1,297 @@
# Visualizzatore 3D Doors (Blazor)
- [Visualizzatore 3D Doors (Blazor)](#visualizzatore-3d-doors-blazor)
- [0️⃣ Prerequisiti](#0️⃣-prerequisiti)
- [1️⃣ Creare un'applicazione Web (Blazor server app)](#1️⃣-creare-unapplicazione-web-blazor-server-app)
- [⚠️ IMPORTANTE PER IL CORRETTO FUNZIONAMENTO DEL VISUALIZZATORE](#-importante-per-il-corretto-funzionamento-del-visualizzatore)
- [2️⃣ Setup helper per la comunicazione](#2️⃣-setup-helper-per-la-comunicazione)
- [3️⃣​ Aggiungere i riferimenti ai file `.js`](#3️⃣-aggiungere-i-riferimenti-ai-file-js)
- [4️⃣ Setup componente blazor per il render](#4️⃣-setup-componente-blazor-per-il-render)
- [5️⃣​ Setup della chiamata alla funzione di render](#5️⃣-setup-della-chiamata-alla-funzione-di-render)
## 0️⃣ Prerequisiti
- .NET SDK installato
## 1️⃣ Creare un'applicazione Web (Blazor server app)
![Tipo di progetto ](image.png)
Una volta creata l'applicazione web creare nella cartella <b>wwroot</b> una sottocartella denominandola <b>lib</b>. Se si importa localmente inl pacchetto npm viene creata alla fase di definizione del path di destinazione
![Import NPM](image-1.png)
E' possibile importare il pacchetto npm che si traova sul nostro repository nexus (https://nexus.steamware.net/#browse/browse:npm-hosted:webgl-door-visualizer) con il comando seguente
npm install webgl-door-visualizer@1.2.240622.1216
Dove il numero versione va modificato di conseguenza a quanto voluto.
![Creazione cartella lib](image-1.png)
Successivamente copiare l'intera cartella <b>src</b> fornita ed incollarla nella cartella <b>lib</b> precedentemente creata.
![Aggiunta libreria WebGl](image-2.png)
## ⚠️ IMPORTANTE PER IL CORRETTO FUNZIONAMENTO DEL VISUALIZZATORE
Visual studio riconosce e permette l'utilizzo di alcuni tipi di file. L'estensione `.3dm` non rientra nella categoria perciò è importante ricordarsi di includere quest'ultima nella classe `Program.cs` le seguenti righe di codice:
```c#
var provider = new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider();
provider.Mappings[".3dm"] = "model"; // aggiungere l'estensione desiderata e il suo tipo
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = provider
});
```
inoltre ma aggiunta la configurazione per distribuire file 3dm dalla cartella appositamente prevista (ed esterna al programma epr "sopravvivere" agli update dello stesso)
```c#
string path3dm = configuration.GetValue<string>("ServerConf:path3dm") ?? configuration.GetValue<string>("OptConf:path3dm") ?? "";
if (!string.IsNullOrEmpty(path3dm))
{
// verifico esista folder disegni
if (Directory.Exists(path3dm))
{
// gestione cartella x PDF
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(path3dm),
RequestPath = "/3dm",
ContentTypeProvider = provider
});
}
}
```
## 2️⃣ Setup helper per la comunicazione
Nella cartella <b>lib</b> dovrebbe trovarsi il file `draw_call.js`. Questo sarà il file che farà da tramite tra chi gestisce il visualizzatore ( `WebGl` ) e chi mostrerà il visualizzatore ( `WebGlViewer` )
Il file conterrà le seguenti righe di codice :
```javascript
import { webgl_original } from './webgl_draw.js';
const WGL = new webgl_original();
const infoDiv = document.getElementById( "infoDiv") ;
const doorDiv = document.getElementById( "DoorRender") ;
const cubeDiv = document.getElementById( "Ref1Render") ;
infoDiv.style.display = "none";
var isAnimated = true;
var isRotating = true;
var showQuote = true;
var showGrid = true;
let options ={
modelPath: "https://iis01.egalware.com/Test3D/THREEJS_DOORS/Door_models",
fName: getUrlParameter("src")
}
// init controllo
WGL.initcall(options);
```
In questo caso sono presenti due funzioni :
- `initcall` permette di avviare i calcoli che permettono il render del visualizzatore 3D. I parametri richiesti :
- modelPath: path da dove vengono restituiti i file 3dm (da configurare nel program.cs come sopra);
- fName: nome del file ( con estensione `.3dm` ) del quale effettuare il render.
<br />
> **N.B.:** E' fondamentale caricare i propri modelli da visualizzare nella cartella sopra definita in program.cs.
>
## 3️⃣​ Aggiungere i riferimenti ai file `.js`
Per far si che il codice scritto nel file di base della libreria e nel file **helper** è importante aggiungere le seguenti righe alla pagina
`Pages/_layout.cshtml` :
```html
<script src="~/lib/node_modules/webgl-door-visualizer/webgl_draw.js" type="module"></script>
<script src="~/lib/node_modules/webgl-door-visualizer/draw_call.js"></script>
```
Di seguito il risultato di come si presenterà la pagina :
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="test.styles.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
@RenderBody()
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="~/lib/WebGl/draw/webgl_draw.js" type="module"></script>
<script src="~/lib/WebGl/draw/webgl_helper.js" type="module"></script>
<script src="_framework/blazor.server.js"></script>
</body>
</html>
```
## 4️⃣ Setup componente blazor per il render
Successivamente creiamo un nuovo componente razor nella cartelle delle pagine `Pages/WebGlViewer`.
Nella nuova pagina inserire le seguenti righe di codice che permetteranno di effettuare il render del visualizzatore.
```html
@inject IJSRuntime JSRuntime
@page "/WebGlViewer"
<div class="d-flex justify-content-between bg-dark bg-opacity-75">
<div class="p-2">
<div class="btn-group" role="group" aria-label="Mode">
<button id="btnOrto" class="btn btn-lg btn-light" onclick="setOrtho()" title="Ortho/ISO View"><i class="fas fa-cube"></i></button>
<button id="btnPers" class="btn btn-lg btn-secondary" onclick="setPersp()" title="Perspective View"><i class="fab fa-unity"></i></button>
</div>
<div class="btn-group" role="group" aria-label="Animation">
<button id="btnRotate" class="btn btn-lg btn-light" onclick="toggleRotate()" title="Toggle Rotate"><i class="fas fa-globe"></i></button>
<button id="btnQuote" class="btn btn-lg btn-light" onclick="toggleQuote()" title="Show Quotation"><i class="fas fa-ruler"></i></button>
<button id="btnGrid" class="btn btn-lg btn-light" onclick="toggleGrid()" title="Toggle Grid"><i class="fas fa-border-all"></i></button>
</div>
</div>
<div id ="divMenu2" class="p-2">
<div>
<button id="btnHelp" class="btn btn-lg btn-light" onclick="toggleHelp()" title="Hide/Show Menu"><i class="fas fa-question"></i></button>
<div class="btn-group" role="group" aria-label="Animation">
<button id="btnPause" class="btn btn-lg btn-secondary" onclick="toggleAnim()" title="Freeze model"><i class="fas fa-pause"></i></button>
<button id="btnPlay" class="btn btn-lg btn-light" onclick="toggleAnim()" title="Animation Active"><i class="fas fa-play"></i></button>
</div>
<button id="btnReset" class="btn btn-lg btn-secondary" onclick="resetCamera()" title="Reset"><i class="fas fa-sync-alt"></i></button>
</div>
<div id = "infoDiv">
<ul class="list-group list-group-sm small" style="font-size: 0.75em;">
<li class="list-group-item p-1 active text-start">
<b>Camera settings</b>
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<b>Zoom</b> Wheel-Scroll
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<b>Pan</b> Drag Mouse-Wheel
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<b>Rotate</b> CTRL + Drag Mouse-Wheel
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Iso / Ortho</b></div>
<div>
<i class="fas fa-cube"></i> | key : <b>O</b>
</div>
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Perspective</b></div>
<div>
<i class="fab fa-unity"></i> | key : <b>P</b>
</div>
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>AutoRotate</b></div>
<div>
<i class="fas fa-globe"></i> | key : <b>R</b>
</div>
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Quotes</b></div>
<div>
<i class="fas fa-ruler"></i> | key : <b>Q</b>
</div>
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Grid</b></div>
<div>
<i class="fas fa-border-all"></i> | key : <b>G</b>
</div>
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Reset</b></div>
<div>
<i class="fas fa-sync-alt"></i> | key: <b>SpaceBar</b>
</div>
</li>
<li class="list-group-item p-1 d-flex justify-content-between">
<div><b>Menu</b></div>
<div>
<i class="fas fa-question"></i> | key : <b>H</b>
</div>
</li>
</ul>
</div>
</div>
</div>
<div id="divLogo" class="bg-dark bg-opacity-50 bg-gradient p-1 small text-light text-center">
<img class="img-fluid" src ="Images/LogoEgw.png" height="32" />
<small>EgalWare</small>
</div>
<div id = "DoorRender"></div>
<div id = "RefRender"></div>
<div id = "Ref1Render"></div>
<div class="fixed-bottom small">
<div class="d-flex justify-content-between bg-dark text-light">
<div class="px-2">
WebDoor 3D
</div>
<div class="px-2">
Egalware | <a class="text-light text-decoration-none" href="https://www.egalware.com/" target="_blank"><img class="img-fluid" width="16" src="images/LogoEgw.png" /></a>
</div>
</div>
</div>
```
`@inject IJSRuntime JSRuntime` permette di usufruire del servizio che si occupa di eseguire chiamate a funzioni javascript direttamente dal codice c#
## 5️⃣​ Setup della chiamata alla funzione di render
... probabilmente non necessario con secondo modulo...
Nella pagina `Pages/WebGlViewer` aggiungere il seguente codice che, una folta effettuato il render della pagina procederà al disegno del visualizzatore.
```c#
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await Task.Delay(1);
if (firstRender)
{
var options = new
{
dimX = 960,
dimY = 540,
fileName = "Cubo.3mf",
_showCalcGrid = false
};
await JSRuntime.InvokeVoidAsync("setup", options);
}
}
}
```
Binary file not shown.
+115
View File
@@ -0,0 +1,115 @@
# Visualizzatore 3D Additive (Vue.js)
- [Visualizzatore 3D Additive (Vue.js)](#visualizzatore-3d-additive-vuejs)
- [0️⃣ Prerequisiti](#0️⃣-prerequisiti)
- [1️⃣ Creare un'applicazione Vue.js](#1️⃣-creare-unapplicazione-vuejs)
- [2️⃣ Includere la libreria nel progetto](#2️⃣-includere-la-libreria-nel-progetto)
- [3️⃣ Setup del componente vue](#3️⃣-setup-del-componente-vue)
- [4️⃣ Setup script per richiamare il codice di render](#4️⃣-setup-script-per-richiamare-il-codice-di-render)
- [5️⃣ Risultato finale](#5️⃣-risultato-finale)
- [6️⃣ Ulteriori funzioni](#6️⃣-ulteriori-funzioni)
## 0️⃣ Prerequisiti
- Node.js installato
- file conf x accesso ai nostri repo nexus in cartella utente (.npmrc contenuto in IcarusView)
## 1️⃣ Creare un'applicazione Vue.js
Il primo passo è creare l'applicazione. Aprire il terminale e navigare fino alla directory nella quale si vuole operare e lanciare il comando:
```sh
> npm create vue@latest
```
Questo comando installerà ed eseguirà `create-vue`, lo strumento ufficiale per eseguire lo scaffolding del progetto Vue.
```ps
Project name: ... Web3Dviewer
Package name: ... web3dviewer
Add TypeScript? ... No / Yes
Add JSX Support? ... No / Yes
Add Vue Router for Single Page Application development? ... No / Yes
Add Pinia for state management? ... No / Yes
Add Vitest for Unit Testing? ... No / Yes
Add an End-to-End Testing Solution? » No
Add ESLint for code quality? ... No / Yes
Scaffolding project in .\Web3Dviewer...
```
> **N.B.:** il nome `Web3Dviewer` è solo per esempio, si può inserire qualsiasi nome progetto si voglia.
>
Una volta creato il progetto, segui le istruzioni per installare le dipendenze e avviare il server di sviluppo:
```sh
> cd Web3Dviewer
> npm install
> npm run dev
```
In questo modo ora abbiamo un'applicazione web funzionante.
## 2️⃣ Includere la libreria nel progetto
Per includere la libreria nel progetto è necessario copiare la cartella fornita `WebGl` ed incollarla all'interno della cartella `Web3Dviewer/src/`.
![Alt text](image-3.png)
## 3️⃣ Setup del componente vue
Usando il componente di esempio `App.vue` eliminare tutto il contenuto e sostituirlo con il seguente codice:
```html
<template>
<main>
<div id = "WebGL-3mfExport">
</div>
</main>
</template>
```
Che permetterà di contenere il visualizzatore.
## 4️⃣ Setup script per richiamare il codice di render
Nella pagina `index.html` è necessario aggiungere il seguente codice per poter richiamare le funzioni della libreria:
```javascript
<script type="module">
import { webgl_original } from './src/WebGl/draw/webgl_drawVue.js';
const WGL = new webgl_original();
let options = {
_dimX : 960,
_dimY: 540,
_fileName: "Cubo.3mf",
_showCalcGrid: false
}
WGL.initcall(options);
</script>
<script src="./src/WebGl/draw/webgl_drawVue.js" type="module"></script>
```
> La variabile `_showCalcGrid` definisce il tipo di griglia da mostrare (Infinita o Calcolata).
## 5️⃣ Risultato finale
![Gif che mostra il risultato finale](chrome_2023-09-19_08-50-36.gif)
## 6️⃣ Ulteriori funzioni
La libreria presenta ulteriori funzioni quali:
- `.refreshCall(nStart, nEnd)`: permette di decidere quali layer dell'oggetto mostrare.
- `.resetCamera()`: gestisce il reset della camera alla posizione iniziale.
- `.setCamerType()`: permette di cambiare il tipo di camera tra:
- Prospettica
- ortografica
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

+229 -9
View File
@@ -1,20 +1,240 @@
import { webgl_original } from './webgl_draw.js';
import { webgl_original } from "./webgl_draw.js";
const WGL = new webgl_original();
const infoDiv = document.getElementById( "infoDiv") ;
const doorDiv = document.getElementById( "DoorRender") ;
const cubeDiv = document.getElementById( "Ref1Render") ;
infoDiv.style.display = "none";
var isAnimated = true;
var isRotating = true;
var showQuote = true;
var showGrid = true;
let options ={
modelPath: 'https://iis01.egalware.com/Test3D/THREEJS_DOORS/Door_models',
fName: getUrlParameter('src')
modelPath: "https://iis01.egalware.com/Test3D/THREEJS_DOORS/Door_models",
fName: getUrlParameter("src")
}
// init controllo
WGL.initcall(options);
// ---------------------------------------------------
// Funzioni pubbliche
// ---------------------------------------------------
window.toggleAnim = () =>
{
isAnimated = !isAnimated;
fixAnimate(true);
}
// reset camera
window.resetCamera = () =>
{
console.log("Reset Camera");
document.getElementById("btnReset").className = "btn btn-lg btn-light";
isAnimated = true;
// isRotating = true;
fixAnimate(true);
// fixBtnRotate();
// WGL.toggleRotation();
WGL.resetCamera();
var millisecondsToWait = 500;
setTimeout(function() {
document.getElementById("btnReset").className = "btn btn-lg btn-secondary";
}, millisecondsToWait);
}
// set camera persp
window.setOrtho = () =>
{
console.log("Set Camera ISO/ORTHO");
document.getElementById("btnOrto").className = "btn btn-lg btn-light";
document.getElementById("btnPers").className = "btn btn-lg btn-secondary";
WGL.setCameraOrtho();
}
// reset camera persp
window.setPersp = () =>
{
console.log("Set Camera Perspective");
document.getElementById("btnOrto").className = "btn btn-lg btn-secondary";
document.getElementById("btnPers").className = "btn btn-lg btn-light";
WGL.setCameraPersp();
}
// toggle griglia
window.toggleGrid = () =>
{
console.log("Toggle Grid");
showGrid = !showGrid;
if(showGrid)
{
document.getElementById("btnGrid").className = "btn btn-lg btn-light";
}
else{
document.getElementById("btnGrid").className = "btn btn-lg btn-secondary";
}
WGL.toggleGrid();
}
// toggle quotatura
window.toggleHelp = () =>
{
console.log("Toggle Menu");
toggleMenu();
}
// toggle quotatura
window.toggleQuote = () =>
{
console.log("Toggle Quote");
showQuote = !showQuote;
if(showQuote)
{
document.getElementById("btnQuote").className = "btn btn-lg btn-light";
}
else{
document.getElementById("btnQuote").className = "btn btn-lg btn-secondary";
}
WGL.toggleQuotes();
}
// toggle rotazione
window.toggleRotate = () =>
{
console.log("Toggle Rotate");
isRotating = !isRotating;
fixBtnRotate();
WGL.toggleRotation();
}
// ---------------------------------------------------
// Funzioni private
// ---------------------------------------------------
// Reading URL parameters -------------------------------------------------------------------------
function getUrlParameter( name) {
// get query string from URL
const queryString = window.location.search ;
const queryString = window.location.search ;
// create URLSearchParams object from query string
const urlParams = new URLSearchParams( queryString) ;
const urlParams = new URLSearchParams( queryString) ;
// get parameter value by name
return urlParams.get( name) ;
}
return urlParams.get( name) ;
}
WGL.initcall(options);
function toggleMenu()
{
console.log("Toggle Menu Camera");
if ( infoDiv.style.display == "none")
infoDiv.style.display = "block" ;
else
infoDiv.style.display = "none";
}
function fixAnimate(setRotate)
{
if( isAnimated )
{
document.getElementById("btnPlay").className = "btn btn-lg btn-light";
document.getElementById("btnPause").className = "btn btn-lg btn-secondary";
if(setRotate)
isRotating = true;
fixBtnRotate();
WGL.setRotate(isRotating);
WGL.doAnimate();
}
else
{
document.getElementById("btnPlay").className = "btn btn-lg btn-secondary";
document.getElementById("btnPause").className = "btn btn-lg btn-light";
if(setRotate)
isRotating = false;
fixBtnRotate();
WGL.setRotate(isRotating);
WGL.doFreeze();
}
}
function fixBtnRotate()
{
var cssClass = "btn btn-lg btn-secondary";
if(isRotating)
{
cssClass = "btn btn-lg btn-light";
}
document.getElementById("btnRotate").className = cssClass;
}
function onKeyPress( event) {
switch (event.key.toLowerCase() ){
case " ":
resetCamera();
break;
case "a":
toggleAnim();
break;
case "h":
toggleMenu();
break;
case "g":
toggleGrid();
break;
case "o":
setOrtho();
break;
case "p":
setPersp();
break;
case "q":
toggleQuote();
break;
case "r":
toggleRotate();
break;
}
}
function checkButton(event)
{
switch(event.button){
case 0:
// salto!
break;
default:
reAnimate();
break;
}
}
function reAnimate()
{
if( !isAnimated )
{
isAnimated = true;
fixAnimate(false);
}
}
function reAnimateRotate()
{
if( !isAnimated )
{
isAnimated = true;
fixAnimate(true);
}
}
// Event Listner -------------------------------------------------------------------
// KEY
document.addEventListener( "keypress", onKeyPress) ;
doorDiv.addEventListener( 'pointerup', checkButton );
doorDiv.addEventListener( 'touchstart', reAnimate );
// doorDiv.addEventListener( 'touchend', reAnimate );
// doorDiv.addEventListener( 'touchcancel', reAnimate );
doorDiv.addEventListener( 'touchmove', reAnimateRotate );
doorDiv.addEventListener( 'click', toggleAnim );
@@ -0,0 +1,179 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Stats = factory());
}(this, (function () { 'use strict';
/**
* @author mrdoob / http://mrdoob.com/
*/
var Stats = function () {
var mode = 0;
var container = document.createElement( 'div' );
container.style.cssText = 'position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000';
container.addEventListener( 'click', function ( event ) {
event.preventDefault();
showPanel( ++ mode % container.children.length );
}, false );
//
function addPanel( panel ) {
container.appendChild( panel.dom );
return panel;
}
function showPanel( id ) {
for ( var i = 0; i < container.children.length; i ++ ) {
container.children[ i ].style.display = i === id ? 'block' : 'none';
}
mode = id;
}
//
var beginTime = ( performance || Date ).now(), prevTime = beginTime, frames = 0;
var fpsPanel = addPanel( new Stats.Panel( 'FPS', '#0ff', '#002' ) );
var msPanel = addPanel( new Stats.Panel( 'MS', '#0f0', '#020' ) );
if ( self.performance && self.performance.memory ) {
var memPanel = addPanel( new Stats.Panel( 'MB', '#f08', '#201' ) );
}
showPanel( 0 );
return {
REVISION: 16,
dom: container,
addPanel: addPanel,
showPanel: showPanel,
begin: function () {
beginTime = ( performance || Date ).now();
},
end: function () {
frames ++;
var time = ( performance || Date ).now();
msPanel.update( time - beginTime, 200 );
if ( time >= prevTime + 1000 ) {
fpsPanel.update( ( frames * 1000 ) / ( time - prevTime ), 100 );
prevTime = time;
frames = 0;
if ( memPanel ) {
var memory = performance.memory;
memPanel.update( memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576 );
}
}
return time;
},
update: function () {
beginTime = this.end();
},
// Backwards Compatibility
domElement: container,
setMode: showPanel
};
};
Stats.Panel = function ( name, fg, bg ) {
var min = Infinity, max = 0, round = Math.round;
var PR = round( window.devicePixelRatio || 1 );
var WIDTH = 80 * PR, HEIGHT = 48 * PR,
TEXT_X = 3 * PR, TEXT_Y = 2 * PR,
GRAPH_X = 3 * PR, GRAPH_Y = 15 * PR,
GRAPH_WIDTH = 74 * PR, GRAPH_HEIGHT = 30 * PR;
var canvas = document.createElement( 'canvas' );
canvas.width = WIDTH;
canvas.height = HEIGHT;
canvas.style.cssText = 'width:80px;height:48px';
var context = canvas.getContext( '2d' );
context.font = 'bold ' + ( 9 * PR ) + 'px Helvetica,Arial,sans-serif';
context.textBaseline = 'top';
context.fillStyle = bg;
context.fillRect( 0, 0, WIDTH, HEIGHT );
context.fillStyle = fg;
context.fillText( name, TEXT_X, TEXT_Y );
context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT );
context.fillStyle = bg;
context.globalAlpha = 0.9;
context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT );
return {
dom: canvas,
update: function ( value, maxValue ) {
min = Math.min( min, value );
max = Math.max( max, value );
context.fillStyle = bg;
context.globalAlpha = 1;
context.fillRect( 0, 0, WIDTH, GRAPH_Y );
context.fillStyle = fg;
context.fillText( round( value ) + ' ' + name + ' (' + round( min ) + '-' + round( max ) + ')', TEXT_X, TEXT_Y );
context.drawImage( canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT );
context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT );
context.fillStyle = bg;
context.globalAlpha = 0.9;
context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round( ( 1 - ( value / maxValue ) ) * GRAPH_HEIGHT ) );
}
};
};
return Stats;
})));
+210 -105
View File
@@ -1,11 +1,12 @@
// importing
import * as THREE from './three.module.js' ;
// import Stats from './jsm/libs/stats.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { Rhino3dmLoader} from './jsm/loaders/3DMLoader.js' ;
import ViewCubeControls from './custom/cubeControls.js';
import { getStaticRef, updateRef } from './custom/refControls.js' ;
// import { getStaticRef, updateRef } from './custom/refControls.js' ;
// VARIABILI DI CONTROLLO
// COSTANTI/VARIABILI DI CONTROLLO
const EPS_SMALL = 0.001 ;
const GRID_GROUP_NAME = 'gridGroup' ;
const FRAME_GROUP_NAME = 'frameGroup' ;
@@ -15,23 +16,34 @@ const DIMENSION_GROUP_NAME = 'dimGroup' ;
const DIMENSION_DISCRIMINANT_NAME = 'dim_' ;
const GENERAL_ENTITY_GROUP_NAME = 'generalGroup' ;
const START_CAMERA_POSITION = ( new THREE.Vector3( -0.3994, 0.6339, 0.66223)).normalize() ;
var SCENE_BACKGROUND_COLOR = new THREE.Color( 0x808080) ;
const _changeEvent = { type: 'change' };
const _startEvent = { type: 'start' };
const _endEvent = { type: 'end' };
const clock = new THREE.Clock();
const fpsTgtHigh = 1 / 60; // Target 60 FPS MAX
const fpsTgtLow = 1 / 6; // Target 6 FPS low
// // statistiche fps
// const stats = new Stats();
// variabili
var SCENE_BACKGROUND_COLOR = new THREE.Color( 0x87a7ad) ;
var CAMERA_TYPE = CAMERA_ORTHO ;
var SHOW_DIMENSION = true ;
var GRID_MAIN_COLOR = new THREE.Color( 0x000000) ;
var GRID_SECOND_COLOR = new THREE.Color( 0xcccccc) ;
var GRID_SECOND_COLOR = new THREE.Color( 0x363636) ;
var PATH = './Door_models' ;
var FILE_NAME = 'Demo.3dm'
var CTRL_DOWN = false ;
var targetTimeStep = fpsTgtHigh;
// ref global variables ---------
var scene_ref ; var renderer_ref ; var camera_ref ; var group_ref ; var cube_ref ;
var scene_ref1 ; var renderer_ref1 ; var camera_ref1 ; var group_ref1 ; var frame_ref1 ;
// var scene_ref1 ; var renderer_ref1 ; var camera_ref1 ; var group_ref1 ; var frame_ref1 ;
// shared variables
/* Box3d of the door ------------ */
var m_box ; var m_size ; var m_center ; // set in setCameraPosition(), used in setGrid(), setFrame()
/* ------------------------------ */
var freezed = false;
// costanti globali
// scene
@@ -49,6 +61,10 @@ renderer.setPixelRatio( 2 * window.devicePixelRatio) ;
document.getElementById( 'DoorRender').appendChild( renderer.domElement) ;
renderer.shadowMap.enabled = true ;
// // aggiunta panel statistiche
// stats.showPanel(0) // 0: fps, 1: ms, 2: mb, 3+: custom
// document.body.appendChild(stats.dom)
// light
const ambientLight = new THREE.AmbientLight( 0xffffff, 2.5) ; // color, intensity
scene.add( ambientLight) ;
@@ -67,8 +83,16 @@ const gridGroup = new THREE.Group() ;
const frameGroup = new THREE.Group() ;
//init();
/*
* Oggetto principale gestione WebGL Door visualizer
*/
class webgl_original {
/**
* Metodo Init con visualizzazzione dati
* @param {string} modelPath Percorso base recupero modello 3dm
* @param {string} fName Nome del modello 3dm da visualizzare
*/
async initcall({ modelPath, fName}) {
PATH = modelPath;
FILE_NAME = fName;
@@ -82,6 +106,95 @@ class webgl_original {
let timeElapsed = endTime - startTime;
console.log('init done in : ' + timeElapsed);
}
async doFreeze()
{
freezed = true;
}
async doAnimate()
{
freezed = false;
// if(freezed)
// {
// freezed = false;
// await animate();
// }
}
/**
* reset posizione camera
*/
resetCamera()
{
myResetCamera();
}
/**
* imposta vista isometrica/ortografica
*/
setCameraOrtho()
{
mySetCameraOrtho()
}
/**
* imposta vista prospettica
*/
setCameraPersp()
{
mySetCameraPersp()
}
/**
* toggle visualizzazione cubo
*/
toggleCube()
{
myToggleCubeVisibility();
}
// /**
// * toggle visualizzazione frame assi
// */
// toggleFrame()
// {
// myToggleFrameVisibility();
// }
/**
* toggle visualizzazione griglia
*/
toggleGrid()
{
myToggleGridVisibility();
}
/**
* toggle visualizzazione quotature
*/
toggleQuotes()
{
myToggleQuote()
}
/**
* toggle rotazione
*/
toggleRotation()
{
myToggleRotation()
}
/**
* Imposta rotazione
* @param {boolean} isRotating
*/
setRotate(isRotating)
{
mySetRotation(isRotating);
}
}
export { webgl_original }
@@ -90,12 +203,31 @@ export { webgl_original }
// rendering
function animate() {
requestAnimationFrame( animate) ;
const elapsedTime = clock.getElapsedTime();
targetTimeStep = fpsTgtHigh;
if (freezed)
{
targetTimeStep = fpsTgtLow;
// Update only if enough time has passed for target FPS
if (elapsedTime < targetTimeStep)
return;
}
// if (freezed)
// {
// console.log(freezed);
// return;
// }
renderer.render( scene, controls.object) ;
controls.update() ;
cube_ref.update( controls) ;
renderer_ref.render( scene_ref, camera_ref) ;
updateRef( frame_ref1, camera_ref1, controls) ;
renderer_ref1.render( scene_ref1, camera_ref1) ;
// updateRef( frame_ref1, camera_ref1, controls) ;
// renderer_ref1.render( scene_ref1, camera_ref1) ;
clock.start();
}
function readDoor() {
@@ -105,22 +237,22 @@ function readDoor() {
// removing shading from colors and adjusting z-fighting with lines ( organizing groups entities )
for ( let i = 0 ; i < object.children.length ; ++ i)
setOpenGLRenderProperties( object.children[i], dimensionGroup, general_entity_Group) ;
// adding groups to scene
// adding groups to scene
scene.add( dimensionGroup) ;
scene.add( general_entity_Group) ;
// setting Box3d of the door
// setting Box3d of the door
set3dBox( object) ;
// setting camera position
// setting camera position
setCameraPosition() ;
// setting grid
// setting grid
setGrid() ;
// setting frame
// setting frame
setFrame() ;
// static cube
// static cube
setStaticCube() ;
// static frame
setStaticFrame() ;
// render loop
// // static frame
// setStaticFrame() ;
// render loop
animate() ;
}) ;
}
@@ -258,6 +390,8 @@ function setStaticCube() {
// renderer
renderer_ref = new THREE.WebGLRenderer({ antialias: true, alpha : true, transparent : true}) ;
renderer_ref.setSize( divContainer.clientWidth, divContainer.clientHeight) ;
// valutare abbassamento risoluzione
// renderer_ref.setPixelRatio( 1 * window.devicePixelRatio) ;
renderer_ref.setPixelRatio( 2 * window.devicePixelRatio) ;
divContainer.appendChild( renderer_ref.domElement) ;
// scene
@@ -288,38 +422,30 @@ function setStaticCube() {
cube_ref._colorCube() ;
}
function setStaticFrame() {
// container of the cube
const divContainer = document.getElementById( 'Ref1Render') ;
// renderer
renderer_ref1 = new THREE.WebGLRenderer({ antialias: true, alpha : true, transparent : true}) ;
renderer_ref1.setSize( divContainer.clientWidth, divContainer.clientHeight) ;
renderer_ref1.setPixelRatio( 2 * window.devicePixelRatio) ;
divContainer.appendChild( renderer_ref1.domElement) ;
// scene
scene_ref1 = new THREE.Scene() ;
if ( CAMERA_TYPE == CAMERA_ORTHO)
camera_ref1 = new THREE.OrthographicCamera( - divContainer.clientWidth / 5, divContainer.clientWidth / 5,
divContainer.clientHeight / 5, - divContainer.clientHeight / 5, 0.1, 1000) ;
else
camera_ref1 = new THREE.PerspectiveCamera( 50, 1, 0.1, 1000) ;
// setting standard camera posizion and lookAt -> made according cube dimension
camera_ref1.position.set( 0, 0, 70) ;
camera_ref1.lookAt( 0, 0, 0) ;
// creating the cube object and adding it to the scene
frame_ref1 = getStaticRef( 1, 25) ;
scene_ref1.add( frame_ref1) ;
}
// function setStaticFrame() {
// // container of the cube
// const divContainer = document.getElementById( 'Ref1Render') ;
// // renderer
// renderer_ref1 = new THREE.WebGLRenderer({ antialias: true, alpha : true, transparent : true}) ;
// renderer_ref1.setSize( divContainer.clientWidth, divContainer.clientHeight) ;
// renderer_ref1.setPixelRatio( 2 * window.devicePixelRatio) ;
// divContainer.appendChild( renderer_ref1.domElement) ;
// // scene
// scene_ref1 = new THREE.Scene() ;
// if ( CAMERA_TYPE == CAMERA_ORTHO)
// camera_ref1 = new THREE.OrthographicCamera( - divContainer.clientWidth / 5, divContainer.clientWidth / 5,
// divContainer.clientHeight / 5, - divContainer.clientHeight / 5, 0.1, 1000) ;
// else
// camera_ref1 = new THREE.PerspectiveCamera( 50, 1, 0.1, 1000) ;
// // setting standard camera posizion and lookAt -> made according cube dimension
// camera_ref1.position.set( 0, 0, 70) ;
// camera_ref1.lookAt( 0, 0, 0) ;
// // creating the cube object and adding it to the scene
// frame_ref1 = getStaticRef( 1, 25) ;
// scene_ref1.add( frame_ref1) ;
// }
function ToggleRotation() {
controls.autoRotate = ( ! controls.autoRotate) ;
}
function toggleDimensionVisibility() {
dimensionGroup.visible = ! dimensionGroup.visible ;
}
function toggleCubeVisibility() {
function myToggleCubeVisibility() {
var cubeContainer = document.getElementById( 'RefRender') ;
if ( cubeContainer.style.display === "none")
cubeContainer.style.display = "block";
@@ -327,67 +453,46 @@ function toggleCubeVisibility() {
cubeContainer.style.display = "none";
}
function toggleFrameVisibility() {
var frameContainer = document.getElementById( 'Ref1Render') ;
if ( frameContainer.style.display === "none")
frameContainer.style.display = "block";
else
frameContainer.style.display = "none";
}
// function myToggleFrameVisibility() {
// var frameContainer = document.getElementById( 'Ref1Render') ;
// if ( frameContainer.style.display === "none")
// frameContainer.style.display = "block";
// else
// frameContainer.style.display = "none";
// }
function toggleGridVisibility() {
function myToggleGridVisibility() {
gridGroup.visible = ! gridGroup.visible ;
frameGroup.visible = ! frameGroup.visible ;
}
// Event Listner -------------------------------------------------------------------
// KEY
document.addEventListener( "keypress", function( event) {
if ( event.key.toLowerCase() === "r")
ToggleRotation() ;
else if ( event.key.toLowerCase() === 'p') {
if ( CAMERA_TYPE == CAMERA_PERSP)
return ;
controls.object = perspCamera.clone() ;
CAMERA_TYPE = CAMERA_PERSP ;
setCameraPosition() ;
}
else if ( event.key.toLowerCase() === 'o') {
if ( CAMERA_TYPE == CAMERA_ORTHO)
return ;
controls.object = ortoCamera.clone() ;
CAMERA_TYPE = CAMERA_ORTHO ;
setCameraPosition() ;
}
else if ( event.key.toLowerCase() === 'd')
toggleDimensionVisibility() ;
else if ( event.key.toLowerCase() === ' ')
setCameraPosition() ;
else if ( event.key.toLowerCase() === 'c')
toggleCubeVisibility() ;
else if ( event.key.toLowerCase() === 'f')
toggleFrameVisibility() ;
else if ( event.key.toLowerCase() === 'g')
toggleGridVisibility() ;
}) ;
function mySetRotation(isRotating) {
controls.autoRotate = isRotating ;
}
function myToggleRotation() {
controls.autoRotate = ( ! controls.autoRotate) ;
}
// Elements
var helpButton = document.getElementById( "helpButton") ;
var infoDiv = document.getElementById( "infoDiv") ;
infoDiv.style.display = "none";
helpButton.addEventListener( "click", function() {
if ( infoDiv.style.display === "none")
infoDiv.style.display = "block" ;
else
infoDiv.style.display = "none";
}) ;
function myToggleQuote() {
dimensionGroup.visible = ! dimensionGroup.visible ;
}
// // Reading URL parameters -------------------------------------------------------------------------
// function getUrlParameter( name) {
// // get query string from URL
// const queryString = window.location.search ;
// // create URLSearchParams object from query string
// const urlParams = new URLSearchParams( queryString) ;
// // get parameter value by name
// return urlParams.get( name) ;
// }
function mySetCameraOrtho() {
if ( CAMERA_TYPE == CAMERA_ORTHO)
return ;
controls.object = ortoCamera.clone() ;
CAMERA_TYPE = CAMERA_ORTHO ;
setCameraPosition() ;
}
function mySetCameraPersp() {
if ( CAMERA_TYPE == CAMERA_PERSP)
return ;
controls.object = perspCamera.clone() ;
CAMERA_TYPE = CAMERA_PERSP ;
setCameraPosition() ;
}
function myResetCamera() {
setCameraPosition() ;
}
+21 -42
View File
@@ -14,59 +14,38 @@ canvas {
#divMenu {
position: fixed ;
top: 10px ;
right: 10px ;
top: 0.5rem;
right: 0.2rem;
background-color: transparent ;
width: 275px ;
}
.container {
width: 100% ;
height: auto ;
margin-bottom: 10px ;
}
.container::after {
content: "" ;
display: table ;
clear: both ;
}
.container img {
width: 100% ;
height: auto ;
display: block ;
}
#helpButton {
text-decoration: underline ;
float: right ;
height: auto ;
#divLogo{
position: fixed ;
top: 4rem;
right: 0.5rem;
height: 5rem;
width: 4rem;
font-size: 0.8rem;
}
#infoDiv {
width: 100% ;
height: auto ;
color: white ;
position: fixed ;
top: 3.75rem;
right: 0.5rem;
z-index: 10;
width: 15rem;
height: auto;
/* color: white ; */
background-color: transparent ;
font-size: 0.9em ;
}
#RefRender {
position: fixed ;
width: 200px ;
height: 200px ;
bottom: 10px ;
right: 10px ;
/*border: 1px solid black ;*/
}
#Ref1Render {
position: fixed ;
width: 150px ;
height: 150px ;
bottom: 10px ;
left: 10px ;
width: 8rem ;
height: 8rem ;
bottom: 0.5rem ;
left: 0.5rem ;
background-color: transparent ;
/*border: 1px solid black ;*/
}