Interactive 3D aquariumOne-line
Nemotron 3 Nano Omni (free)
by NVIDIAReasoning1 console error
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 43.2 s
- Cost
- $0
- Output tokens
- 4,636
- Spent thinking
- 3,503 tokens
- Speed
- 108.3 tok/s
- Console errors
- 1
- First token after
- 403 ms
- First visible text after
- 33.6 s
- Prompt tokens
- 448
- Code size
- 3.7 KB
- Finish reason
- stop
- Served by
- Nvidia
- Model id
nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free- Reasoning sent
model default- Max output
- 32,000 tokens
- Generated
- Nov 9, 2026
Console errors
Caught in the first 3 seconds after load, in a sandboxed iframe like the one above.
(Math.random(...) - 0.5).normalize is not a function
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 · 137 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3D Aquarium</title>
<style>
html,body{margin:0;padding:0;overflow:hidden;background:#000;}
#ui{
position:absolute;top:0;left:0;width:100%;height:100%;
display:flex;align-items:center;justify-content:center;
color:#fff;font-size:24px;background:rgba(0,0,0,0.5);
}
</style>
</head>
<body>
<div id="ui">Click or press a key to start</div>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
// Renderer
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
const renderer = new THREE.WebGLRenderer({canvas, antialias:true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
// Scene
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000088);
// Camera
const camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 100);
camera.position.set(0, 2, 8);
camera.lookAt(0,0,0);
// Ground plane for raycasting
const ground = new THREE.Mesh(
new THREE.PlaneGeometry(200,200),
new THREE.MeshBasicMaterial({color:0x222222})
);
ground.rotation.x = -Math.PI/2;
ground.position.y = -0.01;
scene.add(ground);
// Fish parameters
const fishCount = 12;
const fishes = [];
const fishGeom = new THREE.BoxGeometry(0.3,0.1,0.6);
const fishMat = new THREE.MeshStandardMaterial({color:0xffaa00});
for(let i=0;i<fishCount;i++){
const fish = new THREE.Mesh(fishGeom, fishMat);
// random start position
fish.position.set(
(Math.random()-0.5)*20,
0.5 + Math.random()*5,
(Math.random()-0.5)*20
);
// random speed
fish.userData.speed = 0.02 + Math.random()*0.03;
// initial direction (random)
const dir = new THREE.Vector3(
(Math.random()-0.5),
0,
(Math.random()-0.5).normalize()
).normalize();
fish.userData.direction = dir.clone();
scene.add(fish);
fishes.push({mesh:fish, speed:fish.userData.speed, direction:dir.clone()});
}
// Mouse interaction
let mousePos = new THREE.Vector3();
const raycaster = new THREE.Raycaster();
const plane = new THREE.Plane(new THREE.Vector3(0,1,0), 0); // y = 0 plane
function onMouseMove(event){
const x = (event.clientX / window.innerWidth) * 2 - 1;
const y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(new THREE.Vector2(x,y), camera);
const intersect = new THREE.Vector3();
raycaster.ray.intersectPlane(plane, intersect);
mousePos.copy(intersect);
}
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('touchmove', e=>{
const touch = e.touches[0];
onMouseMove(new MouseEvent('mousemove', {
clientX: touch.clientX,
clientY: touch.clientY
}));
}, false);
// Start UI handling
const startUI = document.getElementById('ui');
canvas.addEventListener('click', ()=>{ startUI.style.display='none'; });
window.addEventListener('keydown', e=>{
if(e.key !== ' ') startUI.style.display='none';
});
// Animation loop
let lastTime = 0;
function animate(time){
const delta = (time - lastTime) / 1000;
lastTime = time;
// Move fish away from mouse
for(const f of fishes){
const dir = f.mesh.position.clone().sub(mousePos).normalize();
f.mesh.position.addScaledVector(dir, f.speed * delta);
// gentle bobbing
f.mesh.position.y = 0.5 + Math.sin(time * 0.001) * 0.2;
}
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
// Resize handling
window.addEventListener('resize', ()=>{
const w = window.innerWidth;
const h = window.innerHeight;
renderer.setSize(w, h);
camera.aspect = w / h;
camera.updateProjectionMatrix();
});
</script>
</body>
</html>Reasoning trace (3,503 tokens)
We need to produce a single HTML file with inline CSS and JS, using import map to load three.js and its addons. The import map must be included as <script type="importmap">. Then we need to load three.module.js via import map. Then we need to create a scene with a camera, renderer, and fish objects (meshes). Fish should swim away when mouse moves near them. So we need to detect mouse position, compute distance to each fish, and apply a repulsion force (maybe change direction or speed). Simpler: each fish has a direction vector; when mouse is near, we invert its direction or apply a push.
We need to ensure the page looks right in 1280x800 and adapt down to 375. So we can set canvas size to window.innerWidth/innerHeight, maybe use CSS to make it fill. Use responsive design.
We need a "Click or press a key to start" message initially, then after click start the demo. The fish should be visible immediately; maybe they are already swimming. The message should disappear on click or keypress.
We need to ensure zero console errors. Use import map, then import { Scene, PerspectiveCamera, WebGLRenderer, Mesh, MeshStandardMaterial, BoxGeometry, SphereGeometry } from 'three'; Actually three.module.js exports everything. In import map we have three and three/addons/. To use addons we need to import from 'three/addons/...' maybe 'three/addons/geometry/BoundingBoxGeometry.js' etc. But for fish we can just use SphereGeometry. For simple fish shape we can use a torus knot or a custom shape? Simpler: use a torus knot (looks like fish). Or use a custom mesh with a shape. But we need fish that swim away when mouse near. Let's use a torus knot geometry (looks like a twisted fish). Or use a custom shape: we can create a simple fish using a cone + sphere. But for demo, we can use a torus knot (makes a fish-like shape). Or use a custom mesh with a shape from examples: 'three/addons/models/Fish.js' maybe not. Let's keep it simple: use a torus knot geometry (makes a spiral shape). Or use a box? Not fish-like. Maybe we can use a custom shape: create a mesh with a torus knot and apply a material.
Simplify: create many fish meshes using a torus knot geometry scaled. Use a simple animation loop where each fish moves forward (its local Z direction). When mouse moves, compute distance and apply a repulsion: set fish direction to opposite of mouse direction (or add a vector pointing away from mouse). Simpler: for each fish, compute direction from fish position to mouse, normalize, and set fish velocity = direction * speed (so fish moves toward mouse? Actually we want fish to swim away, so we need direction from mouse to fish (i.e., fish moves away from mouse). So compute vector = fish.position - mouse.position, normalize, set fish velocity = that * speed.
Implement: store fish data: mesh, speed. In animation loop, for each fish, compute direction = fish.mesh.position.clone().sub(mousePos).normalize(); fish.mesh.position.addScaledVector(direction, fish.speed * delta); Also maybe rotate fish to face direction.
Mouse position: we need to get normalized device coordinates (NDC) from mouse event. On mousemove, store mousePos in world coordinates? Simpler: we can use raycaster to get intersect point on plane? But we can approximate: convert mouse x,y to world x,z (assuming camera looks at -z). Let's set camera looking at -z direction, plane at z=0. Then we can compute mouseXZ = new THREE.Vector3(mouseNDC.x, 0, mouseNDC.y). Then project onto plane z=0: we can use camera.unproject? Simpler: we can use camera.getWorldDirection(ray). Then compute intersection with plane z=0: ray.at(t, intersect); solve for t where intersect.z = 0. Then compute point. But maybe easier: we can use orthographic? Let's do proper: In mousemove, we get clientX/Y, convert to NDC: const x = (event.clientX / window.innerWidth) * 2 - 1; const y = -(event.clientY / window.innerHeight) * 2 + 1; Then create a vector from camera position (0,0,0) through that NDC: const dir = new THREE.Vector3(x, y, 0).normalize(); Actually we need direction from camera to point on near plane (z=0). But we can just use dir = new THREE.Vector3(x, y, 0).normalize(); Then compute point = camera.position.clone().addScaledVector(dir, 10); That's not accurate.
Simplify: Use orthographic camera? But we need perspective.
Maybe easier: we can use raycasting to intersect a plane at y=0 (ground). Let's set a plane at y=0. Then we can compute intersection point. Use camera.getWorldDirection(ray) and camera.position. Then compute intersection: ray.at(t, intersect); solve for t where intersect.y = 0. t = -plane.y / ray.direction.y (if ray.direction.y !=0). Then intersect = ray.at(t). So we get point on ground plane.
We'll create a plane at y=0 (ground). Then on mousemove, compute intersection point on that plane using raycasting. Then for each fish, compute direction = fish.position.clone().sub(intersect).normalize(); fish.position.addScaledVector(direction, fish.speed * delta). Also maybe rotate fish to face direction.
Implement fish as torus knot geometry (makes a twisted shape). Use MeshStandardMaterial with color.
We need to start demo after click or keypress. So initially show a semi-transparent overlay with "Click or press a key to start". When click or keydown occurs, hide overlay and start animation.
We need to ensure the canvas fills the viewport, responsive. Use CSS: #scene { width:100%; height:100vh; } but we need 1280x800 aspect ratio. Maybe set canvas size to width:100%; height:auto; but maintain aspect ratio. Use CSS to set width:100%; height:auto; and container to maintain aspect ratio. Simpler: set canvas width = window.innerWidth, height = window.innerHeight; then camera aspect = width/height. In render loop, set camera.aspect = canvas.width / canvas.height; camera.updateProjectionMatrix();.
We need to ensure no scrollbars: body margin 0; overflow hidden.
Now code structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3D Aquarium</title>
<style>
html,body{margin:0;padding:0;overflow:hidden;background:#000;}
#ui{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:#fff;font-size:24px;background:rgba(0,0,0,0.5);}
</style>
</head>
<body>
<div id="ui">Click or press a key to start</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'; // maybe not needed
// but we can use simple perspective camera, no controls.
// Setup renderer
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
const renderer = new THREE.WebGLRenderer({canvas, antialias:true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
// Scene
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000088); // deep blue
// Camera
const camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 100);
camera.position.set(0, 2, 8);
camera.lookAt(0,0,0);
// Ground plane for raycasting
const ground = new THREE.Mesh(
new THREE.PlaneGeometry(200,200),
new THREE.MeshBasicMaterial({color:0x222222})
);
ground.rotation.x = -Math.PI/2;
ground.position.y = -0.01; // just below fish
scene.add(ground);
// Fish data
const fishCount = 12;
const fishes = [];
const fishGeom = new THREE.TorusKnotGeometry(0.15, 0.07, 100, 16);
const fishMat = new THREE.MeshStandardMaterial({color:0xffaa00});
for(let i=0;i<fishCount;i++){
const fish = new THREE.Mesh(fishGeom, fishMat);
// random position
fish.position.set(
(Math.random()-0.5)*20,
0.5 + Math.random()*5,
(Math.random()-0.5)*20
);
// random speed
fish.userData.speed = 0.02 + Math.random()*0.03;
// random direction initially
const dir = new THREE.Vector3(
(Math.random()-0.5),
0,
(Math.random()-0.5).normalize()
).normalize();
fish.userData.direction = dir.clone();
scene.add(fish);
fishes.push({mesh:fish, speed:fish.userData.speed, direction:dir.clone()});
}
// Mouse interaction
let mousePos = new THREE.Vector3(); // world point on ground plane
const raycaster = new THREE.Raycaster();
const plane = new THREE.Plane(new THREE.Vector3(0,1,0), 0); // y=0 plane
function onMouseMove(event){
// normalize coordinates
const x = (event.clientX / window.innerWidth) * 2 - 1;
const y = -(event.clientY / window.innerHeight) * 2 + 1;
// create ray from camera
raycaster.setFromCamera(new THREE.Vector2(x,y), camera);
// intersect plane y=0
const intersect = new THREE.Vector3();
raycaster.ray.intersectPlane(plane, intersect);
mousePos.copy(intersect);
}
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('touchmove', e=>{ const touch = e.touches[0]; onMouseMove(new MouseEvent('mousemove', {clientX:touch.clientX, clientY:touch.clientY}));}, false);
// Click to start
const startUI = document.getElementById('ui');
canvas.addEventListener('click', ()=>{ startUI.style.display='none'; });
window.addEventListener('keydown', e=>{ if(e.key!==' ') startUI.style.display='none'; });
// Animation loop
let lastTime = 0;
function animate(time){
const delta = (time-lastTime)/1000;
lastTime = time;
// move fish
for(const f of fishes){
// compute direction away from mouse
const dir = f.mesh.position.clone().sub(mousePos).normalize();
// apply movement
f.mesh.position.addScaledVector(dir, f.speed * delta);
// maybe keep fish on ground plane (y ~0.5)
f.mesh.position.y = 0.5 + Math.sin(time*0.001)*0.2; // gentle bobbing
}
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
// Resize handling
window.addEventListener('resize', ()=>{
const w = window.innerWidth;
const h = window.innerHeight;
renderer.setSize(w,h);
camera.aspect = w/h;
camera.updateProjectionMatrix();
});
</script>
</body>
</html>
Need to ensure import map includes three/addons/ but we only need torus knot geometry which is in three/addons? Actually TorusKnotGeometry is in three/examples/jsm/geometries/TorusKnotGeometry.js, which is under three/addons/. So import map entry "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/". That's correct.
But we also need to import OrbitControls maybe not needed. We can remove OrbitControls import.
Potential errors: using three.module.js which exports everything, but we need to import from 'three/addons/...' path. However the import map defines "three/addons/": "...". To import a module from that namespace, we need to use the full path, e.g., import { TorusKnotGeometry } from 'three/addons/geometries/TorusKnotGeometry.js'; But we used import * as THREE from 'three'; then used new THREE.TorusKnotGeometry. That works because three.module.js includes all examples? Actually three.module.js imports everything from examples? I think three.module.js re-exports everything from three and examples. So using THREE.TorusKnotGeometry should work without explicit import. But to be safe, we can import it explicitly: import { TorusKnotGeometry } from 'three/addons/geometries/TorusKnotGeometry.js'; However the import map only maps the folder, not individual files. In import maps, you can import a module by its path relative to the base. So we can do:
import { TorusKnotGeometry } from 'three/addons/geometries/TorusKnotGeometry.js';
But we also need maybe other addons like controls, but not needed.
Simplify: Use a box geometry instead of torus knot to avoid needing addons. BoxGeometry is in core, so we can just use new THREE.BoxGeometry(0.3,0.3,0.6); That's simpler and avoids extra import.
Let's replace fish geometry with BoxGeometry (makes a simple fish shape). Use scaling to look like fish.
So change fishGeom = new THREE.BoxGeometry(0.3,0.1,0.6); Then mesh = new THREE.Mesh(geom, mat); Add random orientation maybe.
Now we don't need addons import. So import map only needs three.
Thus import map:
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js"
}
}
</script>
Now we can remove three/addons import.
Now ensure no console errors: need to ensure that the import map is before any module script. The type="module" script will fetch three module via import map automatically. Should work.
Potential issue: we used 'three/addons/' in import map earlier but we removed. So just three.
Now ensure we hide UI after click or keypress. The UI is a div with id ui. In click handler we set display none. In keydown we set display none if key != ' '. Good.
Now ensure fish move away when mouse near. The direction computed as fish.position - mousePos, normalized, then addScaledVector. That will make fish move away from mouse (if fish is far, direction points away). That's fine.
Potential improvements: keep fish within bounds; maybe clamp positions.
Now ensure page responsive: canvas size set to window.innerWidth/innerHeight. On resize, update renderer size and camera aspect. Also UI overlay covers full screen, but after start it disappears.
Now final code.
Check that everything is inline, no external files. All CSS in <style>. All JS inline in <script type="module">.
Make sure we include <meta charset> etc.
Let's craft final answer.