import Geometry from '../Geometry';
import BoundingBox from '../math/BoundingBox';
/**
* @constructor clay.geometry.Sphere
* @extends clay.Geometry
* @param {Object} [opt]
* @param {number} [widthSegments]
* @param {number} [heightSegments]
* @param {number} [phiStart]
* @param {number} [phiLength]
* @param {number} [thetaStart]
* @param {number} [thetaLength]
* @param {number} [radius]
*/
var Sphere = Geometry.extend(/** @lends clay.geometry.Sphere# */ {
dynamic: false,
/**
* @type {number}
*/
widthSegments: 40,
/**
* @type {number}
*/
heightSegments: 20,
/**
* @type {number}
*/
phiStart: 0,
/**
* @type {number}
*/
phiLength: Math.PI * 2,
/**
* @type {number}
*/
thetaStart: 0,
/**
* @type {number}
*/
thetaLength: Math.PI,
/**
* @type {number}
*/
radius: 1
}, function() {
this.build();
},
/** @lends clay.geometry.Sphere.prototype */
{
/**
* Build sphere geometry
*/
build: function() {
var heightSegments = this.heightSegments;
var widthSegments = this.widthSegments;
var positionAttr = this.attributes.position;
var texcoordAttr = this.attributes.texcoord0;
var normalAttr = this.attributes.normal;
var vertexCount = (widthSegments + 1) * (heightSegments + 1);
positionAttr.init(vertexCount);
texcoordAttr.init(vertexCount);
normalAttr.init(vertexCount);
var IndicesCtor = vertexCount > 0xffff ? Uint32Array : Uint16Array;
var indices = this.indices = new IndicesCtor(widthSegments * heightSegments * 6);
var x, y, z,
u, v,
i, j;
var radius = this.radius;
var phiStart = this.phiStart;
var phiLength = this.phiLength;
var thetaStart = this.thetaStart;
var thetaLength = this.thetaLength;
var radius = this.radius;
var pos = [];
var uv = [];
var offset = 0;
var divider = 1 / radius;
for (j = 0; j <= heightSegments; j ++) {
for (i = 0; i <= widthSegments; i ++) {
u = i / widthSegments;
v = j / heightSegments;
// X axis is inverted so texture can be mapped from left to right
x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
y = radius * Math.cos(thetaStart + v * thetaLength);
z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
pos[0] = x; pos[1] = y; pos[2] = z;
uv[0] = u; uv[1] = v;
positionAttr.set(offset, pos);
texcoordAttr.set(offset, uv);
pos[0] *= divider;
pos[1] *= divider;
pos[2] *= divider;
normalAttr.set(offset, pos);
offset++;
}
}
var i1, i2, i3, i4;
var len = widthSegments + 1;
var n = 0;
for (j = 0; j < heightSegments; j ++) {
for (i = 0; i < widthSegments; i ++) {
i2 = j * len + i;
i1 = (j * len + i + 1);
i4 = (j + 1) * len + i + 1;
i3 = (j + 1) * len + i;
indices[n++] = i1;
indices[n++] = i2;
indices[n++] = i4;
indices[n++] = i2;
indices[n++] = i3;
indices[n++] = i4;
}
}
this.boundingBox = new BoundingBox();
this.boundingBox.max.set(radius, radius, radius);
this.boundingBox.min.set(-radius, -radius, -radius);
}
});
export default Sphere;