mrdoob/three.js — Issue #1078: Creating own Geometry class?
Author: VelvetValve
Created: 2012-01-11 22:05:35+00:00
State: open

hey knowledgeable folks,

I have a question to ask to you, concerning the Geometry class and its derivates:

What do I have to take into account if I want to design my own Geometry-subclass (just like CubeGeometry.js, SphereGeometry.js etc.) and especially: in what order are the vertices stored inside the Geometry-own vertices-array resp. what order do the vertex-indices have inside the array?

I am computing the vertices of my new geometry with polar coordinates by running through 2 for-loops that in turn increment the respective phi angle (around z-axis) and theta angle (around y-axis) from which the radius of the respective vertex is computed (with a formula). After that I push the respective vertex into the Geometry's inner vertices-array. Coordinates are all valid and vertices are successfully pushed into the array, but my problem is that their indices seem to be in an order that I do not quite understand yet.

As the order of the vertex-indices is crucial for the correct arrangement of faces (obviously), I would be very happy if one of you skillful guys could tell me - after looking at my code - in what order I have to imagine the vertices and arrange them in the respective faces. Here is the code that lies in the file src/extras/geometries/MyGeometry.js:

THREE.MyGeometry = function ( params, phi_range, phi_res, theta_range, theta_res ) {

THREE.Geometry.call( this );

var scope = this;

// here some for the issue irrelevant stuff was commented out
this.params = default_settings;

this.phi_range = phi_range || 180.0;
this.phi_res = phi_res || 180.0;

this.theta_range = theta_range || 360.0;
this.theta_res = theta_res || 360.0;

var uvs = [];

function radius(phi, params...) {
... working fine!
}

function getVertexOfSuperShape(theta, params..., phi, params...) {
var cos_theta = Math.cos(theta),
sin_theta = Math.sin(theta),
cos_phi = Math.cos(phi),
sin_phi = Math.sin(phi),
radius_theta = radius(theta, params...),
radius_phi = radius(phi, params...),
x = radius_theta * cos_theta * radius_phi * cos_phi,
y = radius_theta * sin_theta * radius_phi * cos_phi,
z = radius_phi * sin_phi;

return new THREE.Vector3(x, y, z).multiplyScalar(100);
}

var phi_step_size = this.phi_range / this.phi_res;
var theta_step_size = this.theta_range / this.theta_res;

for (var phi_i = 0; phi_i < this.phi_res; phi_i++) {
var phi = -(this.phi_range / 2) + phi_i * phi_step_size;

for (var theta_i = 0; theta_i < this.theta_res; theta_i++) {
var theta = -(this.theta_range / 2) + theta_i * theta_step_size;
var vector = getVertexOfSuperShape(theta, params, phi, params);

this.vertices.push(new THREE.Vertex(vector));

// I AM QUITE UNSURE ABOUT HOW TO COMPUTE THE RIGHT UVs
uvs.push( new THREE.UV( theta_i / this.theta_res, 1 - phi_i / this.phi_res ) );
}
}

for (var phi_i = 0; phi_i < this.phi_res; phi_i++) {
for (var theta_i = 0; theta_i < this.theta_res; theta_i++) {
var next_phi_i, next_theta_i;

if (phi_i = this.phi_res - 1) {
next_phi_i = 0;
}
else {
next_phi_i = phi_i + 1;
}

if (theta_i = this.theta_res - 1) {
next_theta_i = 0;
}
else {
next_theta_i = theta_i + 1;
}

var a = phi_i * this.theta_res + theta_i;
var b = phi_i * this.theta_res + next_theta_i;
var c = next_phi_i * this.theta_res + theta_i;

var face = new THREE.Face3(a, b, c);
this.faces.push( face );

this.faceVertexUvs[ 0 ].push( [ uvs[ a ].clone(), uvs[ b ].clone(), uvs[ c ].clone()] );
}
}

this.computeCentroids();

};

THREE.MyGeometry.prototype = new THREE.Geometry();
THREE.MyGeometry.prototype.constructor = THREE.MyGeometry;

I would really be happy if someone could give me a hint at this and I am always happy about tips about whatelse to consider when making a stable new geometry class (concerning normals, uvs etc.!)

Thanks a lot in advance! :)

VelvetValve