Blog

Webmasters! 3 Ways to 3D Web

2014-08-01

This article explains how to place Blend4Web content on websites.

Method #1 (Simplest): Self-Contained HTML File

The possibility to export scenes from Blender to a single HTML file is one the most exciting features of Blend4Web. Such a file is an all-sufficient web page that can be opened with any standard browser and shared through any means (via email, USB drive/memory card, cloud storage, etc). You can, of course, share it online too. Particularly, you can upload and embed it in a website using iframe for which you can set the dimensions and specify other properties such as allowfullscreen:

<iframe allowfullscreen src="path/to/apple.html" width="800" height="500"></iframe>

The main advantage of this method is its simplicity. Blend4Web newbies can follow these steps:

  • 1. Download and install Blend4Web;
  • 2. Export a pre-created scene via Blender menu File > Export > Blend4Web (.html);
  • 3. Upload the HTML file to your website and embed it with iframe.

Of course, you can use HTML files as standalone web pages without any embedding too.

Method #2 (More Optimized): Web Player + JSON

The second method is an alternative to the first and the result seemingly looks the same: 3D content with control elements is embedded in a web page.

Nevertheless, this method of embedding is different: instead of a single HTML file, a combination of the Web Player and a separate JSON file is used.

<iframe allowfullscreen src="path/to/webplayer.html?load=path/to/apple.json" width="800" height="500"></iframe>

Where do you get the Web Player? You can copy the whole directory blend4web/deploy/apps/webplayer/ with the Web Player files from your Blend4Web SDK and deploy it on your website.

JSON files can be exported in the same way as the HTML files File > Export > Blend4Web (.json). Upload your exported .json file (with the accompanying .bin file and possible textures) to your website and specify the path to it with the load attribute. Both absolute and relative URLs are supported.

Learn more about features of the Web Player in the corresponding section of the User Manual.

Note

If you try to launch this app locally (not from a remote web server), it won't run due to the same-origin policy. For loading and viewing exported .json files we recommend using the Project Manager. With the Project Manager you can also create production-ready apps based on the Web Player without the need to copy files manually.

While this method looks a bit more complicated, it offers several benefits. Exported scenes are:

  • 1. smaller and can be loaded faster;
  • 2. capable to be used by programmed apps other than the standard Web Player;
  • 3. designed to allow you to use Blend4Web's physics engine;
  • 4. decoupled from the Web Player's code and are not subject to the licensing as it is with HTML files.

Method #3 (Customizable): Interactive 3D Web App

Finally, we can convert the web page itself into an interactive 3D application! Let's demonstrate this with a simple example: we'll place a button on this page to trigger interesting animation.

Check it out: the page content can be viewed through translucent animated balloons with volumetric highlights. Plus, there is a magical sound!

The stripped version can be seen live here. The source files can be found in this SDK folder: apps_dev/tutorials/web_page_integration/.

How this animation effect was created is described in this article. Now, let's look at how it was integrated with this page. This isn't any more difficult than making something similar with jQuery or the fading Flash.

Note

Once again, it is very convenient to use the Project Manager to create a full set of application files (HTML, CSS, JS) and modify them instead of creating everything from scratch.

First of all, you should link the Blend4Web JavaScript library b4w.min.js that you can copy from your SDK. The logic is coded in separate script file called example.js:

<script type="text/javascript" src="b4w.min.js"></script>
<script type="text/javascript" src="example.js"></script>

Then we add div elements for the rendering area and the button:

<div id="canvas_cont"></div>
<div id="run_button"></div>

The script for this small app is very short. It starts with a module declaration and then it imports required Blend4Web modules. The app initializes a WebGL context first. Pay attention to the init parameters: div element id is supplied to canvas_container_id yet transparency is enabled with alpha:

exports.init = function() {
    m_app.init({
        canvas_container_id: "canvas_cont",
        callback: init_cb,
        alpha: true
    });
}

Then the .json file is loaded:

m_data.load("path/to/flying_letters.json", load_cb);

After the loading is complete, the load_cb() callback is fired. Inside this function, we can start manipulating our 3D scene. First, we stop the armature animation because it was set to auto-play in Blender settings (our 3D artist used skeletal animation for balloons and it was convenient for him to tweak the animation outside the app).

var letters_arm = m_scs.get_object_by_name("beads_armature");
m_anim.stop(letters_arm);

Then we attach a mousedown event listener to our button:

run_button.addEventListener("mousedown", demo_link_click, false);

Every time the button is clicked the demo_link_click() function is called. Inside it we play sound...

var spk = m_scs.get_object_by_name("Speaker");
m_sfx.play_def(spk);

...and run the animation of flying balloons. So simple!

var letters_arm = m_scs.get_object_by_name("beads_armature");
m_anim.apply(letters_arm, "flying_letters");
m_anim.play(letters_arm, letters_obj_cb);

After all the balloons fly out from the bottom and are positioned in a row, we switch their animation to idle:

m_anim.apply(obj, "flying_letters_idle");
m_anim.set_behavior(obj, m_anim.AB_CYCLIC);
m_anim.play(obj);

That's it!

In Closing

WebGL gives the unique opportunity to seamlessly integrate interactive 3D content with other web technologies. With Blend4Web, you can easily create such content with Blender, deploy it on web pages and combine it with any HTML elements.

Changelog

[2014-08-01] Initial release.

[2014-10-22] Updated file paths.

[2014-10-30] Updated links to the web player. Added allowfullscreen attribute. Removed deprecated bg parameter.

[2014-12-03] Added sound.

[2015-04-23] Updated file path to webplayer sources. Updated variable and animation names. Removed deferred_rendering and context_antialias parameters from m_app.init() function.

[2015-05-15] Added CSS style description. Rendering area resize logic replaces from script to CSS table. Added link to standalone application. Added resize() function description.

[2015-12-10] Removed app.js module.

[2016-02-11] Fixed css.

[2016-04-08] Standalone B4W add-on is no longer mentioned to discourage its use. Fixed links. Removed show_fps URL attribute to simplify things. Added info about the Project Manager. Removed all CSS code and simplified code explanation.

[2016-06-16] Added the possibility to use physics to the benefits list of the second method. Clarified other items in that list.

[2016-09-21] Added an advice to use the Project Manager for creating apps.

[2017-01-12] Minor changes in the text.

[2017-03-22] Updated the link to the licensing options. Fixed the links to the #3 app sources.

Comments
02 mar. 2017 15:53
This is the simple project - project.zip.

You can import it in the Project Manager.

Or.. do you need the another behavior?
02 mar. 2017 16:26
I mean exactly four 3d images.

On this page you can see 1. But I want just 4

http://blender.freemovies.co.uk/blend4web/scripting/hello3.html
02 mar. 2017 17:07
Hello
Do you mean this?

There are 4 interactive canvases on this page. I've attached the sources, just import it to you ProjectManager
02 mar. 2017 17:22
It is correct. This is what I really want

Than you so much for help Dmitry Zhiganov, Roman Sementsov
02 mar. 2017 20:31
Well, I had tried to write it on my own, to understand blend4web. This is my code, but it unfortunately does not work.

b4w.register("sev_canvas_app", function(exports, require) {

// import modules used by the app
var m_app       = require("app");
var m_data      = require("data");
var m_preloader = require("preloader");

exports.init_1 = function() {
    m_app.init({
        canvas_container_id: "main_canvas_container_1",
        callback: init_cb1,
        show_fps: DEBUG,
        console_verbose: DEBUG,
        autoresize: true
    });
}

exports.init_2 = function() {
    m_app.init({
        canvas_container_id: "main_canvas_container_2",
        callback: init_cb2,
        show_fps: DEBUG,
        console_verbose: DEBUG,
        autoresize: true
    });
}

function init_cb1(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;
    };

    load1();
}

function init_cb2(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;
    };

    load2();
}



function load1() {
    m_data.load(APP_ASSETS_PATH + "sev_canvas1.json", load_cb, preloader_cb);
}

function load2() {
    m_data.load(APP_ASSETS_PATH + "sev_canvas2.json", load_cb, preloader_cb);
}

function preloader_cb(percentage) {
    m_preloader.update_preloader(percentage);
}

function load_cb(data_id, success) {

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

    m_app.enable_camera_controls();
}

});

// import the app module and start the app by calling the init method
b4w.require("sev_canvas_app").init_1();
b4w.require("sev_canvas_app").init_2();


	  <div class="wrapper">
        <div id="main_canvas_container_1"></div>
      </div>
	  <div class="wrapper">
        <div id="main_canvas_container_2"></div>
      </div>
03 mar. 2017 12:19
Hello,

You don't have to write init_cb1, init_cb_2. Look. In the example above, we have named our module "sev_canvas_app". It has standard functions: init, init_cb, load, load_cb. But we use this module several times:
b4w.require("sev_canvas_app", "NS_1").init_1();
b4w.require("sev_canvas_app", "NS_2").init_2();

We duplicated the init function twice, because we used different HTML elements: main_canvas_container_1 and main_canvas_container_2. We could write the following code and it would be the same:
b4w.register("sev_canvas_app", function(exports, require) {
var _name_space = b4w.get_namespace(require);
// import modules used by the app
var m_app       = require("app", _name_space);
var m_data      = require("data", _name_space);
var m_preloader = require("preloader", _name_space);

var _loading_scene = "";

exports.init = function(canvas_container_id, loading_scene) {
   _loading_scene = loading_scene;
    m_app.init({
        canvas_container_id: canvas_container_id,
        callback: init_cb1,
        show_fps: DEBUG,
        console_verbose: DEBUG,
        autoresize: 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 + _loading_scene, load_cb, preloader_cb);
}

function preloader_cb(percentage) {
    m_preloader.update_preloader(percentage);
}

function load_cb(data_id, success) {

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

    m_app.enable_camera_controls();
}

});

// import the app module and start the app by calling the init method
b4w.require("sev_canvas_app", "canvas_1").init("main_canvas_container_1", "sev_canvas1.json");
b4w.require("sev_canvas_app", "canvas_2").init("main_canvas_container_2", "sev_canvas2.json");


The main code lines are placed in the end of this example:
b4w.require("sev_canvas_app", "canvas_1").init("main_canvas_container_1", "sev_canvas1.json");
b4w.require("sev_canvas_app", "canvas_2").init("main_canvas_container_2", "sev_canvas2.json");


Take a look at the "canvas_1" and "canvas_2" variables. They are called name space variables. They allow us to use one module twice. And each time, this module will be used as a new module.

Use the last code snippet

Anyway, we are going to write an article about this. I hope, it will be useful for users.
04 apr. 2021 10:42
Нет смысла.

—–
<a href="https://irongamers.ru/sale/key/2045042">Аккаунт Addmefast 20 000 поинтов. Гарантия. Качество</a> https://irongamers.ru/
05 apr. 2021 01:12
Путешественники внутри Вас из мысленно ожидает то место, как скоро выполнимо будет сделать поездку на море совместно с семьей или же компанией. Прибыть в самый центр Черного либо Азовского теплого моря на микроавтобусе в настоящем комфорте - специальное выход для тех, кто из изначально основы важно проникнуться каникулы также вполне вздохнуть. Транспортная предприятие "Синбад" <a href="https://sinbad.com.ua/kirillovka.html">автобус Харьков Кирилловка</a> предоставляет службу проезда до побережье за демократичные цены, на презентованного сайте покупатели имеют возможность лично подобрать море, на котором хотят выполнить лучшие период выходных. Наша фирма гарантирует достаточно признанные поездки у места https://sinbad.com.ua/ на берег Черного также Азовского отдыха с постоянным графиком, также Вы имеют возможность заказать экскурсионную трансфер, выезд, наем транспорта либо прокат на удобный время из Харьковской области также на месте же сформировать прайс ожидаемой поездки на точном форме. Путешествия в принадлежащих нам автобусах - дает вам предел комфорта, надежности SinBad.Com.Ua плюс приятной знакомых для следующих отдыха.
05 apr. 2021 01:55
移动平均线
需要权衡使用移动平均线的优点和缺点。均线是趋势跟踪或滞后指标,始终将其落后。不过,这不一定是一件坏事。毕竟,趋势是您的朋友,最好朝趋势的方向进行交易。移动平均线可确保交易者与当前趋势保持一致。尽管趋势是您的朋友,但证券在交易区间上花费了大量时间,这使得移动平均线无效。一旦处于趋势中,移动平均线将使您进入,但也会发出较晚的信号。不要期望使用移动平均线在顶部卖出并在底部买入。与大多数技术分析工具一样,移动平均值不应单独使用,而应与其他补充工具结合使用。图表专家可以使用移动平均线来定义总体趋势,然后使用RSI来定义超买或超卖水平。
趋势识别
移动平均线的方向传达有关价格的重要信息,无论该平均线是简单的还是指数的。上升的移动平均线表明价格总体上在上涨。下降的移动平均线表明价格平均在下降。长期移动平均线的上升反映了长期的上升趋势。长期移动平均线的下降反映了长期下降趋势。
移动平均线-图表4
free forex signals
上面的图表显示了3M(MMM)和150天的指数移动平均线。此示例显示了趋势强劲时移动平均线的运行情况。为期150天的EMA在2007年11月和2008年1月再次下跌。请注意,下跌15%即可扭转此移动均线的方向。这些滞后指标可以确定趋势反转发生的时间(最好)或发生之后的时间(最坏的情况)。 MMM持续走低至2009年3月,然后飙升40-50%。请注意,直到激增之后,150天EMA才出现。然而,一旦成功,MMM在接下来的12个月中将继续走高。均线在强势趋势中表现出色。
双分频
可以将两个移动平均值一起使用以生成交叉信号。在《金融市场技术分析》中,约翰·墨菲(John Murphy)将其称为“双重交叉法”。双重交叉涉及一个相对较短的移动平均线和一个相对较长的移动平均线。与所有移动平均线一样,移动平均线的总长度定义了系统的时间范围。使用5天EMA和35天EMA的系统将被视为短期系统。使用50天SMA和200天SMA的系统将被视为中期,甚至是长期的。
当较短的移动均线超过较长的移动均线时,将出现看涨交叉。这也被称为金色十字架。当较短的移动均线低于较长的移动均线时,发生看跌交叉。这被称为死十字架。
https://www.freeforex-signals.com/
移动平均交叉产生相对较晚的信号。毕竟,系统采用了两个滞后指标。移动平均周期越长,信号的滞后越大。当良好的趋势发生时,这些信号会发挥作用。但是,在没有强劲趋势的情况下,移动平均交叉系统会产生大量的鞭子。
05 apr. 2021 09:02
Любой внутри Вас из большим желанием ждет то период, когда возможно получиться устроить тур на воде с близкими либо командой. Домчать в самый центр Черного либо Азовского теплого моря на автобусе в стопроцентном удобстве - рабочее идея для людей, кто из первого основы желает пережить выходные также целиком расслабиться. Авто парк "Синбад" <a href="https://sinbad.com.ua/berdjansk.html">Харьков Бердянск</a> рекомендует услуги проезда к морю за демократичные расценки, на страничке презентованного сайте заказчики имеют возможность лично подобрать направление, где желают выполнить красочные дни отдыха. Данная компания презентует самые признанные рейсы на местам https://sinbad.com.ua/ к изморье Черного и Азовского тура из постоянным графиком, и клинеты имеют возможность купить туринговую поездку, турне, наем транспорта или временное использование на удобный период с города Харьков и на месте ж просчитать грядущей поездки на живом формуле. турне в наших автобусных салонах - дает вам большое количество комфорта, устойчивости SinBad.Com.Ua и отличной знакомых под будущего отдыха.
Please register or log in to leave a reply.