Clojurescript, B4W and a resource-loading issue [**Solved**]
14 September 2016 19:34
Hi guys,
I'm attempting to integrate clojurescript with a blend4web. The idea is to get Clojurescript to compile down into javascript code, which in turn controls an existing blend4web scene. This javascript code is similar to the code that's usually used to control blend4web. I say 'similar' code, because Clojurescript's code is (like blend4web) optimized through Google Closure, and it looks a little different than hand-written javascript.
To test this integration out, I'm making a simple blend4web scene to test out the clojurescript bindings. It's just a simple cube, with no materials, images, or (I think) any external data linked to it. I've exported this cube scene with the blend4web exports, using the .json option. I've linked stuff up into the html.
While it appears that clojurescript is loading up the basic b4web modules, B4W is giving the following feedback:
There's a bunch of other warnings after the above, but I suspect they're all a result of the first error. It looks like this error is about not loading some external resources, but my scene is just a cube, with no materials or anything. So I'm not sure what resource my .blend is missing.
I'm pretty sure I'm invoking blend4web improperly, but I can't quite see how. Here's the JS output that is ultimately expected to control the blend4web scene:
You can see this code in it's context in the repo here: https://github.com/mikebelanger/blend4web_test/blob/master/target/main.out/cube_test/core.js
Now, there's obviously an html file, json, .bin, and of course, a .blend. I've uploaded all this stuff to https://github.com/mikebelanger/blend4web_test
If you're just interested in the blend4web side of it, you can see the outputted code in: https://github.com/mikebelanger/blend4web_test/tree/master/target
Thanks for checking this out, I know its a wacky idea.
I'm attempting to integrate clojurescript with a blend4web. The idea is to get Clojurescript to compile down into javascript code, which in turn controls an existing blend4web scene. This javascript code is similar to the code that's usually used to control blend4web. I say 'similar' code, because Clojurescript's code is (like blend4web) optimized through Google Closure, and it looks a little different than hand-written javascript.
To test this integration out, I'm making a simple blend4web scene to test out the clojurescript bindings. It's just a simple cube, with no materials, images, or (I think) any external data linked to it. I've exported this cube scene with the blend4web exports, using the .json option. I've linked stuff up into the html.
While it appears that clojurescript is loading up the basic b4web modules, B4W is giving the following feedback:
B4W WARN: Couldn't determine path to ancillary resources, fallback to the current page directory
There's a bunch of other warnings after the above, but I suspect they're all a result of the first error. It looks like this error is about not loading some external resources, but my scene is just a cube, with no materials or anything. So I'm not sure what resource my .blend is missing.
I'm pretty sure I'm invoking blend4web improperly, but I can't quite see how. Here's the JS output that is ultimately expected to control the blend4web scene:
// Compiled by ClojureScript 1.7.228 {}
goog.provide('cube_test.core');
goog.require('cljs.core');
cube_test.core.check_version = (function cube_test$core$check_version(){
var m_version = b4w.require("version");
return console.log(m_version.version());
});
cube_test.core.check_version.call(null);
cube_test.core.hello = (function cube_test$core$hello(){
var m_main = b4w.require("main");
var m_data = b4w.require("data");
var canvas = document.getElementById("container");
m_main.init(canvas);
return m_data.load("cube_test.json");
});
You can see this code in it's context in the repo here: https://github.com/mikebelanger/blend4web_test/blob/master/target/main.out/cube_test/core.js
Now, there's obviously an html file, json, .bin, and of course, a .blend. I've uploaded all this stuff to https://github.com/mikebelanger/blend4web_test
If you're just interested in the blend4web side of it, you can see the outputted code in: https://github.com/mikebelanger/blend4web_test/tree/master/target
Thanks for checking this out, I know its a wacky idea.
16 September 2016 20:25
Sorry to bump this guys, I had another thought.
After googling this error
I came across this thread where someone encounters a similar error. In that case, it looked like the files weren't sitting in the proper blend4web deploy directory.
So I tried moving my project over to the deploy directory, so that the index.html sits in ../deploy/assets/blend4web_test/target/index.html. Still doesn't load. Am I getting warm though? Do I have to re-export the .blends for the right subdir?
Thanks
After googling this error
B4W WARN: Couldn't determine path to ancillary resources, fallback to the current page directory
I came across this thread where someone encounters a similar error. In that case, it looked like the files weren't sitting in the proper blend4web deploy directory.
So I tried moving my project over to the deploy directory, so that the index.html sits in ../deploy/assets/blend4web_test/target/index.html. Still doesn't load. Am I getting warm though? Do I have to re-export the .blends for the right subdir?
Thanks
21 September 2016 16:11
I had another thought about this problem.
When I created the bindings for blend4web, I *only* used ../tools/closure-compiler/externs_modules.js. Of course, there's other externs files in that subdir.
I feel silly even asking this, but I'm guessing you use all the files the closure-compiler subdir to produce b4w.min.js? Or are some of those for different kinds of builds?
When I created the bindings for blend4web, I *only* used ../tools/closure-compiler/externs_modules.js. Of course, there's other externs files in that subdir.
I feel silly even asking this, but I'm guessing you use all the files the closure-compiler subdir to produce b4w.min.js? Or are some of those for different kinds of builds?
21 September 2016 23:08
Alright so the canvas renders now. The trick was to get uranium.js, **and** uranium.mem.js in the same directory as index.html. It appears the clojurescript-generated js works!
But I'm a little confused. From what the manual says, uranium is the physics engine for blend4web. And, from what the [manual states](https://www.blend4web.com/doc/en/developers.html#loading-scenes-in-apps), isn't necessary for a minimal blend4web project. I didn't have any physics in my scene either, just a cube, light and material.
I have no problem including uranium, I'm just trying to understand how it all works. The more I understand, the better!
But I'm a little confused. From what the manual says, uranium is the physics engine for blend4web. And, from what the [manual states](https://www.blend4web.com/doc/en/developers.html#loading-scenes-in-apps), isn't necessary for a minimal blend4web project. I didn't have any physics in my scene either, just a cube, light and material.
I have no problem including uranium, I'm just trying to understand how it all works. The more I understand, the better!
23 September 2016 22:07
Alright, so I'm trying to get camera navigation in my example. From the documentation, it looks like I need to first use the "scenes" module, and use that to get the active camera.
But the scene instance needs to be active first, and this is where I'm stumped. Right now, I'm just invoking the scenes module like:
as per the documentation.. 0 is the name of the scene in my .blend. I've also tried just invoking set_active without arguments. Either way, I get this error:
I'm not sure what I need for an active scene. Here's the entire compiled JS.
But the scene instance needs to be active first, and this is where I'm stumped. Right now, I'm just invoking the scenes module like:
m_scene.set_active("0");
B4W ERROR: No active scene
I'm not sure what I need for an active scene. Here's the entire compiled JS.
cube_test.core.check_version = (function cube_test$core$check_version(){
var m_version = b4w.require("version");
return console.log(m_version.version());
});
cube_test.core.check_version.call(null);
cube_test.core.start = (function cube_test$core$start(){
var m_main = b4w.require("main");
var m_data = b4w.require("data");
var m_scene = b4w.require("scenes");
var canvas = document.getElementById("container");
m_main.init(canvas);
m_data.load("cube_test.json");
m_scene.set_active("0");
cube_test.core.m_camera = m_scene.get_active_camera("scene");
return console.log(m_scene);
23 September 2016 22:31
I should also mention I found this thread relating to scenes not getting active. In that case, it looked like changing the callback declarations did the trick. In my case, there are no callbacks to be declared (I'm not using the "app" module).
But that makes me wonder, do I need an "app" module instance in order to use a "scenes" instance?
But that makes me wonder, do I need an "app" module instance in order to use a "scenes" instance?
26 September 2016 17:30
Hi,
Sorry for not answering, this is not because we are not interested. This matter looks very sophisticated. All our devs are having hard time preparing the upcoming release but I think somebody will be able to advise something on this topic.
BTW welcome to the Blend4Web forums!
Sorry for not answering, this is not because we are not interested. This matter looks very sophisticated. All our devs are having hard time preparing the upcoming release but I think somebody will be able to advise something on this topic.
BTW welcome to the Blend4Web forums!
26 September 2016 19:45
Hi Yuri - and thank-you! No worries about responding to this, blend4web development itself is an understandably higher priority. Making it work with Clojure is understandably lower. I wasn't sure if anyone else would be interested anyways. But it's cool if anyone else is interested.
I should post an update – I can now grab the active scene. I just had to activate it in the second callback – just like the link in my last post :P I got mixed up because the previous post uses different modules, and so I thought it would be different kinds of callbacks.
I also think my problem (but correct me if I'm wrong) is that I had to have that callback invoked within another function call, much like the tutorials all say. I believe this is important for any CommonJS-based library, so its good I learn for most modern JS dev work.
For what it's worth, here is the clojurescript way of invoking it.
I should post an update – I can now grab the active scene. I just had to activate it in the second callback – just like the link in my last post :P I got mixed up because the previous post uses different modules, and so I thought it would be different kinds of callbacks.
I also think my problem (but correct me if I'm wrong) is that I had to have that callback invoked within another function call, much like the tutorials all say. I believe this is important for any CommonJS-based library, so its good I learn for most modern JS dev work.
For what it's worth, here is the clojurescript way of invoking it.
(ns cube-test.core
(:require blend4web))
(defn check-version []
(let [m-version (.require js/b4w "version")]
(.log js/console "Using Blend4Web Version" (.version m-version))))
(check-version)
(defn ^:export start
[json]
(let [m-main (.require js/b4w "main")
m-data (.require js/b4w "data")
m-scene (.require js/b4w "scenes")
m-config (.require js/b4w "config")
m-trans (.require js/b4w "transform")
m-camera (.require js/b4w "camera")
canvas (.getElementById js/document "container")]
(defn loaded-cb [data-id success]
(.log js/console
"Main scene loaded on thread number: " data-id
"with a success value of: " success))
(defn stageload-cb [data-id success]
"Use camera, translation and other b4w modules in this fn's scope."
(when (.is-primary-loaded m-data)
(let [current-camera (.get-active-camera m-scene)
cube (.get-object-by-name m-scene "Cube")]
(.translate-view m-camera current-camera 0 0.5 0.25)
(.set-rotation m-trans cube 1.2 0 0 0)
(.set-scale m-trans cube 0.25 0.25 0.25))))
(.set m-config "console_verbose" true)
(.load m-data (str json) loaded-cb stageload-cb true false)
(.init m-main canvas)))