Skip to content

Commit

Permalink
fix(engine): Fixed a series of issues and improved functionality (#255)
Browse files Browse the repository at this point in the history
1. Supports MeshCollider;
2. Expand attribute animation to support more attribute curves and fix bugs in clone PropertyAnimation;
3. After picking up the UI from the GUI, it no longer penetrates into the 3D space to pick up 3D objects;
4. Support GUI for adaptive scaling based on screen size;
5. Fix a bug caused by UI Image switching to sprites belonging to different atlases in the GUI.
6. Fix bug: MeshRender clone;
7. Added API (getBaseColor) for material to obtain references to baseColor;
8. Improve the clone method of UnLitMaterial;
9. Fix errors of SphereColliderShape.ts
10. decoration errors of experimentalDecorators
  • Loading branch information
hellmor committed Jul 24, 2023
1 parent 70ece43 commit 1b30982
Show file tree
Hide file tree
Showing 36 changed files with 744 additions and 310 deletions.
69 changes: 69 additions & 0 deletions samples/pick/Sample_MeshColliderPick.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { GUIUtil } from "@samples/utils/GUIUtil";
import { createExampleScene } from "@samples/utils/ExampleScene";
import { Scene3D, Engine3D, BoxGeometry, SphereGeometry, SphereColliderShape, BoxColliderShape, Vector3, Object3D, MeshRenderer, LitMaterial, ColliderComponent, PointerEvent3D, Color, MeshColliderShape } from "@orillusion/core";

class Sample_MeshColliderPick {
scene: Scene3D;
async run() {
Engine3D.setting.pick.enable = true;
Engine3D.setting.pick.mode = `bound`;

// init Engine3D
await Engine3D.init({});

let exampleScene = createExampleScene();
this.scene = exampleScene.scene;

GUIHelp.init();

GUIUtil.renderDirLight(exampleScene.light, false);
Engine3D.startRenderView(exampleScene.view);

this.initPickObject(this.scene);
}

//create some interactive boxes
private initPickObject(scene: Scene3D): void {
let size: number = 9;

//geometry
let boxGeometry = new BoxGeometry(size, size, size);
let sphereGeometry = new SphereGeometry(size / 2, 20, 20);

//collider shape

for (let i = 0; i < 10; i++) {
let obj = new Object3D();
obj.name = 'sphere ' + i;
scene.addChild(obj);
obj.x = (i - 5) * 15;
let renderer = obj.addComponent(MeshRenderer);
renderer.geometry = i % 2 ? boxGeometry : sphereGeometry;
renderer.material = new LitMaterial();

let meshShape = new MeshColliderShape();
meshShape.mesh = renderer.geometry;

// register collider component
let collider = obj.addComponent(ColliderComponent);
collider.shape = meshShape;
}
let pickFire = Engine3D.views[0].pickFire;
// register event
pickFire.addEventListener(PointerEvent3D.PICK_CLICK, this.onMousePick, this);
}

private onMousePick(e: PointerEvent3D) {
let pick = e.data.pick;
if (pick && pick.object3D) {
let obj = pick.object3D;
let meshRenderer = obj.getComponent(MeshRenderer);
//modify base color
meshRenderer.material.baseColor = new Color(Math.random(), Math.random(), Math.random())
}
}

}

new Sample_MeshColliderPick().run();
12 changes: 12 additions & 0 deletions src/Engine3D.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { ShaderLib } from './assets/shader/ShaderLib';
import { ShaderUtil } from './gfx/graphics/webGpu/shader/util/ShaderUtil';
import { ComponentCollect } from './gfx/renderJob/collect/ComponentCollect';
import { ShadowLightsCollect } from './gfx/renderJob/collect/ShadowLightsCollect';
import { GUIConfig } from './components/gui/GUIConfig';

/**
* Orillusion 3D Engine
Expand Down Expand Up @@ -399,10 +400,21 @@ export class Engine3D {
this.resume();
}

private static updateGUIPixelRatio(screenWidth: number, screenHeight: number) {
let xyRatioSolution = GUIConfig.solution.x / GUIConfig.solution.y;
let xyRatioCurrent = screenWidth / screenHeight;
if (xyRatioSolution < xyRatioCurrent) {
GUIConfig.pixelRatio = screenHeight / GUIConfig.solution.y;
} else {
GUIConfig.pixelRatio = screenWidth / GUIConfig.solution.x;
}
}

private static updateFrame(time: number) {
Time.delta = time - Time.time;
Time.time = time;
Time.frame += 1;
this.updateGUIPixelRatio(webGPUContext.canvas.clientWidth, webGPUContext.canvas.clientHeight);

Interpolator.tick(Time.delta);
if (this._beforeRender) this._beforeRender();
Expand Down
4 changes: 2 additions & 2 deletions src/components/ColliderComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Ray } from "../math/Ray";
import { Vector3 } from "../math/Vector3";
import { ComponentBase } from "./ComponentBase";
import { BoxColliderShape } from "./shape/BoxColliderShape";
import { ColliderShape } from "./shape/ColliderShape";
import { ColliderShape, HitInfo } from "./shape/ColliderShape";

/**
* collider component
Expand Down Expand Up @@ -44,7 +44,7 @@ export class ColliderComponent extends ComponentBase {
* @param ray
* @returns
*/
public rayPick(ray: Ray): { intersect: boolean; intersectPoint?: Vector3; distance: number } {
public rayPick(ray: Ray): HitInfo {
if (this._enable) {
return this._shape.rayPick(ray, this.transform.worldMatrix);
}
Expand Down
12 changes: 7 additions & 5 deletions src/components/ComponentBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ export class ComponentBase implements IComponent {
if (this._enable != value) {
this._enable = value;
if (this._enable) {
this.onEnable?.();
this.onEnable?.(this.transform.view3D);
} else {
this.onDisable?.();
this.onDisable?.(this.transform.view3D);
}
}
}
Expand All @@ -74,8 +74,8 @@ export class ComponentBase implements IComponent {
this.start?.();
this.__isStart = true;
}
if (this.transform && this.transform.scene3D) {
this.onEnable?.();
if (this.transform && this.transform.scene3D && this._enable) {
this.onEnable?.(this.transform.view3D);
}
if (this.onUpdate) {
this._onUpdate(this.onUpdate.bind(this));
Expand All @@ -96,7 +96,7 @@ export class ComponentBase implements IComponent {

private __stop() {
if (this.transform && this.transform.scene3D) {
this.onDisable?.();
this.onDisable?.(this.transform.view3D);
}
this._onUpdate(null);
this._onLateUpdate(null);
Expand Down Expand Up @@ -125,6 +125,8 @@ export class ComponentBase implements IComponent {
*/
public cloneTo(obj: Object3D) { }

public copyComponent(from: this): this { return this; }

/**
* internal
* Add update function. Will be executed at every frame update.
Expand Down
150 changes: 74 additions & 76 deletions src/components/anim/curveAnim/AnimationMonitor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Object3D } from '../../../core/entities/Object3D';
import { IObject3DForPropertyAnim, Object3D } from '../../../core/entities/Object3D';
import { repeat, clamp } from '../../../math/MathUtil';
import { Matrix4 } from '../../../math/Matrix4';
import { PropertyAnimClip, WrapMode } from './PropertyAnimClip';
import { PropertyAnimation } from './PropertyAnimation';
import { PropertyHelp } from './PropertyHelp';
import { PropertyAnimTag, PropertyHelp } from './PropertyHelp';

/**
* @internal
Expand All @@ -13,28 +13,28 @@ export class AnimationMonitor {
public static readonly Complete: number = 0;
public static readonly Seek: number = 1;

private _propertyAnimClip: { [animName: string]: PropertyAnimClip };
private _target: Object3D;
private _rootObject3D: Object3D;
private _animation: PropertyAnimation;
private _propertyCache: {
[path: string]: { [attribute: string]: { value: any; property: string } };
};
private _bindObjects: Object3D[] = [];
private _currentClip: PropertyAnimClip;
private _frame: number = 0;
private _time: number = 0;
private _isPlaying: boolean = true;
public speed: number = 1;
private _propertyTagDic: Map<Object3D, PropertyAnimTag>;

constructor(animation: PropertyAnimation) {
this._target = animation.object3D;
this._rootObject3D = animation.object3D;
this._animation = animation;
this._propertyAnimClip = {};
this._propertyCache = {};
this._propertyTagDic = new Map<Object3D, PropertyAnimTag>();
this.reset();
}

public get object3D() {
return this._target;
private reset(): void {
this._propertyCache = {};
this._propertyTagDic.clear();
}

public get time(): number {
Expand All @@ -45,68 +45,59 @@ export class AnimationMonitor {
return this._currentClip;
}

public getClip(name: string): PropertyAnimClip {
return this._propertyAnimClip[name];
public play(clip: PropertyAnimClip, reset: boolean = true) {
this._isPlaying = true;
if (reset) {
this._time = 0;
}
if (clip != this._currentClip) {
if (clip) {
this.parseAnimClip(clip);
}
}
this._currentClip = clip;
this.validProperty();
}

public addClip(clip: PropertyAnimClip): this {
this._propertyAnimClip[clip.name] = clip;
private parseAnimClip(clip: PropertyAnimClip): this {
this.reset();

for (const objPath in clip.objAnimClip) {
let objClip = clip.objAnimClip[objPath];
let bind = this._target;
let bindObject3D = this._rootObject3D;
let attsCache = {};
if (objPath == '') {
bind = this._target;
bindObject3D = this._rootObject3D;
} else {
// let objNames = objPath.split('/');
// let objName = objNames[objNames.length - 1];
bind = this._target.getObjectByName(objPath) as Object3D;
bindObject3D = this._rootObject3D.getObjectByName(objPath) as Object3D;
}
if (!bindObject3D)
continue;

let tag = new PropertyAnimTag();
this._propertyTagDic.set(bindObject3D, tag);

let curve = objClip.curve;
for (const attribute in curve) {
if (Object.prototype.hasOwnProperty.call(curve, attribute)) {
// const attributeAnim = curve[attribute];
// let att = PropertyHelp.property[attribute];
let atts = PropertyHelp.property[attribute].split('.');
if (bind) {
if (this._bindObjects.indexOf(bind) == -1) {
this._bindObjects.push(bind);
}
if (this._propertyCache[objPath] == null) {
this._propertyCache[objPath] = {};

}
this._propertyCache[objPath][attribute] = {
value: bind[atts[0]],
property: atts[1],
};
for (let i = 1; i < atts.length - 1; i++) {
this._propertyCache[objPath][attribute] = {
value: bind[atts[i]],
property: atts[i + 1],
};
}
PropertyHelp.updatePropertyTag(tag, attribute);
let binder = this._propertyCache[objPath] ||= {};

let atts = PropertyHelp.Property[attribute].split('.');
let atts_0 = atts[0];
if (atts.length > 1) {
let value = attsCache[atts_0];
if (!value) {
value = attsCache[atts_0] = bindObject3D[atts_0];
}
binder[attribute] = { value: value, property: atts[1] };
} else {
binder[attribute] = { value: bindObject3D, property: atts[0] };
}
}
}
return this;
}

public play(name: string, reset: boolean = true): PropertyAnimClip {
let clip = this._propertyAnimClip[name];
if (!clip) return null;

this._isPlaying = true;

if (reset || !this._currentClip || this._currentClip.name != name) {
this._time = 0;
}
this._currentClip = clip;
return this._currentClip;
}

public stop(): this {
this._isPlaying = false;
return this;
Expand Down Expand Up @@ -143,7 +134,7 @@ export class AnimationMonitor {

public seek(time: number): this {
this._time = this.calcTime(time);
this.validProperty();
this._rootObject3D && this.validProperty();
return this;
}

Expand All @@ -157,31 +148,38 @@ export class AnimationMonitor {
}

private validProperty() {
if (this._target) {
for (const objName in this._currentClip.objAnimClip) {
let objClip = this._currentClip.objAnimClip[objName];
let hasQuaternion = false;
let curve = objClip.curve;
for (const attribute in curve) {
if (Object.prototype.hasOwnProperty.call(curve, attribute)) {
const attributeAnim = curve[attribute];
// this.target[PropertyHelp.property[key]] = attributeAnim.getValue(this._time);
let value = this._propertyCache[objName][attribute];
let scale = PropertyHelp.property_scale[attribute];
hasQuaternion = hasQuaternion || PropertyHelp.property_quaternion[attribute];
let ret = attributeAnim.getValue(this._time) * scale + PropertyHelp.property_offset[attribute];
value.value[value.property] = ret;
}
for (const objName in this._currentClip.objAnimClip) {
let objClip = this._currentClip.objAnimClip[objName];
let curve = objClip.curve;
for (const attribute in curve) {
const attributeAnim = curve[attribute];
let target = this._propertyCache[objName][attribute];
let ret = attributeAnim.getValue(this._time);
if (attribute in PropertyHelp.Scale) {
ret *= PropertyHelp.Scale[attribute];
}

if (hasQuaternion) {
let transform = this._target.transform;
Matrix4.getEuler(transform.localRotation, transform.localRotQuat, true, 'ZYX');
}
target.value[target.property] = ret;
}
}
for (let i of this._bindObjects) {
i.transform.notifyChange();
//
this._propertyTagDic.forEach((v, k) => {
this.applyProperty(v, k);
})

}

private applyProperty(tag: PropertyAnimTag, obj3d: Object3D) {
if (tag.quaternion) {
Matrix4.getEuler(obj3d.transform.localRotation, obj3d.transform.localRotQuat, true, 'ZYX');
}
if (tag.transform) {
obj3d.transform.notifyChange();
}

let animObj: IObject3DForPropertyAnim = obj3d as any as IObject3DForPropertyAnim;
if (tag.materialColor) {
animObj.notifyMaterialColorChange(0, 'baseColor');
}
}
}

0 comments on commit 1b30982

Please sign in to comment.