Skip to content

Commit

Permalink
fix(culling): Camera frustum culling (#198)
Browse files Browse the repository at this point in the history
Fix rendering objects being incorrectly culled by the camera
rename class
fix error : init boundbox
fix error : init boundbox
  • Loading branch information
hellmor committed May 31, 2023
1 parent 39c1056 commit 8cfd1ab
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 163 deletions.
40 changes: 7 additions & 33 deletions samples/loader/Sample_LoadGLB.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,21 @@
import { Object3D, Scene3D, HoverCameraController, Engine3D, CameraUtil, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, PlaneGeometry, AtmosphericComponent } from "@orillusion/core";
import { Engine3D, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, Scene3D } from "@orillusion/core";
import { createExampleScene } from "@samples/utils/ExampleScene";

// Sample to load glb file
export class Sample_LoadGLB {
lightObj3D: Object3D;
scene: Scene3D;

async run() {
await Engine3D.init();
Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.shadowBias = 0.0001;

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

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

camera.object3D.addComponent(HoverCameraController).setCamera(-45, -30, 15);

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

Engine3D.startRenderView(view);

let exampleScene = createExampleScene();
this.scene = exampleScene.scene;
Engine3D.startRenderView(exampleScene.view);
await this.initScene();
}

async initScene() {
/******** light *******/
{
this.lightObj3D = new Object3D();
this.lightObj3D.rotationX = 21;
this.lightObj3D.rotationY = 108;
this.lightObj3D.rotationZ = 10;
let lc = this.lightObj3D.addComponent(DirectLight);
lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
lc.castShadow = true;
lc.intensity = 10;
lc.debug();
this.scene.addChild(this.lightObj3D);
}

/******** floor *******/
{
let mat = new LitMaterial();
Expand All @@ -50,15 +24,15 @@ export class Sample_LoadGLB {
mat.metallic = 0.1;
let floor = new Object3D();
let mr = floor.addComponent(MeshRenderer);
mr.geometry = new PlaneGeometry(100, 100);
mr.geometry = new PlaneGeometry(200, 200);
mr.material = mat;
this.scene.addChild(floor);
}

/******** load glb file *******/
let model = (await Engine3D.res.loadGltf('gltfs/UR3E/UR3E.glb', { onProgress: (e) => this.onLoadProgress(e), onComplete: (e) => this.onComplete(e) })) as Object3D;
this.scene.addChild(model);
model.scaleX = model.scaleY = model.scaleZ = 5;
model.scaleX = model.scaleY = model.scaleZ = 50;
}

onLoadProgress(e) {
Expand Down
35 changes: 35 additions & 0 deletions samples/loader/Sample_LoadGLTF2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Engine3D, Object3D, Object3DUtil, Scene3D } from "@orillusion/core";
import { createExampleScene } from "@samples/utils/ExampleScene";

//Samples to show models, they are using PBR material
class Sample_LoadGLTF2 {
lightObj3D: Object3D;
scene: Scene3D;
async run() {
//config settings
Engine3D.setting.material.materialChannelDebug = true;
Engine3D.setting.shadow.shadowBound = 80;
Engine3D.setting.shadow.shadowBias = 0.0001;

//init engine
await Engine3D.init();
let exampleScene = createExampleScene();
this.scene = exampleScene.scene;
Engine3D.startRenderView(exampleScene.view);
await this.initScene();
}

async initScene() {

let floor = Object3DUtil.GetSingleCube(100, 4, 100, 0.5, 0.5, 0.5);
floor.y = -10;
this.scene.addChild(floor);

let chair = await Engine3D.res.loadGltf('PBR/SheenChair/SheenChair.gltf') as Object3D;
chair.scaleX = chair.scaleY = chair.scaleZ = 60;
chair.rotationZ = chair.rotationX = 45;
this.scene.addChild(chair);
}
}

new Sample_LoadGLTF2().run();
23 changes: 8 additions & 15 deletions samples/loader/Sample_LoadJson.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,24 @@
import { Scene3D, Engine3D, AtmosphericComponent, CameraUtil, View3D, Object3D, MeshRenderer, BoxGeometry, LitMaterial, PropertyAnimation, PropertyAnimClip, WrapMode, HoverCameraController } from "@orillusion/core";
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { Scene3D, Engine3D, BoxGeometry, LitMaterial, MeshRenderer, Object3D, PropertyAnimClip, PropertyAnimation, WrapMode } from "@orillusion/core";
import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene";

// Sample to load json file
export class Sample_LoadJson {
scene: Scene3D;

async run() {
await Engine3D.init();
let param = createSceneParam();
param.camera.distance = 10;
let exampleScene = createExampleScene(param);

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

let camera = CameraUtil.createCamera3DObject(this.scene);
camera.perspective(60, Engine3D.aspect, 1, 5000.0);
camera.object3D.addComponent(HoverCameraController).setCamera(25, -15, 10);

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

Engine3D.startRenderView(view);
this.scene = exampleScene.scene;
Engine3D.startRenderView(exampleScene.view);

let json = await Engine3D.res.loadJSON('json/anim_0.json', { onProgress: this.onLoadProgress, onComplete: this.onComplete });
console.log('[loaded]', json);

let box = new Object3D()
let mr = box.addComponent(MeshRenderer)
let mr = box.addComponent(MeshRenderer);
mr.geometry = new BoxGeometry()
mr.material = new LitMaterial()
this.scene.addChild(box)
Expand Down
7 changes: 2 additions & 5 deletions src/components/controller/HoverCameraController.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { View3D } from "../..";
import { BoundUtil, View3D } from "../..";
import { Engine3D } from "../../Engine3D";
import { Camera3D } from "../../core/Camera3D";
import { Object3D } from "../../core/entities/Object3D";
import { PointerEvent3D } from "../../event/eventConst/PointerEvent3D";
import { clamp } from "../../math/MathUtil";
import { Quaternion } from "../../math/Quaternion";
import { Vector3 } from "../../math/Vector3";
import { Object3DUtil } from "../../util/Object3DUtil";
import { Time } from "../../util/Time";
import { Vector3Ex } from "../../util/Vector3Ex";
import { ComponentBase } from "../ComponentBase";
Expand Down Expand Up @@ -143,10 +142,8 @@ export class HoverCameraController extends ComponentBase {
}

public focusByBounds(obj: Object3D) {
let bounds = Object3DUtil.genMeshBounds(obj);
let bounds = BoundUtil.genMeshBounds(obj);
this.target = bounds.center;
console.log(bounds.size);
console.log(bounds.center);
}

/**
Expand Down
15 changes: 10 additions & 5 deletions src/core/bound/BoundingBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,16 @@ export class BoundingBox implements IBound {
}

public setFromMinMax(min: Vector3, max: Vector3) {
this.size = max.subtract(min);
this.center = this.size.div(2.0).add(min);
this.extents = new Vector3(this.size.x / 2, this.size.y / 2, this.size.z / 2);
this.min = min;
this.max = max;
this.min ||= new Vector3();
this.max ||= new Vector3();
this.size ||= new Vector3();
this.center ||= new Vector3();
this.extents ||= new Vector3();
this.size.set(max.x - min.x, max.y - min.y, max.z - min.z);
this.extents.copyFrom(this.size).multiplyScalar(0.5);
this.center.copyFrom(this.min).add(this.extents, this.center);
this.min.copyFrom(min);
this.max.copyFrom(max);
}

public setFromCenterAndSize(center: Vector3, size: Vector3) {
Expand Down
39 changes: 6 additions & 33 deletions src/core/entities/Entity.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Matrix4 } from '../..';
import { IComponent } from '../../components/IComponent';
import { RenderNode } from '../../components/renderer/RenderNode';
import { Transform } from '../../components/Transform';
import { CEventDispatcher } from '../../event/CEventDispatcher';
import { ComponentCollect } from '../../gfx/renderJob/collect/ComponentCollect';
import { RenderLayer } from '../../gfx/renderJob/config/RenderLayer';
import { Vector3 } from '../../math/Vector3';
import { BoundUtil } from '../../util/BoundUtil';
import { UUID } from '../../util/Global';
import { BoundingBox } from '../bound/BoundingBox';
import { IBound } from '../bound/IBound';
Expand Down Expand Up @@ -81,6 +81,7 @@ export class Entity extends CEventDispatcher {
* The bounding box of an object
*/
protected _bound: IBound;
protected _boundWorld: IBound;
private _dispose: boolean = false;
// private _visible: boolean = true;

Expand Down Expand Up @@ -318,49 +319,21 @@ export class Entity extends CEventDispatcher {
if (!this._bound) {
this.updateBound();
}
return this._bound;
return this._boundWorld;
}

public set bound(value: IBound) {
this._bound = value;
this._boundWorld = this._bound.clone();
this.updateBound();
}

/**
* Returns a bounding box that defines the display area of the specified layer.
* @returns
*/
public genBounds() {
if (!this._bound) {
this._bound = new BoundingBox(Vector3.ZERO.clone(), Vector3.ONE.clone());
}
for (const children of this.entityChildren) {
// if (children._bound) {
this._bound.merge(children.genBounds());
// }
}
return this._bound;
}

public updateBound() {
if (!this._bound) {
this._bound = new BoundingBox(Vector3.ZERO.clone(), Vector3.ONE.clone());
// this.genBounds();
this._boundWorld = this._bound.clone();
}
let worldMatrix = this.transform.worldMatrix;
worldMatrix.transformPoint(this._bound.min, this.bound.worldMin);
worldMatrix.transformPoint(this._bound.max, this.bound.worldMax);

let sizeX = this._bound.max.x - this._bound.min.x;
let sizeY = this._bound.max.y - this._bound.min.y;
let sizeZ = this._bound.max.z - this._bound.min.z;

this._bound.size.set(sizeX, sizeY, sizeZ);
this._bound.center.set(
sizeX + this._bound.worldMin.x,
sizeY + this._bound.worldMin.y,
sizeZ + this._bound.worldMin.z,
);
BoundUtil.transformBound(this.transform.worldMatrix, this._bound as BoundingBox, this._boundWorld as BoundingBox);
}


Expand Down
4 changes: 2 additions & 2 deletions src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { BoundingBox } from "../../../../core/bound/BoundingBox";
import { Camera3D } from "../../../../core/Camera3D";
import { CameraType } from "../../../../core/CameraType";
import { Object3D } from "../../../../core/entities/Object3D";
import { Object3DUtil } from "../../../../util/Object3DUtil";
import { Graphics3DShape } from "./Graphics3DShape";
import { GraphicConfig } from "./GraphicConfig";
import { Graphic3DFillRenderer } from "./Graphic3DFillRenderer";
import { Graphic3DLineBatchRenderer } from "./Graphic3DLineBatchRenderer";
import { BoundUtil } from "../../../..";

export class Graphic3D extends Object3D {

Expand Down Expand Up @@ -426,7 +426,7 @@ export class Graphic3D extends Object3D {
* @param color The color of the bounding box
*/
public drawObjectBoundingBox(obj: Object3D, color: Color = Color.COLOR_WHITE) {
let boundingBox = Object3DUtil.genMeshBounds(obj);
let boundingBox = BoundUtil.genMeshBounds(obj);
this.drawBox(`Bounds_${obj.uuid}`, boundingBox.min, boundingBox.max, color);
}

Expand Down
9 changes: 3 additions & 6 deletions src/math/Vector3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,9 +507,7 @@ export class Vector3 {
* @returns result
*/
public add(a: Vector3, target: Vector3 = null): Vector3 {
if (!target) {
target = new Vector3();
}
target ||= new Vector3();

var a0x: number = this.x;
var a0y: number = this.y;
Expand All @@ -524,9 +522,8 @@ export class Vector3 {
}

public addXYZW(x: number, y: number, z: number, w: number, target: Vector3 = null): Vector3 {
if (!target) {
target = new Vector3();
}
target ||= new Vector3();

var a0x: number = this.x;
var a0y: number = this.y;
var a0z: number = this.z;
Expand Down
2 changes: 1 addition & 1 deletion src/textures/AtmosphericScatteringSky.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class AtmosphericScatteringSkySetting {
public mieG: number = 0.76;
public mieHeight: number = 1200;
public eyePos: number = 1500;
public sunX: number = 0.55;
public sunX: number = 0.71;
public sunY: number = 0.56;
public sunBrightness: number = 1.0;
public displaySun: boolean = true;
Expand Down

0 comments on commit 8cfd1ab

Please sign in to comment.