Creating a rotating 3D donut involves a more complex mathematical representation than a simple cube. Below is an example of a JavaScript program that generates a rotating 3D donut using HTML5 canvas and JavaScript. The code is based on a well-known donut algorithm called the "donut.c" by Andy Sloane.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
canvas {
display: block;
margin: auto;
border: 1px solid #000;
}
</style>
<title>3D Rotating Donut</title>
</head>
<body>
<canvas id="donutCanvas" width="800" height="800"></canvas>
<script>
const canvas = document.getElementById('donutCanvas');
const ctx = canvas.getContext('2d');
const donut = {
chars: ".,-~:;=!*#$@", // characters to represent the donut
thetaSpacing: 0.07,
phiSpacing: 0.02,
width: 40,
height: 20,
time: 0
};
function drawDonut() {
const { chars, thetaSpacing, phiSpacing, width, height, time } = donut;
const output = [];
const cosTime = Math.cos(time);
const sinTime = Math.sin(time);
for (let j = 0; j < height; j++) {
const phi = j * phiSpacing;
const costheta = Math.cos(phi);
const sintheta = Math.sin(phi);
for (let i = 0; i < width; i++) {
const theta = i * thetaSpacing;
const costheta2 = Math.cos(theta);
const sintheta2 = Math.sin(theta);
const circleX = costheta2;
const circleY = sintheta2;
const x = circleX * (cosTime * 0.5 + 1) * 40;
const y = circleY * (sinTime * 0.5 + 1) * 20;
const z = circleX * (sinTime * 0.5 + 1) * 40 + circleY * (cosTime * 0.5 + 1) * 20;
const ooz = 1 / z;
const xp = Math.round(canvas.width / 2 + x * ooz);
const yp = Math.round(canvas.height / 2 - y * ooz);
const idx = Math.floor((theta + phi) * 0.01) % chars.length;
const char = chars[idx];
if (!output[j]) {
output[j] = [];
}
output[j][i] = { xp, yp, char };
}
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let j = 0; j < height; j++) {
if (output[j]) {
for (let i = 0; i < width; i++) {
if (output[j][i] && output[j][i].char !== ' ') {
ctx.fillStyle = '#fff';
ctx.fillText(output[j][i].char, output[j][i].xp, output[j][i].yp);
}
}
}
}
}
function update() {
donut.time += 0.05;
drawDonut();
requestAnimationFrame(update);
}
update();
</script>
</body>
</html>
```
This code generates a 3D donut and continuously rotates it on the canvas. The donut's shape is represented using ASCII characters. Adjust the parameters in the `donut` object to modify the donut's appearance and rotation speed.