Working on forward ray tracing algorithm using Three.js. Just created this example by using a 2D array. Notice that the Spotlight is not involved here except the parsing of its location.
So in order to shoot lines I declared:
startPoint = position of SpotLight
endPoint = hard code for the first value
Then I create a nested for loop (17x17) and I create a ray every iteration with the usual way as shown below:
forward_RT(){
//Declare the start and end points of the first ray (startPoint never changes )
var f_ray_startPoint = new THREE.Vector3(spotLight.position.x, spotLight.position.y, spotLight.position.z);
var f_ray_endPoint = new THREE.Vector3(-490, 0, 495); //Hard Coding for 1st position of ray endPoint
//Declare material of rays
var ray_material_red = new THREE.LineBasicMaterial( { color: 0xff0000, opacity: 10} );
var ray_material_yellow = new THREE.LineBasicMaterial( { color: 0xffff00 } );
var ray_material_green = new THREE.LineBasicMaterial( { color: 0x00ff00 } );
//Declare ray geometry
var ray_geometry = new THREE.Geometry();
ray_geometry.vertices.push( f_ray_startPoint );
ray_geometry.vertices.push( f_ray_endPoint );
//Declare values for 2d array grid
var rows = 17;
var cols = 17;
var rayOffset = 60; //Offset of ray every X iteration
for(var x=0; x<rows; x++){
for(var z=0; z<cols; z++){
//Declare a ray
var f_ray = new THREE.Line(ray_geometry.clone(), ray_material_red);
f_ray.geometry.vertices[1].x = f_ray_endPoint.x;
scene_Main.add(f_ray); //Add ray into the scene
f_ray_endPoint.x += rayOffset; //Add offset every new ray
if(f_ray_endPoint.x >= 490){
f_ray_endPoint.x -= (cols * rayOffset);
}
}
f_ray_endPoint.z -= rayOffset;
}
}
For the graphics folks, I have noticed that opacity doesn't work on the material of the Three.Line.
Is There a way to add transparency on the line?
Main Question
How to block the iteration so that the corners of the SpotLight will not be drawn? In other words, I want access only to rays that are inside the white circle (SpotLights).
If you want to maintain a discreet grid of X, Y rays and discard those outside the circle, you could use the built-in method Vector2.distanceTo(). Simply keep your loop as it is, but do a distance calculation to the center of the circle, if the distance is larger than the radius, skip to the next loop:
// Find the center of your circle
var center = new THREE.Vector2(centerX, centerZ);
// Assign radius of your circle
var radius = 17 / 2;
// Temp vector to calculate distance per iteration
var rayEnd = new THREE.Vector2();
// Result of distance
var distance = 0;
for (var x = 0; x < rows; x++) {
for (var z = 0; z < cols; z++) {
// Set this ray's end position
rayEnd.set(x, z);
// Calculate distance to center
distance = rayEnd.distanceTo(center);
// Skip loop if distance to center is bigger than radius
if (distance > radius) {
continue;
} else {
// Draw ray to x, z
}
}
}
A few recommendations:
I would use a single LineSegments object, instead of multiple Line objects for faster rendering (Three.js is faster at rendering one object with many vertices than many objects with few vertices).
You could generate the geometry around the origin (from -8 to 8), and calculate the distance to (0, 0), and then displace it by 60 units with position.x = 60, for simplicity.
Related
I am new to Three.js so perhaps I am not going abut this optimally,
I have geometry which I create as follows,
const geo = new THREE.PlaneBufferGeometry(10,0);
I then apply a rotation to it
geo.applyMatrix( new THREE.Matrix4().makeRotationX( Math.PI * 0.5 ) );
then I create a Mesh from it
const open = new THREE.Mesh( geo, materialNormal);
I then apply a bunch of operations to the mesh to position it correctly, as follows:
open.position.copy(v2(10,20);
open.position.z = 0.5*10
open.position.x -= 20
open.position.y -= 10
open.rotation.z = angle;
Now what is the best way to get the vertices of the mesh both before and after it's position is changed? I was surpised to discover that the vertices of a mesh are not in-built into three.js.
Any hints and code samples would be greatly appreciated.
I think you're getting tripped-up by some semantics regarding three.js objects.
1) A Mesh does not have vertices. A Mesh contains references to Geometry/BufferGeometry, and Material(s). The vertices are contained in the Mesh's geometry property/object.
2) You're using PlaneBufferGeometry, which means an implementation of a BufferGeometry object. BufferGeometry keeps its vertices in the position attribute (mesh.geometry.attributes.position). Keep in mind that the vertex order may be affected by the index property (mesh.geometry.index).
Now to your question, the geometric origin is also its parent Mesh's origin, so your "before mesh transformation" vertex positions are exactly the same as when you created the mesh. Just read them out as-is.
To get the "after mesh transformation" vertex positions, you'll need to take each vertex, and convert it from the Mesh's local space, into world space. Luckily, three.js has a convenient function to do this:
var tempVertex = new THREE.Vector3();
// set tempVertex based on information from mesh.geometry.attributes.position
mesh.localToWorld(tempVertex);
// tempVertex is converted from local coordinates into world coordinates,
// which is its "after mesh transformation" position
Here's an example written by typescript.
It gets the grid's position in the world coordinate system.
GetObjectVertices(obj: THREE.Object3D): { pts: Array<THREE.Vector3>, faces: Array<THREE.Face3> }
{
let pts: Array<THREE.Vector3> = [];
let rs = { pts: pts, faces: null };
if (obj.hasOwnProperty("geometry"))
{
let geo = obj["geometry"];
if (geo instanceof THREE.Geometry)
{
for (let pt of geo.vertices)
{
pts.push(pt.clone().applyMatrix4(obj.matrix));
}
rs.faces = geo.faces;
}
else if (geo instanceof THREE.BufferGeometry)
{
let tempGeo = new THREE.Geometry().fromBufferGeometry(geo);
for (let pt of tempGeo.vertices)
{
pts.push(pt.applyMatrix4(obj.matrix));
}
rs.faces = tempGeo.faces;
tempGeo.dispose();
}
}
return rs;
}
or
if (geo instanceof THREE.BufferGeometry)
{
let positions: Float32Array = geo.attributes["position"].array;
let ptCout = positions.length / 3;
for (let i = 0; i < ptCout; i++)
{
let p = new THREE.Vector3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
}
}
I'm worked with Three.JS before, but not on meshes. I think I am approaching my problem the right way, but I'm not sure.
The Goal
I'm trying to make a 3D blobby object that has specific verticies. The direction of the verticies are fixed, but their radius from center varies. You can imagine it sort of like an audio equalizer, except radial and in 3D.
I'm open to scrapping this approach and taking a totally different one if there's some easier way to do this.
Current Progress
I took this example and cleaned/modified it to my needs. Here's the HTML and JavaScript:
HTML (disco-ball.html)
<!DOCTYPE html>
<html>
<head>
<title>Disco Ball</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/ConvexGeometry.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style type='text/css'>
/* set margin to 0 and overflow to hidden, to go fullscreen */
body { margin: 0; overflow: hidden; }
</style>
</head>
<body>
<div id="Stats-output"></div>
<div id="WebGL-output"></div>
<script type="text/javascript" src="01-app.js"></script>
</body>
</html>
And the JavaScript (01-app.js):
window.onload = init;
const PARAMS = {
SHOW_SURFACE : true,
SHOW_POINTS : true,
SHOW_WIREFRAME : true,
SHOW_STATS : true
};
// once everything is loaded, we run our Three.js stuff.
function init() {
var renderParams = {
webGLRenderer : createWebGLRenderer(),
step : 0,
rotationSpeed : 0.007,
scene : new THREE.Scene(),
camera : createCamera(),
};
// Create the actual points.
var points = getPoints(
100, // Number of points (approximate)
10, // Unweighted radius
// Radius weights for a few points. This is a multiplier.
[2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2]
);
if (PARAMS.SHOW_STATS) {
renderParams.stats = initStats();
}
if (PARAMS.SHOW_SURFACE) {
renderParams.surface = getHullMesh(points);
renderParams.scene.add(renderParams.surface);
}
if (PARAMS.SHOW_POINTS) {
renderParams.sphereGroup = getSphereGroup(points);
renderParams.scene.add(sphereGroup);
}
render(renderParams);
}
function render(params) {
if (params.stats) {
params.stats.update();
}
if (params.sphereGroup) {
params.sphereGroup.rotation.y = params.step;
}
params.step += params.rotationSpeed;
if (params.surface) {
params.surface.rotation.y = params.step;
}
// render using requestAnimationFrame
requestAnimationFrame(function () {render(params)});
params.webGLRenderer.render(params.scene, params.camera);
}
// ******************************************************************
// Helper functions
// ******************************************************************
function getPoints (count, baseRadius, weightMap) {
// Because this is deterministic, we can pass in a weight map to adjust
// the radii.
var points = distributePoints(count,baseRadius,weightMap);
points.forEach((d,i) => {
points[i] = new THREE.Vector3(d[0],d[1],d[2]);
});
return points;
}
// A deterministic function for (approximately) evenly distributing n points
// over a sphere.
function distributePoints (count, radius, weightMap) {
// I'm not sure why I need this...
count *= 100;
var points = [];
var area = 4 * Math.PI * Math.pow(radius,2) / count;
var dist = Math.sqrt(area);
var Mtheta = Math.round(Math.PI / dist);
var distTheta = Math.PI / Mtheta
var distPhi = area / distTheta;
for (var m = 0; m < Mtheta; m++) {
let theta = (Math.PI * (m + 0.5)) / Mtheta;
let Mphi = Math.round((2 * Math.PI * Math.sin(theta)) / distPhi);
for (var n = 0; n < Mphi; n++) {
let phi = ((2 * Math.PI * n) / Mphi);
// Use the default radius, times any multiplier passed in through the
// weightMap. If no multiplier is present, use 1 to leave it
// unchanged.
points.push(createPoint(radius * (weightMap[points.length] || 1),theta,phi));
}
}
return points;
}
function createPoint (radius, theta, phi) {
var x = radius * Math.sin(theta) * Math.cos(phi);
var y = radius * Math.sin(theta) * Math.sin(phi);
var z = radius * Math.cos(theta);
return [Math.round(x), Math.round(y), Math.round(z)];
}
function createWebGLRenderer () {
// create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;
// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
return webGLRenderer;
}
function createCamera () {
// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// position and point the camera to the center of the scene
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(new THREE.Vector3(0, 0, 0));
return camera;
}
function getSphereGroup (points) {
sphereGroup = new THREE.Object3D();
var material = new THREE.MeshBasicMaterial({color: 0xFF0000, transparent: false});
points.forEach(function (point) {
var spGeom = new THREE.SphereGeometry(0.2);
var spMesh = new THREE.Mesh(spGeom, material);
spMesh.position.copy(point);
sphereGroup.add(spMesh);
});
return sphereGroup;
}
function getHullMesh (points) {
// use the same points to create a convexgeometry
var surfaceGeometry = new THREE.ConvexGeometry(points);
var surface = createMesh(surfaceGeometry);
return surface;
}
function createMesh(geom) {
// assign two materials
var meshMaterial = new THREE.MeshBasicMaterial({color: 0x666666, transparent: true, opacity: 0.25});
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial({color: 0x0000ff});
wireFrameMat.wireframe = PARAMS.SHOW_WIREFRAME;
// create a multimaterial
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
What I'm Missing
You can see that there are two points on the "ball" for which I've doubled the radius (big spikes). Of course, since I'm using a ConvexGeometry, the shape is convex... so a number of the points are hidden. What kind of ... non-convex geometry can I use to make those points no longer be hidden?
I would like to subdivide the mesh a bit so it's not simply vertex-to-vertex, but a bit smoother. How can I do that (the spikes less spikey and more blobby)?
I'd like to modify the mesh so different points spike different amounts every few seconds (I have some data arrays that describe how much). How do I modify the geometry after its been made? Ideally with some kind of tweening, but I can do without of that's extremely hard =)
Thanks!
Smooth and animate a mesh.
Three provides a huge range of options. These are just suggestions, your best bet is to read the Three documentation start point and find what suits you.
A mesh is just a set of 3D points and an array of indexes describing each triangle. Once you have built the mesh you only need to update the verts and let Three update the shader attributes, and the mesh normals
Your questions
Q1. Use Three.Geometry for the mesh.
Q2. As you are building the mesh you can use the curve helpers eg Three.CubicBezierCurve3 or Three.QuadraticBezierCurve3 or maybe your best option Three.SplineCurve
Another option is to use a modifier and create the simple mesh and then let Three subdivide the mesh for you. eg three example webgl modifier subdivision
Though not the fastest solution, if the vert count is low it will do this each frame without any loss of frame rate.
Q3. Using Three.Geometry you can can set the mesh morph targets, an array of vertices.
Another option is to use a modifier, eg three example webgl modifier subdivision
Or you can modify the vertices directly each frame.
for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
geometry.vertices[ i ].x = ?;
geometry.vertices[ i ].y = ?;
geometry.vertices[ i ].z = ?;
}
mesh.geometry.verticesNeedUpdate = true;
How you do it?
There are a zillion other ways to do this. Which is the best will depend on the load and amount of complexity you want to create. Spend some time and read the doc's, and experiment.
What I would do! maybe?
I am not too sure what you are trying to achieve but the following is a way of getting some life into the animation rather than the overdone curves that seem so ubiquitous these days.
So if the vert count is not too high I would use a Three.BufferGeometry and modify the verts each frame. Rather than use curves I would weight subdivision verts to follow a polynomial curve f(x) = x^2/(x^2 + (1-x)^2) where x is the normalized distance between two control verts (note don't use x=0.5 rather subdivide the mesh in > 2 times)
EG the two control points and two smoothing verts
// two control points
const p1 = {x,y,z};
const p2 = {x,y,z};
// two weighted points
// dx,dy,dz are deltas
// w is the weighted position s-curve
// wa, and wd are acceleration and drag coefficients. Try to keep their sum < 1
const pw1 = {x, y, z, dx, dy, dz, w : 1/3, wa : 0.1,wd : 0.7};
const pw2 = {x, y, z, dx, dy, dz, w : 2/3, wa : 0.1,wd : 0.7};
// Compute w
pw1.w = Math.pow(pw1.w,2) / ( Math.pow(pw1.w,2) + Math.pow(1 - pw1.w,2));
pw2.w = Math.pow(pw2.w,2) / ( Math.pow(pw2.w,2) + Math.pow(1 - pw2.w,2));
Then for each weighted point you can find the new delta and update the position
// do for x,y,z
x = (p2.x - p1.x); // these points are updated every frame
// get the new pw1 vert target position
x = p1.x + x * w;
// get new delta
pw1.dx += (x - pw1.x) * pw1.wa; // set delta
pw1.dx *= pw1.wd;
// set new position
pw1.x += pw1.dx;
Do for all weighted points then set geometry.vertices
The wa,wd coefficients will change the behaviour of the smoothing, you will have to play with these values to suit your own taste. Must be 0 <= (wa,wd) < 1 and the sum should be wa + wd < 1. High sumed values will result in oscillations, too high and the oscillations will be uncontrolled.
I am trying to Extrude the Rectangle drawn in the canvas to Three.js canvas.
Here Blue one is 2d canvas drawing and Green is 3d
var Shape = new THREE.Shape();
Shape.moveTo(0,0,0);
for(var i=0;i<=point.length/2;i++)
{
Shape.lineTo(point[i],point[i+1]);
}
var ExtrusionSettings = {
curveSegments: 3,
bevelThickness:0, bevelSize: 0, bevelEnabled: false,
material: 0, extrudeMaterial: 1,amount: 10
};
var Geometry = new THREE.ExtrudeGeometry( Shape, ExtrusionSettings );
var Material = new THREE.MeshLambertMaterial({color: 0xff8800});
Material.side = THREE.DoubleSide;
Mesh = new THREE.Mesh(Geometry,Material);
Mesh.position.set(0,0,0);
Scene.add(Mesh);
The points is passed as an array which contain the x,y coordinates of the lines in the canvas
the points are passed by
function mouseDown(event)
{
Line[0] = event.pageX - this.offsetLeft;
Line[1] = event.pageY - this.offsetTop;
console.log("down");
}
function mouseUp(event)
{
Line[2] = event.pageX - this.offsetLeft;
Line[3] = event.pageY - this.offsetTop;
console.log("up");
var Width = Math.abs(Line[2] - Line[0]);
var Height = Math.abs(Line[3] - Line[1]);
Context.beginPath();
//Context.moveTo(Line[0], Line[1]);
//Context.lineTo(Line[2], Line[3]);
//Context.rect(Line[0],Line[1],Width,Height);
Context.lineWidth="5";
Context.strokeStyle="red";
var L1P1x = Line[0];
var L1P1y = Line[1];
var L1P2x = Line[0]+Width;
var L1p2Y = Line[1];
var L2P1x = Line[0]+Width;
var L2P1y = Line[1];
var L2P2x = Line[2];
var L2P2y = Line[3];
var L3P1x = Line[2];
var L3P1y = Line[3];
var L3P2x = Line[0];
var L3P2y = Line[1]+Height;
var L4P1x = Line[0];
var L4P1y = Line[1]+Height;
var L4P2x = Line[0];
var L4P2y = Line[1];
Context.moveTo(L1P1x,L1P1y);
Context.lineTo(L1P2x,L1p2Y);
Context.moveTo(L2P1x,L2P1y);
Context.lineTo(L2P2x,L2P2y);
Context.moveTo(L3P1x,L3P1y);
Context.lineTo(L3P2x,L3P2y);
Context.moveTo(L4P1x,L4P1y);
Context.lineTo(L4P2x,L4P2y);
Context.stroke();
Points.push(L1P1x,L1P1y,L1P2x,L1p2Y,L2P1x,L2P1y,L2P2x,L2P2y,L3P1x,L3P1y,L3P2x,L3P2y,L4P1x,L4P1y,L4P2x,L4P2y);
addMesh(Points);//points are passes to draw in 3d
//console.log(Points);
}
Not a fan of three.js but looking at your code you have some basic logic errors.
The short answer
Logic errors in the for loop! Change your first snippet to the following. You have Points in the second snippet and Point in the first. I have used point in the fix as I assume that is the correct name for the array of coordinates.
var i, len, mesh; // define all the vars you will use
len = point.length; // get the number of coordinates.
if(len > 1) { // make sure there are points.
shape.moveTo(point[0], point[1]); // move to the first point
for(i = 2; i < len; i += 2) { // iterate other points and lineTo them
shape.lineTo(point[i], point[i + 1]); // add the line.
}
mesh = new THREE.Mesh(
new THREE.ExtrudeGeometry( // Create geom
shape,
{ // extrusion settings.
curveSegments : 3,
bevelThickness : 0,
bevelSize : 0,
bevelEnabled : false,
material : 0,
extrudeMaterial : 1,
amount : 10
}
),
new THREE.MeshLambertMaterial({color: 0xff8800}) // material
);
mesh.position.set(0, 0 0); // position the mesh
scene.add(mesh); // add it to the scene
}
That will fix the bug. It was the for loop that was bad.
The long answer.
You seem to be a beginner so the long answer is to give you some longer term advice. (advice only as there are no rules).
Creating the shape. You had...
var Shape = new THREE.Shape();
Shape.moveTo(0,0,0);
for(var i=0;i<=point.length/2;i++)
{
Shape.lineTo(point[i],point[i+1]);
}
Now with my pedantic eye
Never name vars with a capital. Capitaitals are reserved for named objects. Though in this case you are safe, using the name Shape in a differing scopy could well overwrite the object constructor.
var Shape = new THREE.Shape(); // you had
should be
var shape = new THREE.shape();
Capitals are only for objects that you can use the new token with, Acronyms, or constants. This is not a trivial convention as all of Javascript's inbuilt naming uses it and I have yet to find a popular framework that does not use it. DON'T CAPITALIZE, it is a bad habit in javascript and will cause endless hours looking for simple syntax bugs.
The THREE.Shape object only deals with 2D paths. You had
// 3 coordinates for for a 2D path???
Shape.moveTo(0,0,0); // remove this line it is not needed
The last 0 is ignored, ( I checked the THREE.js source code) and that is not the error.
You error is here in the following.
for(var i=0;i<=point.length/2;i++) // Only half the points ??
{ // you then line to x,y
Shape.lineTo(point[i],point[i+1]);
// Next lineTo will be y,x then x,y messing everything up.
}
point refers the the array of numbers representing the x and y coordinates of the path. It is organised with the x coord, then y then x then y.
The number of items in the array is the number of 2D points * 2. The * 2 is because there is a X and a ``Y for each point.
So need to iterate the point array correctly.
Step by step.
var i, len; // always put your vars declarations at the top
len = point.length; // I like to get the length before the loop.
The for loop needs to step by 2 as the are two entries for each point.
for(i = 0; i < len; i += 2) { //Put the { at the end. Saves space and is easier to read.
Check for the first point as you need to moveTo (note answer is slightly different)
if(i === 0) {
Add the point to the path (shape).
shape.moveTo(point[i], point[i + 1]);
Then the other points
} else {
shape.lineTo(point[i], point[i + 1]);
}
This will create the correct shape that you can then use to extrude.
Put all together as I would do it.
// where do you define scene. It should be lowercase
var i, len, mesh;
len = point.length;
if(len > 1) { // check if there are points (2 or more.
shape.moveTo(point[0], point[1]); // do the first point outside the for loop
// this saves having to do the if statement
// for each point
for(i = 2; i < len; i += 2) { // iterate points starting at the second
shape.moveTo(point[i], point[i + 1]); // add the line.
}
You had
// Such a long name for a one of abd just a mess
// Your code
//var ExtrusionSettings = {
// curveSegments: 3,
// bevelThickness:0, bevelSize: 0, bevelEnabled: false,
// material: 0, extrudeMaterial: 1,amount: 10
//};
// unless it will be used again put it inline
// Bad naming for the rest
// Your code
//var Geometry = new THREE.ExtrudeGeometry( Shape, ExtrusionSettings );
//var Material = new THREE.MeshLambertMaterial({color: 0xff8800});
//Material.side = THREE.DoubleSide;
//Mesh = new THREE.Mesh(Geometry,Material);
//Mesh.position.set(0,0,0);
//Scene.add(Mesh);
Replace it all with
// Material is used once so no need to create var for it
// Removed Material.side = THREE.DoubleSide; // assuming this is debug code only
// you had Mesh without var. That made it global scope. Never use a var without defining it first with the var token
var mesh = new THREE.Mesh( // define and assign mesh
new THREE.ExtrudeGeometry( // Create geom// indent arguments for readability
shape,
{ // extrusion settings.
curveSegments : 3, // line it all up so you can read it quickly
bevelThickness : 0,
bevelSize : 0,
bevelEnabled : false,
material : 0,
extrudeMaterial : 1,
amount : 10
}
),
new THREE.MeshLambertMaterial({color: 0xff8800})
);
mesh.position.set(0,0,0); // position the mesh
scene.add(mesh); // add it to the scene
// note the lowercase scene for the object instance scene. Need to chage that where you create it.
} // end of if(len > 1){
There is a lot of pedantic stuff there but you are clearly new to programming and bad habits are hard to break so start with good ones. Bugs and debugging are the worst part of programming. Debugging is the single most time consuming part of all programming (even for experienced professionals). The single biggest cause of bugs in all programing languages is bad style and or messy code. Writing clean consistent code makes your code easier to read and hence easier to debug. Try finding a missing { in 5000 lines of `{''s or a capital where a lowercase character should be (Hours debugging code while the simple error is right in front of you hidden in a mess can make or break being a coder)
Hope this helped..
I am adding "n" number of circles on the scene.
var radius = 1;
var segments = 32;
var circleGeometry = new THREE.CircleGeometry( radius, segments);
function generateCircles(){
//scene.remove(circle);
var count=0;
while (1000> count) {
circle = new THREE.Mesh (circleGeometry, material);
scene.add (circle);
count ++;
}
}
Is it effective to do it this way?.
In my code I call this function, and every time you call it, it all goes back slower, I guess it's because there are more objects in the scene. What can I do?
Each time the function is called, I need to completely erase from the memory stage the circles that were generated.
http://jsfiddle.net/v8oxsxtc/
If you don't need to move or change the circles after adding them to the scene, it would be more efficient to merge them all into one Mesh and add them to the scene as one Mesh. Then, you can simply remove that one Mesh from the scene before generating more circles:
var radius = 1;
var segments = 32;
var circleGeometry = new THREE.CircleGeometry(radius, segments);
var circlesMesh;
function generateCircles() {
if (circlesMesh) { scene.remove(circlesMesh); }
circlesMesh = new THREE.Mesh(circleGeometry, material);
var count = 0;
while (count++ < 999) {
THREE.GeometryUtils.merge(circlesMesh, new THREE.Mesh(circleGeometry, material));
}
scene.add(circlesMesh);
}
I am making a space scene in which I am using a particle system to make group of asteroids,
I want to rotate each asteroids on its axis. I am using following code for making a particle system.
var asteroidGeometry = new THREE.Geometry();
for(var i=0;i<=10000;i++)
{
asteroidGeometry.vertices.push( new THREE.Vector3( Math.random()*10000-5000, Math.random()*10000-5000, Math.random()*10000-5000 ) );
}
var asteroidtexture= THREE.ImageUtils.loadTexture("images/asteroids.png");
var asteroidMaterial = new THREE.ParticleBasicMaterial({color: 'white',size:500,map:asteroidtexture,alphaTest: 0.8});
asteroids = new THREE.ParticleSystem(asteroidGeometry,astroidMaterial);
scene.add(asteroids);
If I will do something like
asteroid.position.x +=0.1;
then this will rotate whole system. Is it possible to rotate each particle on its on axis?
Individual vertices in a THREE.Geometry instance are accessible via its vertices array.
I found a tutorial that explains how to animate particles in a particle system independently. Here's the relevant section of the update animation loop with some minor modifications.
function update() {
var pCount = particleCount;
while (pCount--) {
var particle = particles.vertices[pCount];
if (particle.position.y < -200) {
particle.position.y = 200;
particle.velocity.y = 0;
}
particle.velocity.y -= Math.random() * .1;
particle.position.addSelf(particle.velocity);
}
particleSystem.geometry.__dirtyVertices = true;
renderer.render(scene, camera);
requestAnimFrame(update);
}