speed vectors + better scene selection

This commit is contained in:
STEINNI
2025-10-30 19:20:21 +00:00
parent af23d09aa2
commit e12e83c0e1
4 changed files with 101 additions and 11 deletions
+6
View File
@@ -94,4 +94,10 @@ app.helpers.formBuilder = {
return(result) return(result)
}, },
getFieldValue(rootSel, name){
const comp = document.querySelector(`${rootSel} .formbuilder-field[name="${name}"]`)
if(comp) return(comp.value)
else return(null)
},
} }
+33
View File
@@ -112,6 +112,17 @@ app.helpers.helpers3D = {
return center return center
}, },
getObjectTopCenter(object, offset = 0.1) {
object.updateWorldMatrix(true, true)
const box = new THREE.Box3().setFromObject(object)
const center = new THREE.Vector3()
box.getCenter(center)
const up = new THREE.Vector3(0, 1, 0).applyQuaternion(object.quaternion).normalize()
const height = box.max.y - box.min.y
const top = center.clone().addScaledVector(up, height / 2 + offset)
return top
},
init3DHighlighter(options){ init3DHighlighter(options){
if (!this.composer) { if (!this.composer) {
this.composer = new EffectComposer(this.renderer) this.composer = new EffectComposer(this.renderer)
@@ -168,4 +179,26 @@ app.helpers.helpers3D = {
} }
return obj return obj
}, },
createArrow(origin, vector, name='', color = 0xffaa00, headLength = 0.25, headWidth = 0.1) {
//const from = new THREE.Vector3(origin.x, origin.y, origin.z)
const dir = new THREE.Vector3(vector.x, vector.y, vector.z).normalize()
const length = Math.sqrt(vector.x**2 + vector.y**2 + vector.z**2)
if(length==0) return(null)
const arrow = new THREE.ArrowHelper(dir, origin, length, color, headLength, headWidth)
// Optional: add a subtle tube body for style
const shaftGeo = new THREE.CylinderGeometry(0.02, 0.02, length - headLength, 16)
const shaftMat = new THREE.MeshStandardMaterial({ color, metalness: 0.3, roughness: 0.2 })
const shaft = new THREE.Mesh(shaftGeo, shaftMat)
shaft.position.copy(origin.clone().add(dir.clone().multiplyScalar((length - headLength) / 2)))
shaft.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), dir)
const group = new THREE.Group()
group.add(arrow)
group.add(shaft)
if(name) group.name = name
this.scene.add(group)
return group
},
} }
+18 -2
View File
@@ -88,6 +88,7 @@ class KeyframeView extends WindozDomContent {
kfName: kfData.info.ekf_name, kfName: kfData.info.ekf_name,
prevKfId: kfData.info.ekf_prev_uuid, prevKfId: kfData.info.ekf_prev_uuid,
} }
this.outputs.kfName.value = kfData.info.ekf_name
this.kfArena.reloadAgents(kfData.agents) this.kfArena.reloadAgents(kfData.agents)
} }
@@ -124,9 +125,24 @@ class KeyframeView extends WindozDomContent {
} }
onPropsChanged(evt, comp){ onPropsChanged(evt, comp){
console.log('onPropsChanged', comp, evt) console.log('onPropsChanged', comp.name, comp.value)
if(this.currentlySelectedAid && this.kfArena.agents[this.currentlySelectedAid]){ if(this.currentlySelectedAid && this.kfArena.agents[this.currentlySelectedAid]){
const AgentValues = this.getFieldsValues('div[data-output="agentProperties"]')
this.kfArena.agents[this.currentlySelectedAid].values = AgentValues
const val = Number.parseInt(comp.value, 10)
if((comp.name.startsWith('position.')) && (!Number.isNaN(val))){
this.kfArena.moveAgent(this.currentlySelectedAid, {
x: this.getFieldValue('div[data-output="agentProperties"]', 'position.x'),
y: this.getFieldValue('div[data-output="agentProperties"]', 'position.y'),
z: this.getFieldValue('div[data-output="agentProperties"]', 'position.z'),
})
} else if((comp.name.startsWith('speed.')) && (!Number.isNaN(val))){
this.kfArena.changeAgentSpeed(this.currentlySelectedAid, {
x: this.getFieldValue('div[data-output="agentProperties"]', 'speed.x'),
y: this.getFieldValue('div[data-output="agentProperties"]', 'speed.y'),
z: this.getFieldValue('div[data-output="agentProperties"]', 'speed.z'),
})
}
} }
} }
+42 -7
View File
@@ -42,7 +42,7 @@ export class kfArena{
// Base plane // Base plane
const planeGeo = new THREE.PlaneGeometry(100, 100) const planeGeo = new THREE.PlaneGeometry(100, 100)
const planeMat = new THREE.MeshBasicMaterial({ const planeMat = new THREE.MeshBasicMaterial({
color: 0x8888aa, color: 0x000055,
opacity: 0.3, opacity: 0.3,
transparent: true, // needed for opacity < 1 to take effect transparent: true, // needed for opacity < 1 to take effect
side: THREE.DoubleSide side: THREE.DoubleSide
@@ -115,10 +115,14 @@ export class kfArena{
normalizedPointer.y = -((event.clientY - rect.top) / rect.height) * 2 + 1 normalizedPointer.y = -((event.clientY - rect.top) / rect.height) * 2 + 1
this.raycaster.setFromCamera(normalizedPointer, this.camera) this.raycaster.setFromCamera(normalizedPointer, this.camera)
const intersects = this.raycaster.intersectObjects(this.scene.children, true) const intersects = this.raycaster.intersectObjects(this.scene.children, true)
if (intersects.length > 0) { if (intersects.length > 0) {
const hit = this.getNamedParent(intersects[0].object) let hit = null
if(hit) this.onclickAgent(hit) for(let i=0; i<intersects.length; i++){
hit = this.getNamedParent(intersects[i].object)
if((!hit) || (!hit.name)) continue
if(Object.keys(this.agents).includes(hit.name)) break
}
if(hit && Object.keys(this.agents).includes(hit.name)) this.onclickAgent(hit)
} }
} }
@@ -132,8 +136,16 @@ export class kfArena{
const agentObj = this.agentFromJSON(aid, agentSprite.asp_3d) const agentObj = this.agentFromJSON(aid, agentSprite.asp_3d)
agentObj.position.set(values.position.x, values.position.z, values.position.y ) agentObj.position.set(values.position.x, values.position.z, values.position.y )
//TODO Speed vector
this.scene.add(agentObj) this.scene.add(agentObj)
//Speed vector
const objAboveHead = this.getObjectTopCenter(this.scene.getObjectByName(aid))
this.createArrow(objAboveHead, {
x: values.speed.x,
y: values.speed.z,
z:values.speed.y },
`_speed_${aid}`,
0xff0055)
this.agents[aid] = { this.agents[aid] = {
type: typeId, type: typeId,
@@ -143,16 +155,39 @@ export class kfArena{
} }
removeAgent(aid){ removeAgent(aid){
const obj3d = scene.getObjectByName(aid) const obj3d = this.scene.getObjectByName(aid)
this.scene.remove(obj3d) this.scene.remove(obj3d)
if(aid in this.agents) delete(this.agents[aid]) if(aid in this.agents) delete(this.agents[aid])
} }
moveAgent(aid, position){
const obj3d = this.scene.getObjectByName(aid)
new TWEEN.Tween(obj3d.position)
.to({ x: Number(position.x),
y: Number(position.z),
z: Number(position.y),
}, 500)
.easing(TWEEN.Easing.Quadratic.InOut)
.start()
}
changeAgentSpeed(aid, speed){
const objName = `_speed_${aid}`
const obj3d = this.scene.getObjectByName(objName)
if(obj3d) this.scene.remove(obj3d)
const objAboveHead = this.getObjectTopCenter(this.scene.getObjectByName(aid))
this.createArrow(objAboveHead, {
x: speed.x,
y: speed.z,
z: speed.y },
objName,
0xff0055)
}
reloadAgents(agents){ reloadAgents(agents){
for(const aid in this.agents){ for(const aid in this.agents){
this.removeAgent(aid) this.removeAgent(aid)
} }
console.log('====>', agents)
for(const agent of agents){ for(const agent of agents){
this.addAgent(agent.ekfs_atp_id, agent.aid, agent.props, {...agent.gps_values, ...agent.store_values}) this.addAgent(agent.ekfs_atp_id, agent.aid, agent.props, {...agent.gps_values, ...agent.store_values})
} }