Models 44

Qwen3 Coder Next

by Qwenreasoning defaultClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
40.8 s
Cost
$0.0033
Output tokens
4,068
Spent thinking
0 tokens
Speed
101 tok/s
Console errors
0
First token after
537 ms
First visible text after
537 ms
Prompt tokens
569
Code size
15.1 KB
Finish reason
stop
Served by
Parasail
Model id
qwen/qwen3-coder-next
Reasoning sent
model default
Max output
235,929 tokens
Generated
Nov 13, 2026

What it was asked

The prompt
Build a low-poly 3D scene of a campfire in a forest clearing at night, with Three.js in a single HTML file. Load Three.js only through this import map (do not use any other URL or version): <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> Requirements: - A ground with a few low-poly rocks and logs around a campfire in the center. - At least 30 low-poly trees placed randomly around the clearing (not on the fire). - The campfire has animated flames and a warm point light that flickers and casts shadows. - Sparks rising from the fire as a simple particle system. - A dark night sky with stars and a moon, plus fog that fades the distant trees. - OrbitControls to look around, with limits so the camera stays above the ground. - The renderer fills the window and handles resizing correctly.
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 · 414 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Low Poly Campfire - Three.js</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background-color: #050510;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            color: #ffffff;
        }
        canvas {
            display: block;
        }
        #loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 24px;
            font-weight: bold;
            text-align: center;
            pointer-events: none;
            transition: opacity 0.5s;
        }
        #instruction {
            position: absolute;
            bottom: 20px;
            left: 0;
            width: 100%;
            text-align: center;
            pointer-events: none;
            font-size: 14px;
            text-shadow: 1px 1px 2px black;
            opacity: 0.7;
        }
        h1 {
            margin: 0;
            font-size: 1.5rem;
            color: #ffccaa;
        }
    </style>
</head>
<body>
    <div id="loading">
        <h1>Building the Campfire...</h1>
        <p>Generating low-poly environment</p>
    </div>
    <div id="instruction">Left Click: Rotate | Right Click: Pan | Scroll: Zoom</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';

        // --- Configuration ---
        const SCENE_CONFIG = {
            fogColor: 0x050510,
            groundColor: 0x1a1a20,
            treeCount: 35,
            rockCount: 8,
            logCount: 6,
            sparkCount: 100
        };

        // --- Scene Setup ---
        const scene = new THREE.Scene();
        scene.background = new THREE.Color(SCENE_CONFIG.fogColor);
        scene.fog = new THREE.FogExp2(SCENE_CONFIG.fogColor, 0.02);

        const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100);
        camera.position.set(12, 8, 12);

        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.shadowMap.enabled = true;
        renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        document.body.appendChild(renderer.domElement);

        // --- Controls ---
        const controls = new OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;
        controls.dampingFactor = 0.05;
        controls.minDistance = 5;
        controls.maxDistance = 30;
        controls.maxPolarAngle = Math.PI / 2 - 0.1; // Prevent going under ground
        controls.target.set(0, 0, 0);

        // --- Lighting ---
        const ambientLight = new THREE.AmbientLight(0x111111, 1.5); // Dark ambient
        scene.add(ambientLight);

        const moonLight = new THREE.DirectionalLight(0xaaccff, 1.0);
        moonLight.position.set(-10, 20, -10);
        moonLight.castShadow = true;
        moonLight.shadow.mapSize.width = 1024;
        moonLight.shadow.mapSize.height = 1024;
        scene.add(moonLight);

        // --- The Campfire & Light ---
        const fireGroup = new THREE.Group();
        scene.add(fireGroup);

        // Fire Point Light
        const fireLight = new THREE.PointLight(0xffaa00, 10, 25, 1.5);
        fireLight.position.set(0, 2.5, 0);
        fireLight.castShadow = true;
        fireLight.shadow.mapSize.width = 512;
        fireLight.shadow.mapSize.height = 512;
        fireGroup.add(fireLight);

        // Fire Base (Chars)
        const charMat = new THREE.MeshStandardMaterial({ color: 0x111111, roughness: 0.9 });
        const log1 = new THREE.Mesh(new THREE.CylinderGeometry(0.4, 0.6, 0.3, 6), charMat);
        log1.rotation.x = Math.PI / 2;
        log1.position.set(0.3, 0.3, 0.2);
        fireGroup.add(log1);
        
        const log2 = new THREE.Mesh(new THREE.CylinderGeometry(0.4, 0.6, 0.3, 6), charMat);
        log2.rotation.x = Math.PI / 2;
        log2.rotation.y = Math.PI / 2;
        log2.position.set(-0.3, 0.3, -0.2);
        fireGroup.add(log2);

        // Wood Base
        const woodMat = new THREE.MeshStandardMaterial({ color: 0x5c4033, roughness: 0.8 });
        const woodBase = new THREE.Mesh(new THREE.ConeGeometry(1.5, 0.5, 8), woodMat);
        woodBase.position.y = 0.25;
        fireGroup.add(woodBase);

        // The Flames (Animated)
        const flameMat = new THREE.MeshStandardMaterial({ 
            color: 0xff5500, 
            emissive: 0xff3300,
            emissiveIntensity: 2,
            roughness: 0.5,
            transparent: true,
            opacity: 0.9,
            side: THREE.DoubleSide
        });

        const innerFlameGeo = new THREE.ConeGeometry(1, 2.5, 6);
        const innerFlame = new THREE.Mesh(innerFlameGeo, flameMat);
        innerFlame.position.y = 1.5;
        fireGroup.add(innerFlame);

        const outerFlameGeo = new THREE.ConeGeometry(1.6, 3, 6);
        const outerFlame = new THREE.Mesh(outerFlameGeo, flameMat);
        outerFlame.position.y = 1.5;
        outerFlame.scale.set(0.8, 0.8, 0.8);
        fireGroup.add(outerFlame);

        // Sparks Particle System
        const sparkMat = new THREE.PointsMaterial({
            color: 0xffaa00,
            size: 0.15,
            transparent: true,
            opacity: 0.8,
            blending: THREE.AdditiveBlending
        });

        const sparkGeometry = new THREE.BufferGeometry();
        const sparkCount = SCENE_CONFIG.sparkCount;
        const sparkPositions = [];
        const sparkVelocities = [];
        const sparkLifetimes = [];

        for (let i = 0; i < sparkCount; i++) {
            sparkPositions.push(0, 2.5, 0);
            sparkVelocities.push(
                (Math.random() - 0.5) * 0.05,
                0.15 + Math.random() * 0.1,
                (Math.random() - 0.5) * 0.05
            );
            sparkLifetimes.push(Math.random() * 2.0 + 1.0);
        }

        sparkGeometry.setAttribute('position', new THREE.Float32BufferAttribute(sparkPositions, 3));
        const sparkSystem = new THREE.Points(sparkGeometry, sparkMat);
        fireGroup.add(sparkSystem);

        // --- Ground ---
        const groundMat = new THREE.MeshStandardMaterial({ 
            color: SCENE_CONFIG.groundColor, 
            roughness: 1.0,
            flatShading: true
        });
        const ground = new THREE.Mesh(new THREE.PlaneGeometry(60, 60), groundMat);
        ground.rotation.x = -Math.PI / 2;
        ground.receiveShadow = true;
        scene.add(ground);

        // --- Procedural Textures (Canvas) ---
        function createTreeTexture() {
            const canvas = document.createElement('canvas');
            canvas.width = 256;
            canvas.height = 256;
            const ctx = canvas.getContext('2d');
            
            // Dark Green Base
            ctx.fillStyle = '#0a1a0a';
            ctx.fillRect(0, 0, 256, 256);
            
            // Noise/Pattern
            for(let i=0; i<5000; i++){
                ctx.fillStyle = Math.random() > 0.5 ? '#0f250f' : '#051005';
                ctx.fillRect(Math.random()*256, Math.random()*256, 2, 2);
            }
            
            const tex = new THREE.CanvasTexture(canvas);
            tex.magFilter = THREE.NearestFilter; // Keep low-poly look
            return tex;
        }

        const treeTexture = createTreeTexture();
        const treeMat = new THREE.MeshStandardMaterial({ 
            map: treeTexture,
            side: THREE.DoubleSide,
            flatShading: true
        });

        const branchMat = new THREE.MeshStandardMaterial({ color: 0x3d2817, flatShading: true });

        // --- Trees ---
        const trees = [];

        function createTree(x, z) {
            const treeGroup = new THREE.Group();
            treeGroup.position.set(x, 0, z);

            // Trunk
            const trunkGeo = new THREE.CylinderGeometry(0.2, 0.3, 1.5, 5);
            const trunk = new THREE.Mesh(trunkGeo, branchMat);
            trunk.position.y = 0.75;
            trunk.castShadow = true;
            trunk.receiveShadow = true;
            treeGroup.add(trunk);

            // Foliage (3 Low Poly Cones)
            const foliageColors = [0x0b210b, 0x102b10, 0x061606];
            
            for (let i = 0; i < 3; i++) {
                const height = 1.5 - (i * 0.3);
                const radius = 1.2 - (i * 0.3);
                const yOffset = 1.2 + (i * 0.6);
                
                const foliageGeo = new THREE.ConeGeometry(radius, height, 5);
                const foliage = new THREE.Mesh(foliageGeo, treeMat);
                foliage.position.y = yOffset;
                foliage.castShadow = true;
                foliage.receiveShadow = true;
                treeGroup.add(foliage);
            }

            scene.add(treeGroup);
            trees.push(treeGroup);
        }

        // Generate Random Trees
        for (let i = 0; i < SCENE_CONFIG.treeCount; i++) {
            const angle = Math.random() * Math.PI * 2;
            const radius = 5 + Math.random() * 15; // Keep away from center (0,0)
            const x = Math.cos(angle) * radius;
            const z = Math.sin(angle) * radius;
            createTree(x, z);
        }

        // --- Rocks & Logs ---
        const rockMat = new THREE.MeshStandardMaterial({ color: 0x555555, roughness: 1.0, flatShading: true });
        const logMat = new THREE.MeshStandardMaterial({ color: 0x3e2723, roughness: 0.9, flatShading: true });

        function createRock(x, z) {
            const geo = new THREE.DodecahedronGeometry(0.4 + Math.random() * 0.4, 0);
            const rock = new THREE.Mesh(geo, rockMat);
            rock.position.set(x, 0.3, z);
            rock.rotation.set(Math.random()*Math.PI, Math.random()*Math.PI, Math.random()*Math.PI);
            rock.scale.setScalar(0.8 + Math.random() * 0.8);
            rock.castShadow = true;
            rock.receiveShadow = true;
            scene.add(rock);
        }

        function createLog(x, z) {
            const geo = new THREE.CylinderGeometry(0.15, 0.2, 1.5, 5);
            const log = new THREE.Mesh(geo, logMat);
            log.position.set(x, 0.2, z);
            log.rotation.x = Math.random() * Math.PI;
            log.rotation.y = Math.random() * Math.PI;
            log.castShadow = true;
            log.receiveShadow = true;
            scene.add(log);
        }

        for (let i = 0; i < SCENE_CONFIG.rockCount; i++) {
            const angle = Math.random() * Math.PI * 2;
            const radius = 3 + Math.random() * 12;
            createRock(Math.cos(angle) * radius, Math.sin(angle) * radius);
        }
        
        for (let i = 0; i < SCENE_CONFIG.logCount; i++) {
            const angle = Math.random() * Math.PI * 2;
            const radius = 2.5 + Math.random() * 8;
            createLog(Math.cos(angle) * radius, Math.sin(angle) * radius);
        }

        // --- Stars ---
        const starsGeometry = new THREE.BufferGeometry();
        const starCount = 500;
        const starPositions = [];
        for (let i = 0; i < starCount; i++) {
            const x = (Math.random() - 0.5) * 200;
            const y = Math.random() * 50 + 10; // Keep above ground
            const z = (Math.random() - 0.5) * 200;
            starPositions.push(x, y, z);
        }
        starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
        const starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.5, sizeAttenuation: true });
        const starField = new THREE.Points(starsGeometry, starMaterial);
        scene.add(starField);

        // --- Animation Loop ---
        let time = 0;
        const clock = new THREE.Clock();
        
        // UI State
        const loadingDiv = document.getElementById('loading');
        setTimeout(() => {
            loadingDiv.style.opacity = 0;
            setTimeout(() => loadingDiv.remove(), 500);
        }, 1000);

        function animate() {
            requestAnimationFrame(animate);
            
            const delta = clock.getDelta();
            time += delta;

            // 1. Animate Fire Flames
            const wave = Math.sin(time * 5) * 0.2;
            const flickerScale = 1 + Math.random() * 0.1 - 0.05; // Small random flicker
            
            // Inner Flame
            innerFlame.scale.y = 1.0 + Math.sin(time * 8) * 0.2;
            innerFlame.scale.x = 1.0 + Math.cos(time * 8) * 0.1;
            innerFlame.scale.z = innerFlame.scale.x;
            innerFlame.position.y = 1.5 + Math.sin(time * 6) * 0.1;
            
            // Outer Flame
            outerFlame.scale.y = 0.9 + Math.sin(time * 6) * 0.15;
            outerFlame.position.y = 1.5 + Math.cos(time * 5) * 0.05;

            // 2. Animate Fire Light (Flickering)
            const flickerIntensity = 10 + Math.sin(time * 15) * 2 + Math.random() * 2;
            fireLight.intensity = flickerIntensity;
            
            // Slight color shift for warmth
            fireLight.color.setHSL(0.1 + (Math.sin(time * 3) * 0.02), 1.0, 0.5);

            // 3. Animate Sparks
            const positions = sparkSystem.geometry.attributes.position.array;
            for (let i = 0; i < sparkCount; i++) {
                // Update Y position
                sparkPositions[i * 3 + 1] += sparkVelocities[i * 3 + 1];
                
                // Update X/Z position with slight drift
                sparkPositions[i * 3] += sparkVelocities[i * 3];
                sparkPositions[i * 3 + 2] += sparkVelocities[i * 3 + 2];
                
                sparkLifetimes[i] -= delta * 0.8;

                // Reset spark if it goes too high or too long
                if (sparkLifetimes[i] <= 0 || sparkPositions[i * 3 + 1] > 6.0) {
                    sparkPositions[i * 3] = (Math.random() - 0.5) * 0.5; // Reset to fire center X
                    sparkPositions[i * 3 + 1] = 2.5; // Reset to fire height
                    sparkPositions[i * 3 + 2] = (Math.random() - 0.5) * 0.5; // Reset to fire center Z
                    sparkLifetimes[i] = 2.0;
                }
            }
            sparkSystem.geometry.attributes.position.needsUpdate = true;

            // 4. Rotate Trees slightly for wind effect (subtle)
            trees.forEach((tree, i) => {
                tree.rotation.y = Math.sin(time + i) * 0.02;
            });

            controls.update();
            renderer.render(scene, camera);
        }

        // Handle Window Resize
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        // Start Loop
        animate();

    </script>
</body>
</html>