Skip to content

Commit

Permalink
feat(sample): samples of animation (#115)
Browse files Browse the repository at this point in the history
Add samples to show how to use skeletal animation and property animation
Add sample of how to control the morphtarget animation
pdate shadow bias
  • Loading branch information
hellmor authored May 9, 2023
1 parent eeac1fc commit a68bb77
Show file tree
Hide file tree
Showing 6 changed files with 499 additions and 1 deletion.
105 changes: 105 additions & 0 deletions samples/animation/Sample_CurveAnimation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Object3D, Scene3D, AnimationCurve, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, Keyframe, Object3DUtil, Time } from "@orillusion/core";

class Sample_AnimCurve {
lightObj3D: Object3D;
scene: Scene3D;
Duck: Object3D;
curve1: AnimationCurve;
curve2: AnimationCurve;
curve3: AnimationCurve;
curve4: AnimationCurve;

async run() {
await Engine3D.init({ beforeRender: () => this.renderUpdate() });

Engine3D.setting.shadow.shadowBound = 100;
Engine3D.setting.shadow.shadowBias = 0.0001;
Engine3D.setting.shadow.pointShadowBias = 0.6;
Engine3D.setting.shadow.debug = true;

Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.updateFrameRate = 1;
Engine3D.setting.shadow.type = `HARD`;

this.scene = new Scene3D();
this.scene.addComponent(AtmosphericComponent);

let camera = CameraUtil.createCamera3DObject(this.scene);
camera.perspective(60, Engine3D.aspect, 0.01, 5000.0);

camera.object3D.addComponent(HoverCameraController).setCamera(-30, -25, 400);

let view = new View3D();
view.scene = this.scene;
view.camera = camera;

Engine3D.startRenderView(view);

await this.initScene();
}

async initScene() {
/******** light *******/
{
this.lightObj3D = new Object3D();
this.lightObj3D.rotationX = 15;
this.lightObj3D.rotationY = 110;
this.lightObj3D.rotationZ = 0;
let directLight = this.lightObj3D.addComponent(DirectLight);
directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
directLight.castShadow = true;
directLight.intensity = 10;
this.scene.addChild(this.lightObj3D);

//create animation curve 1
this.curve1 = new AnimationCurve();
this.curve1.addKeyFrame(new Keyframe(0, 1));
this.curve1.addKeyFrame(new Keyframe(0.5, 2));
this.curve1.addKeyFrame(new Keyframe(0.7, 2));
this.curve1.addKeyFrame(new Keyframe(1.0, 1));

//create animation curve 2

this.curve2 = new AnimationCurve();
this.curve2.addKeyFrame(new Keyframe(0, 0));
this.curve2.addKeyFrame(new Keyframe(1, 360));

//create animation curve 3
this.curve3 = new AnimationCurve();
this.curve3.addKeyFrame(new Keyframe(0, -5));
this.curve3.addKeyFrame(new Keyframe(0.3, 3));
this.curve3.addKeyFrame(new Keyframe(0.6, 8));
this.curve3.addKeyFrame(new Keyframe(0.9, -2));
this.curve3.addKeyFrame(new Keyframe(1.0, -5));

//create animation curve 4
this.curve4 = new AnimationCurve();
this.curve4.addKeyFrame(new Keyframe(0, 1));
this.curve4.addKeyFrame(new Keyframe(0.3, -9));
this.curve4.addKeyFrame(new Keyframe(0.6, -2));
this.curve4.addKeyFrame(new Keyframe(0.9, 2));
this.curve4.addKeyFrame(new Keyframe(1.0, 1));

}

this.scene.addChild(Object3DUtil.GetSingleCube(300, 5, 300, 1, 1, 1));

// load a gltf model
this.Duck = (await Engine3D.res.loadGltf('PBR/Duck/Duck.gltf')) as Object3D;
this.Duck.scaleX = this.Duck.scaleY = this.Duck.scaleZ = 0.3;
this.scene.addChild(this.Duck);
}

renderUpdate() {
//modify animation attribute values to the model
if (this.Duck) {
let time = (Time.time * 0.4 % (1000) / 1000);
this.Duck.y = this.curve1.getValue(time) * 5;
this.Duck.x = this.curve3.getValue(time) * 5;
this.Duck.z = this.curve4.getValue(time) * 5;
this.Duck.rotationY = this.curve2.getValue(time);
}
}
}

new Sample_AnimCurve().run();
93 changes: 93 additions & 0 deletions samples/animation/Sample_MorphTarget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { Object3D, Scene3D, Engine3D, AtmosphericComponent, webGPUContext, HoverCameraController, View3D, DirectLight, KelvinUtil, Vector3, MorphTargetBlender, Entity, CameraUtil } from "@orillusion/core";
import { GUIUtil } from "@samples/utils/GUIUtil";

// Sample of how to control the morphtarget animation
class Sample_MorphTarget {
lightObj3D: Object3D;
scene: Scene3D;
influenceData: { [key: string]: number } = {};

async run() {
Engine3D.setting.shadow.shadowBias = 0.0001;

await Engine3D.init();

this.scene = new Scene3D();
this.scene.addComponent(AtmosphericComponent);

let camera = CameraUtil.createCamera3DObject(this.scene);
camera.perspective(60, webGPUContext.aspect, 1, 5000.0);
camera.object3D.addComponent(HoverCameraController).setCamera(0, 0, 150);

this.initDirectLight();
await this.initMorphModel();

let view = new View3D();
view.scene = this.scene;
view.camera = camera;

Engine3D.startRenderView(view);
}

/******** light *******/
initDirectLight() {
this.lightObj3D = new Object3D();
this.lightObj3D.rotationX = 21;
this.lightObj3D.rotationY = 108;
this.lightObj3D.rotationZ = 10;

let directLight = this.lightObj3D.addComponent(DirectLight);
directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
directLight.castShadow = true;
directLight.intensity = 25;
GUIUtil.renderDirLight(directLight, false);
this.scene.addChild(this.lightObj3D);
}

private async initMorphModel() {
GUIHelp.init();

// load lion model
let model = await Engine3D.res.loadGltf('gltfs/glb/lion.glb');
model.y = -80.0;
model.x = -30.0;
this.scene.addChild(model);

GUIHelp.addFolder('morph controller');
// register MorphTargetBlender component
let blendShapeComponent = model.addComponent(MorphTargetBlender);
let targetRenderers = blendShapeComponent.cloneMorphRenderers();

// bind influenceData to gui
for (let key in targetRenderers) {
this.influenceData[key] = 0.0;
GUIHelp.add(this.influenceData, key, 0, 1, 0.01).onChange((v) => {
this.influenceData[key] = v;
let list = blendShapeComponent.getMorphRenderersByKey(key);
for (let renderer of list) {
renderer.setMorphInfluence(key, v);
}
});
}

GUIHelp.open();
GUIHelp.endFolder();

// print hierarchy
this.printHierarchy(model);
}


private printHierarchy(obj: Entity, path: string = '') {
console.log(path, obj.name);

path += '== ';
for (let child of obj.entityChildren) {
this.printHierarchy(child, path);
}
}

}

new Sample_MorphTarget().run();
75 changes: 75 additions & 0 deletions samples/animation/Sample_Skeleton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, webGPUContext, HoverCameraController, View3D, LitMaterial, MeshRenderer, BoxGeometry, DirectLight, KelvinUtil, Object3DUtil } from "@orillusion/core";
import { GUIUtil } from "@samples/utils/GUIUtil";

class Sample_Skeleton {
lightObj3D: Object3D;
scene: Scene3D;
async run() {

Engine3D.setting.material.materialDebug = false;
Engine3D.setting.material.materialChannelDebug = true;
Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.updateFrameRate = 2;
Engine3D.setting.shadow.shadowBound = 200;
Engine3D.setting.shadow.shadowBias = 0.0001;

await Engine3D.init();

this.scene = new Scene3D();
this.scene.addComponent(AtmosphericComponent);

let camera = CameraUtil.createCamera3DObject(this.scene);
camera.perspective(60, Engine3D.aspect, 0.01, 5000.0);

let ctrl = camera.object3D.addComponent(HoverCameraController);
ctrl.setCamera(0, -45, 100);
ctrl.maxDistance = 1000;

let view = new View3D();
view.scene = this.scene;
view.camera = camera;

Engine3D.startRenderView(view);

this.initScene(this.scene);
}


async initScene(scene: Scene3D) {
GUIHelp.init();
{
// load model with skeleton animation
let man = await Engine3D.res.loadGltf('gltfs/CesiumMan/CesiumMan_compress.gltf');
man.scaleX = 30;
man.scaleY = 30;
man.scaleZ = 30;
scene.addChild(man);
}

/******** floor *******/
this.scene.addChild(Object3DUtil.GetSingleCube(3000, 1, 3000, 0.5, 0.5, 0.5));

/******** light *******/
{
this.lightObj3D = new Object3D();
this.lightObj3D.x = 0;
this.lightObj3D.y = 30;
this.lightObj3D.z = -40;
this.lightObj3D.rotationX = 144;
this.lightObj3D.rotationY = 0;
this.lightObj3D.rotationZ = 0;
let directLight = this.lightObj3D.addComponent(DirectLight);
directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
directLight.castShadow = true;
directLight.intensity = 25;
GUIUtil.renderDirLight(directLight);
scene.addChild(this.lightObj3D);
}

return true;
}

}

new Sample_Skeleton().run();
101 changes: 101 additions & 0 deletions samples/animation/Sample_Skeleton2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, webGPUContext, HoverCameraController, View3D, LitMaterial, MeshRenderer, BoxGeometry, DirectLight, KelvinUtil, Object3DUtil, SkeletonAnimationComponent } from "@orillusion/core";
import { GUIUtil } from "@samples/utils/GUIUtil";

class Sample_Skeleton2 {
lightObj3D: Object3D;
scene: Scene3D;

async run() {

Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.updateFrameRate = 2;
Engine3D.setting.shadow.shadowBound = 500;
Engine3D.setting.shadow.shadowBias = 0.0001;

await Engine3D.init();

this.scene = new Scene3D();
this.scene.addComponent(AtmosphericComponent);
this.scene.exposure = 1;

let mainCamera = CameraUtil.createCamera3DObject(this.scene);
mainCamera.perspective(60, webGPUContext.aspect, 1, 3000.0);

let hoverCameraController = mainCamera.object3D.addComponent(HoverCameraController);
hoverCameraController.setCamera(45, -30, 300);
hoverCameraController.maxDistance = 500.0;

await this.initScene(this.scene);

let view = new View3D();
view.scene = this.scene;
view.camera = mainCamera;

Engine3D.startRenderView(view);
}

async initScene(scene: Scene3D) {
{
// load model with skeletion animation
let rootNode = await Engine3D.res.loadGltf('gltfs/glb/Soldier.glb');
let character = rootNode.getObjectByName('Character') as Object3D;
character.scaleX = 0.3;
character.scaleY = 0.3;
character.scaleZ = 0.3;
character.rotationY = 180;

// enum animation names
var animName = ['Idel', 'Walk', 'Run', 'TPose'];
let maxCount = 100;
let maxCol = 10;
let maxRow = Math.floor(maxCount / maxCol);
// Clone 100 players to play different animations
for (var i = 0; i < maxCount; i++) {
let cloneObj = character.clone();

let row = Math.floor(i / maxCol);
let col = Math.floor(i % maxCol);

cloneObj.x = (maxCol * -0.5 + col) * 30;
cloneObj.z = (maxRow * -0.5 + row) * 30;
scene.addChild(cloneObj);

let animation = cloneObj.getComponentsInChild(SkeletonAnimationComponent)[0];

if (i < animName.length) {
animation.play(animName[i]);
} else {
let animIndex = Math.floor(Math.random() * 100 % 3);
animation.play(animName[animIndex], -5 + Math.random() * 10);
}
}
}

/******** floor *******/
this.scene.addChild(Object3DUtil.GetSingleCube(3000, 1, 3000, 0.5, 0.5, 0.5));

/******** light *******/
{
this.lightObj3D = new Object3D();
this.lightObj3D.x = 0;
this.lightObj3D.y = 30;
this.lightObj3D.z = -40;
this.lightObj3D.rotationX = 144;
this.lightObj3D.rotationY = 0;
this.lightObj3D.rotationZ = 0;
let directLight = this.lightObj3D.addComponent(DirectLight);
directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
directLight.castShadow = true;
directLight.intensity = 40;
GUIHelp.init();
GUIUtil.renderDirLight(directLight);
scene.addChild(this.lightObj3D);
}

return true;
}

}

new Sample_Skeleton2().run();
Loading

0 comments on commit a68bb77

Please sign in to comment.