I'm using three r73 and got stuck with a simple 3D audio example:
// ...
var listener = new THREE.AudioListener();
camera.add( listener );
var sound1 = new THREE.Audio( listener );
sound1.load( 'sounds/song.ogg' );
sound1.setVolume(1);
sound1.setRefDistance(10);
sound1.autoplay = true;
mesh.add(sound1);
I got setRefDistance is not a function.
If I remove this line sound1.setRefDistance(10);, the sound play but isn't "3D aware".
I don't know what is different from this simple example http://threejs.org/examples/misc_sound.html except I'm in an angular context + nodejs
Ok, my bad, I was in fact using r74dev and I needed to use THREE.PositionalAudio
Related
I am trying to implement drag controls on this text geometry that I am creating in the viewer. I create the text like so:
createText(params) {
const textGeometry = new TextGeometry(params.text,
Object.assign({}, {
font: new Font(FontJson),
params
}));
const geometry = new THREE.BufferGeometry;
geometry.fromGeometry(textGeometry);
const material = this.createColorMaterial(
params.color);
const text = new THREE.Mesh(
geometry, material);
text.scale.set(params.scale, params.scale, params.scale);
text.position.set(
params.position.x,
params.position.y,
10);
this.intersectMeshes.push(text);
this.viewer.impl.scene.add(text);
this.viewer.impl.sceneUpdated(true);
return text;
}
This works great, the meshes get added to the viewer, I can see them. Fantastic! Thus far, it is good. Now, I want to be able to drag them around with my mouse after I have added them. I noticed that Three.js already has drag controls built in, so I just implemented them like so:
enableDragging(){
let controls = new THREE.DragControls( this.viewer, this.viewer.impl.camera.perspectiveCamera, this.viewer.impl.canvas );
controls.addEventListener( 'dragstart', dragStartCallback );
let startColor;
controls.addEventListener( 'dragend', dragendCallback );
function dragStartCallback(event) {
startColor = event.object.material.color.getHex();
event.object.material.color.setHex(0x000000);
}
function dragendCallback(event) {
event.object.material.color.setColor(startColor);
}
}
After a big of debugging, I have seen where the problem occurs. For some reason, when I click on one of the meshes, the raycaster doesn't find any intersections. I.E. the array I get back is empty. No matter where I click on these objects.
Is my implementation wrong, or did I provision these meshes wrong to make them draggable? I have gotten the drag controls to work outside of the viewer, just not within it.
This will not work, looking at the code of DragControls, the viewer implementation is too different in the way it implements the camera. You would need to either implement a custom version of DragControls or take a look at my transform tool and adapt it for custom meshes:
Moving visually your components in the viewer using the TransformTool
I have two boxes. One spawns on the ground and the other is dropped on top of it. Gravity is turned on. I am trying to get the collision event listener to fire on the bottom box which is resting on the ground. However, nothing is logged.
var c = new Physijs.BoxMesh( new THREE.CubeGeometry( 5, 5, 5 ), new THREE.MeshBasicMaterial({ color: 0x888888 }) );
c.__dirtyPosition = true;
c.position.set(10, 0,-5);
c.addEventListener('collision', function(object){
console.log("hello world"); // NOT FIRING
});
scene.add(c);
var p = c.clone();
p.__dirtyPosition = true;
p.position.y = 50;
scene.add(p);
I can't figure out what I'm doing wrong - could it be because of __dirtyPosition?
EDIT: I tested it without clone() and creating the second box anew, but it doesn't make a difference.
EDIT 2: It's worth mentioning that the simulation runs fine I just can't get the listener to work.
Relevant GitHub Issue
It looks like the clone method is part of THREEjs, not Physijs. So your code just clones the physical material, not the physical mesh. You're just going to have to create another BoxMesh using the same code you did for c.
I am currently loading in a bunch of elements of a model and adding them to a group. I then want to be able to move the group as a whole unit after they load.
My issue is, how can I run code once I have ensured that all of my models have loaded?
I don't understand how to use the .onload function with the colladaLoader & its callback functions. Also, is it a bad idea to use a self executing function like I have here? I am not sure how else to go through a list and load in all the models.
My code is below. I have tried to use a hack, by using the counter "complete" but it doesn't work all of the time. Thanks!
for ( var i=0; i<object.asset.length; i++ ) {
loader = new THREE.ColladaLoader();
asset = furniture.asset[i];
(function(asset) {
loader.load(asset["path"], function(collada, materials) {
//this function scales & positions model
var mesh = daeAttributes(collada, object, asset, newMaterial);
var scene = get_scene();
group.add( mesh );
complete++;
//when all assets have been loaded, add the group to the scene
if (complete===object.asset.length-1) {
//want to move the group once all the models are loaded
group = moveModel(group, object);
scene.add( group );
render();
};
});
})(asset);
Update
So if I have a list >1, of unique objects to load in, it works. If there is only 1 object it doesn't load that one object.
If you put everything inside of this it should work:
<body onload="myFunction()">
I am trying to manage click on a mesh (cube) to do some processing stuff.
var cubeFor3D = new THREE.Mesh(new THREE.CubeGeometry(40,80,40),img3D);
scene.add(cubeFor3D);
//
renderer.render(scene,camera);
//
animate();
//Track the click on cube3d
cubeFor3D.on('click', function(){
// response to click...
console.log('you have clicked on cube 2D');
});
When running, i got this error on the web console:
TypeError: cubeFor3D.on is not a function
In the API documentation, it's shown to do like this:
mesh.on('click',..
But i guess i should replace mesh by my mesh real name. Seems i am going wrong. help please.
I am including the API JS in my file: <script src='threex.domevent.js'></script>
Late answer but, if you add this to the begging of the init function it should work:
THREE.Object3D._threexDomEvent.camera(camera);
In fact I normally put in straight after scene = new THREE.Scene();
I'm in the process of building a JavaScript / HTML5 game (using Canvas) for mobile (Android / iPhone/ WebOS) with PhoneGap. I'm currently trying to design out how the UI and playing board should be built and how they should interact but I'm not sure what the best solution is. Here's what I can think of -
Build the UI right into the canvas using things like drawImage and fillText
Build parts of the UI outside of the canvas using regular DOM objects and then float a div over the canvas when UI elements need to overlap the playing board canvas.
Are there any other possible techniques I can use for building the game UI that I haven't thought of? Also, which of these would be considered the "standard" way (I know HTML5 games are not very popular so there probably isn't a "standard" way yet)? And finally, which way would YOU recommend / use?
Many thanks in advance!
EDIT
I've moved this question over to gamedev.stackoverflow.com. You can find the new question here: https://gamedev.stackexchange.com/questions/7090/html5-game-canvas-ui-techniques/7115#7115
You can do it a million ways. However you feel most comfortable and your engineers feel most confident.
If you're looking for inspiration or a code example, here's one way that I do it. I have a function that repeatedly draws a menu until a button is pressed. When the button is pressed, the game loads and the old menu click event listeners are removed and new game click event listeners are added. I also end the old draw loop of the menu and start a new game draw loop. Here's some selected snippets to give you the idea of how its done:
Game.prototype.loadMenu = function() {
var game = this;
var can = this.canvas;
// now we can use the mouse for the menu
can.addEventListener('click', game.menuClickEvent, false);
can.addEventListener('touchstart', game.menuClickEvent, false);
// draw menu
this.loop = setInterval(function() { game.drawMenu() }, 30);
};
Game.prototype.drawMenu = function() {
// ... draw the menu
}
Game.prototype.loadLevel = function(levelstring) {
// unload menu
var can = this.canvas;
var game = this;
can.removeEventListener('click', game.menuClickEvent, false);
can.removeEventListener('touchstart', game.menuClickEvent, false);
if (this.loop) clearInterval(this.loop);
// ... other level init stuff
// now we can press keys for the game
//can.addEventListener('click', game.gameClickEvent, false);
can.addEventListener('touchstart', game.gameClickEvent, false);
can.addEventListener('keydown', game.gameKeyDownEvent, false);
this.loop = setInterval(function() { game.tick() }, 30);
}
// called from tick()
Game.prototype.draw = function(advanceFrame) {
// ...
}
This way I'm able to separate out game drawing and game events from menu drawing and menu events. It also gives me leeway to use game/animation elements in my menus should I want to make them look real pretty.
(I posted this at the twin gamedev discussion too)
I do not think that there is a "standard" for this. It highly depends on your UI. I think using the DOM elements is better in most cases, since you do not need to build all of the UI components, events, etc. yourself. They can be styled with CSS to achieve the desired look. If this is not enough, you'll probably need to build the interface elements yourself, but you should make sure that this is really needed. It is probably a huge amount of work to roll your own solution.
Try this :
With Visual js you can setup page like this :
Visual-JS multiplatform game engine windows GUI - source editor
OnPage editor - for design
You will get :
*99% canvas 2d
Add new object
Create webcam component (nui or normal)
Create coallision (basic - rect)
Create textBox (virtual keyboard for mobile)
Create particle
Atach player (basic movement)
MultipEER (Networking)*
localStarage
App created from visual js always work on all browsers(mobile / desktop). Networking - webRTC - multipeer
Try online at :
https://jsfiddle.net/user/zlatnaspirala/fiddles/
Api look like this :
Application Programming Interface Documentation for Visual JS 0.5 >
GAME_OBJECT is main object in this framework.
1) Adding new game object (name will be 'GO' ):
HELLO_WORLD.ENGINE.MODULES.ACCESS_MODULE("STARTER").NEW_OBJECT("GO" ,
x , y , w , h , speed )
HELLO_WORLD.ENGINE.MODULES.ACCESS_MODULE("STARTER").NEW_OBJECT( "GO" ,
45 , 45 , 10 , 10 , 10)
// 2) Adding image or animation :
// DRAW TYPE can be // 'DRAW_FRAME' no animation // 'LOOP' playing
animation // this number '1111123123' is ID can be any number
//ANIMATION ( surf ,TYPE_, FrameIndex ,source , PARENT , ID , blink_
, min_ , max_ , step , speed_ , opacity_ )
HELLO_WORLD.ENGINE.MODULES.ACCESS_MODULE("STARTER").GAME_OBJECTS.ACCESS("GO").CREATE_ANIMATION(
SURF , "DRAW_FRAME" , 6 , RESOURCE.Tiles , 1111123123 , "no" ,
1,11,1,1,1)
3)Disable draging GO.DRAG = false;
// RESOURCE.NAMEOFFOLDERANIMATION
add folder "Tiles" with images in folder /res/ and run node res.js
// refresh page and you will get
RESOURCE.Tiles ready for use !
// MAKE MODULE ACCESS EASY var
STARTER = HELLO_WORLD.ENGINE.MODULES.ACCESS_MODULE("STARTER");
STARTER.GAME_OBJECTS.ACCESS("GO").CREATE_ANIMATION( SURF ,
"DRAW_FRAME" , 6 , RESOURCE.Tiles , 1111123123 , "no" , 1,11,1,1,1)
//DRAG initial value is true GO.DRAG = false;
//setup quard height = width GO.POSITION.DIMENSION.H = GO.POSITION.DIMENSION.W;
4) EVENTS FOR MOUSE AND MOBILE TOUCH HANDLED
//CLICK OR TOUCH START GO.TAP = function(){
//this make point directing to the game object instance
// this.NAME or this.ANIMATION.CURRENT_FRAME };
GO.TOUCH_DOWN = function(){
STARTER.DESTROY_OBJECT("GO") console.log("THIS MUST BE TERMINATED
ON MOUSE DOWN or TOUCH_DOWN : " + this.NAME);
//this.DESTROY_ME_AFTER_X_SECUND( 100 ); //console.log("THIS MUST BE
TERMINATED ON CLICK : " + this.NAME); };
GO.TOUCH_MOVE = function(){
console.log("HOVER ON OBJECT OR MOBILE TOUCH_MOVE : " + this.NAME); };
GO.TOUCH_UP = function(){
console.log("MOUSE UP ON OBJECT OR MOBILE TOUCH_UP : " + this.NAME); };*
Download git