bot propelMove

This commit is contained in:
STEINNI
2025-12-11 20:57:20 +00:00
parent 122861dbee
commit 0b708c2dbd
22 changed files with 221 additions and 17442 deletions
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

-11
View File
@@ -1,11 +0,0 @@
Model Information:
* title: Mech Drone
* source: https://sketchfab.com/3d-models/mech-drone-8d06874aac5246c59edb4adbe3606e0e
* author: Willy Decarpentrie (https://sketchfab.com/skudgee)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "Mech Drone" (https://sketchfab.com/3d-models/mech-drone-8d06874aac5246c59edb4adbe3606e0e) by Willy Decarpentrie (https://sketchfab.com/skudgee) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 MiB

+8
View File
@@ -41,6 +41,14 @@ body[eicapp] {
box-sizing: border-box;
background: repeating-linear-gradient( -45deg, #000, #333 10px, #000 10px, #333 20px );
}
.helperBotCanvas{
display: block;
width: 100vw;
height: 100vh;
background: transparent;
pointer-events: none;
z-index: 9;
}
[eicapp] [eicapptoolbar] {
display: flex;
+6 -1
View File
@@ -12,7 +12,12 @@
"path": "/Windoz",
"classes": [ "WindozController", "WindozDomContent", "WindozDialogContent", "WindozMetaData", "WindozModel", "WindozPluralModel", "WindozBusModel" ],
"dependencies" : { "WindozPluralModel": [ "WindozModel" ] }
}
},
{
"path": "/HelperBot",
"classes": [ "HelperBot.module" ],
"dependencies" : { }
}
],
"masterController": "WindozAppController",
"defaultMasterTemplate": "templates/EICAppTemplate"
+198
View File
@@ -0,0 +1,198 @@
import * as THREE from 'three'
import * as TWEEN from 'three/examples/jsm/libs/tween.module.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
class HelperBot{
constructor(canvasSelector){
this.renderer = null
this.canvasEl = document.querySelector(canvasSelector)
this.initScene()
window.bot=this
}
initScene(){
this.canvasEl .width = window.innerWidth
this.canvasEl .height = window.innerHeight
this.scene = new THREE.Scene()
this.camera = new THREE.PerspectiveCamera(30, this.canvasEl.clientWidth / this.canvasEl.clientHeight, 0.1, 1000)
this.camera.position.set(0, 1, 10)
this.camera.lookAt(0, 0, 0)
// Lights
const dLight1 = new THREE.DirectionalLight(0xffffff, 1.5)
dLight1.position.set(5, 5, 5)
this.scene.add(dLight1)
const dLight2 = new THREE.DirectionalLight(0xffffff, 1.5)
dLight2.position.set(-5, -5, 5)
this.scene.add(dLight2)
this.scene.add(new THREE.AmbientLight(0xffffff, 1))
this.renderer = new THREE.WebGLRenderer({
canvas: this.canvasEl ,
alpha: true
})
this.renderer.setSize(this.canvasEl .width, this.canvasEl .height)
this.renderer.setPixelRatio(window.devicePixelRatio)
this.renderer.setClearColor(0x000000, 0)
this.threeClock = new THREE.Clock()
const loader = new GLTFLoader().setPath('/app/assets/3dModels/')
loader.load('mecha2.glb', async gltf => {
this.mecha = new THREE.Group()
this.scene.add(this.mecha)
this.mechaModel = gltf.scene
this.mecha.add(this.mechaModel)
this.mechaModel.scale.set(5, 5, 5)
this.mechaModel.rotation.set(0, 0, 0)
this.mechaModel.position.set(0, -1.5, 0)
this.mechaModel.updateMatrix()
this.mechaModel.rotateY(-Math.PI) // 180deg so facing user
// GPU compilation (optimization)
await this.renderer.compileAsync(this.mechaModel, this.camera, this.scene)
this.mechaModel.traverse(obj => {
if (obj.isMesh && obj.material && obj.material.color) {
const c = obj.material.color.clone()
const boost = 0.1
obj.material.emissive = c
obj.material.emissiveIntensity = boost
}
})
if (gltf.animations && gltf.animations.length > 0) {
this.mixer = new THREE.AnimationMixer(this.mechaModel)
const action = this.mixer.clipAction(gltf.animations[0])
action.play()
}
this.leftArm = this.mechaModel.getObjectByName('ArmL1_01')
this.animate = true
})
this.resizeWindow()
window.addEventListener('resize', this.resizeWindow.bind(this))
this.render()
}
resizeWindow() {
const w = window.innerWidth
const h = window.innerHeight
this.canvasEl .width = w
this.canvasEl .height = h
this.renderer.setSize(w, h)
this.renderer.setPixelRatio(window.devicePixelRatio)
this.camera.aspect = w / h
this.camera.updateProjectionMatrix()
}
startRendering(){
this.addControls()
this.render()
}
render() {
TWEEN.update()
const resized = this.resizeRendererToDisplaySize()
const delta = this.threeClock.getDelta()
if(this.mixer && this.animate) this.mixer.update(delta)
this.renderer.render(this.scene, this.camera)
requestAnimationFrame(this.render.bind(this))
}
resizeRendererToDisplaySize() {
const width = this.canvasEl.clientWidth
const height = this.canvasEl.clientHeight
if (this.canvasEl.width !== width || this.canvasEl.height !== height) {
this.renderer.setSize(width, height, false)
return true
}
return false
}
translateBot(position, delay=500, endcb, updatecb){
if(this.movingBotTween) this.movingBotTween.end()
this.movingBotTween = new TWEEN.Tween(this.mecha.position)
.to({ x: Number(position.x),
y: Number(position.z),
z: Number(position.y),
}, delay)
.easing(TWEEN.Easing.Sinusoidal.InOut)
if(typeof(endcb)=='function') this.movingBotTween.onComplete(endcb)
if(typeof(updatecb)=='function') this.movingBotTween.onUpdate(updatecb)
this.movingBotTween.start()
}
rotateBot(rotation, delay=500, endcb, updatecb){
//TODO : respect existing Z
if(this.rotatingBotTween) this.rotatingBotTween.end()
this.rotatingBotTween = new TWEEN.Tween(this.mecha.rotation)
.to({ x: Number(rotation.x*Math.PI/180),
y: Number(rotation.z*Math.PI/180),
z: Number(rotation.y*Math.PI/180),
}, delay)
.easing(TWEEN.Easing.Sinusoidal.InOut)
if(typeof(endcb)=='function') this.rotatingBotTween.onComplete(endcb)
if(typeof(updatecb)=='function') this.rotatingBotTween.onUpdate(updatecb)
this.rotatingBotTween.start()
}
propelMove(position){
//TODO : respect existing Z rotation
const moveDelay = 1000
const dx = this.mecha.position.x - position.x
const dy = this.mecha.position.z - position.y
const dz = this.mecha.position.y - position.z
const delay = Math.max(Math.abs(dx), Math.abs(dy), Math.abs(dz)) * moveDelay
const ax = (dy>0.5) ? -10 : ((dy<-0.5) ? 10 : 0 )
const ay = (dx>0.5) ? 10 : ((dx<-0.5) ? -10 : 0 )
console.log( this.mecha.position.x, this.mecha.position.y)
console.log(dx,dy,ax,ay)
const rotationDelay = Math.min(delay/4, 500)
this.rotateBot({x: ax, y: ay, z: 0}, rotationDelay)
let chkpt1 = true, chkpt2 = true, chkpt3 = true
const startTime = Date.now()
this.translateBot(position, delay, null, () => {
const t = (Date.now()-startTime)/delay
if(chkpt1 && (t >= 0.2)){ //Time to stop accelerating
this.rotateBot({x: 0, y: 0, z: 0}, rotationDelay)
chkpt1 = false
}
if(chkpt2 && (t >= 0.7)){ //Time to brake
this.rotateBot({x: -ax, y: -ay, z: 0}, rotationDelay)
chkpt2 = false
}
if(chkpt3 && (t >= 0.9)){ //Time to restore
this.rotateBot({x: 0, y: 0, z: 0}, rotationDelay)
chkpt3 = false
}
})
}
}
app.registerClass('HelperBot', HelperBot)
+3 -1
View File
@@ -89,7 +89,9 @@ export class Threetobus{
if(mapping.child) id += '_'+mapping.child
if(id){
const obj3D = this.scene.getObjectByName(id)
this.assignFromConfig(payload, mapping, obj3D)
if(obj3D){
this.assignFromConfig(payload, mapping, obj3D)
}
}
}
}
+1
View File
@@ -235,6 +235,7 @@ API remove
API listAgentTypes
if unsavec changes in scene => confirm before reloading
agent rotation (param + tween)
Bugs
@@ -1,7 +1,6 @@
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import * as TWEEN from 'three/examples/jsm/libs/tween.module.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
export class kfArena{
+2 -1
View File
@@ -5,4 +5,5 @@
<menu eicmenu class="app-menu">
</menu>
<div class="app-workspace"></div>
<div class="app-content-thesaurus"></div>
<div class="app-content-thesaurus"></div>
<canvas class="helperBotCanvas"></canvas>
+3
View File
@@ -18,6 +18,8 @@ class EICAppTemplate extends WindozDomContent {
// todo : replace with something more dynamic
this.loadAppMenu('global/app-menu-map.json');
new app.LoadedClasses.HelperBot('.helperBotCanvas')
}
onGlobalResize() { WindozController.resize(); }
@@ -117,6 +119,7 @@ class EICAppTemplate extends WindozDomContent {
onBusConnected() { this.userIcon.online = true; }
onBusClosed() { this.userIcon.online = false; }
}
app.registerClass('EICAppTemplate', EICAppTemplate);