1

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

2 Answers 2

2

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>

Sign up to request clarification or add additional context in comments.

3 Comments

I have animate() function as well and I call it after init() function. If I didn't do that, I wouldn't have any picture, but I have main scene visual. Also in function onWindowResize() I don't call renderer, I only change it "settings" like in the example.
If you don't show all of the relevant code... ie. your animate function.. we can't really give you the help you want. Like I said, you probably want a render loop, which in the case of the example I posted in the animate function. What makes it a loop is the requestAnimationFrame(animate); call.
Ok, I've updated post. But this does't solve the problem.
0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.