Loading various models into separate div elements on the same page
02 February 2016 08:23
I'm looking at the code for "simple_app.js" that's provided with Blend4Web SDK.
I already know how to position and style div elements on a page with html and css, so I understand that part of the sample project. What I don't understand is how to load additional 3D models into separate divs.
From what I can see, the Blend4Web app is loaded into a div with the id of "main_canvas_container". How would the code look if I wanted to load a couple of different models into their own divs, so you could view them as you scroll down the page? It's important that the models are in their own divs, not in the same scene, and that they have their own rotate controls, etc. I don't need any UI elements or extra features. Just simply displaying 3D models in their own divs on the same page, with the ability to rotate/zoom/etc. like the "simple_app" example.
I've provided the "simple_app.js" code to make it easier to show me what lines I need to modify or add for each new 3D model and corresponding div element:
I already know how to position and style div elements on a page with html and css, so I understand that part of the sample project. What I don't understand is how to load additional 3D models into separate divs.
From what I can see, the Blend4Web app is loaded into a div with the id of "main_canvas_container". How would the code look if I wanted to load a couple of different models into their own divs, so you could view them as you scroll down the page? It's important that the models are in their own divs, not in the same scene, and that they have their own rotate controls, etc. I don't need any UI elements or extra features. Just simply displaying 3D models in their own divs on the same page, with the ability to rotate/zoom/etc. like the "simple_app" example.
I've provided the "simple_app.js" code to make it easier to show me what lines I need to modify or add for each new 3D model and corresponding div element:
"use strict"
// register the application module
b4w.register("simple_app", function(exports, require) {
// import modules used by the app
var m_anim = require("animation");
var m_app = require("app");
var m_data = require("data");
var m_scenes = require("scenes");
var _previous_selected_obj = null;
/**
* export the method to initialize the app (called at the bottom of this file)
*/
exports.init = function() {
m_app.init({
canvas_container_id: "main_canvas_container",
callback: init_cb,
show_fps: true,
console_verbose: true,
autoresize: true
});
}
/**
* callback executed when the app is initizalized
*/
function init_cb(canvas_elem, success) {
if (!success) {
console.log("b4w init failure");
return;
}
canvas_elem.addEventListener("mousedown", main_canvas_click, false);
load();
}
/**
* load the scene data
*/
function load() {
m_data.load("simple_app.json", load_cb);
}
/**
* callback executed when the scene is loaded
*/
function load_cb(data_id) {
m_app.enable_controls();
m_app.enable_camera_controls();
// place your code here
}
function main_canvas_click(e) {
if (e.preventDefault)
e.preventDefault();
var x = e.clientX;
var y = e.clientY;
var obj = m_scenes.pick_object(x, y);
if (obj) {
if (_previous_selected_obj) {
m_anim.stop(_previous_selected_obj);
m_anim.set_frame(_previous_selected_obj, 0);
}
_previous_selected_obj = obj;
m_anim.apply_def(obj);
m_anim.play(obj);
}
}
});
// import the app module and start the app by calling the init method
b4w.require("simple_app").init();
02 February 2016 11:57
Hi, there are several ways to do that.
The easiest is to load every model in a separate iframe. This is what we do, for example, in our release articles. Our WebPlayer is the most suitable application in this case, because you can pass the "load" parameter to refer to a specific scene/model json file:
But if you don't want any additional features (basically it's a Webplayer UI) you can also use your own application like "simple_app.html" instead of Webplayer. But it should know somehow which scene to load, for example, through the similar URL parameter:
This parameter should be parsed right before the json loading in the "load" method:
There is an additional logic in the "simple_app.js". I would suggest to comment the following line:
or just create a clean new application via the Project Manager to avoid possible errors.
The easiest is to load every model in a separate iframe. This is what we do, for example, in our release articles. Our WebPlayer is the most suitable application in this case, because you can pass the "load" parameter to refer to a specific scene/model json file:
<iframe src="webplayer/webplayer.html?load=test0.json"></iframe>
<iframe src="webplayer/webplayer.html?load=test1.json"></iframe>
<iframe src="webplayer/webplayer.html?load=test2.json"></iframe>
...
But if you don't want any additional features (basically it's a Webplayer UI) you can also use your own application like "simple_app.html" instead of Webplayer. But it should know somehow which scene to load, for example, through the similar URL parameter:
<iframe src="simple_app/simple_app.html?model=test0.json"></iframe>
<iframe src="simple_app/simple_app.html?model=test1.json"></iframe>
<iframe src="simple_app/simple_app.html?model=test2.json"></iframe>
...
This parameter should be parsed right before the json loading in the "load" method:
function load() {
var url_params = m_app.get_url_params();
if (url_params && url_params["model"])
m_data.load(url_params["model"], load_cb);
}
There is an additional logic in the "simple_app.js". I would suggest to comment the following line:
canvas_elem.addEventListener("mousedown", main_canvas_click, false);
or just create a clean new application via the Project Manager to avoid possible errors.
02 February 2016 12:30
There is an option to do it without iframes.
An application is usually initialized at the end of the module like this:
In addition, a single application can be initialized many times and each time it would be an independent app instance.
The second "namespace" parameter is responsible for this:
But it isn't enough. You should also specify a unique canvas container element for every app instance. For example passing its id in the init() method:
An application is usually initialized at the end of the module like this:
b4w.require("simple_app").init();
In addition, a single application can be initialized many times and each time it would be an independent app instance.
The second "namespace" parameter is responsible for this:
b4w.require("simple_app", "inst_0").init();
b4w.require("simple_app", "inst_1").init();
But it isn't enough. You should also specify a unique canvas container element for every app instance. For example passing its id in the init() method:
...
exports.init = function(id) {
m_app.init({
canvas_container_id: id,
callback: init_cb,
show_fps: true,
console_verbose: true,
autoresize: true
});
}
...
b4w.require("simple_app", "inst_0").init("canvas_container_0");
b4w.require("simple_app", "inst_1").init("canvas_container_1");