nested entity relative scaling

This commit is contained in:
Aigars Zeiza 2025-07-04 20:04:42 +03:00
parent ddef066f7d
commit 4e3d25c27a
3 changed files with 135 additions and 12 deletions

View File

@ -0,0 +1,25 @@
<html>
<head>
<title>Draco loader sample</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script
type="text/javascript"
src="https://www.gstatic.com/draco/versioned/decoders/1.5.7/draco_decoder.js"
></script>
<script src="./nestedEntities.js" type="module"></script>
<link rel="stylesheet" href="../../css/og.css" type="text/css" />
<style>
body {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div style="width: 100%; height: 100%">
<canvas id="frame" style="width: 100%; height: 100%"> </canvas>
</div>
</body>
</html>

View File

@ -0,0 +1,98 @@
/* eslint-disable no-undef */
import {
control,
Entity,
Object3d,
Renderer,
Vec3,
Mat4,
RenderNode,
EntityCollection,
scene,
} from "../../lib/og.es.js";
let renderer = new Renderer("frame", {
msaa: 8,
controls: [new control.SimpleNavigation({ speed: 0.01 }), new control.GeoObjectEditor()],
autoActivate: true
});
class MyScene extends RenderNode {
constructor() {
super("MyScene");
}
init() {
const baseObj = Object3d.createCube(0.4, 2, 0.4).translate(new Vec3(0, 1, 0)).setMaterial({
ambient: "#882a2a",
diffuse: "#fb3434",
shininess: 1
});
const frustumObj = Object3d.createFrustum(3, 2, 1).setMaterial({
ambient: "#236028",
diffuse: "#1cdd23",
shininess: 1
});
const cylinderObj = Object3d.createCylinder(1, 0, 1)
.applyMat4(new Mat4().setRotation(new Vec3(1, 0, 0), (90 * Math.PI) / 180))
.setMaterial({
ambient: "#773381",
diffuse: "#ef00ff",
shininess: 1
});
let parentEntity = new Entity({
cartesian: new Vec3(0, 0, 0),
independentPicking: true,
geoObject: {
color: "rgb(90,90,90)",
scale: 1,
instanced: true,
tag: `baseObj`,
object3d: baseObj
}
});
let childEntity = new Entity({
cartesian: new Vec3(0, 1, 0),
independentPicking: true,
relativePosition: true,
geoObject: {
color: "rgb(90,90,90)",
instanced: true,
tag: `frustumObj`,
object3d: frustumObj
}
});
let childChildEntity = new Entity({
cartesian: new Vec3(0, 3, -1),
independentPicking: true,
relativePosition: true,
geoObject: {
color: "rgb(90,90,90)",
instanced: true,
tag: `cylinderObj`,
object3d: cylinderObj
}
});
childEntity.appendChild(childChildEntity);
parentEntity.appendChild(childEntity);
let collection = new EntityCollection({
entities: [parentEntity]
});
collection.addTo(this);
this.renderer.activeCamera.set(new Vec3(-4, 11, 13), new Vec3(1, 0, 0));
this.renderer.activeCamera.update();
}
}
renderer.addNodes([new scene.Axes(), new MyScene()]);

View File

@ -299,6 +299,7 @@ class Entity {
protected _yawRad: number;
protected _rollRad: number;
protected _scale: Vec3;
protected _absoluteScale: Vec3;
protected _qFrame: Quat;
protected _qRot: Quat;
public _absoluteQRot: Quat;
@ -357,6 +358,7 @@ class Entity {
this._rollRad = options.roll || 0;
this._scale = utils.createVector3(options.scale, new Vec3(1, 1, 1));
this._absoluteScale = new Vec3();
this._qFrame = Quat.IDENTITY;
this._qRot = Quat.IDENTITY;
@ -596,11 +598,8 @@ class Entity {
* @param {Vec3} scale - Scale factor
*/
public setScale3v(scale: Vec3) {
this._scale.copy(scale);
this.geoObject && this.geoObject.setScale3v(this._scale);
this._updateAbsolutePosition();
for (let i = 0; i < this.childEntities.length; i++) {
let chi = this.childEntities[i];
if (chi.forceGlobalScale) {
@ -617,19 +616,16 @@ class Entity {
* @param {number} val - Scale factor
*/
public setScale(val: number) {
this._scale.set(val, val, val);
this.geoObject && this.geoObject.setScale(val);
this._updateAbsolutePosition();
for (let i = 0; i < this.childEntities.length; i++) {
let chi = this.childEntities[i];
if (chi.forceGlobalScale) {
chi.setScale(val);
chi.setScale3v(this._scale);
} else {
chi.setScale3v(this.childEntities[i].getScale());
}
}
}
}
/**
@ -871,7 +867,7 @@ class Entity {
if (this.parent && this._relativePosition) {
let scd = this._getScaleByDistance();
pos = absolutCartesian.sub(this.parent.getAbsoluteCartesian()).scale(1 / scd);
pos = absolutCartesian.sub(this.parent.getAbsoluteCartesian()).scale(1 / scd).divA(this._absoluteScale);
pos = this.parent._absoluteQRot.conjugate().mulVec3(pos);
}
@ -945,13 +941,15 @@ class Entity {
let parent = this.parent;
if (parent && this._relativePosition) {
this._scale.mulRes(parent._absoluteScale, this._absoluteScale);
this._qFrame.copy(parent._qFrame);
this._rootCartesian.copy(parent._rootCartesian);
this._qRot.setPitchYawRoll(this._pitchRad, this._yawRad, this._rollRad);
parent._absoluteQRot.mulRes(this._qRot, this._absoluteQRot);
let rotCart = parent._absoluteQRot.mulVec3(this._cartesian.add(this._localPosition));
let rotCart = parent._absoluteQRot.mulVec3(this._cartesian.add(this._localPosition)).mulA(this._absoluteScale);
parent._absoluteLocalPosition.addRes(rotCart, this._absoluteLocalPosition);
} else {
this._qFrame = Quat.IDENTITY;
@ -963,12 +961,14 @@ class Entity {
} else {
this._qRot.setPitchYawRoll(this._pitchRad, this._yawRad, this._rollRad, this._qFrame);
}
this._absoluteScale.copy(this._scale);
this._absoluteQRot.copy(this._qRot);
this._rootCartesian.copy(this._cartesian);
this._absoluteLocalPosition.copy(this._localPosition);
}
if (this.geoObject) {
this.geoObject.setScale3v(this._absoluteScale);
this.geoObject.setRotation(this._absoluteQRot);
this.geoObject.setPosition3v(this._rootCartesian);
this.geoObject.setLocalPosition3v(this._absoluteLocalPosition);