I've developed simple project using three.dart framework. It launches and shows web page ok. But after 3-5 seconds it crashes with unknown error. Dart editor and browser don't show the reason why it crashed
Here is a code:
import 'dart:html';
import 'dart:math' as Math;
import 'package:three/three.dart';
class MyClass {
Element container;
PerspectiveCamera camera;
Scene scene;
CanvasRenderer renderer;
Mesh plane;
num targetRotation;
num targetRotationOnMouseDown;
num windowHalfX;
num windowHalfY;
var evtSubscriptions = [];
void run() {
init();
animate(0);
}
void init() {
targetRotation = 0;
targetRotationOnMouseDown = 0;
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
container = new Element.tag('div');
document.body.nodes.add( container );
Element info = new Element.tag('div');
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHtml = 'Drag to spin the cube';
container.nodes.add( info );
scene = new Scene();
camera = new PerspectiveCamera( 70.0, window.innerWidth / window.innerHeight, 1.0, 1000.0 );
camera.position.y = 150.0;
camera.position.z = 500.0;
scene.add( camera );
// Plane
plane = new Mesh( new PlaneGeometry( 200.0, 200.0 ), null);
scene.add( plane );
renderer = new CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.nodes.add( renderer.domElement );
}
void render() {
renderer.render( scene, camera );
}
animate(num time) {
window.requestAnimationFrame(animate);
render();
}
}
void main() {
new Canvas_Geometry_Cube().run();
}
How to fix a crash?
I found out the problem. It works with Web GL properly (NOT canvas).
Sergio three.dart might need some work to be updated, its been awhile since a latest version was published on pub. Sorry. Please feel free to checkout the latest branch or code review on the https://github.com/threeDart/three.dart site
Related
I work on a human face that the mouth should move about external coordinates (OpenCV and dlibs). In a first step I try to control the dat.GUI by code, which already works. But now I have the problem that the morph targets do not move when I control by code. The sliders move, but the face doesn't. When I use the mouse, they work perfectly. I ask for help with this problem.
<script>
// Laden der 3DScene
var scene = new THREE.Scene();
// Laden der Kamear Perspektive
var camera = new THREE.PerspectiveCamera(15, window.innerWidth/window.innerHeight, 1, 10000);
camera.position.z = 17;
camera.position.y = 3;
// Laden des Renderers
var renderer = new THREE.WebGLRenderer({ alpha: false });
renderer.setClearColor( 0x000000 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Laden des Orbitcontrollers
var controls = new THREE.OrbitControls( camera, renderer.domElement );
// Laden der Lichter (Beleuchtung)
var ambientLight = new THREE.AmbientLight(0x111111);
scene.add(ambientLight);
var light = new THREE.PointLight( 0xFFFFDD );
light.position.set( -15, 10, 15 );
scene.add(light);
// Laden des Json Modells
var loader = new THREE.JSONLoader();
loader.load( "./three/models/JSON/test/mkh_shapes.json", function (geometry) {
var material = new THREE.MeshLambertMaterial({morphTargets: true});
var mesh = new THREE.Mesh(geometry, material);
mesh.scale.set(1.2,1.2,1.2); //Modellgrösse die angezeigt wird
mesh.position.x = 0; //Position (x = nach rechts+ links-)
mesh.position.y = -19; //Position (y = nach oben +, unten-)
mesh.position.z = 0; //Position (z = nach vorne +, hinten-)
scene.add(mesh);
//dat.Gui
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var shape = {
mouth_open: 0.0, //Anfangsposition 0.0
};
var gui = new dat.GUI();
var folder = gui.addFolder( 'Morph Targets' );
folder.add( shape, 'mouth_open', 0, 1 ).step( 0.01 ).name('mouth_open').listen().onChange ( function( a ) { mesh.morphTargetInfluences[ 40 ] = a;} );
folder.open();
var updateGui = function() {
for (var i in folder.__controllers) {
folder.__controllers[i].updateDisplay();
}
}
var time = Date.now() * 0.003;
shape.mouth_open = 0.50 //* Math.sin( 0.5 * time ) + 0.3;
//scene.add(shape);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
});
function animate() {
render();
requestAnimationFrame( animate );
}
function render() {
renderer.clear();
renderer.render( scene, camera );
}
animate();
</script>
I have made my own version with extra features like :
Gui auto resize based on content div.
Improved slidecontroller as unique controller (slide or number insert);
Multi language automatic support
Auto check for conflicts in options, then ask for confirm or cancel.
Auto Show/hide other controllers when option selected deselected (example show color list only if "custom color is selected")
ecc.. ecc..
here is the Video
Now is more confortable and easy to use.
I'm trying to create a box on canvas that reacts to MouseClick events using Dart and StageXL. My code is as follows:
import 'dart:html' as html;
import 'package:stagexl/stagexl.dart' as sxl;
void main() {
var canvas = html.querySelector('#canvas');
setCanvasFullScreen(canvas);
var stage = new sxl.Stage(canvas);
var renderLoop = new sxl.RenderLoop();
renderLoop.addStage(stage);
var rect = new sxl.Shape();
rect.graphics.rect(80, 50, 100, 100);
rect.graphics.fillColor(sxl.Color.Crimson);
// rect.on(sxl.MouseEvent.CLICK).listen(react);
rect.addEventListener(sxl.MouseEvent.CLICK, react);
stage.addChild(rect);
}//end main
void react(sxl.MouseEvent event){
var w = html.window;
w.alert("I'm clicked!");
}//end onClick
void setCanvasFullScreen(canv) {
var w = html.window;
// w.alert("Holla!!!");
int _width = w.innerWidth as int;
int _height = w.innerHeight as int;
canv.setAttribute('width', '$_width');
canv.setAttribute('height', '$_height');
}
I've tried both on(MouseEvent.CLICK).listen(react); and addEventListener(MouseEvent.CLICK, react); without success there is no reaction. I'm using Dart Editor & SDK version 1.8.5 and debugging on the default Dartium browser.
Any help is appreciated.
After some search on the internet I found this link on StageXL forum that properly explained why it did not work. So I've changed the line:
var rect = new sxl.Shape();
to:
var rect = new sxl.Sprite();
and it reacts nicely.
Hope this is helpful to someone.
before I totally give up on this idea I wanted to check with the three.js community to make sure that I'm not doing something wrong?
Essentially I have taken Mr doobs canvas geometry cube example http://mrdoob.github.io/three.js/examples/canvas_geometry_cube.html and applied an image to the cube faces. When testing on the iPad I have frame a frame speed of 1fps (as opposed to 60fps with the original example). The image also looks really broken up on rotation.
Are there any tricks on getting this to work well on the iPad? I'm aware that WebGL isn't supported but I thought the canvas renderer would perform better than it is?
Code below
Many thanks
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'Drag to spin the cube';
container.appendChild( info );
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.y = 150;
camera.position.z = 500;
scene = new THREE.Scene();
// Cube
var loader = new THREE.TextureLoader();
loader.load( 'test-texture.png', function ( texture ) {
var materials = [];
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
material.transparent = true;
for ( var i = 0; i < 6; i ++ ) {
materials.push( material );
}
// then the cube definitions
cube = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200,4,4,4), new THREE.MeshFaceMaterial(materials));
cube.position.y = 150;
scene.add( cube );
animate();
});
// Plane
var geometry = new THREE.PlaneGeometry( 200, 200 );
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0, overdraw: 0.5 } );
plane = new THREE.Mesh( geometry, material );
scene.add( plane );
renderer = new THREE.CanvasRenderer();
renderer.setClearColor( 0xf0f0f0 );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
}
I would suggest to wait for iOS8 which should bring WebGL support.
I'am trying to program some animations but I am having troubles to understand how the Futures work on Dart.
The main problem is that the animation itself is an asynchronous process and, if I try to chain several points, they pile up and the sprite moves directly to the last point. All the examples I've seen work when the function returns a value but this is not the case when dealing with animations.
I'd like to be able to detect then the animation is finished, in order to trigger the next movement, but I've not been really successful so far.
Here is my code:
class MovingThing {
String name;
DivElement sprite = new DivElement();
MovingThing(this.name){
sprite.id = name;
sprite.text = name;
sprite.style..width = "30px"
..height = "30px"
..border = "1px solid black"
..position = "absolute"
..transition = "all 2000ms ease-in-out";
querySelector("body").children.add(sprite);
}
Future move(Point p) {
sprite.style..top = p.y.toString() + "px"
..left = p.x.toString() + "px";
return Future.wait([sprite.onTransitionEnd.first]);
}
}
main () {
List<Point> points = [
new Point(20, 20)
, new Point(200, 20)
, new Point(20, 200)
, new Point(100, 100)
];
MovingThing mt = new MovingThing("MT");
Future.forEach(points, (Point p) => mt.move(p));
}
I several things
Future.wait() does return immediately not when onTransitionEnd is fired.
Future.wait is for waiting for more than one Future hence the List parameter.
you could use return sprite.onTransitionEnd.first; instead this line.
You should add your action to mt.move(p).then((v) => doThisAfterTransitionEnd);
I tried your code and onTransitionEnd was not fired.
not perfect but should you show how to start.
new Future() is only used to give the event loop time to do it's work not to chain the animations.
The next iteration of the animation starts with the onSubscriptionEnd event.
import 'dart:html';
import 'dart:async';
class MovingThing {
String name;
DivElement sprite = new DivElement();
List<Point> points;
MovingThing(this.name){
sprite.id = name;
sprite.text = name;
sprite.style
..top = "30px"
..left = "30px"
..width = "30px"
..height = "30px"
..border = "1px solid black"
..position = "absolute"
..transition = "all 1.5s ease-in-out";
document.body.children.add(sprite);
}
void move(int idx) {
if(idx >= points.length) {
return;
} else {
var f = sprite.onTransitionEnd.first.then((TransitionEvent e) {
new Future(() {
print('transitionEnd$idx');
move(idx + 1);
});
});
sprite.style
..top = '${points[idx].x}px'
..left = '${points[idx].y}px';
sprite.text = '$idx';
}
}
}
main () {
List<Point> points = [
new Point(120, 120)
, new Point(200, 20)
, new Point(20, 200)
, new Point(100, 100)
, new Point(150, 30)
, new Point(30, 150)
, new Point(20, 20)
, new Point(120, 120)
];
MovingThing mt = new MovingThing("MT");
mt.points = points;
new Future(() => mt.move(0));
}
I am trying to add texture to a model that I converted to json and imported from 3ds Max. I searched but didn't find any code online which applies texture to json models using three.js r53. I guess the way Three.js handles textures changed from previous version. Any guidance?
Following is my code:
var texloader = new THREE.TextureLoader();
var tex=texloader.load("second.jpg");
var mat = new THREE.MeshBasicMaterial({ map: tex });
loader = new THREE.JSONLoader();
loader.load( "js/JsonModels/toothz.js", function( geometry, mat ) {
mat[0].shading = THREE.SmoothShading;
var material = new THREE.MeshFaceMaterial( mat);
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set( 3, 3, 3 );
mesh.position.y = 0;
mesh.position.x = 0;
scene.add( mesh );
} );
May be the other answer worked on the older version, this is how I got it working
var textureLoader = new THREE.TextureLoader();
textureLoader.load(url);
// Add the event listener
textureLoader.addEventListener('load', function(event){
// The actual texture is returned in the event.content
sphere.material.map = event.content;
});
EDIT:
This post was a year old when I answered it, and it seems like my answer got posted shortly before the API changed.
This answer won't work (trusting the words of Kumar Sanket Sahu, haven't tested)
Even if this is older than a year, since I came around it now when searching for the solution:
textureloader gives you a callback once the texture is loaded:
var texloader = new THREE.TextureLoader();
texloader.load("second.jpg", function(tex) {
var mat = new THREE.MeshBasicMaterial({ map: tex });
var loader = new THREE.JSONLoader();
loader.load( "js/JsonModels/toothz.js", function( geometry, mat ) {
mat[0].shading = THREE.SmoothShading;
material = new THREE.MeshFaceMaterial( mat);
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set( 3, 3, 3 );
mesh.position.y = 0;
mesh.position.x = 0;
scene.add( mesh );
} );
});
This works for the example.
This worked for me on September 2019
load(
url: string,
onLoad?: ( texture: Texture ) => void,
onProgress?: ( event: ProgressEvent ) => void,
onError?: ( event: ErrorEvent ) => void
): Texture;
setCrossOrigin( crossOrigin: string ): TextureLoader;
Usage:
// instantiate a loader & load a resource
new THREE.TextureLoader().load(
// resource URL
'textures/land_ocean_ice_cloud_2048.jpg',
// onLoad callback
( texture )=> {
// in this example we create the material when the texture is loaded
var material = new THREE.MeshBasicMaterial( {
map: texture
} );
},
// onProgress callback currently not supported
undefined,
// onError callback
( err )=> {
console.error( 'An error happened.' );
}
);