xxxxxxxxxx
132
let m;
function setup() {
createCanvas(300, 300, WEBGL);
// bottomRadius, topRadius, height, detailX, detailY, bottomCap, topCap
m = createTruncatedCone(100, 50, 70, 60, 1, true, true);
noStroke();
fill(255, 222, 0);
}
function draw() {
background(0);
orbitControl(5, 5, 5);
rotateZ(frameCount * 0.01);
rotateX(frameCount * 0.01);
rotateY(frameCount * 0.01);
pointLight(255, 255, 0, -width/2, -height/2, 100);
pointLight(255, 255, 0, width/2, -height/2,100);
pointLight(255, 255, 0, width/2, height/2, 100);
pointLight(255, 255, 0, -width/2, height/2, 100);
model(m)
}
function createTruncatedCone(bottomRadius, topRadius, height, detailX, detailY, bottomCap, topCap) {
return new p5.Geometry(
detailX,
detailY,
function () {
bottomRadius = bottomRadius <= 0 ? 1 : bottomRadius;
topRadius = topRadius < 0 ? 0 : topRadius;
height = height <= 0 ? bottomRadius : height;
detailX = detailX < 3 ? 3 : detailX;
detailY = detailY < 1 ? 1 : detailY;
bottomCap = bottomCap === undefined ? true : bottomCap;
topCap = topCap === undefined ? topRadius !== 0 : topCap;
const start = bottomCap ? -2 : 0;
const end = detailY + (topCap ? 2 : 0);
//ensure constant slant for interior vertex normals
const slant = Math.atan2(bottomRadius - topRadius, height);
const sinSlant = Math.sin(slant);
const cosSlant = Math.cos(slant);
let yy, ii, jj;
for (yy = start; yy <= end; ++yy) {
let v = yy / detailY;
let y = height * v;
let ringRadius;
if (yy < 0) {
//for the bottomCap edge
y = 0;
v = 0;
ringRadius = bottomRadius;
} else if (yy > detailY) {
//for the topCap edge
y = height;
v = 1;
ringRadius = topRadius;
} else {
//for the middle
ringRadius = bottomRadius + (topRadius - bottomRadius) * v;
}
if (yy === -2 || yy === detailY + 2) {
//center of bottom or top caps
ringRadius = 0;
}
y -= height / 2; //shift coordiate origin to the center of object
for (ii = 0; ii < detailX; ++ii) {
const u = ii / (detailX - 1);
const ur = 2 * Math.PI * u;
const sur = Math.sin(ur);
const cur = Math.cos(ur);
//VERTICES
this.vertices.push(new p5.Vector(sur * ringRadius, y, cur * ringRadius));
//VERTEX NORMALS
let vertexNormal;
if (yy < 0) {
vertexNormal = new p5.Vector(0, -1, 0);
} else if (yy > detailY && topRadius) {
vertexNormal = new p5.Vector(0, 1, 0);
} else {
vertexNormal = new p5.Vector(sur * cosSlant, sinSlant, cur * cosSlant);
}
this.vertexNormals.push(vertexNormal);
//UVs
this.uvs.push(u, v);
}
}
let startIndex = 0;
if (bottomCap) {
for (jj = 0; jj < detailX; ++jj) {
const nextjj = (jj + 1) % detailX;
this.faces.push([
startIndex + jj,
startIndex + detailX + nextjj,
startIndex + detailX + jj,
]);
}
startIndex += detailX * 2;
}
for (yy = 0; yy < detailY; ++yy) {
for (ii = 0; ii < detailX; ++ii) {
const nextii = (ii + 1) % detailX;
this.faces.push([
startIndex + ii,
startIndex + nextii,
startIndex + detailX + nextii,
]);
this.faces.push([
startIndex + ii,
startIndex + detailX + nextii,
startIndex + detailX + ii,
]);
}
startIndex += detailX;
}
if (topCap) {
startIndex += detailX;
for (ii = 0; ii < detailX; ++ii) {
this.faces.push([
startIndex + ii,
startIndex + ((ii + 1) % detailX),
startIndex + detailX,
]);
}
}
}
);
}