Forum

Camera Location and Target Move in HTML

11 April 2017 18:26
Hi Again

I had an issue when the camera was static and on the other hand I had many targets to develop a tour for the viewers. I also needed to end the tour with "target" camera setting. The project is not finished yet. But I'd like to share it in here.

My next wish would be on how to shrink the code in less lines and / or re-using the functions. I could not do them in a loop or callback function. Or maybe I did not know the right way of coding it. Eventually, I will post the link to the 3D view when I am done. I believe that it looks fantastic at the moment.

Here is the html Code;
<body>
    <div class="banner" id="logo"> Doubleview</div>
    <div id="main_canvas_container"></div>

    <div class="main-button" id="start_anim"> V. TOUR
        <div class="tooltiptext">Begin a virtual tour<br>around the <br><b>Lisle Deposit</b>
        </div>
    </div>
    <div class="main-button" id="top-view">Top View
        <div class="tooltiptext">Property <br>Aerial View
        </div></div>
        <div class="exchange" id="exch">TSX.V : DBV - OTCBB.pink : DBLVF - GER : 1D4</div>
        <div class="main-button" id="information"> ?
            <div class="tooltiptext">
                <b>Navigation:</b> <br>
                <ul>
                    <li>Mouse+left Click to Examine/Navigate <br></li>
                    <li>Mouse+right Click to Pan view Around <br></li>
                    <li>Mouse+middle Roll to zoom in/out</li>
                </ul>
            </div>
        </div>
     
</body>

</html>


and here is the JS Code:

 

"use strict";

 b4w.register("3Dmodel-Hat-06_app", function (exports, require) {

     var m_app = require("app");
     var m_cam = require("camera");
     var m_cfg = require("config");
     var m_preloader = require("preloader");
     var m_cont = require("container");
     var m_ctl = require("controls");
     var m_data = require("data");
     var m_scenes = require("scenes");
     var m_time = require("time");
     var m_trans = require("transform");
     var m_vec3 = require("vec3");
     var m_version = require("version");

     var eyes = ["Eye-0", "Eye-2", "Eye-3", "Eye-4", "Eye-5", "Eye-6", "Eye-7", "Eye-1"];
     var targets = ["Eye-0-Target", "Eye-2-Target", "Eye-3-Target", "Eye-4-Target", "Eye-5-Target", "Eye-6-Target", "Eye-7-Target", "Eye-1-Target"];
     var stops = [5, 5, 5, 5, 5, 5, 5, 5, 5];

     var DEBUG = (m_version.type() === "DEBUG");

     var ANIM_TIME = 5;
     var counter = 1;
     var APP_ASSETS_PATH = m_cfg.get_assets_path("3Dmodel-Hat-06");

     var _anim_stop = false;
     var _delta_target = ANIM_TIME;
     var _cam_anim = {
         timeline: -ANIM_TIME,
         starting_eye: new Float32Array(3),
         starting_target: new Float32Array(3),
         final_eye: new Float32Array(3),
         final_target: new Float32Array(3),
         current_eye: new Float32Array(3),
         current_target: new Float32Array(3)
     }

     var _vec3_tmp = new Float32Array(3);

     exports.init = function () {
         m_app.init({
             canvas_container_id: "main_canvas_container",
             callback: init_cb,
             physics_enabled: false,
             alpha: true,
             //show_fps: true,
             autoresize: true,
             // assets_dds_available: !DEBUG,
             //assets_min50_available: !DEBUG,
             console_verbose: true
         });
     }

     function init_cb(canvas_elem, success) {

         if (!success) {
             console.log("b4w init failure");
             return;
         }

         m_preloader.create_preloader();

         // ignore right-click on the canvas element
         canvas_elem.oncontextmenu = function (e) {
             e.preventDefault();
             e.stopPropagation();
             return false;
         };


         load();
     }

     function load() {
         m_data.load(APP_ASSETS_PATH + "3Dmodel-Hat-06.json", load_cb, preloader_cb);
     }

     /**
      * update the app's preloader
      */
     function preloader_cb(percentage) {
         m_preloader.update_preloader(percentage);
     }

     function load_cb(data_id) {
         m_app.enable_camera_controls();
         var camobj = m_scenes.get_active_camera();
         init_camera_animation(camobj);
         var move_camera_element = document.getElementById("start_anim");
         move_camera_element.addEventListener("click", main_show_start);
         var main_canvas = m_cont.get_canvas();
         main_canvas.addEventListener("mouseup", main_canvas_up);
         main_canvas.addEventListener("mousedown", main_canvas_down);
     }

     function main_show_start(e) {
         var target = m_scenes.get_object_by_name(targets[1]);
         var eye = m_scenes.get_object_by_name(eyes[1]);
         if (eye && target) {
             var camobj = m_scenes.get_active_camera();
             var pos_view = m_trans.get_translation(eye);
             var pos_target = m_trans.get_translation(target);
             m_scenes.show_object(m_scenes.get_object_by_name("Box-Parent"), false);
             start_camera_animation(camobj, pos_view, pos_target);
         }
         setTimeout(main_show_continue2, 1000 * stops[1] + 1000);
     }

     function main_show_continue2(e) {
         var target = m_scenes.get_object_by_name(targets[2]);
         var eye = m_scenes.get_object_by_name(eyes[2]);
         if (eye && target) {
             var camobj = m_scenes.get_active_camera();
             var pos_view = m_trans.get_translation(eye);
             var pos_target = m_trans.get_translation(target);
             start_camera_animation(camobj, pos_view, pos_target);
         }
         setTimeout(main_show_continue3, 1000 * stops[2] + 1000);
     }

     function main_show_continue3(e) {
         var target = m_scenes.get_object_by_name(targets[3]);
         var eye = m_scenes.get_object_by_name(eyes[3]);
         if (eye && target) {
             var camobj = m_scenes.get_active_camera();
             var pos_view = m_trans.get_translation(eye);
             var pos_target = m_trans.get_translation(target);
             start_camera_animation(camobj, pos_view, pos_target);
         }
         setTimeout(main_show_continue4, 1000 * stops[3] + 1000);
     }

     function main_show_continue4(e) {
         var target = m_scenes.get_object_by_name(targets[4]);
         var eye = m_scenes.get_object_by_name(eyes[4]);
         if (eye && target) {
             var camobj = m_scenes.get_active_camera();
             var pos_view = m_trans.get_translation(eye);
             var pos_target = m_trans.get_translation(target);
             start_camera_animation(camobj, pos_view, pos_target);
         }
         setTimeout(main_show_continue5, 1000 * stops[4] + 1000);
     }

     function main_show_continue5(e) {
         var target = m_scenes.get_object_by_name(targets[5]);
         var eye = m_scenes.get_object_by_name(eyes[5]);
         if (eye && target) {
             var camobj = m_scenes.get_active_camera();
             var pos_view = m_trans.get_translation(eye);
             var pos_target = m_trans.get_translation(target);
             start_camera_animation(camobj, pos_view, pos_target);
         }
         setTimeout(main_show_continue6, 1000 * stops[5] + 1000);
     }

     function main_show_continue6(e) {
         var target = m_scenes.get_object_by_name(targets[6]);
         var eye = m_scenes.get_object_by_name(eyes[6]);
         if (eye && target) {
             var camobj = m_scenes.get_active_camera();
             var pos_view = m_trans.get_translation(eye);
             var pos_target = m_trans.get_translation(target);
             start_camera_animation(camobj, pos_view, pos_target);
         }
         setTimeout(main_show_continue7, 1000 * stops[6] + 1000);
     }

     function main_show_continue7(e) {
         var target = m_scenes.get_object_by_name(targets[7]);
         var eye = m_scenes.get_object_by_name(eyes[7]);
         if (eye && target) {
             var camobj = m_scenes.get_active_camera();
             var pos_view = m_trans.get_translation(eye);
             var pos_target = m_trans.get_translation(target);
             start_camera_animation(camobj, pos_view, pos_target);
         }
         // m_scenes.hide_object(m_scenes.get_object_by_name("Box-Parent"), false);
         // setTimeout(main_show_continue1, 1000 * stops[1] +1000);
     }

     function main_canvas_up(e) {

         if (e.button != 0)
             return;

         if (e.preventDefault)
             e.preventDefault();

         var obj = m_scenes.pick_object(e.clientX, e.clientY);

         if (obj)
             switch (m_scenes.get_object_name(obj)) {
                 case "Box-Parent":
                     var target = m_scenes.get_object_by_name("Cube-Target");
                     var eye = m_scenes.get_object_by_name("Cube-Eye-3");
                     break;
                 case "Cylinder.000":
                     var target = m_scenes.get_object_by_name("Cylinder.000");
                     var eye = m_scenes.get_object_by_name("Cube.001");
                     break;
                 default:
                     return;
             }

         if (eye && target) {
             var camobj = m_scenes.get_active_camera();
             var pos_view = m_trans.get_translation(eye);
             var pos_target = m_trans.get_translation(target);
             start_camera_animation(camobj, pos_view, pos_target);



         }

     }

     function main_canvas_down(e) {

         if (e.button != 0) return;

         var camobj = m_scenes.get_active_camera();

         if (m_ctl.get_sensor_value(camobj, "CAMERA_MOVE", 0) - _cam_anim.timeline < ANIM_TIME) _anim_stop = true;

     }

     function start_camera_animation(camobj, pos_view, pos_target) {
         // retrieve camera current position
         m_cam.target_get_pivot(camobj, _cam_anim.current_target);
         m_trans.get_translation(camobj, _cam_anim.current_eye);

         // set camera starting position
         m_vec3.copy(_cam_anim.current_target, _cam_anim.starting_target);
         m_vec3.copy(_cam_anim.current_eye, _cam_anim.starting_eye);

         // set camera final position
         m_vec3.copy(pos_view, _cam_anim.final_eye);
         m_vec3.copy(pos_target, _cam_anim.final_target);

         // start animation
         _delta_target = ANIM_TIME;
         _cam_anim.timeline = m_time.get_timeline();

         return;
     }

     function init_camera_animation(camobj) {

         var t_sensor = m_ctl.create_timeline_sensor();
         var e_sensor = m_ctl.create_elapsed_sensor();

         var logic_func = function (s) {
             // s[0] = m_time.get_timeline() (t_sensor value)
             return s[0] - _cam_anim.timeline < ANIM_TIME;
         }

         var cam_move_cb = function (camobj, id, pulse) {

             if (pulse == 1) {
                 if (_anim_stop) {
                     _cam_anim.timeline = -ANIM_TIME;
                     return;
                 }

                 m_app.disable_camera_controls();
                 // elapsed = frame time (e_sensor value)
                 var elapsed = m_ctl.get_sensor_value(camobj, id, 1);
                 var delta = elapsed / ANIM_TIME;

                 m_vec3.subtract(_cam_anim.final_eye, _cam_anim.starting_eye, _vec3_tmp);
                 m_vec3.scaleAndAdd(_cam_anim.current_eye, _vec3_tmp, delta, _cam_anim.current_eye);

                 _delta_target -= elapsed;
                 delta = 1 - _delta_target * _delta_target / (ANIM_TIME * ANIM_TIME);
                 m_vec3.subtract(_cam_anim.final_target, _cam_anim.starting_target, _vec3_tmp);
                 m_vec3.scaleAndAdd(_cam_anim.starting_target, _vec3_tmp, delta, _cam_anim.current_target);

                 m_cam.target_set_trans_pivot(camobj, _cam_anim.current_eye, _cam_anim.current_target);

             } else {
                 m_app.enable_camera_controls(false);
                 if (!_anim_stop)
                     m_cam.target_set_trans_pivot(camobj, _cam_anim.final_eye, _cam_anim.final_target);
                 else
                     _anim_stop = false;
             }
         }

         m_ctl.create_sensor_manifold(camobj, "CAMERA_MOVE", m_ctl.CT_CONTINUOUS, [t_sensor, e_sensor], logic_func, cam_move_cb);
     }
 });
 b4w.require("3Dmodel-Hat-06_app").init();


I add the CSS code here too.

body {
background-color: #fff;
margin: 0;
overflow: hidden;
}

#main_canvas_container {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
}


.main-button {

-moz-box-shadow:inset 0px 0px 0px 0px #97c4fe;
-webkit-box-shadow:inset 0px 0px 0px 0px #97c4fe;
box-shadow:inset 0px 0px 0px 0px #97c4fe;
background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #3d94f6), color-stop(1, #1e62d0));
background:-moz-linear-gradient(top, #3d94f6 5%, #1e62d0 100%);
background:-webkit-linear-gradient(top, #3d94f6 5%, #1e62d0 100%);
background:-o-linear-gradient(top, #3d94f6 5%, #1e62d0 100%);
background:-ms-linear-gradient(top, #3d94f6 5%, #1e62d0 100%);
background:linear-gradient(to bottom, #3d94f6 5%, #1e62d0 100%);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#3d94f6', endColorstr='#1e62d0',GradientType=0);
background-color:#3d94f6;
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
border:1px solid #337fed;
display:inline-block;
cursor:pointer;
color:#ffffff;
font-family:Arial;
font-size:12px;
font-weight:bold;
padding:7px 5px;
text-decoration:none;
text-shadow:0px 2px 1px #1570cd;
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
}

.main-button:hover {
background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #1e62d0), color-stop(1, #3d94f6));
background:-moz-linear-gradient(top, #1e62d0 5%, #3d94f6 100%);
background:-webkit-linear-gradient(top, #1e62d0 5%, #3d94f6 100%);
background:-o-linear-gradient(top, #1e62d0 5%, #3d94f6 100%);
background:-ms-linear-gradient(top, #1e62d0 5%, #3d94f6 100%);
background:linear-gradient(to bottom, #1e62d0 5%, #3d94f6 100%);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#1e62d0', endColorstr='#3d94f6',GradientType=0);
background-color:#1e62d0;
}

.main-button:active {
position:relative;
}

.main-button .tooltiptext {
background-color: grey;
border-radius: 6px;
bottom: 100%;
color: #fff;
margin-left: -8px;
padding: 5px 8px;
position: absolute;
text-align: left;
visibility: hidden;
width: auto;
z-index: 1;
margin-bottom: 10px;
font-weight: normal;
min-width: 120px;
}

.main-button:hover .tooltiptext {
visibility: visible;
}

#start_anim {
left: 20px;
position: fixed;
bottom: 20px;
}


#top-view {
bottom: 20px;
left: 88px;
position: fixed;
}

#information {
bottom: 20px;
left: 188px;
position: fixed;
width: auto;
}
ul {
width: 209px;
}

#twitter {
display: inline-flex;
position: fixed;
right: 63px;
top: 13px;
z-index: 12;
}
#linkedin {
display: inline-flex;
position: fixed;
right: 10px;
top: 10px;
z-index: 12;
}
#exch {
display: inline-flex;
position: fixed;
right: 10px;
bottom: 10px;
z-index: 12;
color: rgb(0, 85, 175);
cursor: progress;

float: left;
font: bold 20px/0 Verdana,Geneva,sans-serif;
}


#doubleview {
left: 10px;
position: fixed;
top:20px;

}
#logo {
border: medium none;
border-radius: 10px;
box-sizing: border-box;
color: rgb(0, 85, 175);
cursor: progress;
display: inline-block;
float: left;
font: bold 43px/1 Verdana,Geneva,sans-serif;
position: relative;
text-overflow: ellipsis;
text-shadow: -1px -1px 0 rgba(255, 255, 255, 0.2);
width: 19em;
z-index: 3;
}



Blender File
Sat-Image
19 April 2017 02:31
Hi Again

I tried deploying the project and I had no luck. I have reported the bug under #16542 ticket. Can you please help?

Thanks
20 April 2017 18:25
Hello

My next wish would be on how to shrink the code in less lines and / or re-using the functions. I could not do them in a loop or callback function. Or maybe I did not know the right way of coding it. Eventually, I will post the link to the 3D view when I am done. I believe that it looks fantastic at the moment.

I haven't tested this code but I guess it should be something like this:
"use strict";

 b4w.register("3Dmodel-Hat-06_app", function (exports, require) {

     var m_app = require("app");
     var m_cam = require("camera");
     var m_cfg = require("config");
     var m_preloader = require("preloader");
     var m_cont = require("container");
     var m_ctl = require("controls");
     var m_data = require("data");
     var m_scenes = require("scenes");
     var m_time = require("time");
     var m_trans = require("transform");
     var m_vec3 = require("vec3");
     var m_version = require("version");

     var eyes = ["Eye-0", "Eye-2", "Eye-3", "Eye-4", "Eye-5", "Eye-6", "Eye-7", "Eye-1"];
     var targets = ["Eye-0-Target", "Eye-2-Target", "Eye-3-Target", "Eye-4-Target", "Eye-5-Target", "Eye-6-Target", "Eye-7-Target", "Eye-1-Target"];
     var stops = [5, 5, 5, 5, 5, 5, 5, 5, 5];

     var DEBUG = (m_version.type() === "DEBUG");

     var ANIM_TIME = 5;
     var counter = 1;
     var APP_ASSETS_PATH = m_cfg.get_assets_path("3Dmodel-Hat-06");

     var _anim_stop = false;
     var _delta_target = ANIM_TIME;
     var _cam_anim = {
         timeline: -ANIM_TIME,
         starting_eye: new Float32Array(3),
         starting_target: new Float32Array(3),
         final_eye: new Float32Array(3),
         final_target: new Float32Array(3),
         current_eye: new Float32Array(3),
         current_target: new Float32Array(3)
     }

     var _vec3_tmp = new Float32Array(3);

     exports.init = function () {
         m_app.init({
             canvas_container_id: "main_canvas_container",
             callback: init_cb,
             physics_enabled: false,
             alpha: true,
             //show_fps: true,
             autoresize: true,
             // assets_dds_available: !DEBUG,
             //assets_min50_available: !DEBUG,
             console_verbose: true
         });
     }

     function init_cb(canvas_elem, success) {

         if (!success) {
             console.log("b4w init failure");
             return;
         }

         m_preloader.create_preloader();

         // ignore right-click on the canvas element
         canvas_elem.oncontextmenu = function (e) {
             e.preventDefault();
             e.stopPropagation();
             return false;
         };


         load();
     }

     function load() {
         m_data.load(APP_ASSETS_PATH + "3Dmodel-Hat-06.json", load_cb, preloader_cb);
     }

     /**
      * update the app's preloader
      */
     function preloader_cb(percentage) {
         m_preloader.update_preloader(percentage);
     }

     function load_cb(data_id) {
         m_app.enable_camera_controls();
         var camobj = m_scenes.get_active_camera();
         init_camera_animation(camobj);
         var move_camera_element = document.getElementById("start_anim");
         move_camera_element.addEventListener("click", start_action);
         var main_canvas = m_cont.get_canvas();
         main_canvas.addEventListener("mouseup", main_canvas_up);
         main_canvas.addEventListener("mousedown", main_canvas_down);
     }
     function start_action() {
        var counter = 1;
        var main_show = function() {
            var target = m_scenes.get_object_by_name(targets[counter]);
             var eye = m_scenes.get_object_by_name(eyes[counter]);
             if (eye && target) {
                 var camobj = m_scenes.get_active_camera();
                 var pos_view = m_trans.get_translation(eye);
                 var pos_target = m_trans.get_translation(target);
                 m_scenes.show_object(m_scenes.get_object_by_name("Box-Parent"), false);
                 start_camera_animation(camobj, pos_view, pos_target);
             }
             if (counter < eyes.length - 1)
                 setTimeout(function() {
                    counter++;
                    main_show();
                 }, 1000 * stops[counter] + 1000);
        }
        main_show();
     }

     function main_canvas_up(e) {

         if (e.button != 0)
             return;

         if (e.preventDefault)
             e.preventDefault();

         var obj = m_scenes.pick_object(e.clientX, e.clientY);

         if (obj)
             switch (m_scenes.get_object_name(obj)) {
                 case "Box-Parent":
                     var target = m_scenes.get_object_by_name("Cube-Target");
                     var eye = m_scenes.get_object_by_name("Cube-Eye-3");
                     break;
                 case "Cylinder.000":
                     var target = m_scenes.get_object_by_name("Cylinder.000");
                     var eye = m_scenes.get_object_by_name("Cube.001");
                     break;
                 default:
                     return;
             }

         if (eye && target) {
             var camobj = m_scenes.get_active_camera();
             var pos_view = m_trans.get_translation(eye);
             var pos_target = m_trans.get_translation(target);
             start_camera_animation(camobj, pos_view, pos_target);



         }

     }

     function main_canvas_down(e) {

         if (e.button != 0) return;

         var camobj = m_scenes.get_active_camera();

         if (m_ctl.get_sensor_value(camobj, "CAMERA_MOVE", 0) - _cam_anim.timeline < ANIM_TIME) _anim_stop = true;

     }

     function start_camera_animation(camobj, pos_view, pos_target) {
         // retrieve camera current position
         m_cam.target_get_pivot(camobj, _cam_anim.current_target);
         m_trans.get_translation(camobj, _cam_anim.current_eye);

         // set camera starting position
         m_vec3.copy(_cam_anim.current_target, _cam_anim.starting_target);
         m_vec3.copy(_cam_anim.current_eye, _cam_anim.starting_eye);

         // set camera final position
         m_vec3.copy(pos_view, _cam_anim.final_eye);
         m_vec3.copy(pos_target, _cam_anim.final_target);

         // start animation
         _delta_target = ANIM_TIME;
         _cam_anim.timeline = m_time.get_timeline();

         return;
     }

     function init_camera_animation(camobj) {

         var t_sensor = m_ctl.create_timeline_sensor();
         var e_sensor = m_ctl.create_elapsed_sensor();

         var logic_func = function (s) {
             // s[0] = m_time.get_timeline() (t_sensor value)
             return s[0] - _cam_anim.timeline < ANIM_TIME;
         }

         var cam_move_cb = function (camobj, id, pulse) {

             if (pulse == 1) {
                 if (_anim_stop) {
                     _cam_anim.timeline = -ANIM_TIME;
                     return;
                 }

                 m_app.disable_camera_controls();
                 // elapsed = frame time (e_sensor value)
                 var elapsed = m_ctl.get_sensor_value(camobj, id, 1);
                 var delta = elapsed / ANIM_TIME;

                 m_vec3.subtract(_cam_anim.final_eye, _cam_anim.starting_eye, _vec3_tmp);
                 m_vec3.scaleAndAdd(_cam_anim.current_eye, _vec3_tmp, delta, _cam_anim.current_eye);

                 _delta_target -= elapsed;
                 delta = 1 - _delta_target * _delta_target / (ANIM_TIME * ANIM_TIME);
                 m_vec3.subtract(_cam_anim.final_target, _cam_anim.starting_target, _vec3_tmp);
                 m_vec3.scaleAndAdd(_cam_anim.starting_target, _vec3_tmp, delta, _cam_anim.current_target);

                 m_cam.target_set_trans_pivot(camobj, _cam_anim.current_eye, _cam_anim.current_target);

             } else {
                 m_app.enable_camera_controls(false);
                 if (!_anim_stop)
                     m_cam.target_set_trans_pivot(camobj, _cam_anim.final_eye, _cam_anim.final_target);
                 else
                     _anim_stop = false;
             }
         }

         m_ctl.create_sensor_manifold(camobj, "CAMERA_MOVE", m_ctl.CT_CONTINUOUS, [t_sensor, e_sensor], logic_func, cam_move_cb);
     }
 });
 b4w.require("3Dmodel-Hat-06_app").init();
Blend4Web developer
20 April 2017 19:22
Thank you Roman

I have a bigger issue, that I can not deploy the project via the platform. Is there a way to make the final <script> section manually and deploy it to the server. Currently when I try deploying it, the <script> section is empty and no JS file is included in the zipped package.

Thank you for the reply, and i test it today.
 
Please register or log in to leave a reply.