From 0b33f978a895067642bc5488ee9cc4e894693111 Mon Sep 17 00:00:00 2001
From: Lucio Zambon <lucio.zambon@elettra.eu>
Date: Mon, 20 May 2024 02:30:35 +0000
Subject: [PATCH] Update bundle_elettra.js

---
 components/bundle_elettra.js | 1255 +++++++++++++++++++++++++++++++++-
 1 file changed, 1254 insertions(+), 1 deletion(-)

diff --git a/components/bundle_elettra.js b/components/bundle_elettra.js
index 4002ee0..884b0ac 100644
--- a/components/bundle_elettra.js
+++ b/components/bundle_elettra.js
@@ -1883,7 +1883,7 @@
 		return continer;
 	}
 	// PLC
-	export function plc_backup(param) {
+	export function plc(param) {
 		const plcObject = new THREE.Object3D();
 		const cardsObject = new THREE.Object3D();
 		
@@ -1996,4 +1996,1257 @@
 		plcObject.scale.setZ(0.7);		
 
 		return plcObject;
+	}	
+		//RV
+	export function rv(param) {
+		const width=800, height=2500, depth=800;
+		const rv = new THREE.Object3D();
+		const rv_rackObject = new THREE.Object3D();
+		const pspump_rackObject = new THREE.Object3D();
+	
+		const materialGreyDark= new THREE.MeshLambertMaterial({color: 0x9d9d9d});
+		const materialGreyMedium= new THREE.MeshLambertMaterial({color: 0x636363});
+		const materialVeryGreyDark= new THREE.MeshLambertMaterial({color: 0x242424});
+		const silvermaterial = new THREE.MeshLambertMaterial({color: 0xcfcfcf});
+		const greenmaterial = new THREE.MeshLambertMaterial({color: 0x17fc03});
+		const Darkwhitematerial = new THREE.MeshLambertMaterial({color: 0xbababa});
+		const bluematerial = new THREE.MeshLambertMaterial({color: 0x0053d9});
+		const softbluematerial = new THREE.MeshLambertMaterial({color: 0x2b7cff});
+		const screenmaterial = new THREE.MeshLambertMaterial({color: 0xdeebff});
+		const target = new THREE.MeshLambertMaterial({color: 0xfbe928});
+
+		const materialBase = new THREE.MeshLambertMaterial({color: 0x0000d0});
+		const text = param.name;
+		let group, textMesh, textGeo, materials;
+		let size = 60;
+		let textheight = 10;
+		let pos = [];
+		let rot = [];
+		const hover = 30;
+		const curveSegments = 8;
+		let font;
+		function insertText(isize, ipos, irot) {
+			group = new THREE.Group();
+			group.position.y = 100;
+			rv.add( group );
+			size = isize;
+			pos = ipos;
+			rot = irot;
+			loadFont();
+		}
+		function loadFont() {
+			const loader = new FontLoader();
+			// https://threejs.org/examples/fonts/droid_sans_bold.typeface.json
+			loader.load( './fonts/droid_sans_bold.typeface.json', function ( response ) {
+				font = response;
+				refreshText();
+			} );
+		}
+		function createText() {
+			textGeo = new TextGeometry(text, {font: font, size: size, height: textheight, curveSegments: curveSegments});
+			textGeo.computeBoundingBox();
+			const centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
+			textMesh = new THREE.Mesh(textGeo, materialBase);
+			textMesh.position.x = pos[0];
+			textMesh.position.y = pos[1];
+			textMesh.position.z = pos[2];
+			textMesh.rotation.x = rot[0];
+			textMesh.rotation.y = rot[1];
+			textMesh.rotation.z = rot[2];
+			group.add( textMesh );
+			const group2 = group.clone();
+			group2.rotateY(Math.PI);
+			group2.position.set(800, 90, 800);
+			rv.add(group2);				
+			
+		}
+		function refreshText() {
+			group.remove( textMesh );
+			if ( ! text ) return;
+			createText();
+		}
+		insertText(50, [850, 1290, 550], [0, Math.PI / 2, 0]);
+	
+		
+		
+		// rack
+		const rrgeometry = new THREE.BoxGeometry(width, height, depth);
+		const rrmesh = new THREE.Mesh(rrgeometry, softbluematerial);
+		//rrmesh.position.set( 0, 0 , -810);
+		rv_rackObject.add(rrmesh);
+		
+		//front yellow tag
+		const Ftarget = new THREE.BoxGeometry(2, 90, 600);
+		const Ftargetmesh = new THREE.Mesh(Ftarget, target);
+		Ftargetmesh.position.set( -451, 1200 , -5);
+		rv_rackObject.add(Ftargetmesh);		
+		//Rear yellow tag
+		const Rtarget = new THREE.BoxGeometry(2, 90, 600);
+		const Rtargetmesh = new THREE.Mesh(Rtarget, target);
+		Rtargetmesh.position.set( 401, 1200 , -5);
+		rv_rackObject.add(Rtargetmesh);				
+		
+		//edge lle	
+		const llegeometry = new THREE.BoxGeometry(width-750, height, depth-750);
+		const llemesh = new THREE.Mesh(llegeometry, bluematerial);
+		llemesh.position.set( -425, 0 , -365);
+		rv_rackObject.add(llemesh);
+		
+		//edge lre		
+		const lregeometry = new THREE.BoxGeometry(width-750, height, depth-750);
+		const lremesh = new THREE.Mesh(lregeometry, bluematerial);
+		lremesh.position.set( -425, 0 , 380);
+		rv_rackObject.add(lremesh);		
+
+		//edge lue		
+		const luegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const luemesh = new THREE.Mesh(luegeometry, bluematerial);
+		luemesh.position.set( -425, 1225 , 3);
+		rv_rackObject.add(luemesh);		
+
+		//edge lde		
+		const ldegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const ldemesh = new THREE.Mesh(ldegeometry, bluematerial);
+		ldemesh.position.set( -425, -1230 , 3);
+		rv_rackObject.add(ldemesh);				
+		//silverbase		
+		const drawer1geometry = new THREE.BoxGeometry(10, 2450, 750);
+		const drawer1geometrymesh = new THREE.Mesh(drawer1geometry, silvermaterial);
+		drawer1geometrymesh.position.set( -400, 0 , -10);
+		rv_rackObject.add(drawer1geometrymesh);
+		
+		//base PS ionic Pump
+		const baseionicpump = new THREE.BoxGeometry(10, 250, 300);
+		const baseionicpumpmesh = new THREE.Mesh(baseionicpump, Darkwhitematerial);
+		baseionicpumpmesh.position.set( -401, 900 , -150);
+		pspump_rackObject.add(baseionicpumpmesh);		
+
+		//sceen PS ionic Pump
+		const screenionicpump = new THREE.BoxGeometry(10, 60, 180);
+		const screenionicpumpmesh = new THREE.Mesh(screenionicpump, screenmaterial);
+		screenionicpumpmesh.position.set( -402, 950 , -150);
+		pspump_rackObject.add(screenionicpumpmesh);			
+		
+		//button ON OFF PS ionic Pump
+		const buttonionicpump = new THREE.BoxGeometry(10, 50, 30);
+		const buttonionicpumpmesh = new THREE.Mesh(buttonionicpump, materialVeryGreyDark);
+		buttonionicpumpmesh.position.set( -402, 830 , -250);
+		pspump_rackObject.add(buttonionicpumpmesh);	
+		
+		//button ON Details 
+		const I = new THREE.BoxGeometry(3, 12, 3);
+		const IMesh = new THREE.Mesh(I, Darkwhitematerial);
+		IMesh.position.set( -407, 844 , -250);
+		pspump_rackObject.add(IMesh);	
+		
+		//button OFF Details 
+		const OI1 = new THREE.CylinderGeometry(8, 8, 2, 15);
+		const OI1Mesh = new THREE.Mesh(OI1, Darkwhitematerial);
+		OI1Mesh.rotateX(Math.PI * 0.5);
+		OI1Mesh.rotateY(Math.PI * 1);
+		OI1Mesh.rotateZ(Math.PI * 0.5);
+		OI1Mesh.position.set( -407, 817 , -250);		
+		pspump_rackObject.add(OI1Mesh);		
+
+		//button OFF Details 2
+		const OI2 = new THREE.CylinderGeometry(6, 6, 2, 15);
+		const OI2Mesh = new THREE.Mesh(OI2, materialVeryGreyDark);
+		OI2Mesh.rotateX(Math.PI * 0.5);
+		OI2Mesh.rotateY(Math.PI * 1);
+		OI2Mesh.rotateZ(Math.PI * 0.5);
+		OI2Mesh.position.set( -408, 817 , -250);		
+		pspump_rackObject.add(OI2Mesh);	
+		
+		//border up
+		const borderup = new THREE.BoxGeometry(10, 2, 260);
+		const borderupmesh = new THREE.Mesh(borderup, bluematerial);
+		borderupmesh.position.set( -402, 1000 , -150);
+		pspump_rackObject.add(borderupmesh);	
+		
+		//border mid
+		const bordermid = new THREE.BoxGeometry(10, 2, 260);
+		const bordermidmesh = new THREE.Mesh(bordermid, bluematerial);
+		bordermidmesh.position.set( -402, 900 , -150);
+		pspump_rackObject.add(bordermidmesh);
+		
+		//border left
+		const borderleft = new THREE.BoxGeometry(10, 100, 2);
+		const borderleftmesh = new THREE.Mesh(borderleft, bluematerial);
+		borderleftmesh.position.set( -402, 950 , -280);
+		pspump_rackObject.add(borderleftmesh);	
+		
+		//border right
+		const borderright = new THREE.BoxGeometry(10, 100, 2);
+		const borderrightmesh = new THREE.Mesh(borderright, bluematerial);
+		borderrightmesh.position.set( -402, 950 , -20);
+		pspump_rackObject.add(borderrightmesh);		
+		
+		//button1  PS ionic Pump
+		const button1ionicpump = new THREE.BoxGeometry(10, 30, 30);
+		const button1ionicpumpmesh = new THREE.Mesh(button1ionicpump, materialGreyDark);
+		button1ionicpumpmesh.position.set( -402, 830 , -200);
+		pspump_rackObject.add(button1ionicpumpmesh);			
+		
+		//button2 up  PS ionic Pump
+		const button2ionicpump = new THREE.BoxGeometry(10, 30, 30);
+		const button2ionicpumpmesh = new THREE.Mesh(button2ionicpump, materialGreyDark);
+		button2ionicpumpmesh.position.set( -402, 860 , -160);
+		pspump_rackObject.add(button2ionicpumpmesh);
+		
+		//button3 up  PS ionic Pump
+		const button3ionicpump = new THREE.BoxGeometry(10, 30, 30);
+		const button3ionicpumpmesh = new THREE.Mesh(button3ionicpump, materialGreyDark);
+		button3ionicpumpmesh.position.set( -402, 860 , -120);
+		pspump_rackObject.add(button3ionicpumpmesh);
+		
+		//button4 up  PS ionic Pump
+		const button4ionicpump = new THREE.BoxGeometry(10, 30, 30);
+		const button4ionicpumpmesh = new THREE.Mesh(button4ionicpump, materialGreyDark);
+		button4ionicpumpmesh.position.set( -402, 860 , -80);
+		pspump_rackObject.add(button4ionicpumpmesh);
+		
+		//button5 up  PS ionic Pump
+		const button5ionicpump = new THREE.BoxGeometry(10, 30, 30);
+		const button5ionicpumpmesh = new THREE.Mesh(button5ionicpump, materialGreyDark);
+		button5ionicpumpmesh.position.set( -402, 860 , -40);
+		pspump_rackObject.add(button5ionicpumpmesh);	
+
+		rv_rackObject.add(pspump_rackObject);
+		//CLONE PS PUMP
+
+		const pump2 = pspump_rackObject.clone();
+		pump2.position.set( 0, 0 , 310);
+		rv_rackObject.add(pump2);
+		
+		const pump3 = pspump_rackObject.clone();
+		pump3.position.set( 0, -260 , 0);
+		rv_rackObject.add(pump3);	
+		
+		const pump4 = pspump_rackObject.clone();
+		pump4.position.set( 0, -260 , 310);
+		rv_rackObject.add(pump4);
+		
+		const pump5 = pspump_rackObject.clone();
+		pump5.position.set( 0, -520 , 0);
+		rv_rackObject.add(pump5);
+		
+		const pump6 = pspump_rackObject.clone();
+		pump6.position.set( 0, -520 , 310);
+		rv_rackObject.add(pump6);
+
+		if (typeof param.reverse != 'undefined') rv_rackObject.rotateY(Math.PI);
+		rv_rackObject.position.set(400, 200, 400);
+		rv.add(rv_rackObject);
+		return rv;
+	}
+
+	// rrf rack
+	export function rrf(param) {
+		const width=800, height=2500, depth=600;
+		const rrf = new THREE.Object3D();
+		const rrf_rackObject = new THREE.Object3D();
+	
+		const bluematerial = new THREE.MeshLambertMaterial({color: 0x0053d9});
+		const softbluematerial = new THREE.MeshLambertMaterial({color: 0x2b7cff});
+		const target = new THREE.MeshLambertMaterial({color: 0xfbe928});
+		const materialGreyDark= new THREE.MeshLambertMaterial({color: 0x9d9d9d});
+		const materialGreyMedium= new THREE.MeshLambertMaterial({color: 0x636363});
+		const silvermaterial = new THREE.MeshLambertMaterial({color: 0xf0f0f0});
+		const materialVeryGreyDark= new THREE.MeshLambertMaterial({color: 0x242424});		
+
+		const materialBase = new THREE.MeshLambertMaterial({color: 0x0000d0});
+		const text = param.name;
+		let group, textMesh, textGeo, materials;
+		let size = 60;
+		let textheight = 10;
+		let pos = [];
+		let rot = [];
+		const hover = 30;
+		const curveSegments = 8;
+		let font;
+		function insertText(isize, ipos, irot) {
+			group = new THREE.Group();
+			group.position.y = 100;
+			rrf.add( group );
+			size = isize;
+			pos = ipos;
+			rot = irot;
+			loadFont();
+		}
+		function loadFont() {
+			const loader = new FontLoader();
+			// https://threejs.org/examples/fonts/droid_sans_bold.typeface.json
+			loader.load( './fonts/droid_sans_bold.typeface.json', function ( response ) {
+				font = response;
+				refreshText();
+			} );
+		}
+		function createText() {
+			textGeo = new TextGeometry(text, {font: font, size: size, height: textheight, curveSegments: curveSegments});
+			textGeo.computeBoundingBox();
+			const centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
+			textMesh = new THREE.Mesh(textGeo, materialBase);
+			textMesh.position.x = pos[0];
+			textMesh.position.y = pos[1];
+			textMesh.position.z = pos[2];
+			textMesh.rotation.x = rot[0];
+			textMesh.rotation.y = rot[1];
+			textMesh.rotation.z = rot[2];
+			group.add( textMesh );
+			const group2 = group.clone();
+			group2.rotateY(Math.PI);
+			group2.position.set(800, 90, 800);
+			rrf.add(group2);				
+			
+		}
+		function refreshText() {
+			group.remove( textMesh );
+			if ( ! text ) return;
+			createText();
+		}
+		insertText(50, [850, 1290, 550], [0, Math.PI / 2, 0]);		
+		
+		
+		//rack
+		const rrgeometry = new THREE.BoxGeometry(width, height, depth);
+		const rrmesh = new THREE.Mesh(rrgeometry, silvermaterial);
+		rrmesh.position.set( 0, 0 , -10);
+		rrf_rackObject.add(rrmesh);		
+		
+		//front yellow target
+		const Ftarget = new THREE.BoxGeometry(2, 90, 500);
+		const Ftargetmesh = new THREE.Mesh(Ftarget, target);
+		Ftargetmesh.position.set( -451, 1200 , -15);
+		rrf_rackObject.add(Ftargetmesh);		
+		//Rear yellow target
+		const Rtarget = new THREE.BoxGeometry(2, 90, 500);
+		const Rtargetmesh = new THREE.Mesh(Rtarget, target);
+		Rtargetmesh.position.set( 401, 1200 , -15);
+		rrf_rackObject.add(Rtargetmesh);				
+		
+		//edge le	
+		const llegeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const llemesh = new THREE.Mesh(llegeometry, materialGreyDark);
+		llemesh.position.set( -425, 0 , -285);
+		rrf_rackObject.add(llemesh);
+		
+		//edge re		
+		const lregeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const lremesh = new THREE.Mesh(lregeometry, materialGreyDark);
+		lremesh.position.set( -425, 0 , 265);
+		rrf_rackObject.add(lremesh);		
+
+		//edge ue		
+		const luegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const luemesh = new THREE.Mesh(luegeometry, materialGreyDark);
+		luemesh.position.set( -425, 1225 , -7);
+		rrf_rackObject.add(luemesh);		
+
+		//edge de		
+		const ldegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const ldemesh = new THREE.Mesh(ldegeometry, materialGreyDark);
+		ldemesh.position.set( -425, -1230 , -7);
+		rrf_rackObject.add(ldemesh);				
+
+		
+		//drawer 1
+		const libera1geometry = new THREE.BoxGeometry(10, 200, 600);
+		const libera1geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera1geometrymesh.position.set( -400, 900 , -10);
+		rrf_rackObject.add(libera1geometrymesh);		
+		
+		//drawer 2
+		const libera2geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera2geometrymesh.position.set( -400, 600 , -10);
+		rrf_rackObject.add(libera2geometrymesh);				
+		
+		//drawer 3
+		const libera3geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera3geometrymesh.position.set( -400, 300 , -10);
+		rrf_rackObject.add(libera3geometrymesh);			
+		
+		//drawer 4
+		const libera4geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera4geometrymesh.position.set( -400, 0 , -10);
+		rrf_rackObject.add(libera4geometrymesh);			
+		
+		//drawer 5
+		const libera5geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera5geometrymesh.position.set( -400, -300 , -10);
+		rrf_rackObject.add(libera5geometrymesh);			
+		
+		//drawer 6
+		const libera6geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera6geometrymesh.position.set( -400, -600 , -10);
+		rrf_rackObject.add(libera6geometrymesh);	
+		
+		if (typeof param.reverse != 'undefined') rrf_rackObject.rotateY(Math.PI);
+		rrf_rackObject.position.set(400, 200, 400);
+		rrf.add(rrf_rackObject);
+		return rrf;
+	}
+
+
+	// PS rack
+	export function rps(param) {
+		const width=800, height=2500, depth=600;
+		const psObject = new THREE.Object3D();
+		const rps_rackObject = new THREE.Object3D();
+		const rps = new THREE.Object3D();
+
+		const materialBase = new THREE.MeshLambertMaterial({color: 0x0000b0});
+		const text = param.name;
+		let group, textMesh, textGeo, materials;
+		let size = 60;
+		let textheight = 10;
+		let pos = [];
+		let rot = [];
+		const hover = 30;
+		const curveSegments = 8;
+		let font;
+		function insertText(isize, ipos, irot) {
+			group = new THREE.Group();
+			group.position.y = 100;
+			rps.add( group );
+			size = isize;
+			pos = ipos;
+			rot = irot;
+			loadFont();
+		}
+		function loadFont() {
+			const loader = new FontLoader();
+			// https://threejs.org/examples/fonts/droid_sans_bold.typeface.json
+			loader.load( './fonts/droid_sans_bold.typeface.json', function ( response ) {
+				font = response;
+				refreshText();
+			} );
+		}
+		function createText() {
+			textGeo = new TextGeometry(text, {font: font, size: size, height: textheight, curveSegments: curveSegments});
+			textGeo.computeBoundingBox();
+			const centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
+			textMesh = new THREE.Mesh(textGeo, materialBase);
+			textMesh.position.x = pos[0];
+			textMesh.position.y = pos[1];
+			textMesh.position.z = pos[2];
+			textMesh.rotation.x = rot[0];
+			textMesh.rotation.y = rot[1];
+			textMesh.rotation.z = rot[2];
+			group.add( textMesh );
+			const group2 = group.clone();
+			group2.rotateY(Math.PI);
+			group2.position.set(800, 90, 550);
+			rps.add(group2);			
+			
+		}
+		function refreshText() {
+			group.remove( textMesh );
+			if ( ! text ) return;
+			createText();
+		}
+		insertText(50, [870, 1290, 550], [0, Math.PI / 2, 0]);
+	
+		const materialGreyDark= new THREE.MeshLambertMaterial({color: 0x9d9d9d});
+		const materialGreyMedium= new THREE.MeshLambertMaterial({color: 0x636363});
+		const materialVeryGreyDark= new THREE.MeshLambertMaterial({color: 0x242424});
+		const Darkwhitematerial = new THREE.MeshLambertMaterial({color: 0xbababa});
+		const silvermaterial = new THREE.MeshLambertMaterial({color: 0xf0f0f0});
+		const greenmaterial = new THREE.MeshLambertMaterial({color: 0x17fc03});
+		const whitematerial = new THREE.MeshLambertMaterial({color: 0xffffff});
+		const bluematerial = new THREE.MeshLambertMaterial({color: 0x0053d9});
+		const softbluematerial = new THREE.MeshLambertMaterial({color: 0x2b7cff});
+		const screenmaterial = new THREE.MeshLambertMaterial({color: 0xdeebff});
+		const target = new THREE.MeshLambertMaterial({color: 0xfbe928});
+		
+		// rack
+		const rrgeometry = new THREE.BoxGeometry(width, height, depth);
+		const rrmesh = new THREE.Mesh(rrgeometry, softbluematerial);
+		rrmesh.position.set( 0, 0 , 0);
+		rps_rackObject.add(rrmesh);		
+		
+		//edge le	
+		const llegeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const llemesh = new THREE.Mesh(llegeometry, bluematerial);
+		llemesh.position.set( -425, 0 , -285);
+		rps_rackObject.add(llemesh);
+		
+		//edge re		
+		const lregeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const lremesh = new THREE.Mesh(lregeometry, bluematerial);
+		lremesh.position.set( -425, 0 , 265);
+		rps_rackObject.add(lremesh);		
+
+		//edge ue		
+		const luegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const luemesh = new THREE.Mesh(luegeometry, bluematerial);
+		luemesh.position.set( -425, 1225 , -7);
+		rps_rackObject.add(luemesh);		
+
+		//edge de		
+		const ldegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const ldemesh = new THREE.Mesh(ldegeometry, bluematerial);
+		ldemesh.position.set( -425, -1230 , -7);
+		rps_rackObject.add(ldemesh);				
+
+		//front yellow target
+		const Ftarget = new THREE.BoxGeometry(2, 90, 600);
+		const Ftargetmesh = new THREE.Mesh(Ftarget, target);
+		Ftargetmesh.position.set( -451, 1200 , -15);
+		rps_rackObject.add(Ftargetmesh);		
+		//Rear yellow target
+		const Rtarget = new THREE.BoxGeometry(2, 90, 600);
+		const Rtargetmesh = new THREE.Mesh(Rtarget, target);
+		Rtargetmesh.position.set( 401, 1200 , -15);
+		rps_rackObject.add(Rtargetmesh);				
+	
+		// START PS base RED 
+		const basered = new THREE.BoxGeometry(10, 30, 110);
+		const baseredmesh = new THREE.Mesh(basered, silvermaterial);
+		baseredmesh.position.set( -401, 1100 , -170);
+		psObject.add(baseredmesh);
+		
+		//  PS base BLUE 
+		const baseblue = new THREE.BoxGeometry(10, 180, 110);
+		const basebluemesh = new THREE.Mesh(baseblue, Darkwhitematerial);
+		basebluemesh.position.set( -401, 995 , -170);
+		psObject.add(basebluemesh);			
+
+		//  PS base SILVER 
+		const basesilver = new THREE.BoxGeometry(10, 2450, 500);
+		const basesilvermesh = new THREE.Mesh(basesilver, materialGreyDark);
+		basesilvermesh.position.set( -400, 0 , 0);
+		rps_rackObject.add(basesilvermesh);			
+		
+		rps_rackObject.add(psObject);
+		
+		//CLONE PS 
+
+		const psA3 = psObject.clone();
+		psA3.position.set( 0, 0 , 240);
+		rps_rackObject.add(psA3);	
+		
+		const psB1 = psObject.clone();
+		psB1.position.set( 0, -220 , 0);
+		rps_rackObject.add(psB1);
+		
+     	const psB3 = psObject.clone();
+		psB3.position.set( 0, -220 , 240);
+		rps_rackObject.add(psB3);
+		
+		const psC1 = psObject.clone();
+		psC1.position.set( 0, -440 , 0);
+		rps_rackObject.add(psC1);
+
+		const psC3 = psObject.clone();
+		psC3.position.set( 0, -440 , 240);
+		rps_rackObject.add(psC3);
+		
+		const psD1 = psObject.clone();
+		psD1.position.set( 0, -660 , 0);
+		rps_rackObject.add(psD1);
+	
+		const psD3 = psObject.clone();
+		psD3.position.set( 0, -660 , 240);
+		rps_rackObject.add(psD3);	
+		
+		const psE1 = psObject.clone();
+		psE1.position.set( 0, -880 , 0);
+		rps_rackObject.add(psE1);
+		
+		
+		const psE3 = psObject.clone();
+		psE3.position.set( 0, -880 , 240);
+		rps_rackObject.add(psE3);		
+		
+		if (typeof param.reverse != 'undefined') rps_rackObject.rotateY(Math.PI);
+		rps_rackObject.position.set(400, 200, 300);
+		rps.add(rps_rackObject);	
+		return rps;
 	}
+
+	// Control rack
+	export function rc(param) {
+		const width=800, height=2500, depth=600;
+		const rc = new THREE.Object3D();
+		const rc_rackObject = new THREE.Object3D();
+		const materialBase = new THREE.MeshLambertMaterial({color: 0x0000d0});
+		const text = param.name;
+		let group, textMesh, textGeo, materials;
+		let size = 60;
+		let textheight = 10;
+		let pos = [];
+		let rot = [];
+		const hover = 30;
+		const curveSegments = 8;
+		let font;
+		function insertText(isize, ipos, irot) {
+			group = new THREE.Group();
+			group.position.y = 100;
+			rc.add( group );
+			size = isize;
+			pos = ipos;
+			rot = irot;
+			loadFont();
+		}
+		function loadFont() {
+			const loader = new FontLoader();
+			// https://threejs.org/examples/fonts/droid_sans_bold.typeface.json
+			loader.load( './fonts/droid_sans_bold.typeface.json', function ( response ) {
+				font = response;
+				refreshText();
+			} );
+		}
+		function createText() {
+			textGeo = new TextGeometry(text, {font: font, size: size, height: textheight, curveSegments: curveSegments});
+			textGeo.computeBoundingBox();
+			const centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
+			textMesh = new THREE.Mesh(textGeo, materialBase);
+			textMesh.position.x = pos[0];
+			textMesh.position.y = pos[1];
+			textMesh.position.z = pos[2];
+			textMesh.rotation.x = rot[0];
+			textMesh.rotation.y = rot[1];
+			textMesh.rotation.z = rot[2];
+			group.add( textMesh );
+			const group2 = group.clone();
+			group2.rotateY(Math.PI);
+			group2.position.set(850, 90, 550);
+			rc.add(group2);			
+			
+		}
+		function refreshText() {
+			group.remove( textMesh );
+			if ( ! text ) return;
+			createText();
+		}
+		insertText(50, [900, 1290, 500], [0, Math.PI / 2, 0]);
+	
+		const bluematerial = new THREE.MeshLambertMaterial({color: 0x0053d9});
+		const softbluematerial = new THREE.MeshLambertMaterial({color: 0x2b7cff});
+		const target = new THREE.MeshLambertMaterial({color: 0xfbe928});
+		const materialGreyDark= new THREE.MeshLambertMaterial({color: 0x9d9d9d});
+		const materialGreyMedium= new THREE.MeshLambertMaterial({color: 0x636363});
+		
+		//rack
+		const rrgeometry = new THREE.BoxGeometry(width, height, depth);
+		const rrmesh = new THREE.Mesh(rrgeometry, softbluematerial);
+		rrmesh.position.set( 0, 0 , -10);
+		rc_rackObject.add(rrmesh);		
+		
+		//front yellow target
+		const Ftarget = new THREE.BoxGeometry(2, 90, 500);
+		const Ftargetmesh = new THREE.Mesh(Ftarget, target);
+		Ftargetmesh.position.set( -451, 1200 , -15);
+		rc_rackObject.add(Ftargetmesh);		
+		//Rear yellow target
+		const Rtarget = new THREE.BoxGeometry(2, 90, 500);
+		const Rtargetmesh = new THREE.Mesh(Rtarget, target);
+		Rtargetmesh.position.set( 401, 1200 , -15);
+		rc_rackObject.add(Rtargetmesh);				
+		
+		//edge le	
+		const llegeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const llemesh = new THREE.Mesh(llegeometry, bluematerial);
+		llemesh.position.set( -425, 0 , -285);
+		rc_rackObject.add(llemesh);
+		
+		//edge re		
+		const lregeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const lremesh = new THREE.Mesh(lregeometry, bluematerial);
+		lremesh.position.set( -425, 0 , 265);
+		rc_rackObject.add(lremesh);		
+
+		//edge ue		
+		const luegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const luemesh = new THREE.Mesh(luegeometry, bluematerial);
+		luemesh.position.set( -425, 1225 , -7);
+		rc_rackObject.add(luemesh);		
+
+		//edge de		
+		const ldegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const ldemesh = new THREE.Mesh(ldegeometry, bluematerial);
+		ldemesh.position.set( -425, -1230 , -7);
+		rc_rackObject.add(ldemesh);				
+
+	
+		//borderEC down
+		const borderECgeometry = new THREE.BoxGeometry(10, 400, 600);
+		const borderECgeometrymesh = new THREE.Mesh(borderECgeometry, materialGreyDark);
+		borderECgeometrymesh.position.set( -400, -250 , -10);
+		rc_rackObject.add(borderECgeometrymesh);
+		
+		//EC1 down
+		const EC1geometry = new THREE.BoxGeometry(10, 350, 40);
+		const EC1geometrymesh = new THREE.Mesh(EC1geometry, materialGreyMedium);
+		EC1geometrymesh.position.set( -402, -250 , -200);
+		rc_rackObject.add(EC1geometrymesh);			
+		//EC2 down
+		const EC2geometry = new THREE.BoxGeometry(10, 350, 40);
+		const EC2geometrymesh = new THREE.Mesh(EC2geometry, materialGreyMedium);
+		EC2geometrymesh.position.set( -402, -250 , -150);
+		rc_rackObject.add(EC2geometrymesh);			
+		//EC2 down
+		const EC3geometry = new THREE.BoxGeometry(10, 350, 40);
+		const EC3geometrymesh = new THREE.Mesh(EC3geometry, materialGreyMedium);
+		EC3geometrymesh.position.set( -402, -250 , -100);
+		rc_rackObject.add(EC3geometrymesh);		
+		
+		//borderEC up
+		const borderupECgeometry = new THREE.BoxGeometry(10, 400, 600);
+		const borderupECgeometrymesh = new THREE.Mesh(borderupECgeometry, materialGreyDark);
+		borderupECgeometrymesh.position.set( -400, 250 , -10);
+		rc_rackObject.add(borderupECgeometrymesh);
+		
+		//EC1 up
+		const EC1geometryup = new THREE.BoxGeometry(10, 350, 40);
+		const EC1geometryupmesh = new THREE.Mesh(EC1geometryup, materialGreyMedium);
+		EC1geometryupmesh.position.set( -402, 250 , -200);
+		rc_rackObject.add(EC1geometryupmesh);			
+		//EC2 up
+		const EC2geometryup = new THREE.BoxGeometry(10, 350, 40);
+		const EC2geometryupmesh = new THREE.Mesh(EC2geometryup, materialGreyMedium);
+		EC2geometryupmesh.position.set( -402, 250 , -150);
+		rc_rackObject.add(EC2geometryupmesh);			
+		//EC2 up
+		const EC3geometryup = new THREE.BoxGeometry(10, 350, 40);
+		const EC3geometryupmesh = new THREE.Mesh(EC3geometryup, materialGreyMedium);
+		EC3geometryupmesh.position.set( -402, 250 , -100);
+		rc_rackObject.add(EC3geometryupmesh);				
+		
+		if (typeof param.reverse != 'undefined') rc_rackObject.rotateY(Math.PI);
+		rc_rackObject.position.set(400, 200, 300);
+		rc.add(rc_rackObject);	
+		return rc;
+	}
+
+	// diagnostic rack
+	export function rd(param) {
+		const width=800, height=2500, depth=600;
+		const rd = new THREE.Object3D();
+		const rd_rackObject = new THREE.Object3D();
+
+		const materialBase = new THREE.MeshLambertMaterial({color: 0x0000d0});
+		const text = param.name;
+		let group, textMesh, textGeo, materials;
+		let size = 60;
+		let textheight = 10;
+		let pos = [];
+		let rot = [];
+		const hover = 30;
+		const curveSegments = 8;
+		let font;
+		function insertText(isize, ipos, irot) {
+			group = new THREE.Group();
+			group.position.y = 100;
+			rd.add( group );
+			size = isize;
+			pos = ipos;
+			rot = irot;
+			loadFont();
+		}
+		function loadFont() {
+			const loader = new FontLoader();
+			// https://threejs.org/examples/fonts/droid_sans_bold.typeface.json
+			loader.load( './fonts/droid_sans_bold.typeface.json', function ( response ) {
+				font = response;
+				refreshText();
+			} );
+		}
+		function createText() {
+			textGeo = new TextGeometry(text, {font: font, size: size, height: textheight, curveSegments: curveSegments});
+			textGeo.computeBoundingBox();
+			const centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
+			textMesh = new THREE.Mesh(textGeo, materialBase);
+			textMesh.position.x = pos[0];
+			textMesh.position.y = pos[1];
+			textMesh.position.z = pos[2];
+			textMesh.rotation.x = rot[0];
+			textMesh.rotation.y = rot[1];
+			textMesh.rotation.z = rot[2];
+			group.add( textMesh );
+			const group2 = group.clone();
+			group2.rotateY(Math.PI);
+			group2.position.set(850, 90, 550);
+			rd.add(group2);			
+			
+		}
+		function refreshText() {
+			group.remove( textMesh );
+			if ( ! text ) return;
+			createText();
+		}
+		insertText(50, [900, 1290, 500], [0, Math.PI / 2, 0]);
+		
+		const bluematerial = new THREE.MeshLambertMaterial({color: 0x0053d9});
+		const softbluematerial = new THREE.MeshLambertMaterial({color: 0x2b7cff});
+		const target = new THREE.MeshLambertMaterial({color: 0xfbe928});
+		const materialGreyDark= new THREE.MeshLambertMaterial({color: 0x9d9d9d});
+		const materialGreyMedium= new THREE.MeshLambertMaterial({color: 0x636363});
+		
+		//rack
+		const rrgeometry = new THREE.BoxGeometry(width, height, depth);
+		const rrmesh = new THREE.Mesh(rrgeometry, softbluematerial);
+		rrmesh.position.set( 0, 0 , -10);
+		rd_rackObject.add(rrmesh);		
+		
+		//front yellow target
+		const Ftarget = new THREE.BoxGeometry(2, 90, 500);
+		const Ftargetmesh = new THREE.Mesh(Ftarget, target);
+		Ftargetmesh.position.set( -451, 1200 , -15);
+		rd_rackObject.add(Ftargetmesh);		
+		//Rear yellow target
+		const Rtarget = new THREE.BoxGeometry(2, 90, 500);
+		const Rtargetmesh = new THREE.Mesh(Rtarget, target);
+		Rtargetmesh.position.set( 401, 1200 , -15);
+		rd_rackObject.add(Rtargetmesh);				
+		
+		//edge le	
+		const llegeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const llemesh = new THREE.Mesh(llegeometry, bluematerial);
+		llemesh.position.set( -425, 0 , -285);
+		rd_rackObject.add(llemesh);
+		
+		//edge re		
+		const lregeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const lremesh = new THREE.Mesh(lregeometry, bluematerial);
+		lremesh.position.set( -425, 0 , 265);
+		rd_rackObject.add(lremesh);		
+
+		//edge ue		
+		const luegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const luemesh = new THREE.Mesh(luegeometry, bluematerial);
+		luemesh.position.set( -425, 1225 , -7);
+		rd_rackObject.add(luemesh);		
+
+		//edge de		
+		const ldegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const ldemesh = new THREE.Mesh(ldegeometry, bluematerial);
+		ldemesh.position.set( -425, -1230 , -7);
+		rd_rackObject.add(ldemesh);				
+
+	
+		//borderEC 
+		const borderECgeometry = new THREE.BoxGeometry(10, 400, 600);
+		const borderECgeometrymesh = new THREE.Mesh(borderECgeometry, materialGreyDark);
+		borderECgeometrymesh.position.set( -400, 0 , -10);
+		rd_rackObject.add(borderECgeometrymesh);
+		
+		//EC1 
+		const EC1geometry = new THREE.BoxGeometry(10, 350, 40);
+		const EC1geometrymesh = new THREE.Mesh(EC1geometry, materialGreyMedium);
+		EC1geometrymesh.position.set( -402, 0 , -200);
+		rd_rackObject.add(EC1geometrymesh);			
+		//EC2 
+		const EC2geometry = new THREE.BoxGeometry(10, 350, 40);
+		const EC2geometrymesh = new THREE.Mesh(EC2geometry, materialGreyMedium);
+		EC2geometrymesh.position.set( -402, 0 , -150);
+		rd_rackObject.add(EC2geometrymesh);			
+		//EC2 
+		const EC3geometry = new THREE.BoxGeometry(10, 350, 40);
+		const EC3geometrymesh = new THREE.Mesh(EC3geometry, materialGreyMedium);
+		EC3geometrymesh.position.set( -402, 0 , -100);
+		rd_rackObject.add(EC3geometrymesh);		
+		
+		//libera 1
+		const libera1geometry = new THREE.BoxGeometry(10, 100, 600);
+		const libera1geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera1geometrymesh.position.set( -400, 900 , -10);
+		rd_rackObject.add(libera1geometrymesh);		
+		
+		//libera 2
+		const libera2geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera2geometrymesh.position.set( -400, 750 , -10);
+		rd_rackObject.add(libera2geometrymesh);				
+		
+		//libera 3
+		const libera3geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera3geometrymesh.position.set( -400, 600 , -10);
+		rd_rackObject.add(libera3geometrymesh);			
+		
+		//libera 4
+		const libera4geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera4geometrymesh.position.set( -400, -600 , -10);
+		rd_rackObject.add(libera4geometrymesh);			
+		
+		//libera 5
+		const libera5geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera5geometrymesh.position.set( -400, -750 , -10);
+		rd_rackObject.add(libera5geometrymesh);			
+		
+		//libera 6
+		const libera6geometrymesh = new THREE.Mesh(libera1geometry, materialGreyMedium);
+		libera6geometrymesh.position.set( -400, -900 , -10);
+		rd_rackObject.add(libera6geometrymesh);	
+
+		if (typeof param.reverse != 'undefined') rd_rackObject.rotateY(Math.PI);
+		rd_rackObject.position.set(400, 200, 300);
+		rd.add(rd_rackObject);	
+		return rd;
+	}		
+	// NULL rack
+	export function zero(param) {
+		const width=800, height=2500, depth=600;
+		const zero = new THREE.Object3D();
+		const zero_rackObject = new THREE.Object3D();
+
+		const materialBase = new THREE.MeshLambertMaterial({color: 0x0000d0});
+		const text = param.name;
+		let group, textMesh, textGeo, materials;
+		let size = 60;
+		let textheight = 10;
+		let pos = [];
+		let rot = [];
+		const hover = 30;
+		const curveSegments = 8;
+		let font;
+		function insertText(isize, ipos, irot) {
+			group = new THREE.Group();
+			group.position.y = 100;
+			zero.add( group );
+			size = isize;
+			pos = ipos;
+			rot = irot;
+			loadFont();
+		}
+		function loadFont() {
+			const loader = new FontLoader();
+			// https://threejs.org/examples/fonts/droid_sans_bold.typeface.json
+			loader.load( './fonts/droid_sans_bold.typeface.json', function ( response ) {
+				font = response;
+				refreshText();
+			} );
+		}
+		function createText() {
+			textGeo = new TextGeometry(text, {font: font, size: size, height: textheight, curveSegments: curveSegments});
+			textGeo.computeBoundingBox();
+			const centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
+			textMesh = new THREE.Mesh(textGeo, materialBase);
+			textMesh.position.x = pos[0];
+			textMesh.position.y = pos[1];
+			textMesh.position.z = pos[2];
+			textMesh.rotation.x = rot[0];
+			textMesh.rotation.y = rot[1];
+			textMesh.rotation.z = rot[2];
+			group.add( textMesh );
+			const group2 = group.clone();
+			group2.rotateY(Math.PI);
+			group2.position.set(850, 90, 550);
+			zero.add(group2);			
+			
+		}
+		function refreshText() {
+			group.remove( textMesh );
+			if ( ! text ) return;
+			createText();
+		}
+		insertText(50, [900, 1290, 500], [0, Math.PI / 2, 0]);
+		
+		const bluematerial = new THREE.MeshLambertMaterial({color: 0x0053d9});
+		const softbluematerial = new THREE.MeshLambertMaterial({color: 0x2b7cff});
+		const target = new THREE.MeshLambertMaterial({color: 0xfbe928});
+		const materialGreyDark= new THREE.MeshLambertMaterial({color: 0x9d9d9d});
+		const materialGreyMedium= new THREE.MeshLambertMaterial({color: 0x636363});
+		
+		//rack
+		const rrgeometry = new THREE.BoxGeometry(width, height, depth);
+		const rrmesh = new THREE.Mesh(rrgeometry, softbluematerial);
+		rrmesh.position.set( 0, 0 , -10);
+		zero_rackObject.add(rrmesh);		
+		
+		//front yellow target
+		const Ftarget = new THREE.BoxGeometry(2, 90, 500);
+		const Ftargetmesh = new THREE.Mesh(Ftarget, target);
+		Ftargetmesh.position.set( -451, 1200 , -15);
+		zero_rackObject.add(Ftargetmesh);		
+		//Rear yellow target
+		const Rtarget = new THREE.BoxGeometry(2, 90, 500);
+		const Rtargetmesh = new THREE.Mesh(Rtarget, target);
+		Rtargetmesh.position.set( 401, 1200 , -15);
+		zero_rackObject.add(Rtargetmesh);				
+		
+		//edge le	
+		const llegeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const llemesh = new THREE.Mesh(llegeometry, bluematerial);
+		llemesh.position.set( -425, 0 , -285);
+		zero_rackObject.add(llemesh);
+		
+		//edge re		
+		const lregeometry = new THREE.BoxGeometry(width-750, height, depth-550);
+		const lremesh = new THREE.Mesh(lregeometry, bluematerial);
+		lremesh.position.set( -425, 0 , 265);
+		zero_rackObject.add(lremesh);		
+
+		//edge ue		
+		const luegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const luemesh = new THREE.Mesh(luegeometry, bluematerial);
+		luemesh.position.set( -425, 1225 , -7);
+		zero_rackObject.add(luemesh);		
+
+		//edge de		
+		const ldegeometry = new THREE.BoxGeometry(width-750, height-2450, depth-50);
+		const ldemesh = new THREE.Mesh(ldegeometry, bluematerial);
+		ldemesh.position.set( -425, -1230 , -7);
+		zero_rackObject.add(ldemesh);				
+
+	
+
+		if (typeof param.reverse != 'undefined') zero_rackObject.rotateY(Math.PI);
+		zero_rackObject.position.set(400, 200, 300);
+		zero.add(zero_rackObject);	
+		return zero;
+	}	
+
+
+
+	// Rack Bending Booster
+	export function rpsb(param) {
+		const width=1000, height=2100, depth=1500;
+		const rpsb = new THREE.Object3D();
+		const rpsb_rackObject = new THREE.Object3D();
+		
+		const materialBase = new THREE.MeshLambertMaterial({color: 0x0000d0});
+		const text = param.name;
+		let group, textMesh, textGeo, materials;
+		let size = 60;
+		let textheight = 10;
+		let pos = [];
+		let rot = [];
+		const hover = 30;
+		const curveSegments = 8;
+		let font;
+		function insertText(isize, ipos, irot) {
+			group = new THREE.Group();
+			group.position.y = 100;
+			rpsb.add( group );
+			size = isize;
+			pos = ipos;
+			rot = irot;
+			loadFont();
+		}
+		function loadFont() {
+			const loader = new FontLoader();
+			// https://threejs.org/examples/fonts/droid_sans_bold.typeface.json
+			loader.load( './fonts/droid_sans_bold.typeface.json', function ( response ) {
+				font = response;
+				refreshText();
+			} );
+		}
+		function createText() {
+			textGeo = new TextGeometry(text, {font: font, size: size, height: textheight, curveSegments: curveSegments});
+			textGeo.computeBoundingBox();
+			const centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
+			textMesh = new THREE.Mesh(textGeo, materialBase);
+			textMesh.position.x = pos[0];
+			textMesh.position.y = pos[1];
+			textMesh.position.z = pos[2];
+			textMesh.rotation.x = rot[0];
+			textMesh.rotation.y = rot[1];
+			textMesh.rotation.z = rot[2];
+			group.add( textMesh );
+			const group2 = group.clone();
+			group2.rotateY(Math.PI);
+			group2.position.set(790, 90, -850);
+			rpsb.add(group2);				
+		}
+		function refreshText() {
+			group.remove( textMesh );
+			if ( ! text ) return;
+			createText();
+		}
+		insertText(50, [900, 940, -180], [0, Math.PI / 2, 0]);		
+
+		const greenmaterial = new THREE.MeshLambertMaterial({color: 0x00ac76});
+		const target = new THREE.MeshLambertMaterial({color: 0xfbe928});
+		const redmaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
+		const yellowmaterial = new THREE.MeshLambertMaterial({color: 0xcc9d02});
+		const whitematerial = new THREE.MeshLambertMaterial({color: 0xffffff});
+		const materialThightblue = new THREE.MeshLambertMaterial({color: 0x96a5fa});
+		const materialDarkblue = new THREE.MeshLambertMaterial({color: 0x021061});
+		const silvermaterial = new THREE.MeshLambertMaterial({color: 0xf0f0f0});
+		
+		//rack
+		const geometry = new THREE.BoxGeometry(width, height, depth);
+		const rackmesh = new THREE.Mesh(geometry, greenmaterial);
+		rackmesh.position.set( 0, 0 ,0);
+		rpsb_rackObject.add(rackmesh);	
+		
+		//emergencybutton yellow 
+		const emergencybuttonyellow = new THREE.CylinderGeometry(70, 70, 5, 15);
+		const emergencybuttonyellowmesh = new THREE.Mesh(emergencybuttonyellow, yellowmaterial);
+		emergencybuttonyellowmesh.rotateX(Math.PI * 0.5);
+		emergencybuttonyellowmesh.rotateY(Math.PI * 1);
+		emergencybuttonyellowmesh.rotateZ(Math.PI * 0.5);		
+		emergencybuttonyellowmesh.position.set(-503, 520 , 0);		
+		rpsb_rackObject.add(emergencybuttonyellowmesh);				
+		
+		//emergencybutton red  
+		const emergencybutton = new THREE.CylinderGeometry(50, 50, 30, 15);
+		const emergencybuttonmesh = new THREE.Mesh(emergencybutton, redmaterial);
+		emergencybuttonmesh.rotateX(Math.PI * 0.5);
+		emergencybuttonmesh.rotateY(Math.PI * 1);
+		emergencybuttonmesh.rotateZ(Math.PI * 0.5);		
+		emergencybuttonmesh.position.set(-505, 520 , 0);		
+		rpsb_rackObject.add(emergencybuttonmesh);	
+		
+		//base border	
+		const screenbordergeometry = new THREE.BoxGeometry(10, 350, 450);
+		const screenbordergeometrymesh = new THREE.Mesh(screenbordergeometry, whitematerial);
+		screenbordergeometrymesh.position.set( -500, 600 , 0);
+		rpsb_rackObject.add(screenbordergeometrymesh);
+		
+		//screen border	
+		const basebordergeometry = new THREE.BoxGeometry(10,  100, 100);
+		const basebordergeometrymesh = new THREE.Mesh(basebordergeometry, silvermaterial);
+		basebordergeometrymesh.position.set( -501, 700 , 0);
+		rpsb_rackObject.add(basebordergeometrymesh);
+		
+		//screen 	
+		const screengeometry = new THREE.BoxGeometry(10, 80, 80);
+		const screengeometrymesh = new THREE.Mesh(screengeometry, materialDarkblue);
+		screengeometrymesh.position.set( -502, 700 , 0);
+		rpsb_rackObject.add(screengeometrymesh);		
+		
+		//front yellow target
+		const Ftarget = new THREE.BoxGeometry(2, 90, 600);
+		const Ftargetmesh = new THREE.Mesh(Ftarget, target);
+		Ftargetmesh.position.set( -504, 999 , 0);
+		rpsb_rackObject.add(Ftargetmesh);		
+		//Rear yellow target
+		const Rtarget = new THREE.BoxGeometry(2, 90, 600);
+		const Rtargetmesh = new THREE.Mesh(Rtarget, target);
+		Rtargetmesh.position.set( 504, 999 , 0);
+		rpsb_rackObject.add(Rtargetmesh);		
+		
+		if (typeof param.reverse != 'undefined') rpsb_rackObject.rotateY(Math.PI);
+		rpsb_rackObject.position.set(400, 50, -400);
+		rpsb.add(rpsb_rackObject);	
+		return rpsb;
+	}
+
+	// Rack Quadrupoli Booster
+	export function rpsq(param) {
+		const width=1000, height=2100, depth=1500;
+		const rpsb = new THREE.Object3D();
+		const rpsb_rackObject = new THREE.Object3D();
+		
+		const materialBase = new THREE.MeshLambertMaterial({color: 0x0000d0});
+		const text = param.name;
+		let group, textMesh, textGeo, materials;
+		let size = 60;
+		let textheight = 10;
+		let pos = [];
+		let rot = [];
+		const hover = 30;
+		const curveSegments = 8;
+		let font;
+		function insertText(isize, ipos, irot) {
+			group = new THREE.Group();
+			group.position.y = 100;
+			rpsb.add( group );
+			size = isize;
+			pos = ipos;
+			rot = irot;
+			loadFont();
+		}
+		function loadFont() {
+			const loader = new FontLoader();
+			// https://threejs.org/examples/fonts/droid_sans_bold.typeface.json
+			loader.load( './fonts/droid_sans_bold.typeface.json', function ( response ) {
+				font = response;
+				refreshText();
+			} );
+		}
+		function createText() {
+			textGeo = new TextGeometry(text, {font: font, size: size, height: textheight, curveSegments: curveSegments});
+			textGeo.computeBoundingBox();
+			const centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
+			textMesh = new THREE.Mesh(textGeo, materialBase);
+			textMesh.position.x = pos[0];
+			textMesh.position.y = pos[1];
+			textMesh.position.z = pos[2];
+			textMesh.rotation.x = rot[0];
+			textMesh.rotation.y = rot[1];
+			textMesh.rotation.z = rot[2];
+			group.add( textMesh );
+			const group2 = group.clone();
+			group2.rotateY(Math.PI);
+			group2.position.set(790, 90, -850);
+			rpsb.add(group2);				
+		}
+		function refreshText() {
+			group.remove( textMesh );
+			if ( ! text ) return;
+			createText();
+		}
+		insertText(50, [900, 940, -180], [0, Math.PI / 2, 0]);		
+
+		const greenmaterial = new THREE.MeshLambertMaterial({color: 0x00ac76});
+		const target = new THREE.MeshLambertMaterial({color: 0xfbe928});
+		const redmaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
+		const yellowmaterial = new THREE.MeshLambertMaterial({color: 0xcc9d02});
+		const whitematerial = new THREE.MeshLambertMaterial({color: 0xffffff});
+		const materialThightblue = new THREE.MeshLambertMaterial({color: 0x96a5fa});
+		const materialDarkblue = new THREE.MeshLambertMaterial({color: 0x021061});
+		const silvermaterial = new THREE.MeshLambertMaterial({color: 0xf0f0f0});
+		
+		//rack
+		const geometry = new THREE.BoxGeometry(width, height, depth);
+		const rackmesh = new THREE.Mesh(geometry, redmaterial);
+		rackmesh.position.set( 0, 0 ,0);
+		rpsb_rackObject.add(rackmesh);	
+		
+		//emergencybutton yellow 
+		const emergencybuttonyellow = new THREE.CylinderGeometry(70, 70, 5, 15);
+		const emergencybuttonyellowmesh = new THREE.Mesh(emergencybuttonyellow, yellowmaterial);
+		emergencybuttonyellowmesh.rotateX(Math.PI * 0.5);
+		emergencybuttonyellowmesh.rotateY(Math.PI * 1);
+		emergencybuttonyellowmesh.rotateZ(Math.PI * 0.5);		
+		emergencybuttonyellowmesh.position.set(-503, 520 , 0);		
+		rpsb_rackObject.add(emergencybuttonyellowmesh);				
+		
+		//emergencybutton red  
+		const emergencybutton = new THREE.CylinderGeometry(50, 50, 30, 15);
+		const emergencybuttonmesh = new THREE.Mesh(emergencybutton, redmaterial);
+		emergencybuttonmesh.rotateX(Math.PI * 0.5);
+		emergencybuttonmesh.rotateY(Math.PI * 1);
+		emergencybuttonmesh.rotateZ(Math.PI * 0.5);		
+		emergencybuttonmesh.position.set(-505, 520 , 0);		
+		rpsb_rackObject.add(emergencybuttonmesh);	
+		
+		//base border	
+		const screenbordergeometry = new THREE.BoxGeometry(10, 350, 450);
+		const screenbordergeometrymesh = new THREE.Mesh(screenbordergeometry, whitematerial);
+		screenbordergeometrymesh.position.set( -500, 600 , 0);
+		rpsb_rackObject.add(screenbordergeometrymesh);
+		
+		//screen border	
+		const basebordergeometry = new THREE.BoxGeometry(10,  100, 100);
+		const basebordergeometrymesh = new THREE.Mesh(basebordergeometry, silvermaterial);
+		basebordergeometrymesh.position.set( -501, 700 , 0);
+		rpsb_rackObject.add(basebordergeometrymesh);
+		
+		//screen 	
+		const screengeometry = new THREE.BoxGeometry(10, 80, 80);
+		const screengeometrymesh = new THREE.Mesh(screengeometry, materialDarkblue);
+		screengeometrymesh.position.set( -502, 700 , 0);
+		rpsb_rackObject.add(screengeometrymesh);		
+		
+		//front yellow target
+		const Ftarget = new THREE.BoxGeometry(2, 90, 600);
+		const Ftargetmesh = new THREE.Mesh(Ftarget, target);
+		Ftargetmesh.position.set( -504, 999 , 0);
+		rpsb_rackObject.add(Ftargetmesh);		
+		//Rear yellow target
+		const Rtarget = new THREE.BoxGeometry(2, 90, 600);
+		const Rtargetmesh = new THREE.Mesh(Rtarget, target);
+		Rtargetmesh.position.set( 504, 999 , 0);
+		rpsb_rackObject.add(Rtargetmesh);		
+		
+		if (typeof param.reverse != 'undefined') rpsb_rackObject.rotateY(Math.PI);
+		rpsb_rackObject.position.set(400, 50, -400);
+		rpsb.add(rpsb_rackObject);	
+		return rpsb;
+	}
+
+		
+	
-- 
GitLab