Ok. I’m sorry for sending such a long message, but I can’t seem to figure out how to set up a CodePen, because my .glb file can not be used in CodePen.
The following is all of my JavaScript/Three.js code. I personaly think the problem lies within the Renderer or Room Class.
My code is split up into classes, to make it more manageable. I really hope someone can help, because I am going nuts.
Could there be a problem within my .glb file? Is it because I have set up my blender file incorrectly perhaps, or handled the texture files wrong?
export default class Experience {
static instance
constructor(canvas) {
if (Experience.instance) {
return Experience.instance
}
Experience.instance = this;
this.canvas = canvas;
this.scene = new THREE.Scene() //I set up my scene here
this.time = new Time() //I set up time here for animations
this.sizes = new Sizes() //I set up sizes here
this.camera = new Camera() //I set up the camera here
this.renderer = new Renderer() //I set up my renderer here
this.recources = new Resources() //I get the blender file from here
this.world = new World() //I set the view here, where I load the blender file
this.sizes.on("resize", ()=> {
this.resize();
})
this.time.on("update", ()=> {
this.update();
})
}
resize() {
this.camera.resize()
this.renderer.resize()
this.world.room.resize()
}
update() {
this.camera.update()
this.renderer.update()
if (this.world.room !== undefined) {
this.world.room.update()
}
}
}
//I don't think this is the problem
export default class Sizes extends EventEmitter {
constructor() {
super()
this.width = window.innerWidth;
this.height = window.innerHeight;
this.aspect = this.width/this.height
this.pixelRatio = Math.min(window.devicePixelRatio, 2)
window.addEventListener("resize",()=> {
this.width = window.innerWidth;
this.height = window.innerHeight;
this.aspect = this.width/this.height
this.pixelRatio = Math.min(window.devicePixelRatio, 2)
this.emit("resize");
})
}
}
//This is not the problem either
export default class Time extends EventEmitter {
constructor() {
super()
this.start = Date.now()
this.current = this.start
this.elapsed = 0 //Time since start
this.delta = 16 //Time between each frame
this.update()
}
update() {
const currentTime = Date.now()
this.delta = currentTime - this.current
this.current = currentTime
this.elapsed = this.current - this.start
this.emit("update");
window.requestAnimationFrame(() => this.update())
}
}
//This is not the problem either I think
export default class Camera {
constructor() {
this.experience = new Experience()
this.sizes = this.experience.sizes
this.scene = this.experience.scene
this.canvas = this.experience.canvas
this.createPerspectiveCamera();
}
createPerspectiveCamera() {
this.perspectiveCamera = new THREE.PerspectiveCamera(45, this.sizes.aspect, 0.1, 10000)
this.scene.add(this.perspectiveCamera)
this.perspectiveCamera.rotation.set(0 * Math.PI / 180, -50 * Math.PI / 180, 0 * Math.PI / 180)
this.perspectiveCamera.position.set(-950, 500, 600)
}
resize() {
//Updating Perpective Camera on Resize
this.perspectiveCamera.aspect = this.sizes.aspect
this.perspectiveCamera.updateProjectionMatrix()
}
}
//I have a feeling the problem is withing here or the next couple of classes
export default class Renderer {
constructor() {
this.experience = new Experience()
this.sizes = this.experience.sizes
this.scene = this.experience.scene
this.canvas = this.experience.canvas
this.camera = this.experience.camera
this.setRenderer()
}
setRenderer() {
THREE.ColorManagement.enabled = false
//WebGLRenderer
this.renderer = new THREE.WebGLRenderer();
this.renderer.physicallyCorrectLight = true
this.renderer.outputColorSpace = THREE.SRGBColorSpace
this.renderer.toneMapping = THREE.ReinhardToneMapping
this.renderer.toneMappingExposure = 1
this.renderer.shadowMap.enabled = true
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
this.renderer.setClearColor( 0xf111ff, 0 )
this.renderer.setSize(this.sizes.width, this.sizes.height)
this.renderer.setPixelRatio(this.sizes.pixelRatio)
document.querySelector('.experince-canvas').appendChild( this.renderer.domElement )
//CSS3DRenderer
this.css3DRenderer = new CSS3DRenderer();
this.css3DRenderer.setSize( this.sizes.width, this.sizes.height );
this.css3DRenderer.domElement.style.position = 'absolute';
this.css3DRenderer.domElement.style.top = '0px';
document.querySelector('.html-canvas').appendChild( this.css3DRenderer.domElement );
//Unreal Bloom
this.target = new THREE.WebGLRenderTarget(this.sizes.width, this.sizes.height, {
type: THREE.HalfFloatType,
format: THREE.RGBAFormat,
colorSpace: THREE.SRGBColorSpace,
})
this.target.samples = 8
this.renderScene = new RenderPass(this.scene, this.camera.perspectiveCamera)
this.bloomPass = new UnrealBloomPass( new THREE.Vector2(this.sizes.width, this.sizes.height), 1, 1.5, 1 )
this.bloomPass.renderToScreen = true
this.composer = new EffectComposer(this.renderer, this.target)
this.composer.setSize(this.sizes.width, this.sizes.height)
this.composer.addPass( this.renderScene )
// this.composer.addPass( this.bloomPass )
}
resize() {
this.renderer.setSize(this.sizes.width, this.sizes.height)
this.css3DRenderer.setSize(this.sizes.width, this.sizes.height)
this.renderer.setPixelRatio(this.sizes.pixelRatio)
this.composer.setSize(this.sizes.width, this.sizes.height)
}
update() {
this.composer.render()
this.css3DRenderer.render(this.scene, this.camera.perspectiveCamera)
}
}
//I load in the .glb (Blender) file here
export default class Resources extends EventEmitter {
constructor(assets) {
super()
this.experience = new Experience()
this.assets = ["/models/Arcade Room 38.glb"]
this.items = {}
this.queue = this.assets.length
this.loaded = 0
this.setLoaders();
this.startLoading();
}
setLoaders() {
this.loaders = {} //This makes it easier to load more files. Even though I only load one file now
this.loaders.gltfLoader = new GLTFLoader()
this.loaders.dracoLoader = new DRACOLoader()
this.loaders.dracoLoader.setDecoderPath("/draco/")
this.loaders.gltfLoader.setDRACOLoader(this.loaders.dracoLoader)
}
startLoading() {
for(const asset of this.assets) {
this.loaders.gltfLoader.load(asset.path, (file) => {
this.singleAssetLoaded(asset, file)
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
}
);
}
}
singleAssetLoaded(asset, file) {
this.items[asset.name] = file;
this.loaded++
if (this.loaded === this.queue) {
this.emit("ready")
}
}
}
//The World file that contains the Enviorenment and Room class
export default class World {
constructor() {
this.experience = new Experience()
this.recources = this.experience.recources
this.recources.on("ready", () => {
this.environment = new Environment()
this.room = new Room()
})
}
}
//Environment with controling of the lights
export default class Environment {
constructor() {
this.experience = new Experience()
this.scene = this.experience.scene
this.resoruces = this.experience.recources
this.setLight()
this.setLFloorLampLight()
}
setLight() {
//Fan Lights
for(let i = 0; i < 4; i++) {
this.pointLight = new THREE.PointLight(0xffea90, 2, 1300)
this.pointLight.castShadow = true
this.pointLight.position.set(300 - (i < 2 ? 1120 : 0), 790, (i % 2 === 1 ? -210 : 700))
this.scene.add(this.pointLight)
}
}
setLFloorLampLight() {
for(let i = 0; i < 2; i++) {
this.lampLight = new THREE.PointLight(0xffea90, 1.3, 1000)
this.pointLight.castShadow = true
this.lampLight.position.set(i === 0 ? 1100 : 890, 400, i === 0 ? 490 : -710)
this.scene.add(this.lampLight)
}
}
}
//Room Class, I also think the problem is in this Class
export default class Room {
constructor() {
this.experience = new Experience()
this.scene = this.experience.scene
this.resoruces = this.experience.recources
this.room = this.resoruces.items.room
this.actualRoom = this.room.scene
this.setModel()
//Raycast
this.INTERSECTED = null;
this.raycaster = new THREE.Raycaster();
}
setModel() {
this.scene.add(this.actualRoom)
this.actualRoom.scale.set(100, 100, 100)
this.actualRoom.position.z = 0
}
}