Scene Model
We initialized the camera projection and pose in the initCamera()
function:
initCamera() {
/**
* Create our camera model with a perspective projection defined by a 90 degree field of view,
* aspect ratio of 1 (this can change when the window resizes), a near plane at depth of 0.01
* and a far plane at depth of 10.
*/
this.cameraModel = ACameraModel.CreatePerspectiveFOV(90, 1, 0.01, 10);
/**
* Set to pose of our camera
*/
this.cameraModel.setPose(
/**
* Create a transform for our camera pose using the LookAt function, which takes a
* location, target, and up vector.
*/
NodeTransform3D.LookAt(
V3(0.0, -AppConfigs.CameraDefaultHeight, AppConfigs.CameraDefaultHeight), V3(0,0,0),
V3(0,0,1)
)
)
}
initTerrain()
creates the terrain
async initTerrain(){
this.terrain = await TerrainModel.Create(
AppConfigs.GroundTexture, // texture
AppConfigs.TerrainScaleX, // scaleX
AppConfigs.TerrainScaleY, // scaleY
AppConfigs.TerrainDataTextureWidth, // number of vertices wide
AppConfigs.TerrainDataTextureHeight, // number of vertices tall
undefined, // transform for terrain, identity if left blank
AppConfigs.TerrainWrapTextureX, // number of times texture should wrap across surface in X
AppConfigs.TerrainWrapTextureY, // number of times texture should wrap across surface in Y
);
this.addChild(this.terrain);
}
AppConfigs is a convenient place to collect global constants that you may want to set or tweak while developing your project. The code above uses AppConfigs
to control properties of the terrain. Check out the TerrainModel class to learn more about how it works.
We initialize the characters with:
async initCharacters(){
/**
* First we will initialze the player and add it to the scene.
*/
this.playerTexture = await ATexture.LoadAsync("./images/tanktexburngreen.jpeg")
this.player = await PlayerModel.Create(this.playerTexture);
this.addChild(this.player);
/**
* Then we will create a bunch of bots with different cat faces...
* Let's make each one a child of the last.
*/
let parent:AModel = this;
for(let e=0;e<6; e++) {
let bot = await BotModel.Create(`./images/catfaces/catface0${e + 1}.jpeg`);
bot.position = new Vec3((Math.random() - 0.5) * AppConfigs.TerrainScaleX, (Math.random() - 0.5) * AppConfigs.TerrainScaleY, 0);
bot.mass = 50;
this.bots.push(bot);
parent.addChild(bot);
parent = bot;
}
}
Most of the setup is executed through initScene()
:
async initScene() {
await this.initTerrain();
await this.initCharacters();
this.addChild(new ExampleThreeJSNodeModel());
/**
* Now an example particle system.
*/
let particles = new ExampleParticleSystemModel();
particles.orbitRadius = 0.3;
let radius = 0.05;
particles.addParticle(new SphereParticle(undefined, undefined, radius));
particles.addParticle(new SphereParticle(undefined, undefined, radius));
particles.addParticle(new SphereParticle(undefined, undefined, radius));
/**
* We will add the particle system to one of the bots for kicks...
*/
this.bots[this.bots.length-1].addChild(particles);
/**
* Now let's initialize the view light
*/
this.initViewLight();
}
And we also define a function for updating the model every time a frame is rendered:
timeUpdate(t: number, ...args:any[]) {
/**
* We can call timeUpdate on all of the model nodes in the scene here, which will trigger any updates that they
* individually define.
*/
for(let c of this.getDescendantList()){
c.timeUpdate(t);
}
/**
* For interactions between models, we can trigger logic here. For example, if you want characters to walk on
* uneven terrain, you can make that happen by completing the functions used here:
*/
const self = this;
function adjustHeight(character:Particle3D){
let height = self.terrain.getTerrainHeightAtPoint(character.position.xy);
if(character.position.z<height){character.position.z = height;}
}
/**
* Here we would apply our adjust height function to the player
*/
adjustHeight(this.player);
/**
* Now lets update bots
*/
let orbitradius = 0.25;
for(let ei=0;ei<this.bots.length;ei++){
let e = this.bots[ei];
/**
* Characters have velocity and mass properties in case you want to implement particle physics
* But for now we will just have them orbit each other.
*/
e.position = new Vec3(Math.cos(t*(ei+1)), Math.sin(t*(ei+1)),0).times(orbitradius);
/**
* adjust their height
*/
adjustHeight(e);
}
}