Mikhail_Timoshkin
Mikhail_Timoshkin

Reputation: 11

THREE js image not displayng in canvas

I have two scenes and to renders. I alse use Bootstrap 4 for modal window. One scene is main, another is shown in modal window, that's why I am using two renders: one for the element on the main screen and one for modal window.

Code:

Main scene:

<div class="output3d" id="WebGL-output"></div>

function setMainScene() {
        scene = new THREE.Scene();
        scene.background = new THREE.Color("#ffffff");

        renderer = new THREE.WebGLRenderer({antialias: true, logarithmicDepthBuffer: true});
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.getElementById("WebGL-output").appendChild(renderer.domElement);

        camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 2000);
        camera.position.x = home[0];
        camera.position.y = home[1];
        camera.position.z = home[2];
        camera.lookAt(home[3], home[4], home[5])

        controls = initOrbitControls(camera, renderer, new THREE.Vector3(home[3], home[4], home[5]))
}

Scene for modal window:

<div class="modal" data-backdrop="static" id="ObjectInfo" role="dialog" tabindex="-1">
    <div class="modal-dialog modal-xl modal-dialog-scrollable" role="document" style="bottom: 0">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="ObjectId"></h5>
                <button aria-label="Close" class="close" data-dismiss="modal" onclick="" type="button">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <div class="container">
                    <div class="row">
                        <div class="col">
                            <div>
                                <img src="css/360.jpg" alt="<-->">
                            </div>
                            <div id="FrontView"></div>
                        </div>
                        <div class="col">
                            <p id="ObjectType" class="mb-0"></p>
                            <p id="ObjectInfoText" class="mb-0"></p>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                </div>
            </div>
        </div>
    </div>
</div>
 function setModalWindowScene() {
        modalWindowScene = new THREE.Scene()
        modalWindowScene.background = new THREE.Color("#ffffff");

        modalWindowRenderer = new THREE.WebGLRenderer({antialias: true});
        modalWindowRenderer.setPixelRatio(window.devicePixelRatio);
        modalWindowRenderer.setSize(450, 450);
        document.getElementById("FrontView").appendChild(modalWindowRenderer.domElement);

        modalWindowCamera = new THREE.PerspectiveCamera(45, document.getElementById("FrontView").innerWidth / document.getElementById("FrontView").innerHeight, 1, 100);
        modalWindowControls = new THREE.OrbitControls(modalWindowCamera, modalWindowRenderer.domElement);

Init:

function init() {
    setMainScene()
    setModalWindowScene()

    // adding objects to main scene
    addRoom()
    addRacks()
    addExtinguishingCylinders()
    addHotHalls()
    addWires()
    addLights()

    window.addEventListener('resize', onWindowResize, false);
}

Rendering:

function animate() {
    requestAnimationFrame(animate);
    render();
}

function render() {
    renderer.render(scene, camera);
    if (modalWindowOpen) {
        modalWindowRenderer.render(modalWindowScene, modalWindowCamera);
    }
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    modalWindowCamera.aspect = document.getElementById("FrontView").offsetWidth / document.getElementById("FrontView").offsetHeight;

    camera.updateProjectionMatrix();
    modalWindowCamera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);
    modalWindowRenderer.setSize(document.getElementById("FrontView").offsetWidth, document.getElementById("FrontView").offsetHeight)
}

HTML:

<script type="text/javascript">
    init();
    animate();
</script>

When user opens modal window, object is added to modal scene and the user can interact with it in modal scene with modal controls.

Problem:

When the first time user opens the modal window, picture of the object isn't drawn, despite that object is append to <div id="FrontView"></div> in the modal window, but it is empty. But when user resize the window , picture appears and stay forever.

Interesting thing. When there is no picture in modal window, I can rotate object with controls, which was binded to modal scene.

Demonstration: Before resizing After resizing

Upvotes: 1

Views: 698

Answers (2)

Mikhail_Timoshkin
Mikhail_Timoshkin

Reputation: 11

Ok, it's look like I set zero aspect when creating modelWindowCamera because object document.getElementById("FrontView") had no size before first render. And when I changed scale of the window, document.getElementById("FrontView") had no zero sizes and aspect of the camera updated with no zero aspect.

For solution I just set aspect to constant 1, and code is now like this:

   modalWindowCamera = new THREE.PerspectiveCamera(45, 1, 1, 100);

Upvotes: 0

2pha
2pha

Reputation: 10155

You need to call render in your init function.
It looks like you only call render in your onWindowResize function which will not fire until the window is actually resized (not when the page loads).
You probably want a render loop also.

Take a look at the example below.
You will see at the top, I call the init function to set the scene, then the animate function to start the render loop.

var camera, scene, renderer, mesh, material;
// init scene.
init();
// Start animation/render loop.
animate();

function init() {
    // Renderer.
    renderer = new THREE.WebGLRenderer();
    //renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    // Add renderer to page
    document.body.appendChild(renderer.domElement);

    // Create camera.
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.z = 400;

    // Create scene.
    scene = new THREE.Scene();

    // Create material
    material = new THREE.MeshPhongMaterial();

    // Create cube and add to scene.
    var geometry = new THREE.BoxGeometry(200, 200, 200);
    mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    // Create ambient light and add to scene.
    var light = new THREE.AmbientLight(0x404040); // soft white light
    scene.add(light);

    // Create directional light and add to scene.
    var directionalLight = new THREE.DirectionalLight(0xffffff);
    directionalLight.position.set(1, 1, 1).normalize();
    scene.add(directionalLight);

    // Add listener for window resize.
    window.addEventListener('resize', onWindowResize, false);

}

function animate() {
    requestAnimationFrame(animate); // this makes the animate function a loop that runs every frame.
    mesh.rotation.x += 0.005;
    mesh.rotation.y += 0.01;
    renderer.render(scene, camera);
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}
<script src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>

Upvotes: 2

Related Questions