Interactive 3D aquariumOne-line
Nemotron 3.5 Super VL (free)
by NVIDIAReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 37.1 s
- Cost
- $0
- Output tokens
- 4,451
- Spent thinking
- 0 tokens
- Speed
- 121.2 tok/s
- Console errors
- 0
- First token after
- 356 ms
- First visible text after
- 356 ms
- Prompt tokens
- 448
- Code size
- 13.5 KB
- Finish reason
- stop
- Served by
- Nvidia
- Model id
nvidia/nemotron-3.5-super-vl:free- Reasoning sent
{"effort":"none"}- Max output
- 32,000 tokens
- Generated
- Nov 9, 2026
What it was asked
The prompt
“a 3D aquarium with Three.js where the fish swim away when I move the mouse near them (Load Three.js only through this import map: <script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}</script>)”
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task. Output rules: - Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block. - Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task. - Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw. - The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar. - Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction. - Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session. - Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing. - The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message. - The code must run with zero errors in the console of the latest Chrome.
Code run-1.html · 463 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Aquarium - Mouse Repellent Fish</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { overflow: hidden; background: #050510; font-family: system-ui, sans-serif; }
#canvas {
position: absolute;
top: 0; left: 0;
width: 100vw; height: 100vh;
display: block;
}
#ui {
position: absolute;
top: 0; left: 0;
width: 100%;
height: 100%;
pointer-events: none;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
text-align: center;
z-index: 10;
}
#hint {
background: rgba(10, 20, 40, 0.75);
padding: 1rem 1.5rem;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.15);
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
}
#hint h1 { font-size: 1.6rem; margin-bottom: 0.25rem; font-weight: 600; letter-spacing: 0.5px; }
#hint p { font-size: 0.9rem; opacity: 0.85; line-height: 1.4; }
#stat {
position: absolute;
top: 12px; left: 12px;
color: rgba(255,255,255,0.7);
font-size: 0.85rem;
pointer-events: none;
z-index: 10;
}
</style>
</head>
<body>
<div id="canvas"></div>
<div id="ui">
<div id="hint">
<h1>3D Aquarium</h1>
<p>Move your mouse near the fish to scare them away</p>
</div>
</div>
<div id="stat">Fish: <span id="fishCount">12</span></div>
<script type="importmap">
{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// Resize-safe container
const container = document.getElementById('canvas');
const hint = document.getElementById('hint');
const hintTitle = hint.querySelector('h1');
const hintText = hint.querySelector('p');
// Scene setup
const scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x050510, 0.018);
const camera = new THREE.PerspectiveCamera(55, innerWidth / innerHeight, 0.1, 100);
camera.position.set(0, 2, 8);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(innerWidth, innerHeight);
renderer.setClearColor(0x050510, 1);
container.appendChild(renderer.domElement);
// Controls (subtle)
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.enableZoom = false;
controls.enablePan = false;
controls.autoRotate = true;
controls.autoRotateSpeed = 0.4;
controls.minPolarAngle = Math.PI / 2 - 1.2;
controls.maxPolarAngle = Math.PI / 2 + 0.6;
// Lights
const ambient = new THREE.AmbientLight(0xffffff, 0.35);
scene.add(ambient);
const dirLight = new THREE.DirectionalLight(0xffffff, 1.0);
dirLight.position.set(5, 10, 7);
scene.add(dirLight);
const pointLight = new THREE.PointLight(0x00ffff, 1.5, 12);
pointLight.position.set(0, 0, 0);
scene.add(pointLight);
// Bubbles helper
function createBubbles(count, range) {
const geo = new THREE.SphereGeometry(0.02, 6, 6);
const mat = new THREE.MeshStandardMaterial({ color: 0xffffff, transparent: true, opacity: 0.6 });
const group = new THREE.Group();
for (let i = 0; i < count; i++) {
const m = new THREE.Mesh(geo, mat);
m.position.set(
(Math.random() - 0.5) * range * 2,
Math.random() * range,
(Math.random() - 0.5) * range * 2
);
m.userData = { speed: 0.01 + Math.random() * 0.02, yRange: range };
group.add(m);
}
scene.add(group);
return group;
}
const bubbleGroup = createBubbles(40, 6);
// Floor
const floorGeo = new THREE.PlaneGeometry(30, 30);
const floorMat = new THREE.MeshStandardMaterial({
color: 0x0a1426,
roughness: 0.8,
metalness: 0.1,
transparent: true,
opacity: 0.5
});
const floor = new THREE.Mesh(floorGeo, floorMat);
floor.rotation.x = -Math.PI / 2;
floor.position.y = -4;
scene.add(floor);
// Tank decoration: coral-ish simple torus
function addCoral(x, z, color) {
const geo = new THREE.TorusKnotGeometry(0.15, 0.04, 60, 16);
const mat = new THREE.MeshStandardMaterial({ color, roughness: 0.7 });
const m = new THREE.Mesh(geo, mat);
m.position.set(x, -3.6, z);
m.scale.set(0.6, 0.6, 0.6);
scene.add(m);
}
addCoral(-6, -4, 0xff3366);
addCoral(6, -4, 0x33ff99);
addCoral(-4, 4, 0x3399ff);
addCoral(4, 4, 0xffcc00);
// Fish class
class Fish {
constructor() {
// Build fish geometry (body + tail + fins)
const group = new THREE.Group();
// Body: stretched sphere
const bodyGeo = new THREE.SphereGeometry(0.25, 16, 16);
const bodyMat = new THREE.MeshStandardMaterial({
color: new THREE.Color().setHSL(Math.random(), 0.7, 0.5),
roughness: 0.4,
metalness: 0.1
});
this.body = new THREE.Mesh(bodyGeo, bodyMat);
this.body.scale.set(1.4, 0.8, 0.6);
group.add(this.body);
// Tail
const tailGeo = new THREE.ConeGeometry(0.15, 0.5, 4);
const tailMat = new THREE.MeshStandardMaterial({ color: this.body.material.color, transparent: true, opacity: 0.8 });
this.tail = new THREE.Mesh(tailGeo, tailMat);
this.tail.position.set(-0.35, 0, 0);
this.tail.rotation.z = Math.PI / 2;
group.add(this.tail);
// Top fin
const finGeo = new THREE.ConeGeometry(0.1, 0.3, 4);
const finMat = new THREE.MeshStandardMaterial({ color: 0x222222, transparent: true, opacity: 0.6 });
this.fin = new THREE.Mesh(finGeo, finMat);
this.fin.position.set(0, 0.15, 0);
this.fin.rotation.x = -Math.PI / 4;
group.add(this.fin);
// Eye
const eyeGeo = new THREE.SphereGeometry(0.04, 8, 8);
const eyeMat = new THREE.MeshBasicMaterial({ color: 0xffffff });
this.eye = new THREE.Mesh(eyeGeo, eyeMat);
this.eye.position.set(0.25, 0.08, 0.22);
group.add(this.eye);
scene.add(group);
this.mesh = group;
// State
this.position = new THREE.Vector3(
(Math.random() - 0.5) * 12,
(Math.random() - 0.5) * 4,
(Math.random() - 0.5) * 12
);
this.velocity = new THREE.Vector3();
this.acceleration = new THREE.Vector3();
this.maxSpeed = 0.06 + Math.random() * 0.04;
this.maxForce = 0.002;
this.neighborRadius = 2;
this.desiredSeparation = 1.2;
// Facing
const angle = Math.random() * Math.PI * 2;
this.velocity.set(Math.cos(angle), 0, Math.sin(angle)).normalize().multiplyScalar(this.maxSpeed * 0.5);
this.mesh.position.copy(this.position);
this.updateOrientation();
}
updateOrientation() {
if (this.velocity.lengthSq() > 0.0001) {
this.mesh.lookAt(this.position.clone().add(this.velocity));
// Roll based on turn
this.mesh.rotateX(Math.PI / 2); // fish model faces -Z by default? adjust
}
}
applyBehaviors(fishies, mousePos, repelRange) {
const sep = this.separate(fishies);
const ali = this.align(fishies);
const coh = this.cohesion(fishies);
const flee = this.flee(mousePos, repelRange);
sep.multiplyScalar(1.5);
ali.multiplyScalar(1.0);
coh.multiplyScalar(1.0);
flee.multiplyScalar(2.0);
this.applyForce(sep);
this.applyForce(ali);
this.applyForce(coh);
this.applyForce(flee);
// Boundary soft steer
const boundary = 10;
const steer = new THREE.Vector3();
if (Math.abs(this.position.x) > boundary) steer.x = -Math.sign(this.position.x) * 0.003;
if (Math.abs(this.position.z) > boundary) steer.z = -Math.sign(this.position.z) * 0.003;
if (this.position.y > 2.5) steer.y = -0.003;
if (this.position.y < -5.5) steer.y = 0.003;
this.applyForce(steer);
// Random wander jitter
if (Math.random() < 0.02) {
this.applyForce(new THREE.Vector3(
(Math.random() - 0.5) * 0.001,
(Math.random() - 0.5) * 0.001,
(Math.random() - 0.5) * 0.001
));
}
this.velocity.add(this.acceleration);
const speed = this.velocity.length();
if (speed > this.maxSpeed) this.velocity.setLength(this.maxSpeed);
this.position.add(this.velocity);
this.acceleration.set(0, 0, 0);
// Keep within bounds
this.position.x = Math.max(-11, Math.min(11, this.position.x));
this.position.z = Math.max(-11, Math.min(11, this.position.z));
this.position.y = Math.max(-5.8, Math.min(2.8, this.position.y));
this.mesh.position.copy(this.position);
this.updateOrientation();
// Animate tail/body swim based on speed
const swim = speed * 20;
this.tail.rotation.z = Math.PI / 2 + Math.sin(Date.now() * 0.015 * swim) * 0.3;
this.body.scale.y = 0.8 + Math.sin(Date.now() * 0.015 * swim) * 0.05;
}
applyForce(force) {
this.acceleration.add(force);
}
separate(fishies) {
const steer = new THREE.Vector3();
let count = 0;
for (let other of fishies) {
const d = this.position.distanceTo(other.position);
if (d > 0 && d < this.desiredSeparation) {
const diff = new THREE.Vector3().subVectors(this.position, other.position).normalize().divideScalar(d);
steer.add(diff);
count++;
}
}
if (count > 0) {
steer.divideScalar(count);
if (steer.lengthSq() > 0) {
steer.normalize().multiplyScalar(this.maxSpeed).sub(this.velocity).clampLength(0, this.maxForce);
}
}
return steer;
}
align(fishies) {
const steer = new THREE.Vector3();
let count = 0;
for (let other of fishies) {
const d = this.position.distanceTo(other.position);
if (d > 0 && d < this.neighborRadius) {
steer.add(other.velocity);
count++;
}
}
if (count > 0) {
steer.divideScalar(count);
steer.normalize().multiplyScalar(this.maxSpeed).sub(this.velocity).clampLength(0, this.maxForce);
}
return steer;
}
cohesion(fishies) {
const steer = new THREE.Vector3();
let count = 0;
for (let other of fishies) {
const d = this.position.distanceTo(other.position);
if (d > 0 && d < this.neighborRadius) {
steer.add(other.position);
count++;
}
}
if (count > 0) {
steer.divideScalar(count);
steer.sub(this.position);
if (steer.lengthSq() > 0) {
steer.normalize().multiplyScalar(this.maxSpeed).sub(this.velocity).clampLength(0, this.maxForce);
}
}
return steer;
}
flee(mousePos, range) {
const steer = new THREE.Vector3();
const d = this.position.distanceTo(mousePos);
if (d > 0 && d < range) {
const diff = new THREE.Vector3().subVectors(this.position, mousePos).normalize().divideScalar(d);
steer.add(diff);
steer.normalize().multiplyScalar(this.maxSpeed * 1.5).sub(this.velocity).clampLength(0, this.maxForce * 2);
}
return steer;
}
}
// Init fish
const fishCount = 14;
const fishies = [];
for (let i = 0; i < fishCount; i++) fishies.push(new Fish());
document.getElementById('fishCount').textContent = fishCount;
// Mouse state
const mouse = new THREE.Vector2(-100, -100); // start off-screen
const mouse3D = new THREE.Vector3(-100, 0, -100);
const repelRange = 3.5;
let pointerActive = false;
window.addEventListener('mousemove', (e) => {
pointerActive = true;
hint.style.opacity = '0';
setTimeout(() => { hint.style.display = 'none'; }, 400);
// Normalize mouse to -1..1
mouse.x = (e.clientX / innerWidth) * 2 - 1;
mouse.y = -(e.clientY / innerHeight) * 2 + 1;
// Unproject to world plane at y=0 roughly
mouse3D.set(mouse.x, mouse.y, 0.5);
mouse3D.unproject(camera);
// Project onto y=0 plane from camera
const dir = new THREE.Vector3().subVectors(mouse3D, camera.position).normalize();
const dist = -camera.position.y / dir.y;
mouse3D.copy(camera.position).addScaledVector(dir, dist);
mouse3D.y = 0;
});
// Touch support
window.addEventListener('touchmove', (e) => {
if (e.touches.length === 0) return;
pointerActive = true;
hint.style.opacity = '0';
setTimeout(() => { hint.style.display = 'none'; }, 400);
const t = e.touches[0];
mouse.x = (t.clientX / innerWidth) * 2 - 1;
mouse.y = -(t.clientY / innerHeight) * 2 + 1;
mouse3D.set(mouse.x, mouse.y, 0.5);
mouse3D.unproject(camera);
const dir = new THREE.Vector3().subVectors(mouse3D, camera.position).normalize();
const dist = -camera.position.y / dir.y;
mouse3D.copy(camera.position).addScaledVector(dir, dist);
mouse3D.y = 0;
}, { passive: true });
// Hide hint after a few seconds even without interaction
setTimeout(() => {
if (!pointerActive) {
hint.style.transition = 'opacity 0.5s';
hint.style.opacity = '0';
setTimeout(() => { hint.style.display = 'none'; }, 500);
}
}, 4000);
// Animation loop
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const dt = clock.getDelta();
const time = clock.getElapsedTime();
// Subtle camera breathing
camera.position.y = 2 + Math.sin(time * 0.3) * 0.3;
camera.lookAt(0, -0.5, 0);
controls.update();
// Bubbles rise
bubbleGroup.children.forEach(b => {
b.position.y += b.userData.speed;
b.position.x += Math.sin(time + b.position.y) * 0.002;
b.position.z += Math.cos(time * 0.7 + b.position.z) * 0.002;
if (b.position.y > 7) b.position.y = -4;
b.material.opacity = 0.3 + Math.sin(time * 2 + b.position.y) * 0.2;
});
// Point light drift
pointLight.position.set(Math.sin(time * 0.5) * 4, 2 + Math.sin(time * 0.7) * 1, Math.cos(time * 0.5) * 4);
// Fish
fishies.forEach(f => f.applyBehaviors(fishies, mouse3D, repelRange));
renderer.render(scene, camera);
}
// Resize
window.addEventListener('resize', () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
// Start
animate();
</script>
</body>
</html>