I'm trying to load two different maya files that are animated but only one is animating, the second one isn't.
I tried to load fbx files using the fbx loaders
var loader = new THREE.FBXLoader();
loader.load('models/jumpi.fbx', function(object) {
mixer = new THREE.AnimationMixer(object);
var action = mixer.clipAction(object.animations[0]);
action.play();
window.addEventListener("keydown", function(event) {
if (event.defaultPrevented) {
return; // Do nothing if the event was already processed
keyPressed = event.key;
// If the button pressed is "e" or "E" (using caps lock or shift), then the player jumps.
if (keyPressed == "e" || keyPressed == "E") {
// call your jump function.
// console.log('working');
//action.play();
}
// Cancel the default action to avoid it being handled twice
event.preventDefault();
}, true); object.traverse(function(child) {}); scene.add(object);
});
var loader = new THREE.FBXLoader(); loader.load('models/move.fbx', function(object) {
mixer = new THREE.AnimationMixer(object);
object.traverse(function(child) {});
object.position.y = 2;
object.position.x = 50;
object.scale.x = 20;
object.scale.y = 20;
object.scale.z = 20;
scene.add(object);
});
Related
My goal is to be able to create a navbar in the three.js environment. Iv set up all the CSS3D appropriately and have set up a mouse down event listener but when it comes to intersects nothing comes up.
//CSS3D Scene
scene2 = new THREE.Scene();
//HTML
element = document.getElementById('dialogueBox');
shop = document.getElementById('shop');
FREEkxxx = document.getElementById('FREEkxxx');
//card
card = new THREE.CSS3DObject(element);
card.position.x = 0;
card.position.y = 0;
card.position.z = 0;
scene2.add(card);
//shop link
shopNav = new THREE.CSS3DObject(shop);
shopNav.position.x = -250;
shopNav.position.y = 250;
shopNav.position.z = 0;
shopNav.userData = {
URL: "http://stackoverflow.com",
name: "shopNav"
};
scene2.add(shopNav);
// videolink
FREEkNav = new THREE.CSS3DObject(FREEkxxx);
FREEkNav.position.x = 220;
FREEkNav.position.y = 250;
FREEkNav.position.z = 0;
FREEkNav.userData = {
URL: "http://stackoverflow.com",
name: "FREEkNav"
};
scene2.add(FREEkNav);
// grouping the nav objects
nav = new THREE.Object3D();
nav.add(shopNav);
nav.add(FREEkNav);
nav.userData = {
URL: "http://stackoverflow.com",
name: "FREEkNav"
};
scene2.add(nav);
document.addEventListener('mousedown', onDocumentMouseDown, false);
var raycaster = new THREE.Raycaster(),
INTERSECTED;
var mouse = new THREE.Vector2();
function onDocumentMouseDown(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
intersects = raycaster.intersectObjects(nav.children);
console.log(intersects)
if (raycaster.intersects === shopNav) {
window.open(link1)
} else if (raycaster.intersects === FREEkNav) {
window.open(link2)
}
};
I'v grouped the 2 nav elements using THREE.Object3D(); so i assumed i could intersect using nav.children but when you console.log intersects and click one the nav elements you get nothing / [].
There's no need to do raycasting on CSS3D Objects. After all, a CSS3DObject is still an HTML element, just with a more complex CSS transformMatrix() property. You can add event listeners to it like any other HTML element, as it's still part of the DOM:
var element = document.getElementById('dialogueBox');
// Add click listener as usual
element.addEventListener("click", function(event){
console.log("I've been clicked!");
console.log(event);
});
//card
card = new THREE.CSS3DObject(element);
card.position.x = 0;
card.position.y = 0;
card.position.z = 0;
scene2.add(card);
You only need to do raycasting when dealing with THREE.Mesh, THREE.Point or other WebGL-based elements that live inside the <canvas> context.
I am fairly new to JavaScript and have searched everywhere for an answer to my question and cant seem to find anything related at all. This tells me that I'm missing something with my understanding of how my program works.
I have written a small game where the player navigates through a randomly generated maze using a gameloop that checks keydown events every x milliseconds. The game has a difficulty dropdown menu and then the game is started my clicking a button that calls a function to create a canvas where the game is drawn.
My problem is that when the button is clicked again to create a new maze without reloading the page, the gameloop for the original maze is still running and so key events are registered twice. This is causing some unexpected behavior. It's as though every time the button is clicked, a new instance of the function is running. Is there some way that each time the button is clicked I can set it to stop the previous game function?
var canvas;
var div;
var mazeGenButton;
$(document).ready(function () {
canvas = null;
div = document.getElementById('canvascontainer');;
mazeGenButton = document.getElementById("mazeGenButton");
mazeGenButton.onclick = createInstance;
});
function createInstance() {
if (canvas != null) {
div.removeChild(document.getElementById("myCanvas"));
}
canvas = document.createElement('canvas');
canvas.id = "myCanvas";
canvas.width = 1000;
canvas.height = 1000;
div.appendChild(canvas);
drawMaze();
};
var drawMaze = function () {
//code here to create the game(not posted)
//here is the Key listener - not sure if it's related
var keyState = {};
window.addEventListener('keydown', function (e) {
keyState[e.keyCode || e.which] = true;
}, true);
window.addEventListener('keyup', function (e) {
keyState[e.keyCode || e.which] = false;
}, true);
function gameLoop() {
//left
if (keyState[37] || keyState[65]) {
if (isLegalMove(playerXPos - 1, playerYPos)) {
grid[playerXPos][playerYPos].removePlayerCell();
playerXPos -= 1;
grid[playerXPos][playerYPos].setPlayerCell();
}
}
//right
if (keyState[39] || keyState[68]) {
if (isLegalMove(playerXPos + 1, playerYPos)) {
grid[playerXPos][playerYPos].removePlayerCell();
playerXPos += 1;
grid[playerXPos][playerYPos].setPlayerCell();
}
}
//up
if (keyState[38] || keyState[87]) {
if (isLegalMove(playerXPos, playerYPos - 1)) {
grid[playerXPos][playerYPos].removePlayerCell();
playerYPos -= 1;
grid[playerXPos][playerYPos].setPlayerCell();
}
}
//down
if (keyState[40] || keyState[83]) {
if (isLegalMove(playerXPos, playerYPos + 1)) {
grid[playerXPos][playerYPos].removePlayerCell();
playerYPos += 1;
grid[playerXPos][playerYPos].setPlayerCell();
}
}
drawSurroundingCells();
setTimeout(gameLoop, 50);
}
}
I tried loading my .obj and .mtl files and now I'm trying to change the material of the object on keypress, I'm able to do changes as expected using texture images. However when I want to change materials using a phong effect with or without texture image it's not happening.
//THIS METHOD IS WORKING FINE WHEN I USE BASIC TEXTURE IMAGES ON KEYPRESS
var texture1 = THREE.ImageUtils.loadTexture("neavik/9.jpg");
var texture2 = THREE.ImageUtils.loadTexture("neavik/10.jpg");
if (child.material.name == "meta") {
child.material.map = texture1;
child.material.needsUpdate = true;
child.receiveShadow = true;
var index = 0;
var onKeyDown = function(event) {
if (event.keyCode == 67) { // when 'c' is pressed
object.traverse(function(child) {
if (child instanceof THREE.Mesh) {
var colors = [texture2, texture1];
if (child.material.name == "meta") {
if (index == colors.length) index = 0;
child.material.map = colors[index++];
child.material.needsUpdate = true;
child.geometry.buffersNeedUpdate = true;
child.geometry.uvsNeedUpdate = true;
}
}
}
};
document.addEventListener('keyup', onKeyDown, true);
});
// Now if i try to change materials with same effect like PHONG it doesn't reflect any changes on Keypress.[ No errors as well ]
var texture1 = THREE.ImageUtils.loadTexture("neavik/9.jpg");
var texture2 = THREE.ImageUtils.loadTexture("neavik/10.jpg");
var cleana = new THREE.MeshPhongMaterial({
map: texture1,
color: 0xffffef,
specular: 0x000000,
combine: THREE.AddOperation,
reflectivity: 0
})
var cleanb = new THREE.MeshPhongMaterial({
map: texture2,
color: 0xffffef,
specular: 0x000000,
combine: THREE.AddOperation,
reflectivity: 0
})
if (child.material.name == "meta") {
child.material = cleana;
child.material.needsUpdate = true;
child.receiveShadow = true;
var index = 0;
var onKeyDown = function(event) {
if (event.keyCode == 67) { // when 'c' is pressed
object.traverse(function(child) {
if (child instanceof THREE.Mesh) {
var colors = [cleana, cleanb];
if (child.material.name == "meta") {
if (index == colors.length) index = 0;
child.material = colors[index++];
child.material.needsUpdate = true;
child.geometry.buffersNeedUpdate = true;
child.geometry.uvsNeedUpdate = true;
}
}
}
};
document.addEventListener('keyup', onKeyDown, true);
});
Please let me know if there is another way to do this.
If you want to exchange the whole material you need to do:
child.material = cleana;
or
child.material = cleanb;
and then you most likely have to do:
child.material.needsUpdate = true;
Read more on how to update material in this How to update things reference page in the chapter Materials
UPDATE
So if you want to set using an array:
var materials = [cleana, cleanb];
child.material = materials[0]; // cleana
or
child.material = materials[1]; // cleanb
and then also most likely:
child.material.needsUpdate = true;
It works totally fine with an array of materials. You don't even need to set material.needsUpdate = true. A demonstration here in this fiddle.
Hey if anybody can please help me animate this object :
Up - Down To Move |
Left - Right to Rotate |
a to look up |
z to look down
Link to orignal file : http://www.aacctrust.org/anim/anim.htm
JSON Model File (with animation tail-wag):
http://wikisend.com/download/654748/wolf.json
The problem is the json model file has been provided with necessary details regarding the animation of the tail. The tail of the wolf is suppose to wag.
But it doesnot , I have tried everything but to no help .
Is something wrong in the code or am I not exporting properly frm Blender.
Below is the code :
<html>
<head>
<style>
body { margin: 0; }
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script src="three.js"></script>
<script>
var scene = new THREE.Scene();
var canvas = document.getElementById("myCanvas");
renderer = new THREE.WebGLRenderer({ canvas: canvas });
var camera = new THREE.PerspectiveCamera( 75, (canvas.width / canvas.height) , 1, 10000 );
var clock = new THREE.Clock(),mixer;
var forest,wolf,animation;
var fwd,bck,lft,rgt,up,down = 0 ;
var action = {};
camera.fov *= 0.3;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight);
document.body.appendChild( renderer.domElement );
renderer.setClearColor (0x22222222, 1);
camera.position.z = 28;
var material = new THREE.MeshPhongMaterial( { map: THREE.ImageUtils.loadTexture('wolf_uvcons.png') } );
// Wolf Texture Above # Forest Uses Local Materials #Blender
var loader = new THREE.JSONLoader();
loader.load('forest.json', function(geometry, materials) {
forest = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
forest.scale.x = forest.scale.y = forest.scale.z = 0.25;
forest.rotateX( Math.PI / 2 );forest.rotateZ( Math.PI ); //load :env:
forest.translation = THREE.GeometryUtils.center(geometry);
scene.add(forest);
});
loader.load('wolf.json', function(geometry, materials) {
wolf = new THREE.SkinnedMesh(geometry,material);
wolf.scale.x = wolf.scale.y = wolf.scale.z = 0.25; //load wolf
wolf.translation = THREE.GeometryUtils.center(geometry);
scene.add(wolf);
wolf.add(camera);
wolf.translateY(-27); /// Bring it down
wolf.translateZ(100); /// Bring it down
action.idle = new THREE.AnimationAction(geometry.animations[ 0 ]);
action.idle.weight = 1;
// Create animation mixer and pass object to it
mixer = new THREE.AnimationMixer(wolf);
mixer.addAction( action.idle );
});
var light = new THREE.AmbientLight(0xFFFFFFFF,1);
scene.add(light);
var pointLight = new THREE.PointLight( 0xffcccc,0.41 );
pointLight.position.set( 0, 100, 3 );
scene.add( pointLight );
var pointLight1 = new THREE.PointLight( 0xff0000,0.81 );
pointLight1.position.set( 100, 200, 3 );
scene.add( pointLight1 );
function moveWolf()
{
if (fwd==1)
{ wolf.translateZ(-1);}
if (bck==1)
{ wolf.translateZ(1);}
if (lft==1)
{ wolf.rotateY(Math.PI/200)}
if (rgt==1)
{ wolf.rotateY(-Math.PI/200);}
if (up==1)
{ camera.rotateX(Math.PI/200);}
if (down==1)
{ camera.rotateX(-Math.PI/200);}
}
function animate() {
requestAnimationFrame( animate );
moveWolf();
render();
var delta = clock.getDelta();
var theta = clock.getElapsedTime();
if ( mixer ) { mixer.update( delta ); }
}
function render() {
renderer.render( scene, camera );
}
animate();
</script>
<script>
document.onkeydown = checkKey1;
document.onkeyup = checkKey2;
function checkKey1(e) {
e = e || window.event;
if (e.keyCode == '38') {
// up arrow
fwd=1;
}
else if (e.keyCode == '40') {
// down arrow
bck=1;
}
else if (e.keyCode == '37') {
// left arrow
lft=1;
}
else if (e.keyCode == '39') {
// right arrow
rgt=1;
}
else if (e.keyCode == '65') {
up=1;
}
else if (e.keyCode == '90') {
down=1;
}
}
function checkKey2(e) {
e = e || window.event;
if (e.keyCode == '38') {
// up arrow
fwd=0;
}
else if (e.keyCode == '40') {
// down arrow
bck=0;
}
else if (e.keyCode == '37') {
// left arrow
lft=0;
}
else if (e.keyCode == '39') {
// right arrow
rgt=0;
}
else if (e.keyCode == '65') {
// right arrow
up=0;
}
else if (e.keyCode == '90') {
// right arrow
down=0;
}
}
</script>
</body>
</html>
UPDATE :
During the process of waiting for a reply I went on a self-exploration trip ;)
And found a nearly acceptable solution , steps are aa follows :
File >> Export >> Wavefront (OBJ)
Ensure that Animation is checked as option .
Click export (while exporting plz do it in a separate folder as no of files could be large depending on the number of frames.)
Copy the folder in Blender > Python > Bin directory.
Copy convertor from three.js utils OBJ for python3 to Blender > Python > Bin directory.
Launch command prompt in Admin mode and run the following command :
python objtothreejs_conv_python3 -i meshdirname\meshname_000001.obj -o output.js -m "meshdirname\meshname_*.obj"
Output Animation would be morph animation and would require some changes in the mixer for playing MorphAnims.
I am playing with the canvas, and it seems to be working great in FF6, but in Chrome 13, the sprite that I am drawing does not appear reliably. I have done some research and found that the problem stems from the function firing before the asset has loaded completely.
Fiddle here:
http://jsfiddle.net/LqHY9/
Relevant Javascript:
function sprite(ipath, sh, sw, ih, iw){
/* BASIC INFO FOR SPRITE */
this.frameWidth = sw;
this.frameHeight= sh;
frame_rows = ih/sh;
frame_columns = iw/sw;
num_frames = frame_columns*frame_rows ;
this.frame = new Array();
frameNumber = 0;
for(row = 0; row<frame_rows; row++){
for(i=0;i<frame_columns;i++){
this.frame[frameNumber] = {};
this.frame[frameNumber].offsetX = this.frameWidth*i;
this.frame[frameNumber].offsetY = this.frameHeight*row;
frameNumber++
}
}
this.sheight = sh;
this.swidth = sw;
this.raw = new Image();
this.raw.src = ipath;
}
animation=new sprite("http://www.melonjs.org/tutorial/tutorial_final/data/sprite/gripe_run_right.png",64,64,64,512);
context.drawImage(animation.raw, animation.frame[0].offsetX, animation.frame[0].offsetY, animation.frameWidth, animation.frameHeight, 0, 0, animation.frameWidth,animation.frameHeight)
(Don't worry, my context variable is defined, I just cut that bit out, you can see the whole thing in the JSFiddle.)
The Image object has an onload event which you should hook into.
Assuming you have more than one image, you could implement a sort of a "loader". This would basically just take an array of image URLs, load each of them, and listen to their onload events. Once each image has loaded, it would in turn call some other function, which would signal that every resource has finished loading.
the Image() object has an onload(and onerror) event. If you need to execute something after it loads you can attach a function.
e.g.
var img = new Image();
img.onload = function() {
//do something
};
Just make sure you attach the onload before setting the src.
You need to use the onload handler for the image. You must set the handler before you set the .src for the object because in some browsers, the load event may fire immediately upon setting .src if the image is in the browser cache. Here's a piece of pseudo code:
var img = new Image();
img.onload = function () {
// image is now loaded and ready for handling
// you can safely start your sprite animation
}
img.src = "xxx";
You can see related sample code from another answer I wrote here: jQuery: How to check when all images in an array are loaded?.
function Sprite(urls, speed, box)
{
var that = this, running = false, interval = 0, loaded = false;
that.urls = urls;
that.speed = speed;
that.images = new Array();
that.box = box || { x: 0.0, y: 0.0, w: 64, h: 64 };
for(var i = 0; i < that.urls.length; ++i)
{
that.images[i] = new Image();
that.images[i].src = that.urls[i];
that.images[i].id = i;
var len = that.urls.length;
that.images[i].onload = function(){ if(parseInt(this.id) === len) { loaded = true; } };
}
that.current = 0;
var Draw = function(ctx)
{
if(loaded)
{
var curr = that.images[that.current];
ctx.drawImage(curr, 0.0, 0.0, curr.width, curr.height, that.box.x, that.box.y, that.box.w, that.box.h);
}
};
that.Run = function(ctx)
{
if(!running)
{
running = true;
interval = setInterval(function(){
Draw(ctx);
if(that.current < that.urls.length)
{
that.current++;
}
else
{
that.current = 0;
}
}, that.speed);
}
};
that.Clear = function()
{
if(running)
{
running = false;
clearInterval(interval);
}
};
}
// Exemple
var test = new Sprite(["image1.png", "image2.png", "image3.png"], 250);
test.Run(myContext);