Just following along with a Babylon tutorial and it might be that its using an older version of BabylonJS - but I am getting the error:
e.Gamepads is not a constructor
with the following code
var bApp = bApp || {};
bApp.init = function(){
//get the canvas
var canvas = document.getElementById('renderCanvas');
//create a BabylonJS engine object, true for antialias
var engine = new BABYLON.Engine(canvas, true);
//create a scene
var scene = new BABYLON.Scene(engine);
//create a camera
var camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 15, BABYLON.Vector3.Zero(), scene);
//let the user move the camera
camera.attachControl(canvas);
//light
var light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0,1,0), scene);
var sun = BABYLON.Mesh.CreateSphere('sun', 16, 4, scene);
engine.runRenderLoop(function () {
scene.render();
});
// the canvas/window resize event handler
window.addEventListener('resize', function(){
engine.resize();
});
}
window.addEventListener('DOMContentLoaded', function(){
bApp.init();
});
The tutorial seems to an older version of Babylon (2.1) and I am trying to use 2.4.
Related
I'm setting up a website that loads 3d models in ply format, and I'm using Three.js with his PLYLOADER to do that.
My problem is that every model is loading in a different position. I've managed to make them load in a perpendicular way with the ground, but some of them are looking, some are looking far away from the camera and others look like they turn around a Y axis (not their center).
This is my HTML div:
<div id="WebGL-output"></div>
This is my JS code:
<script type="text/javascript">
var lesson7 = {
scene: null,
camera: null,
renderer: null,
container: null,
controls: null,
clock: null,
stats: null,
init: function() { // Initialization
// create main scene
this.scene = new THREE.Scene();
this.scene.fog = new THREE.FogExp2(0xcce0ff, 0.0003);
var SCREEN_WIDTH = '800',
SCREEN_HEIGHT = '600';
// prepare camera
var VIEW_ANGLE = 60, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
this.camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
this.scene.add(this.camera);
this.camera.position.set(0, 0, 300);
this.camera.lookAt(new THREE.Vector3(0,0,0));
// prepare renderer
this.renderer = new THREE.WebGLRenderer({ antialias:true });
this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
this.renderer.setClearColor(this.scene.fog.color);
this.renderer.shadowMapEnabled = true;
this.renderer.shadowMapSoft = true;
// prepare container
this.container = document.getElementById('WebGL-output');
this.container.appendChild(this.renderer.domElement);
// events
THREEx.WindowResize(this.renderer, this.camera);
// prepare controls (OrbitControls)
this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
this.controls.target = new THREE.Vector3(0, 0, 0);
this.controls.maxDistance = 20000;
// prepare clock
this.clock = new THREE.Clock();
this.scene.add( new THREE.AmbientLight(0xFFFFFF) );
// light
var dirLight = new THREE.DirectionalLight(0x606060);
dirLight.position.set(200, 200, 1000).normalize();
this.camera.add(dirLight);
this.camera.add(dirLight.target);
// load models
this.loadModels();
},
loadModels: function() {
// prepare PLY loader and load the model
var scene = new THREE.Scene();
var oPlyLoader = new THREE.PLYLoader();
oPlyLoader.load("../models/{{ $analysis->three_d_model }}", function(geometry) {
var material = new THREE.MeshPhongMaterial( { color: 0xAAAAAA, specular: 0x111111, shininess: 0 } );
var meshMaterial = material;
// if (geometry.hasColors) { // to fix when models will have colors
meshMaterial = new THREE.MeshPhongMaterial({ opacity: 1, vertexColors: THREE.VertexColors });
// }
var mesh = new THREE.Mesh(geometry, meshMaterial);
// Solution: center mesh to world origin
mesh.geometry.computeBoundingBox();
var bbox = mesh.geometry.boundingBox;
var centerVec = new THREE.Vector3();
bbox.getCenter(centerVec); // get center of bbox into centerVec
// move mesh so that center of bbox is placed to world origin
mesh.applyMatrix(new THREE.Matrix4().makeTranslation(-centerVec.x, -centerVec.y, -centerVec.z));
// proceed doing stuff
// mesh.position.set(0, -6, 0);
// mesh.scale.set(5, 5, 5);
lesson7.scene.add(mesh);
});
}
};
// Animate the scene
function animate() {
requestAnimationFrame(animate);
render();
update();
}
// Update controls and stats
function update() {
lesson7.controls.update(lesson7.clock.getDelta());
// lesson7.stats.update();
}
// Render the scene
function render() {
if (lesson7.renderer) {
lesson7.renderer.render(lesson7.scene, lesson7.camera);
}
}
// Initialize lesson on page load
function initializeLesson() {
lesson7.init();
animate();
}
if (window.addEventListener)
window.addEventListener('load', initializeLesson, false);
else if (window.attachEvent)
window.attachEvent('onload', initializeLesson);
else window.onload = initializeLesson;
</script>
I need help to make them all load with the same camera position, looking centred and in the same size.
PS: If i can have better results loading in different extension, I'm up for it.
Thanks in advance
EDIT:
I updated the code with the help of #alex. Now my models are very well centered. The only thing missing now si a fixed camera position however the model was saved
Currently see two solutions here ( if i understand correctly )
You objects are not centered correctly. The solution would be to open the model files in a 3d editor and set them all to the same size and make their center points consistent.
Once you load the model add it to an Object3D and find its center.
Docs about that here: https://threejs.org/docs/#api/en/core/Object3D
the below code this.objectAll is the Object3D. Which is put into a box and we make the controls look at the center of that box. If all model are consistent then this should work.
this.boundingBox = new THREE.Box3();
this.boundingBox.setFromObject(this.objectAll);
this.boundingBox.center(this.controls.target);
Best of luck!
I am just getting into babylon.js, but I can't seem to figure out, how would you change color of a material ?
My code currently is:
/* eslint-disable */
import * as BABYLON from 'babylonjs';
// Get the canvas element from our HTML above
const canvas = document.getElementById("root");
// Load the BABYLON 3D engine
const engine = new BABYLON.Engine(canvas, true);
let fn;
let mainColor = new BABYLON.Color3(1.0, 0.2, 0.7);
setTimeout(() => {
mainColor = new BABYLON.Color3(0.3, 0.2, 0.2);
fn();
}, 2000);
// This begins the creation of a function that we will 'call' just after it's built
function createScene () {
// Now create a basic Babylon Scene object
const scene = new BABYLON.Scene(engine);
// Change the scene background color to green.
scene.clearColor = new BABYLON.Color4(0.5, 0.8, 0.6, 0.8);
// This creates and positions a free camera
const camera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 30, new BABYLON.Vector3(0, 0, 0), scene);
// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());
// This attaches the camera to the canvas
camera.attachControl(canvas, false);
// This creates a light, aiming 0,1,0 - to the sky.
const light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 1, 1), scene);
// Dim the light a small amount
light.intensity = .5;
// Let's try our built-in 'sphere' shape. Params: name, subdivisions, size, scene
const sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
const materialSphere1 = new BABYLON.StandardMaterial("texture1", scene);
materialSphere1.alpha = 1;
materialSphere1.diffuseColor = mainColor;
sphere.material = materialSphere1;
sphere.position.y = 1;
// Move the sphere upward 1/2 its height
// Let's try our built-in 'ground' shape. Params: name, width, depth, subdivisions, scene
const ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);
fn = () => {
materialSphere1.diffuseColor = mainColor;
}
// Leave this function
return scene;
}; // End of createScene function
const scene = createScene();
engine.runRenderLoop(function () {
scene.render();
});
window.addEventListener("resize", function () {
engine.resize();
});
It looks aweful to me. As you can see i am defining fn inside the createScene which then allows me to modify it that way, however I believe that there should be a better way of doing it. I tried creating a function outside the createScene(), that would fetch the color, and then use that for materialSphere1.diffuseColor, however that did not work. So my question is: Is there any other (nicer) way to change a color of a material in babylon.js
Why not declaring your material outside of the callback?
You can also use scene.materials to browse materials
I'm experiencing with Three JS after reading an article about augmented reality using a webcam.
Like experiment, i try to put a simple canvas in a scene, where before i have put a webglrender, by insert an webcam stream.
I read in this article (https://hacks.mozilla.org/2013/10/an-ar-game-technical-overview/) that for the virtual scene, is needed create a virtual scene, where is renderer by the object webglrenderer, and a reality scene(the webcam). In my file testingthreejs.js, between the line 30 and 41 is where i wrote the lines for create the new scene (the virtual), and where i created and inserting the canvas inside my mesh object.
But nothing happen, ¿how i can insert the canvas like a Mesh object?
I try to avoid draw a canvas, as it is supposed that the rendering by canvas is more slow that rendering with webgl (i also think use the ray class)
This is my gist : https://gist.github.com/fernandosg/75ec701c0295761a77e6, inside are the files testingthreejs.js and index.html.
Thanks for your help.
You can take a look at the Stemkoski s website which has a lot of examples with very nice explanations.
I think this is what you are looking for, take a look at the script.
More precisely, here is the commented code :
/////// draw text on canvas /////////
// create a canvas element
var canvas1 = document.createElement('canvas');
var context1 = canvas1.getContext('2d');
context1.font = "Bold 40px Arial";
context1.fillStyle = "rgba(255,0,0,0.95)";
context1.fillText('Hello, world!', 0, 50);
// canvas contents will be used for a texture
var texture1 = new THREE.Texture(canvas1)
texture1.needsUpdate = true;
var material1 = new THREE.MeshBasicMaterial( {map: texture1, side:THREE.DoubleSide } );
material1.transparent = true;
var mesh1 = new THREE.Mesh(
new THREE.PlaneGeometry(canvas1.width, canvas1.height),
material1
);
mesh1.position.set(0,50,0);
scene.add( mesh1 );
/////// draw image on canvas /////////
// create a canvas element
var canvas2 = document.createElement('canvas');
var context2 = canvas2.getContext('2d');
// canvas contents will be used for a texture
var texture2 = new THREE.Texture(canvas2);
// load an image
var imageObj = new Image();
imageObj.src = "images/Dice-Blue-1.png";
// after the image is loaded, this function executes
imageObj.onload = function()
{
context2.drawImage(imageObj, 0, 0);
if ( texture2 ) // checks if texture exists
texture2.needsUpdate = true;
};
var material2 = new THREE.MeshBasicMaterial( {map: texture2, side:THREE.DoubleSide} );
material2.transparent = true;
var mesh2 = new THREE.Mesh(
new THREE.PlaneGeometry(canvas2.width, canvas2.height),
material2
);
mesh2.position.set(0,50,-50);
scene.add( mesh2 );
}
I think that maybe i am getting closer to the solution, finally i can put the canvas (using a MeshBasicMaterial and a PlaneGeometry), but now the canvas was drawed, the video was not rendered:
problem canvas
The code:
var canvas=document.createElement("canvas");
canvas.width=512;
canvas.height=512;
var video=document.createElement("video");
streamVideo(video);
var canvasContext=canvas.getContext("2d");
var glCanvas=document.createElement("canvas");
var renderer_webgl=new THREE.WebGLRenderer({canvas:glCanvas});
renderer_webgl.setSize(512,512);
renderer_webgl.autoClear=false;
document.getElementById("container").appendChild(glCanvas);
var camera = new THREE.Camera();
var scene=new THREE.Scene();
var geometry=new THREE.PlaneGeometry(2,2,0);
var texture=new THREE.Texture(canvas);
var material=new THREE.MeshBasicMaterial({
map:texture,
depthTest:false,
depthWrite:false
});
var mesh=new THREE.Mesh(geometry,material);
canvas_draw=document.createElement("canvas");
canvas_draw.width=128;
canvas_draw.height=128;
ctx=canvas_draw.getContext("2d");
ctx.fillStyle = "#AAA";
ctx.fillRect(1,1,20,25);
// HERE IS WHEN INSERT THE CANVAS
var texture_canvas=new THREE.Texture(canvas_draw);
texture_canvas.needsUpdate=true;
var basic_material_canvas=new THREE.MeshBasicMaterial({
map:texture_canvas
});
var mesh_canvas=new THREE.Mesh(new THREE.PlaneGeometry(2,2,0),basic_material_canvas);
scene.add(mesh);
scene.add(mesh_canvas);
function renderScenes(){
renderer_webgl.render(scene,camera);
}
function loop(){
if(video.readyState===video.HAVE_ENOUGH_DATA){
canvas.changed=true;
canvasContext.drawImage(video,0,0);
verifyDetector();
texture.needsUpdate=true;
texture_canvas.needsUpdate=true;
renderScenes();
}
requestAnimationFrame(loop);
}
loop();
function verifyDetector(){
detector = new AR.Detector();
imageData = canvasContext.getImageData(0, 0, canvas.width, canvas.height);
var markers = detector.detect(imageData);
/*if(markers.length>0)
canvasContext.drawImage(canvas_draw,markers[0].corners[0].x,markers[0].corners[0].y);
*/
}
¿Why this happen?
I created a mesh in Blender and called it "Walking.babylon". I set it up in my code just how it states in the babylon tutorial:
///<reference path="/ref script/babylon.1.14-debug.js"/>
"use strict"
var canvas;
var engine;
var scene;
document.addEventListener("DOMContentLoaded", startBabylonJS, false);
function startBabylonJS() {
if (BABYLON.Engine.isSupported()) {
canvas = document.getElementById("renderCanvas");
engine = new BABYLON.Engine(canvas, true);
scene = new BABYLON.Scene(engine);
var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
light.position = new BABYLON.Vector3(20, 150, 70);
//create the camera that will view our scene
var cam = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
cam.setTarget(new BABYLON.Vector3.Zero());
cam.attachControl(canvas, false);
scene.ambientColor = new BABYLON.Color3(0.3, 0.3, 0.3);
// Ground
var ground = BABYLON.Mesh.CreateGround("ground", 1000, 1000, 1, scene, false);
var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
groundMaterial.diffuseColor = new BABYLON.Color3(0.2, 0.2, 0.2);
groundMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
ground.material = groundMaterial;
ground.receiveShadows = true;
// Shadows
var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
// Dude
BABYLON.SceneLoader.ImportMesh("man", "Scenes/Models/Animation/", "Walking.babylon", scene, function (newMeshes, particleSystems, skeletons) {
var dude = newMeshes[0];
for (var index = 0; index < newMeshes.length; index++) {
shadowGenerator.getShadowMap().renderList.push(newMeshes[index]);
}
dude.rotation.y = Math.PI;
dude.position = new BABYLON.Vector3(0, 0, -80);
scene.beginAnimation(skeletons[0], 0, 100, true, 1.0);
});
//Once the scene is loaded, just register a render loop to render it
engine.runRenderLoop(function () {
scene.render();
});
//Resize
window.addEventListener("resize", function () {
engine.resize();
});
}
}
But When I load my scene and hit F12 I get this message in the console: Failed to load resource: the server responded with a status of 404 (Not Found) and right next to it is this link: http://localhost:50207/Scenes/Models/Animation/Walking.babylon.manifest?1419869394361
So my question is: what am I doing wrong that is causing my animated mesh not to show?
Open notepad and put this:
{
"version" : 1,
"enableSceneOffline" : true,
"enableTexturesOffline" : true
}
Then rename it: Walking.babylon.manifest
And put it where "Walking.babylon" is.
I am having an issue that I discussed on the Haxe IRC channel but was unable to come up with a fix. It seems to be a bug with the compiler.
Here is the Haxe code:
package;
import js.Lib;
import js.three.Three;
import haxe.Timer;
class Main {
public var timer:Timer;
public var renderer:WebGLRenderer;
public var scene:Scene;
public var camera:PerspectiveCamera;
public function new() {
timer = new Timer(30);
var w = Lib.window.innerWidth;
var h = Lib.window.innerHeight;
scene = new Scene();
// create a red cube
var material = new MeshLambertMaterial({color:0xff0000});
var geometry = new CubeGeometry(50, 50, 50, 1, 1, 1, material, null);
var cube = new Mesh(geometry, new MeshFaceMaterial());
cube.position.set(0, 100, 0);
scene.add(cube);
// add some light
var pointLight = new PointLight(0xffffff, 1, 0);
pointLight.position.set(10, 50, 130);
scene.add(pointLight);
// and a camera
camera = new PerspectiveCamera(70, w/h, 1, 1000);
camera.position.z = 500;
scene.add(camera);
// setup renderer in the document
renderer = new WebGLRenderer(null);
renderer.setSize(w, h);
Lib.document.body.appendChild(renderer.domElement);
untyped Lib.window.onload = onLoad;
}
public function onLoad() {
timer.run = function(){
renderer.render(scene, camera, null, null);
}
}
public static function main() {
new Main();
}
}
The solution is to get the compiler to add the following to the beginning of the JS file that it creates.
var $_, $hxClasses = $hxClasses || {},
As it stands right now the first line in the JS file looks like this
$estr = function() { return js.Boot.__string_rec(this,''); }
Not sure what needs to be done to fix this or a possible work around other than adding in that line by hand after compilation ?
Found the issue - three.js has Date.hx and Timer.hx files in it (older versions) delete them and it works (on my win install it's in c:\Motion-Twin\haxe\lib\three,js\0,2,46\ and c:\Motion-Twin\haxe\lib\three,js\0,2,46\haxe)