Files
appRobotSimulation/public/Visualize.js
2026-02-01 13:40:05 +01:00

587 lines
21 KiB
JavaScript

import * as THREE from "../node_modules/three/build/three.module.js"
import { VRButton } from "../node_modules/three/examples/jsm/webxr/VRButton.js";
import { XRControllerModelFactory } from "../node_modules/three/examples/jsm/webxr/XRControllerModelFactory.js";
import { XRHandModelFactory } from "../node_modules/three/examples/jsm/webxr/XRHandModelFactory.js";
import { OrbitControls } from "../node_modules/three/examples/jsm/controls/OrbitControls.js";
import { OculusHandModel } from "../node_modules/three/examples/jsm/webxr/OculusHandModel.js";
import { OculusHandPointerModel } from "../node_modules/three/examples/jsm/webxr/OculusHandPointerModel.js";
import { STLLoader } from "../node_modules/three/examples/jsm/loaders/STLLoader.js";
const scene = new THREE.Scene();
const zHinten = -1.0;
const yOben = 0.0;
function main() {
const renderer = new THREE.WebGLRenderer({canvas: document.querySelector('#c')});
const handModelFactory = new XRHandModelFactory();
const fov = 45;
const aspect = window.innerWidth/window.innerHeight; // the canvas default
const near = 0.1;
const far = 150;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(-0.5, 1.0, 1.0);
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff );
document.body.appendChild(renderer.domElement );
renderer.xr.enabled = true;
document.body.appendChild(VRButton.createButton(renderer));
var controls = new OrbitControls(camera, renderer.domElement);
const color = 0xFFFFFF;
const intensity = 1.1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
const ambient = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambient);
const hemi = new THREE.HemisphereLight(0xfffffb, 0x444444, 0.18);
hemi.position.set(0, 10, 0);
scene.add(hemi);
const geometry = new THREE.BoxGeometry(0.05, 0.05, 0.05);
const material = new THREE.MeshPhongMaterial({color:0x44aa88});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
cube.position.set(-0.5,0,zHinten);
const axesHelper = new THREE.AxesHelper(2);
axesHelper.position.set(0,0,zHinten);
scene.add( axesHelper );
// Hands
if(typeof renderer !== "undefined"){
const controllerModelFactory = new XRControllerModelFactory();
// Hand 0 = Links
const controllerGripL = renderer.xr.getControllerGrip( 0 );
controllerGripL.add( controllerModelFactory.createControllerModel( controllerGripL ) );
scene.add( controllerGripL );
const handL = renderer.xr.getHand( 0 );
handL.addEventListener( 'pinchend', () => {
//scaling.active = false;
var p = handR.joints[ 'thumb-tip' ].position;
//socket.send("Info: L x="+p.x+" y="+(p.y-yOben)+" z="+p.z);
} );
handL.add( handModelFactory.createHandModel( handL ) );
scene.add( handL );
// Hand 1 = Rechts
const controllerGripR = renderer.xr.getControllerGrip( 1 );
controllerGripR.add( controllerModelFactory.createControllerModel( controllerGripR ) );
scene.add( controllerGripR );
const handR = renderer.xr.getHand( 1 );
handR.addEventListener( 'pinchend', () => {
//scaling.active = false;
var p = handR.joints[ 'thumb-tip' ].position;
//socket.send("Info: R x="+p.x+" y="+(p.y-yOben)+" z="+p.z);
socket.send("Info: Raum x="+(p.x*1000)+" y="+(-1.0*p.z*1000)+" z="+((p.y-yOben)*1000));
robot.x = -(p.x*1000);
robot.y = (1.0*(p.z-zHinten)*1000);
robot.z = ((p.y-yOben)*1000);
robot.processAndShow();
} );
handR.add( handModelFactory.createHandModel( handR ) );
scene.add( handR );
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
const speed = 1 + .1;
const rot = time * speed;
cube.rotation.x = rot;
cube.rotation.y = rot;
renderer.render(scene, camera);
}
renderer.setAnimationLoop(render);
}
main();
var bauteile = [];
function show3D(r){
if(bauteile.length == 0){
// Weißes, leicht transluzentes PLA-ähnliches Material
var matPLA = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0.0,
roughness: 0.55,
transmission: 0.05,
opacity: 0.98,
transparent: true,
clearcoat: 0.0
});
// Holz Anfnag
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
const holz = new THREE.ShaderMaterial({
uniforms: {
ringWidth: { value: 0.006 }, // Abstand der Ringe
seed: { value: 42.0 },
grainScale: { value: 180.0 }, // Skaliert die feine Maserung
ringJitter: { value: 0.45 }, // wie stark die Ringpositionen variieren
thicknessMin: { value: 0.028 }, // minimale Ringdicke
thicknessMax: { value: 0.065 }, // maximale Ringdicke
rayIntensity: { value: 0.14 }, // Stärke der „Holzstrahlen“
warble: { value: 0.008 } // Verzerrung der Ringe (welliger Effekt)
},
vertexShader: `
varying vec3 vW;
void main() {
vec4 wp = modelMatrix * vec4(position,1.0);
vW = wp.xyz;
gl_Position = projectionMatrix * viewMatrix * wp;
}
`,
fragmentShader: `
varying vec3 vW;
uniform float ringWidth;
uniform float seed;
uniform float grainScale;
uniform float ringJitter;
uniform float thicknessMin;
uniform float thicknessMax;
uniform float rayIntensity;
uniform float warble;
float hash(vec3 p) {
return fract(sin(dot(p + seed, vec3(127.1,311.7,74.7))) * 43758.5453);
}
float noise(vec3 p) {
vec3 i = floor(p);
vec3 f = fract(p);
f = f*f*(3.0-2.0*f);
float a = hash(i);
float b = hash(i+vec3(1.0,0.0,0.0));
float c = hash(i+vec3(0.0,1.0,0.0));
float d = hash(i+vec3(1.0,1.0,0.0));
float e = hash(i+vec3(0.0,0.0,1.0));
float f1 = hash(i+vec3(1.0,0.0,1.0));
float g = hash(i+vec3(0.0,1.0,1.0));
float h = hash(i+vec3(1.0,1.0,1.0));
return mix(mix(mix(a,b,f.x), mix(c,d,f.x), f.y),
mix(mix(e,f1,f.x), mix(g,h,f.x), f.y), f.z);
}
float fbm(vec3 p){
float v = 0.0;
float amp = 0.5;
for(int i=0;i<5;i++){
v += amp * noise(p);
p *= 2.0;
amp *= 0.5;
}
return v;
}
void main() {
vec2 center = vec2(-0.3, 0.0);
vec2 pos = vW.xz - center;
float r = length(pos);
float ang = atan(pos.y, pos.x);
float warp = fbm(vec3(vW.x*3.0, vW.y*1.0, vW.z*3.0)) * warble;
r += warp;
float base = r / ringWidth;
float jitter = fbm(vec3(vW.x*1.2, vW.y*0.5, vW.z*1.2)) * ringJitter;
float ringsVal = fract(base + jitter);
float tNoise = fbm(vec3(vW.x*12.0, vW.y*6.0, vW.z*12.0));
float thickness = mix(thicknessMin, thicknessMax, tNoise);
float d = abs(ringsVal - 0.5);
// Ringmask mit stärkerem Kontrast
float ringMask = 1.0 - smoothstep(0.0, thickness, d);
ringMask = pow(ringMask, 1.5);
float grain = fbm(vec3(vW.x * (grainScale * 0.001), vW.y * 0.02, vW.z * (grainScale * 0.001)));
grain = grain * 0.5 + 0.5;
float raysNoise = fbm(vec3(vW.x*6.0, vW.y*3.0, vW.z*6.0));
float rays = pow(max(0.0, cos(ang * 12.0 + raysNoise * 6.2831)), 16.0) * rayIntensity;
// Farben: leicht mehr Kontrast
vec3 c1 = vec3(0.85, 0.65, 0.42); // hell
vec3 c2 = vec3(0.72, 0.50, 0.32); // mittel
vec3 c3 = vec3(0.55, 0.38, 0.20); // dunkel
vec3 baseColor = mix(c2, c1, (grain * 0.25 + 0.25));
vec3 color = mix(baseColor, c3, ringMask * 0.75);
color *= (1.0 - rays * 0.85);
float spots = fbm(vec3(vW.x*30.0, vW.y*6.0, vW.z*30.0));
color += (spots - 0.5) * 0.015;
color = clamp(color, 0.0, 1.0);
gl_FragColor = vec4(color, 1.0);
}
`
});
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Holz Ende
var material = new THREE.MeshStandardMaterial( { color: 0x22ee22, roughness: 0.2, metalness: 0.2} );
// 00: BodenBrett, 61mm unter der Achse, 24mm vor der Achse
var brettBox = new THREE.BoxGeometry( 0.8, 0.027, 0.078);
var brettMesh = new THREE.Mesh( brettBox, holz );
brettMesh.geometry.translate(0,-0.061-0.027/2,-1+0.078/2+0.024);
scene.add( brettMesh );
// 0: BasisBox
var basisBox = new THREE.BoxGeometry( 0.060, 0.080, 0.080 );
var m2 = new THREE.MeshStandardMaterial({ color: 0xadd8e6, roughness: 0.2, metalness: 0.2});
var basisMesh = new THREE.Mesh( basisBox, material );
basisMesh.castShadow = true;
scene.add( basisMesh );
var stlLoader = new STLLoader();
stlLoader.load('/model/Robot7M/1_01_Bodenplatte.stl', function (geometry) {
// dunkelblaue, hochglänzende Lack-/Pulverbeschichtung
var matO = new THREE.MeshStandardMaterial({
color: 0x0b3d91,
metalness: 0.15,
roughness: 0.08,
clearcoat: 1.0,
clearcoatRoughness: 0.02
});
var mesh = new THREE.Mesh( geometry, matO );
mesh.castShadow = true;
mesh.rotation.x = Math.PI/2;
mesh.rotation.z = 0;
mesh.rotation.y = 0;
mesh.scale.set(0.001, 0.001, 0.001);
mesh.position.x = -63/2000;
mesh.position.y = -80/2000;;
mesh.position.z = -80/2000;;
basisMesh.add(mesh);
});
bauteile.push(basisMesh);
// 1: Bizeps
var oberarmMesh = new THREE.Object3D();
scene.add( oberarmMesh );
bauteile.push(oberarmMesh);
stlLoader.load('/model/Robot7M/2_01_Holm_SeitenBlech.stl', function (geometry) {
// dunkelblaue, hochglänzende Lack-/Pulverbeschichtung
var matO = new THREE.MeshStandardMaterial({
color: 0x0b3d91,
metalness: 0.15,
roughness: 0.08,
clearcoat: 1.0,
clearcoatRoughness: 0.02
});
var mesh = new THREE.Mesh( geometry, matO );
mesh.castShadow = true;
mesh.rotation.x = -Math.PI/2;
mesh.rotation.z = -Math.PI/2;
mesh.rotation.y = Math.PI;
mesh.scale.set(0.001, 0.001, 0.001);
oberarmMesh.add(mesh);
});
// Bizeps MotorHalter
stlLoader.load('/model/Robot7M/2_02_Bizeps_Motor_Holder.stl', function (geometry) {
var mesh = new THREE.Mesh( geometry, matPLA );
mesh.castShadow = true;
mesh.rotation.z = Math.PI/2;
mesh.rotation.x = Math.PI/2;
mesh.scale.set(0.001, 0.001, 0.001);
mesh.geometry.translate(275,-57/2,28.5);
oberarmMesh.add(mesh);
});
// 2: Ellebogen
var ellebogenMesh = new THREE.Object3D();
scene.add( ellebogenMesh );
bauteile.push(ellebogenMesh);
stlLoader.load('/model/Robot7M/3_01_Ellebogen_Schlank.stl', function (geometry) {
var mesh = new THREE.Mesh( geometry, matPLA );
mesh.castShadow = true;
mesh.rotation.z = -Math.PI/2;
mesh.rotation.x = Math.PI; // lange achse
mesh.scale.set(0.001, 0.001, 0.001);
// Mesh zentrieren
mesh.geometry.translate(0,0,25);
ellebogenMesh.add(mesh);
});
// 3: Unterarm
var unterarmMesh = new THREE.Object3D();
scene.add( unterarmMesh );
bauteile.push(unterarmMesh);
stlLoader.load('/model/Robot7M/4_01_Unterarm_Schlank_Rund.stl', function (geometry) {
var mesh = new THREE.Mesh( geometry, matPLA );
mesh.castShadow = true;
mesh.rotation.x = -Math.PI/2; // lange achse
mesh.rotation.z = -Math.PI/2;
mesh.scale.set(0.001, 0.001, 0.001);
mesh.geometry.translate(0,0,0);
unterarmMesh.add(mesh);
});
// 4: Handgelenk
var handMeshR = new THREE.Object3D();
scene.add( handMeshR );
bauteile.push(handMeshR);
stlLoader.load('/model/Robot7M/5_01_Hand_7M_Schlank.stl', function (geometry) {
var mesh = new THREE.Mesh( geometry, matPLA );
mesh.castShadow = true;
mesh.rotation.x = 0; // -Math.PI/2; // lange achse
mesh.rotation.z = 0; //-Math.PI/2;
mesh.scale.set(0.001, 0.001, 0.001);
mesh.geometry.translate(0,0,0);
handMeshR.add(mesh);
});
// 5: Hand
var handMeshF = new THREE.Object3D();
scene.add( handMeshF );
bauteile.push(handMeshF);
stlLoader.load('/model/Robot7M/5_03_Hand_7M_60for50_Fingerhalter.stl', function (geometry) {
var mesh = new THREE.Mesh( geometry, matPLA );
mesh.castShadow = true;
mesh.rotation.x = 0;
mesh.rotation.z = 0;
mesh.scale.set(0.001, 0.001, 0.001);
mesh.geometry.translate(0,0,0);
handMeshF.add(mesh);
});
// 6: Finger1
var handMeshFinger = new THREE.Object3D();
scene.add( handMeshFinger );
bauteile.push(handMeshFinger);
stlLoader.load('/model/Robot7M/5_05_Finger_Monolith.stl', function (geometry) {
var mesh = new THREE.Mesh( geometry, matPLA );
mesh.castShadow = true;
mesh.rotation.x = 0;
mesh.rotation.z = 0;
mesh.scale.set(0.001, 0.001, 0.001);
mesh.geometry.translate(-9,-23,0);
handMeshFinger.add(mesh);
});
// 6: Finger2
var handMeshFinger2 = new THREE.Object3D();
scene.add( handMeshFinger2 );
bauteile.push(handMeshFinger2);
stlLoader.load('/model/Robot7M/5_05_Finger_Monolith.stl', function (geometry) {
var mesh = new THREE.Mesh( geometry, matPLA );
mesh.castShadow = true;
mesh.rotation.x = 0;
mesh.rotation.z = 0;
mesh.scale.set(0.001, 0.001, 0.001);
mesh.geometry.translate(-9,-23,0);
handMeshFinger2.add(mesh);
});
}
bauteile[0].position.x = -robot.xMotor/1000;
bauteile[0].position.y = 0;
bauteile[0].position.z = 0;
// Bizeps
bauteile[1].position.y = 28.5/1000;
bauteile[1].position.x = -robot.xMotor/1000 + 0.04;
bauteile[1].position.z = -25/1000;;
bauteile[1].rotation.y = 0;
bauteile[1].rotation.x = 0;
bauteile[1].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.alpha))
// Ellebogen
bauteile[2].position.x = 0;
bauteile[2].position.z = (robot.l2*0.2)/2000;
bauteile[2].position.y = 0;
bauteile[2].rotation.x = 0;
bauteile[2].rotation.y = 0;
bauteile[2].rotation.z = 0;
bauteile[2].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.beta))
bauteile[2].position.z += Math.cos(robot.alpha)*robot.l1/1000;
bauteile[2].position.y += Math.sin(robot.alpha)*robot.l1/1000;
bauteile[2].position.x -= robot.xMotor/1000 - 0.160;
// Unterarm
bauteile[3].position.x = 0;
bauteile[3].position.z = robot.l2/1000;
bauteile[3].position.y = 0;
bauteile[3].rotation.x = 0;
bauteile[3].rotation.y = 0;
bauteile[3].rotation.z = 0;
bauteile[3].applyMatrix4(new THREE.Matrix4().makeRotationZ(-robot.a + Math.PI))
bauteile[3].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.beta))
bauteile[3].position.z += Math.cos(robot.alpha)*robot.l1/1000;
bauteile[3].position.y += Math.sin(robot.alpha)*robot.l1/1000;
bauteile[3].position.x -= robot.xMotor/1000 - 0.160;
// Handgelenk
bauteile[4].position.x = 0;
bauteile[4].position.z = 0;
bauteile[4].position.y = 0;
bauteile[4].rotation.x = 0;
bauteile[4].rotation.y = 0;
bauteile[4].rotation.z = 0;
bauteile[4].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.b + Math.PI));
bauteile[4].applyMatrix4(new THREE.Matrix4().makeRotationZ(-robot.a+ Math.PI));
bauteile[4].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.beta));
bauteile[4].position.z += Math.cos(robot.alpha)*robot.l1/1000;
bauteile[4].position.y += Math.sin(robot.alpha)*robot.l1/1000;
bauteile[4].position.z += Math.cos(robot.beta)*robot.l2/1000;
bauteile[4].position.y += Math.sin(robot.beta)*robot.l2/1000;
bauteile[4].position.x -= robot.xMotor/1000 - 0.160;
// Finger Halter
bauteile[5].position.x = -0.057;
bauteile[5].position.z = -0.026;
bauteile[5].position.y = 0;
bauteile[5].rotation.x = 0;
bauteile[5].rotation.y = 0;
bauteile[5].rotation.z = 0;
bauteile[5].applyMatrix4(new THREE.Matrix4().makeRotationZ(robot.c));
bauteile[5].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.b));
bauteile[5].applyMatrix4(new THREE.Matrix4().makeRotationZ(-robot.a+ Math.PI));
bauteile[5].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.beta));
bauteile[5].position.z += Math.cos(robot.alpha)*robot.l1/1000;
bauteile[5].position.y += Math.sin(robot.alpha)*robot.l1/1000;
bauteile[5].position.z += Math.cos(robot.beta)*robot.l2/1000;
bauteile[5].position.y += Math.sin(robot.beta)*robot.l2/1000;
bauteile[5].position.x -= robot.xMotor/1000 - 0.160;
// Finger1
bauteile[6].position.x = 0;
bauteile[6].position.z = 0;
bauteile[6].position.y = 0;
bauteile[6].rotation.x = 0;
bauteile[6].rotation.y = 0;
bauteile[6].rotation.z = 0;
bauteile[6].applyMatrix4(new THREE.Matrix4().makeRotationZ(Math.PI/2));
bauteile[6].position.z = 0.026 + 0.009;
bauteile[6].position.x += robot.e/1000;
bauteile[6].applyMatrix4(new THREE.Matrix4().makeRotationX(Math.PI));
bauteile[6].applyMatrix4(new THREE.Matrix4().makeRotationZ(robot.c));
bauteile[6].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.b));
bauteile[6].applyMatrix4(new THREE.Matrix4().makeRotationZ(-robot.a+ Math.PI));
bauteile[6].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.beta));
bauteile[6].position.z += Math.cos(robot.alpha)*robot.l1/1000;
bauteile[6].position.y += Math.sin(robot.alpha)*robot.l1/1000;
bauteile[6].position.z += Math.cos(robot.beta)*robot.l2/1000;
bauteile[6].position.y += Math.sin(robot.beta)*robot.l2/1000;
bauteile[6].position.x -= robot.xMotor/1000 - 0.160;
// Finger2
bauteile[7].position.x = 0;
bauteile[7].position.z = 0;
bauteile[7].position.y = 0;
bauteile[7].rotation.x = 0;
bauteile[7].rotation.y = 0;
bauteile[7].rotation.z = 0;
bauteile[7].applyMatrix4(new THREE.Matrix4().makeRotationZ(-Math.PI/2));
bauteile[7].position.z = 0.026 + 0.009;
bauteile[7].position.x -= robot.e/1000;
bauteile[7].applyMatrix4(new THREE.Matrix4().makeRotationX(Math.PI));
bauteile[7].applyMatrix4(new THREE.Matrix4().makeRotationZ(robot.c));
bauteile[7].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.b));
bauteile[7].applyMatrix4(new THREE.Matrix4().makeRotationZ(-robot.a+ Math.PI));
bauteile[7].applyMatrix4(new THREE.Matrix4().makeRotationX(-robot.beta));
bauteile[7].position.z += Math.cos(robot.alpha)*robot.l1/1000;
bauteile[7].position.y += Math.sin(robot.alpha)*robot.l1/1000;
bauteile[7].position.z += Math.cos(robot.beta)*robot.l2/1000;
bauteile[7].position.y += Math.sin(robot.beta)*robot.l2/1000;
bauteile[7].position.x -= robot.xMotor/1000 - 0.160;
for (var i = 0; i < bauteile.length; i++) {
bauteile[i].position.z += zHinten;
bauteile[i].position.y += yOben;
}
}
if(!robot.showFunctions.includes(show3D)){
robot.showFunctions.push(show3D);
}
robot.showRobot();