I'm quite new to WebGL, and I'm trying to create cake with animated candles. So, I have found this examples: https://stemkoski.github.io/Three.js/Particle-Engine.html with candle flame and tried to change code due to my task (cake). But I struggled with creating several flames into same scene (I found some information how to create cubes or spheres, but unfortunately it is unhelpful in this case).
As far as I understand animated flame displaying is in the code:
this.engine = new ParticleEngine();
engine.setValues( Examples.fountain );
engine.initialize();
but I can't figure out how to create 5 different examples same time.
UPD: I finally created several instances, here is my code:
var engines = [];
var coordinates = [
{x:5, y:105},
{x:-40, y:115},
{x:-75,y:111},
{x:37, y:117},
{x:68, y:110}
];
coordinates.forEach(function(item, i){
var params = clone(Examples.candle);
params.positionBase = new THREE.Vector3(item.x, item.y, 10);
var engine = new ParticleEngine();
engine.setValues(instances[i]);
engine.initialize();
engines.push(engine);
}
But when I tried to set different example (smoke from examples) to one instance all other instance's parameters had been changed too. Can't figure out how to change each instance separately without any influence others.
Related
I am making a 2d sandbox game with procedural terrain generation, and for a few weeks, I have used this noise function by joeiddon, slightly modified so I can have multiple noise instances. The problem was that this function doesn't have a seed option, so there's no way to tell it to generate the same world two times. To solve that, I have been googling and coding for a few hours. Eventually, I stumbled upon this function (also slightly modified), which does support seeds. The problem is that when I use this function, there is almost no variation in the worlds. They can all be divided in five categories, and the difference between different worlds in the same category will never be more than a few blocks. So, basically, I either need a way to make the first function work with seeds, or I need to find out why the second function doesn't give enough variation. I don't know if this will help, but here is the code that initializes the noises based on a random seed:
seed = Math.random();
grassNoise = new Perlin(seed);
goldMaxNoise = new Perlin(seed/7);
goldMinNoise = new Perlin(seed/2);
treeNoise = new Perlin(seed*3/2);
cloudUpNoise = new Perlin(seed);
cloudDownNoise = new Perlin(seed*1.2);
coalMaxNoise = new Perlin((seed - 78) / 3);
coalMinNoise = new Perlin(seed*7);
I only use the perlin2 function. Could anyone please point out what I'm doing wrong?
I am not able to implement LOD to a 3d Object with json data.
Here is my implementation:
loader.load('models/robot-threejs/robot.json', function(object){
var lod = new THREE.LOD(object);
for (var i=1; i<=3;i++) {
console.log("this"+i);
lod.addLevel(object,i);
}
lod.updateMatrix();
lod.matrixAutoUpdate = false;
// lod.updateMatrix();
// lod.matrixAutoUpdate = false;
scene.add(lod);
//scene.add(object);
// object.position.set(30, 30, 30);
})
You're implementing THREE.LOD wrong.
The constructor does not take any parameters, so when you do this: new THREE.LOD(object);, it does nothing. You just have to use new THREE.LOD();
You're adding the same mesh to LOD 3 times, so you're not gonna see any difference. You need to create separate meshes with different geometries if you want to see any change in detail. Keep in mind that you have to generate these geometries yourself. Three.js doesn't automatically change the geometry for you. But you could use the SimplifyModifier for this.
Not sure why you're playing with matrix updates. There's no reason for this here.
You also need to call lod.update(camera) on your render loop if you want to see the change in detail.
I strongly recommend you read the documentation for LOD and read through the code in this example to better understand how it works.
The easiest thing to do instead of pasting the entire code here inconveniently is give a link to the Babylon.js playground..If you're not familiar with it, its basically an environment like jsfiddle but specifically for Babylon.js webGL rendering. It's got the canvas, engine, and render loop already initiated (term?)
http://www.babylonjs-playground.com/#LYEU3#0
I have created constructors for 3 different star types:YellowStar, WhiteStar, and RedStar. I have them pasted in the playground code, but locally, the 3 functions are in a separate file. You'll notice that YellowStar's emitting particles do not have the image rendered, which is fine as it doesn't relate to the question. The larger white spheres in the foreground are supposed to be an emissive red color(RedStar objects). The smaller white spheres in the background (WhiteStar objectcs) are white as they are supposed to be, but the emissive property isn't working on those either.
I know its a problem with the way I have them constructed. Because there aren't that many properties in common, I don't have set up to inherit from main Star constructor. Passing sphere and material parameters for the objects would sort of defeat the convenience of creating the constructors in the first place. But there is something I"m doing wrong, unaware of, or not considering that is making the .mat property not work, and the material therefore to not render. I'd like to have all my objects (including planets eventually), originating from one file.
Every time I have an issue I can't figure out, its usually related to scope. WhiteStar and RedStar's material properties are not being recognized. I dont get that because the scope of each .mat should be limited within its own function.
var YellowStar = function (position, size, scene) {
this.sphere = BABYLON.Mesh.CreateSphere("sphere1", 30, 30*size, scene);
this.mat = new BABYLON.StandardMaterial("white", scene);
this.mat.diffuseTexture = new BABYLON.Texture("textures/suntexture.jpg", scene);
this.mat.specularColor = new BABYLON.Color3(0, 0, 0);
this.sphere.material = this.mat;
this.sphere.position = position;
/*...this material works...*/
};
var WhiteStar = function(position, size, scene){
this.sphere = BABYLON.Mesh.CreateSphere("whiteStar", 20, 15*size, scene);
this.mat = new BABYLON.StandardMaterial("white", scene);
this.mat.emissiveColor = new BABYLON.Color3(1, 1, 1);
this.sphere.material = this.mat; /* doesn't work */
}
var RedStar = function (position, size, scene) {
this.sphere = BABYLON.Mesh.CreateSphere("redStar", 20, 30*size, scene);
this.mat = new BABYLON.StandardMaterial("red", scene);
this.mat.emissiveColor = new BABYLON.Color3(0.714, 0.239, 0.169);
this.sphere.material = this.mat; /*doesnt work*/
};
Babylon does have a community, but the questions relate more toward the engine, and I have more success getting general Javascript questions answered here. Thanks
After fiddling about with it, it looks like you have to explicitly add/define the diffuse colour before the emissive colour to work. I don't know why.
NB The white star emissive colour is full on white, so I'm unsure how you'd know whether it's working or not.
HTH
I have a Three.js scene rendered and I would like to export how it looks after the animations have rendered. For example, after the animation has gone ~100 frames, the user hits export and the scene should be exported to STL just as it is at that moment.
From what I've tried (using STLExporter.js, that is), it seems to export the model using the initial positions only.
If there's already a way to do this, or a straightforward work around, I would appreciate a nudge in that direction.
Update: After a bit more digging into the internals, I've figured out (at least superficially) why STLExporter did not work. STLExporter finds all objects and asks them for the vertices and faces of the Geometry object. My model has a bunch of bones that are skinned. During the animation step, the bones get updated, but these updates does not propagate to the original Geometry object. I know these transformed vertices are being calculated and exist somewhere (they get displayed on the canvas).
The question is where are these transformed vertices and faces stored and can I access them to export them as an STL?
The question is where are these transformed vertices and faces stored and can I access them to export them as an STL?
The answer to this, unfortunately, is nowhere. These are all computed on the GPU through calls to WebGL functions by passing in several large arrays.
To explain how to calculate this, let's first review how animation works, using this knight example for reference.
The SkinnedMesh object contains, among other things, a skeleton (made of many Bones) and a bunch of vertices. They start out arranged in what's known as a bind pose. Each vertex is bound to 0-4 bones and if those bones move, the vertexes will move, creating animation.
If you were to take our knight example, pause the animation mid-swing, and try the standard STL exporter, the STL file generated would be exactly this pose, not the animated one. Why? Because it simply looks at mesh.geometry.vertices, which are not changed from the original bind pose during animation. Only the bones experience change and the GPU does some math to move the vertices corresponding to each bone.
That math to move each vertex is pretty straight forward - transform the bind-pose vertex position into bone-space and then from bone-space to global-space before exporting.
Adapting the code from here, we add this to the original exporter:
vector.copy( vertices[ vertexIndex ] );
boneIndices = []; //which bones we need
boneIndices[0] = mesh.geometry.skinIndices[vertexIndex].x;
boneIndices[1] = mesh.geometry.skinIndices[vertexIndex].y;
boneIndices[2] = mesh.geometry.skinIndices[vertexIndex].z;
boneIndices[3] = mesh.geometry.skinIndices[vertexIndex].w;
weights = []; //some bones impact the vertex more than others
weights[0] = mesh.geometry.skinWeights[vertexIndex].x;
weights[1] = mesh.geometry.skinWeights[vertexIndex].y;
weights[2] = mesh.geometry.skinWeights[vertexIndex].z;
weights[3] = mesh.geometry.skinWeights[vertexIndex].w;
inverses = []; //boneInverses are the transform from bind-pose to some "bone space"
inverses[0] = mesh.skeleton.boneInverses[ boneIndices[0] ];
inverses[1] = mesh.skeleton.boneInverses[ boneIndices[1] ];
inverses[2] = mesh.skeleton.boneInverses[ boneIndices[2] ];
inverses[3] = mesh.skeleton.boneInverses[ boneIndices[3] ];
skinMatrices = []; //each bone's matrix world is the transform from "bone space" to the "global space"
skinMatrices[0] = mesh.skeleton.bones[ boneIndices[0] ].matrixWorld;
skinMatrices[1] = mesh.skeleton.bones[ boneIndices[1] ].matrixWorld;
skinMatrices[2] = mesh.skeleton.bones[ boneIndices[2] ].matrixWorld;
skinMatrices[3] = mesh.skeleton.bones[ boneIndices[3] ].matrixWorld;
var finalVector = new THREE.Vector4();
for(var k = 0; k<4; k++) {
var tempVector = new THREE.Vector4(vector.x, vector.y, vector.z);
//weight the transformation
tempVector.multiplyScalar(weights[k]);
//the inverse takes the vector into local bone space
tempVector.applyMatrix4(inverses[k])
//which is then transformed to the appropriate world space
.applyMatrix4(skinMatrices[k]);
finalVector.add(tempVector);
}
output += '\t\t\tvertex ' + finalVector.x + ' ' + finalVector.y + ' ' + finalVector.z + '\n';
This yields STL files that look like:
The full code is available at https://gist.github.com/kjlubick/fb6ba9c51df63ba0951f
After a week of pulling my hair out I managed to modify the code to include morphTarget data in the final stl file. you can find the modified code to Kevin's change at https://gist.github.com/jcarletto27/e271bbb7639c4bed2427
As JS is not my favored language, it's not pretty but, it manages to work without much fuss. Hopefully someone gets some use out of this besides me!
I am very new to Easel and HTML5 itself. I am trying to draw a line using on a canvas using EaselJS. The X- Co ordinate is fixedd to 100 and the Y-Co ordinate is got from a array list. The code that i have written is given below. Could please someone let me know where i am going wrong?
function myFunction(attachPoint)
{
//Code for canvas creation is written here.[Not shown];
//created a stage.
stage = new createjs.Stage(canvas.domElement());
//3. create some shapes.MagnitudeLessThanTwo is the array where we get the YAxis Coordinates from
alert("The lenght before function is"+MagnitudeLessThanTwo.length);
myShape = new drawLineGraph(MagnitudeLessThanTwo);
//4. finally add that shape to the stage
stage.addChild(myShape);
//5. set up the ticker
if (!createjs.Ticker.hasEventListener("tick")) {
createjs.Ticker.addEventListener("tick", ourTickFunction);
};
};
function drawLineGraph(dataList)
{
this.index=0;//To keep the track of the index of the array from which we get the Y Axis.
var graphics = new createjs.Graphics();
graphics.setStrokeStyle(1);
graphics.beginStroke("white");
graphics.moveTo(50,(dataList[this.index].magnitude)*100);
graphics.lineTo(50,(dataList[(this.index)++].magnitude)*100);
createjs.Shape.call(this,graphics);
this.tick = function() {
graphics.moveTo(100,(dataList[this.index].magnitude)*100);
graphics.lineTo(100,(dataList[(this.index)++].magnitude)*100);
stage.addChild(graphics);
};
};
drawLineGraph.prototype = new createjs.Shape(); //set prototype
drawLineGraph.prototype.constructor = drawLineGraph; //fix constructor pointer
I am getting the following Error.
"Object [object Object] has no method 'isVisible'"- This is inside the EaselJS Library.
There are a few issues here. The error you are seeing is because you are adding the Graphics to the Stage, and not the Shape.
The other issue is how the Graphics are modified in the tick:
this.tick = function() {
graphics.moveTo(100,(dataList[this.index].magnitude)*100);
graphics.lineTo(100,(dataList[(this.index)++].magnitude)*100);
stage.addChild(graphics);
};
You only need to add your Shape to the stage one time, and it will redraw your graphics each time every time the Stage is updated. Your tick call is adding new Graphics instructions every frame, so it will stack all those calls up, and eventually be really slow.
Make sure you clear your Graphics before you draw new things to it, unless you are trying to create an additive effect (and if you are, perhaps look into caching/updateCache to make it performant). Check out the "curveTo" and "updateCache" examples in the GitHub repository for usage.
Once you have added the Shape to the stage instead of the Graphics, feel free to post some follow up questions, and I can try and assist further.
Cheers :)