import Geometry from '../Geometry';
import BoundingBox from '../math/BoundingBox';
import vec3 from '../glmatrix/vec3';
import vec2 from '../glmatrix/vec2';
/**
* @constructor clay.geometry.Cone
* @extends clay.Geometry
* @param {Object} [opt]
* @param {number} [opt.topRadius]
* @param {number} [opt.bottomRadius]
* @param {number} [opt.height]
* @param {number} [opt.capSegments]
* @param {number} [opt.heightSegments]
*/
var Cone = Geometry.extend(/** @lends clay.geometry.Cone# */ {
dynamic: false,
/**
* @type {number}
*/
topRadius: 0,
/**
* @type {number}
*/
bottomRadius: 1,
/**
* @type {number}
*/
height: 2,
/**
* @type {number}
*/
capSegments: 20,
/**
* @type {number}
*/
heightSegments: 1
}, function() {
this.build();
},
/** @lends clay.geometry.Cone.prototype */
{
/**
* Build cone geometry
*/
build: function() {
var positions = [];
var texcoords = [];
var faces = [];
positions.length = 0;
texcoords.length = 0;
faces.length = 0;
// Top cap
var capSegRadial = Math.PI * 2 / this.capSegments;
var topCap = [];
var bottomCap = [];
var r1 = this.topRadius;
var r2 = this.bottomRadius;
var y = this.height / 2;
var c1 = vec3.fromValues(0, y, 0);
var c2 = vec3.fromValues(0, -y, 0);
for (var i = 0; i < this.capSegments; i++) {
var theta = i * capSegRadial;
var x = r1 * Math.sin(theta);
var z = r1 * Math.cos(theta);
topCap.push(vec3.fromValues(x, y, z));
x = r2 * Math.sin(theta);
z = r2 * Math.cos(theta);
bottomCap.push(vec3.fromValues(x, -y, z));
}
// Build top cap
positions.push(c1);
// FIXME
texcoords.push(vec2.fromValues(0, 1));
var n = this.capSegments;
for (var i = 0; i < n; i++) {
positions.push(topCap[i]);
// FIXME
texcoords.push(vec2.fromValues(i / n, 0));
faces.push([0, i+1, (i+1) % n + 1]);
}
// Build bottom cap
var offset = positions.length;
positions.push(c2);
texcoords.push(vec2.fromValues(0, 1));
for (var i = 0; i < n; i++) {
positions.push(bottomCap[i]);
// FIXME
texcoords.push(vec2.fromValues(i / n, 0));
faces.push([offset, offset+((i+1) % n + 1), offset+i+1]);
}
// Build side
offset = positions.length;
var n2 = this.heightSegments;
for (var i = 0; i < n; i++) {
for (var j = 0; j < n2+1; j++) {
var v = j / n2;
positions.push(vec3.lerp(vec3.create(), topCap[i], bottomCap[i], v));
texcoords.push(vec2.fromValues(i / n, v));
}
}
for (var i = 0; i < n; i++) {
for (var j = 0; j < n2; j++) {
var i1 = i * (n2 + 1) + j;
var i2 = ((i + 1) % n) * (n2 + 1) + j;
var i3 = ((i + 1) % n) * (n2 + 1) + j + 1;
var i4 = i * (n2 + 1) + j + 1;
faces.push([offset+i2, offset+i1, offset+i4]);
faces.push([offset+i4, offset+i3, offset+i2]);
}
}
this.attributes.position.fromArray(positions);
this.attributes.texcoord0.fromArray(texcoords);
this.initIndicesFromArray(faces);
this.generateVertexNormals();
this.boundingBox = new BoundingBox();
var r = Math.max(this.topRadius, this.bottomRadius);
this.boundingBox.min.set(-r, -this.height/2, -r);
this.boundingBox.max.set(r, this.height/2, r);
}
});
export default Cone;