I have created a 3D model website for showing JSON files with three.js.
This is working if I open the html file locally stored on my computer.
But if I upload all files to my webserver (apache2) nothing is displayed.
I have tried to run a simple Three.js example without JSON loader and this is working on my webserver.
I also checked the paths to the JSON files and they are all relative paths I can open each file in the browser if I type the name or if I use firebug I can browse all files.
I checked the apache error log but no error message appears.
What can be the problem or how can I find out what the problem is?
This is my Script part.
var scene;
var camera;
var controls;
var geometryArray;
initializeScene();
animateScene();
function initializeScene(){
if(!Detector.webgl){
Detector.addGetWebGLMessage();
return;
}
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setClearColor(0x000000, 1);
canvasWidth = window.innerWidth;
canvasHeight = window.innerHeight;
renderer.setSize(canvasWidth, canvasHeight);
document.getElementById("WebGLCanvas").appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 100);
camera.position.set(0, 0, 6);
camera.lookAt(scene.position);
scene.add(camera);
controls = new THREE.TrackballControls(camera, renderer.domElement);
axisSystem = new AxisSystem(camera, controls);
geometryArray = new Object();
var loader = new THREE.JSONLoader();
for(var i = 0; i < jsonFileNames.length; i++){
var layerName = jsonFileNames[i].split("/")[2].split(".")[0];
loader.load(layerName, jsonFileNames[i], function(geometry, materials, layerName){
mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({vertexColors: THREE.FaceColors, side:THREE.DoubleSide}));
mesh.scale.set(0.013, 0.013, 0.013);
scene.add(mesh);
geometryArray[layerName] = mesh;
}, layerName);
}
var directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
directionalLight.position = camera.position;
scene.add(directionalLight);
}
function animateScene(){
controls.update();
axisSystem.animate();
requestAnimationFrame(animateScene);
renderScene();
}
function renderScene(){
renderer.render(scene, camera);
axisSystem.render();
}
My guess is that your files are not being loaded because of the for loop you are using. Load is asynchronous, so each time you call loader.load, you corrupt object state from previous call. Try creating new loader in every step or come up with different way of loading multiple files.
Related
I'm using three.js for an AR application to show a 3D object (exported from Maya with maya exporter to threejs) on a marker detected using JSARToolKit.
It all works fine on localhost(I see texture), but when I upload it online (github) and I see the preview object appears all black without texture (like if I remove the light).
// load the model
var loader = new THREE.JSONLoader;
var object;
//var geometry = new THREE.BoxGeometry(1, 1, 1);
loader.load('js/object3d.js', function(geometry, materials){
var material = new THREE.MeshFaceMaterial(materials);
object = new THREE.Mesh(geometry, material);
container.add(object);
});
var ambLight = new THREE.AmbientLight( 0x909090, 2.0 );
container.add( ambLight );
Any ideas?
I am not sure if this is the problem, but it might be that your loader runs into some error but since you didn't set an error handler for your loader you don't get notified.
The JSONLoader load method takes four arguments (url, onLoad, onProgress, onError) as you can see here in the class on line 40.
Try to set an error handler (onError callback method) and see what you get. For example:
var onload = function(geometry, materials){
var material = new THREE.MeshFaceMaterial(materials);
object = new THREE.Mesh(geometry, material);
container.add(object);
});
var onProgress = function(){
// your optional on progress logic
}
var onError = function(error){
console.log( error );
}
var loader = new THREE.JSONLoader;
loader.load('js/object3d.js', onLoad, onProgress, onError);
I'm using three.js and the attached code is returning the following error
Uncaught TypeError: THREE.Scene is not a function
init # new 1.html:18
on this line
scene=new THREE.Scene();
What could be causing this and how can I go about fixing it?
window.onload = init
var scene, camera, render;
function init() {
container = document.createElement('div');
document.body.appendChild(container);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 200); //перспективная проекция
camera.position.y = 150;
camera.position.z = 500;
var line_geometry = new THREE.Geometry();
line_geometry.vertices.push(new THREE.Vector3(0, 0, 0));
line_geometry.vertices.push(new THREE.Verctor3(0, 40, 50));
var line = new THREE.Line(line_geometry);
scene.add(line);
render = new THREE.WebGLRender(); //рендеринг
render = setSize(window.innerWidth, window.innerHeight); //инициализация рендеринга
container.appendChild(render.domElement); //??
render.render(scene);
}
Here is a screen shot of the error.
You have many typos in your code:
Verctor3 instead of Vector3
WebGLRender instead of WebGLRenderer
render.render(scene); instead of render.render(scene, camera);
and so on.
Also you should just run init() at start instead of window.onload=init.
Generally - please refer to this page. There are many working examples there.
I have been trying out Three.js lately and i used the exporter addon for Blender to test out making models in blender and exporting so i can use them in a three.js program.
I included the add-on to blender, and using just the basic cube model of blender, exported it to .json as the exporter says. Then i imported the model into my three.js using this as a guide
but that gave me an error:
Uncaught TypeError: Cannot read property 'length' of undefined.
Ive already searched online and tried a few different approaches(like including a materials in the function call of the loader) but nothing seems to work.
I also checked stackoverflow for answers but so far nothing seems solved. If anyone would clarify what im doing wrong I would be very grateful.
The code for my three.js program:
var WIDTH = 1000,
HEIGHT = 1000;
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;
var radius = 50,
segments = 16,
rings = 16;
var sphereMaterial =
new THREE.MeshLambertMaterial(
{
color: 0xCCCCCC
});
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(
radius,
segments,
rings),
sphereMaterial);
var pointLight =
new THREE.PointLight(0x660000);
var $container = $('#container');
var renderer = new THREE.WebGLRenderer();
var camera =
new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR);
var scene = new THREE.Scene();
var loader = new THREE.JSONLoader(); // init the loader util
scene.add(camera);
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
scene.add(pointLight);
camera.position.z = 300;
renderer.setSize(WIDTH, HEIGHT);
$container.append(renderer.domElement);
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
loader.load('test.json', function (geometry, materials) {
var material = new THREE.MeshFaceMaterial(materials);
var object = new THREE.Mesh(geometry, material);
scene.add(object);
});
(function animloop() {
requestAnimFrame(animloop);
renderer.render(scene, camera);
})();
When you export, change the Type from buffergeometry to Geometry (Blender 2.76)
In my experience so far with the exporter, you have to be very careful which boxes you tick!
This length error is usually because you are either not exporting the vertexes, or exporting the scene rather the object.
I have the same issue with the new exporter.
If select SCENE then I usually get "Cannot read property 'length' of undefined"
If I select only the object and the materials and vertices. It usually just seems to get stuck forever.
UPDATE
Check this response to this issue!
Threejs blender exporter exports in wrong format
As roadkill stated earlier, exporting as Geometry instead of BufferedGeometry works.
Also note that loading JSON model loading is handled asyncronously (the callback is only called only when the operation is completed, the rest of your code keeps running). The model won't exist for the first frame or two, so check that your model exists before doing any operations with it inside the animation loop.
I have a 3D object of a chair made in Blender and exported as a .obj and .mtl. First of all, the load time is a horrendous 40+ seconds; I have no idea why (Visual Studio possibly?) Second, the images textures are not loading properly. With no ambient or directional lighting I get a silhouette. With the lighting I get a slight hint of gray to give a little depth but nothing close to the many colors in the original object. I have only been working with ThreeJS for a few days now so I'm quite new to it. Hence, I am at a loss. I have read several artciles related to my issue but none seem to solve the problem. I even went so far as to add an addon to Blender to export to .js. I could not get it to even load properly (I assume it had to do with the fact I kept the same loader info from the .OBJMTLLoader and the .JSONLoader doesn't support or needs more than what I gave; I just am not familiar enough with it know). Any ideas/suggestions? Here is my script:
`
<script src="js/three.min.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script src="js/loaders/MTLLoader.js"></script>
<script src="js/loaders/OBJMTLLoader.js"></script>
<script src="js/Detector.js"></script>
<script>
if (!Detector.webgl) Detector.addGetWebGLMessage();
var container;
var camera, controls, scene, renderer;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.01, 1e10);
camera.position.z = 2;
//controls
controls = new THREE.TrackballControls(camera);
controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;
controls.panSpeed = 2;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
scene = new THREE.Scene();
scene.add(camera);
//lights
var ambient = new THREE.AmbientLight(0xCCCCCC);
scene.add(ambient);
var directionalLight = new THREE.DirectionalLight(0xCCCCCC);
directionalLight.position.set(0, 0, 2).normalize();
scene.add(directionalLight);
//main img
var material = new THREE.MeshBasicMaterial({ color: '0xCCCCCC' });
var loader = new THREE.OBJMTLLoader();
loader.addEventListener('load', function (event) {
var geometry = event.content;
//var mesh = new THREE.Mesh(geometry);
scene.add(geometry, material);
});
loader.load('chair.obj', 'chair.mtl');
// renderer
renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
//
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
controls.handleResize();
}
function animate() {
requestAnimationFrame(animate);
render();
controls.update();
}
function render() {
var timer = Date.now() * 0.0005;
renderer.render(scene, camera);
}
</script>
`
Well, you are defining a gray MeshBasicMaterial to use with your obj instead of using the material(s) that the loader will create for you, i guess.
Just use this. The "object" should have the material defined in your mtl-file.
loader.addEventListener( 'load', function ( event ) {
var object = event.content;
scene.add( object );
});
loader.load( 'chair.obj', 'chair.mtl' );
Concerning your load time: Could be your local server. Also, be aware that the obj file format ist quite big in raw ascii format. Also, if the mtl-file defines textures, they are maybe quite big in file size, too.
#GuyGood was correct in my case for the long load time. I was using the python simplehttpserver and switch to a node server and no more slow texture loading problems. Check out the threejs wiki for other local server options.
I am trying to save a Sprite object as a file on the device I'm working on and it seems to work. the problem I'm having is reading the saved file back and placing it back on stage as a sprite. Below is the code I have so far, could someone tell me what it is I'm doing wrong? I have a suspicion that the saved isn't what I expect it to be since the file sizes have been under a kilobyte.
public function save_album(e:Event):void
{
var outFile:File = File.documentsDirectory; // dest folder is desktop
outFile = outFile.resolvePath("canvas3.bin");
var fs:FileStream = new FileStream();
var bytes:ByteArray = new ByteArray();
//trace (File.documentsDirectory.url + "/canvas2.bin");
fs.open(outFile, FileMode.WRITE);
bytes.writeObject(graffitiContainer) //graffitiContainer is a Sprite
bytes.position = 0;
fs.writeBytes(bytes, 0, bytes.length);
fs.close();
}
public function open_album(e:Event):void
{
var inBytes:ByteArray = new ByteArray();
var inFile:File = File.documentsDirectory;
inFile = inFile.resolvePath("canvas3.bin"); // name of file to read
var inStream:FileStream = new FileStream();
inStream.open(inFile, FileMode.READ);
inStream.readBytes(inBytes, 0, inBytes.length);
inStream.close();
inBytes.position = 0;
ui.removeChild(graffitiContainer);
var obj:Sprite = inBytes.readObject() as Sprite; //returns a null
graffitiContainer = obj;
ui = new UIComponent();
graffitiContainer.x = 0;
graffitiContainer.y = 100;
ui.addChild(graffitiContainer);
}
Not fully sure I understand what you're trying to accomplish; however, this implementation doesn't do what you're thinking - writeObject could only serialize general public properties, and not the graphics member.
You could render it to a Bitmap.
Saw a blog post about this:
http://jacwright.com/201/serializing-display-objects/