playcanvas
Version:
PlayCanvas WebGL game engine
183 lines (180 loc) • 7.11 kB
JavaScript
import { Vec3 } from '../../core/math/vec3.js';
import { Geometry } from './geometry.js';
var primitiveUv1Padding = 4.0 / 64;
var primitiveUv1PaddingScale = 1.0 - primitiveUv1Padding * 2;
class ConeBaseGeometry extends Geometry {
constructor(baseRadius, peakRadius, height, heightSegments, capSegments, roundedCaps){
super();
var pos = new Vec3();
var bottomToTop = new Vec3();
var norm = new Vec3();
var top = new Vec3();
var bottom = new Vec3();
var tangent = new Vec3();
var positions = [];
var normals = [];
var uvs = [];
var uvs1 = [];
var indices = [];
var offset;
if (height > 0) {
for(var i = 0; i <= heightSegments; i++){
for(var j = 0; j <= capSegments; j++){
var theta = j / capSegments * 2 * Math.PI - Math.PI;
var sinTheta = Math.sin(theta);
var cosTheta = Math.cos(theta);
bottom.set(sinTheta * baseRadius, -height / 2, cosTheta * baseRadius);
top.set(sinTheta * peakRadius, height / 2, cosTheta * peakRadius);
pos.lerp(bottom, top, i / heightSegments);
bottomToTop.sub2(top, bottom).normalize();
tangent.set(cosTheta, 0, -sinTheta);
norm.cross(tangent, bottomToTop).normalize();
positions.push(pos.x, pos.y, pos.z);
normals.push(norm.x, norm.y, norm.z);
var u = j / capSegments;
var v = i / heightSegments;
uvs.push(u, 1 - v);
var _v = v;
v = u;
u = _v;
u = u * primitiveUv1PaddingScale + primitiveUv1Padding;
v = v * primitiveUv1PaddingScale + primitiveUv1Padding;
u /= 3;
uvs1.push(u, 1 - v);
if (i < heightSegments && j < capSegments) {
var first = i * (capSegments + 1) + j;
var second = i * (capSegments + 1) + (j + 1);
var third = (i + 1) * (capSegments + 1) + j;
var fourth = (i + 1) * (capSegments + 1) + (j + 1);
indices.push(first, second, third);
indices.push(second, fourth, third);
}
}
}
}
if (roundedCaps) {
var latitudeBands = Math.floor(capSegments / 2);
var longitudeBands = capSegments;
var capOffset = height / 2;
for(var lat = 0; lat <= latitudeBands; lat++){
var theta1 = lat * Math.PI * 0.5 / latitudeBands;
var sinTheta1 = Math.sin(theta1);
var cosTheta1 = Math.cos(theta1);
for(var lon = 0; lon <= longitudeBands; lon++){
var phi = lon * 2 * Math.PI / longitudeBands - Math.PI / 2;
var sinPhi = Math.sin(phi);
var cosPhi = Math.cos(phi);
var x = cosPhi * sinTheta1;
var y = cosTheta1;
var z = sinPhi * sinTheta1;
var u1 = 1 - lon / longitudeBands;
var v1 = 1 - lat / latitudeBands;
positions.push(x * peakRadius, y * peakRadius + capOffset, z * peakRadius);
normals.push(x, y, z);
uvs.push(u1, 1 - v1);
u1 = u1 * primitiveUv1PaddingScale + primitiveUv1Padding;
v1 = v1 * primitiveUv1PaddingScale + primitiveUv1Padding;
u1 /= 3;
v1 /= 3;
u1 += 1.0 / 3;
uvs1.push(u1, 1 - v1);
}
}
offset = (heightSegments + 1) * (capSegments + 1);
for(var lat1 = 0; lat1 < latitudeBands; ++lat1){
for(var lon1 = 0; lon1 < longitudeBands; ++lon1){
var first1 = lat1 * (longitudeBands + 1) + lon1;
var second1 = first1 + longitudeBands + 1;
indices.push(offset + first1 + 1, offset + second1, offset + first1);
indices.push(offset + first1 + 1, offset + second1 + 1, offset + second1);
}
}
for(var lat2 = 0; lat2 <= latitudeBands; lat2++){
var theta2 = Math.PI * 0.5 + lat2 * Math.PI * 0.5 / latitudeBands;
var sinTheta2 = Math.sin(theta2);
var cosTheta2 = Math.cos(theta2);
for(var lon2 = 0; lon2 <= longitudeBands; lon2++){
var phi1 = lon2 * 2 * Math.PI / longitudeBands - Math.PI / 2;
var sinPhi1 = Math.sin(phi1);
var cosPhi1 = Math.cos(phi1);
var x1 = cosPhi1 * sinTheta2;
var y1 = cosTheta2;
var z1 = sinPhi1 * sinTheta2;
var u2 = 1 - lon2 / longitudeBands;
var v2 = 1 - lat2 / latitudeBands;
positions.push(x1 * peakRadius, y1 * peakRadius - capOffset, z1 * peakRadius);
normals.push(x1, y1, z1);
uvs.push(u2, 1 - v2);
u2 = u2 * primitiveUv1PaddingScale + primitiveUv1Padding;
v2 = v2 * primitiveUv1PaddingScale + primitiveUv1Padding;
u2 /= 3;
v2 /= 3;
u2 += 2.0 / 3;
uvs1.push(u2, 1 - v2);
}
}
offset = (heightSegments + 1) * (capSegments + 1) + (longitudeBands + 1) * (latitudeBands + 1);
for(var lat3 = 0; lat3 < latitudeBands; ++lat3){
for(var lon3 = 0; lon3 < longitudeBands; ++lon3){
var first2 = lat3 * (longitudeBands + 1) + lon3;
var second2 = first2 + longitudeBands + 1;
indices.push(offset + first2 + 1, offset + second2, offset + first2);
indices.push(offset + first2 + 1, offset + second2 + 1, offset + second2);
}
}
} else {
offset = (heightSegments + 1) * (capSegments + 1);
if (baseRadius > 0) {
for(var i1 = 0; i1 < capSegments; i1++){
var theta3 = i1 / capSegments * 2 * Math.PI;
var x2 = Math.sin(theta3);
var y2 = -height / 2;
var z2 = Math.cos(theta3);
var u3 = 1 - (x2 + 1) / 2;
var v3 = (z2 + 1) / 2;
positions.push(x2 * baseRadius, y2, z2 * baseRadius);
normals.push(0, -1, 0);
uvs.push(u3, 1 - v3);
u3 = u3 * primitiveUv1PaddingScale + primitiveUv1Padding;
v3 = v3 * primitiveUv1PaddingScale + primitiveUv1Padding;
u3 /= 3;
v3 /= 3;
u3 += 1 / 3;
uvs1.push(u3, 1 - v3);
if (i1 > 1) {
indices.push(offset, offset + i1, offset + i1 - 1);
}
}
}
offset += capSegments;
if (peakRadius > 0) {
for(var i2 = 0; i2 < capSegments; i2++){
var theta4 = i2 / capSegments * 2 * Math.PI;
var x3 = Math.sin(theta4);
var y3 = height / 2;
var z3 = Math.cos(theta4);
var u4 = 1 - (x3 + 1) / 2;
var v4 = (z3 + 1) / 2;
positions.push(x3 * peakRadius, y3, z3 * peakRadius);
normals.push(0, 1, 0);
uvs.push(u4, 1 - v4);
u4 = u4 * primitiveUv1PaddingScale + primitiveUv1Padding;
v4 = v4 * primitiveUv1PaddingScale + primitiveUv1Padding;
u4 /= 3;
v4 /= 3;
u4 += 2 / 3;
uvs1.push(u4, 1 - v4);
if (i2 > 1) {
indices.push(offset, offset + i2 - 1, offset + i2);
}
}
}
}
this.positions = positions;
this.normals = normals;
this.uvs = uvs;
this.uvs1 = uvs1;
this.indices = indices;
}
}
export { ConeBaseGeometry };