a

Qwen3.5-4B-GLB-3D-Coder-MTP-Repacked

CCORE GLB-3D-Coder (ccore/Qwen3.5-4B-GLB-3D-Coder, checkpoint u008186) is an open-weight (Apache-2.0), specialized 4B-parameter coding model fine-tuned from Qwen/Qwen3.5-4B that turns English text prompts into editable, low-poly 3D game assets and procedural scenes. Given a short or detailed description of a character, prop, vehicle, building, or environment, the model generates a complete standalone Three.js HTML/JavaScript page featuring a live browser preview, optional animations, and an Export GLB button to download ready-to-use .glb files for game engines like Godot. Evaluated with thinking enabled (temperature=0.8, top_k=40, top_p=0.95, repeat_penalty=1.0) and showcased against DeepSeek V4.1 Flash 1017 on unseen complex prompts, it is available in compact Q4_K_M and Q8_0 GGUF quantizations, original 5-shard Safetensors (~17.49 GB with FP32 text and BF16 vision weights), and an optional 644 MiB BF16 mmproj vision projector for multimodal GGUF runtimes.

MTP β€” Speculative Decoding: Yes | GGUF β€” Qwen3.5-4B-GLB-3D-Coder-MTP-Repacked(GGUF)

Multi-Token Prediction (MTP) GGUF is a specialized GGUF model file format extension that integrates speculative decoding directly into the model weights to significantly accelerate local inference. Unlike traditional speculative decoding which requires a separate, smaller "draft" model, MTP GGUF files include additional output heads within the main model architecture that predict multiple future tokens in a single forward pass.

Model Files [GGUF]

File Name Quant Type File Size File Link Description
Qwen3.5-4B-GLB-3D-Coder-MTP.BF16.gguf BF16 8.67 GB Link Full BF16 weights. Highest quality, largest file size.
Qwen3.5-4B-GLB-3D-Coder-MTP.Q3_K_L.gguf Q3_K_L 2.48 GB Link Lower quality but usable, good for low RAM availability.
Qwen3.5-4B-GLB-3D-Coder-MTP.Q3_K_M.gguf Q3_K_M 2.32 GB Link Low quality.
Qwen3.5-4B-GLB-3D-Coder-MTP.Q4_K_M.gguf Q4_K_M 2.78 GB Link Good quality, default size for most use cases, recommended.
Qwen3.5-4B-GLB-3D-Coder-MTP.Q4_K_S.gguf Q4_K_S 2.63 GB Link Slightly lower quality with more space savings, recommended.
Qwen3.5-4B-GLB-3D-Coder-MTP.Q5_K_M.gguf Q5_K_M 3.16 GB Link High quality, recommended.
Qwen3.5-4B-GLB-3D-Coder-MTP.Q5_K_S.gguf Q5_K_S 3.07 GB Link High quality, recommended.
Qwen3.5-4B-GLB-3D-Coder-MTP.Q6_K.gguf Q6_K 3.56 GB Link Very high quality, near perfect, recommended.
Qwen3.5-4B-GLB-3D-Coder-MTP.Q8_0.gguf Q8_0 4.61 GB Link Extremely high quality, generally unneeded but max available quant.
Qwen3.5-4B-GLB-3D-Coder-MTP.mmproj-bf16.gguf mmproj-bf16 676 MB Link Multimodal projection file in BF16 format. Used for vision/video/3D-language models.

MTP-Repacked [Transformers, BF16]

File Name File Type File Size File Link Description
chat_template.jinja Jinja Template 7.76 kB Link Chat template for formatting conversations and prompts.
config.json JSON 2.96 kB Link Core model architecture and configuration parameters.
generation_config.json JSON 254 Bytes Link Default text generation parameters (e.g., temperature, top_p).
model-00001-of-00006.safetensors Safetensors 3.08 GB Link Model weight shard 1/6. Required to load the model.
model-00002-of-00006.safetensors Safetensors 3.02 GB Link Model weight shard 2/6. Required to load the model.
model-00003-of-00006.safetensors Safetensors 3.06 GB Link Model weight shard 3/6. Required to load the model.
model-00004-of-00006.safetensors Safetensors 3.02 GB Link Model weight shard 4/6. Required to load the model.
model-00005-of-00006.safetensors Safetensors 3.02 GB Link Model weight shard 5/6. Required to load the model.
model-00006-of-00006.safetensors Safetensors 2.52 GB Link Model weight shard 6/6. Required to load the model.
model.safetensors.index.json JSON 67.3 kB Link Index file mapping model weights to their respective shards.
preprocessor_config.json JSON 390 Bytes Link Configuration for preprocessing vision/image inputs.
tokenizer.json JSON 20 MB Link Complete tokenizer vocabulary and encoding rules.
tokenizer_config.json JSON 1.47 kB Link Tokenizer-specific configuration parameters.
video_preprocessor_config.json JSON 385 Bytes Link Configuration for preprocessing video inputs.

Run Inference (llama.cpp)

/path/to/llama.cpp/build/bin/llama-cli \
  -m /path/to/models/Qwen3.5-4B-GLB-3D-Coder-MTP.BF16.gguf \
  --spec-type draft-mtp \
  --spec-draft-n-max 2 \
  -ngl 99 \
  -c 32768 \
  --cache-type-k q8_0 \
  --seed 42 \
  -n 16384 \
  -st \
  --chat-template-kwargs '{"enable_thinking":false}' \
  -p "Create a modern bus stop with a bench and route sign."

Output (llama.cpp)

Expand the dropdown to view the full output.

Create a modern bus stop with a bench and route sign.

We need produce HTML complete. Need likely use CDN imports, create scene. Need asset modern bus stop bench route sign. Should be good. Need perhaps export GLTF? User asks create. We should provide code likely one HTML. Need include controls maybe orbit. We can use Three.js and GLTFExporter modules via importmap. Need ensure working. We can create stylized bus stop: glass enclosure, bench, route sign, timetable, trash bin perhaps modern. Need focus bench and route sign. Bus stop map maybe route board. Low-poly.

Need likely answer with HTML code only perhaps instructions. We need ensure export includes selected group and no ground? Can export group. Three.js version pinned CDN. Import maps: "three": https://cdn.jsdelivr.net/npm/three@0.166.1/build/three.module.js "three/addons/": ...examples/jsm/ import OrbitControls, GLTFExporter.

Need ensure GLTFExporter parse async and binary. use parser.parse(input,onDone,onError,{binary:true, onlyVisible:true}). Export group. Materials. Use MeshPhysical maybe transparency supported. GLTFExporter can export MeshPhysicalMaterial extension? likely yes but standard safer. Use MeshStandardMaterial transparent.

Scene:

  • ground slab maybe circular/plane
  • shelter with four posts, flat roof, back glass panel and side glass panel. Modern bus stop.
  • bench: wood slats seat and back, steel legs. Maybe bench centered.
  • route sign: pole with rectangular dark board, cyan display "BUS 24 / CENTRAL" perhaps text via canvas texture. GLTF export canvas texture works. Sign board with icon.
  • timetable case.
  • bin.
  • maybe person? User didn't ask. Asset only.
  • road side curb, tactile paving maybe. Need export group includes all. Could use canvas textures for sign and timetable. Since export GLTF can handle textures from canvas, need preserve. Set colorSpace SRGBColorSpace. Need make text readable. Scene composition with ground and backdrop, camera, shadows, lights. Need perhaps click export. Provide status. Need asset all procedural no external models. The HTML should be complete. Need perhaps add screenshot? Not possible. Answer code.

Need ensure geometry orientation. Let's design coordinate: X width, Y up, Z depth. Shelter at x=-0.7? Bench facing road (positive Z?). Camera at (8,6,10) looking origin. Road at z=2.2 maybe. Shelter back at z=-1.4, roof. Ground platform maybe 10x6. Shelter width 4.4, depth 2.0, back z=-1.0. bench inside at z=-0.15 facing +z. Sign outside at x=3.0 z=1.7. Maybe bus stop group centered.

Shelter: posts x Β±2.0, z -1.0 and +0.8? Four posts. roof dimensions 4.6x0.18x2.2 at y3.0. Back glass panel x width 4.1 y 2.1 z=-1.02. Maybe side glass panels? one left side panel to enhance. Metal frame dark blue. Roof with dark slab and blue fascia. Add solar panel? modern but maybe not necessary. Could add rain gutter. Bench: seat width 3.3, depth 0.58, y .58, slats along x? Bench seat slats run x, 4 slats across z. Back slats run x at y .95,1.2,1.45 z=-.63. Frame legs. Bus stop sign: pole x=3.2 z=1.6 y maybe 2.6, board at y3.4. Board dimensions 1.25x1.5 maybe. Route sign in dark navy with cyan top and white text. Canvas texture maybe create 512x640. Add route number big. Timetable case at x=-3.1 z=1.4? maybe. Bin x=3.8 z=-0.3. Curb road at z=2.5 maybe. The ground is perhaps sidewalk at z<2.0 and road at z>2.2. But export asset should include ground context? Maybe platform and road strip. Good.

Need labels as canvas textures maybe sign uses actual texture. For export, GLTFExporter CanvasTexture should serialize to PNG. Need set map and maybe board material is meshstandard with map. But board itself dark, use canvas texture as map including full visual. Could create canvas texture visually rich. We can use canvas 1024x1400 and draw route bus icon, "BUS 24", "CENTRAL AVE", etc. MeshBasic? MeshStandard with map. Ensure texture.needsUpdate. Use a sign frame behind.

Timetable texture 512x700 with white/blue and trip rows. Maybe tactile yellow paving at curb.

Geometry helpers box. cylinder.

Need model clean. Low poly.

Maybe use RoundedBoxGeometry? Addons geometries/RoundedBoxGeometry.js. But exports okay. Yet low poly and modern. Could import. However standalone file with module import. Use BoxGeometry mostly. Bench slats bevel not needed. Could use Extrude? Keep.

Need maybe transparent back glass with opacity .25 and transmission? MeshPhysical might export extension. Use MeshStandard transparent, depthWrite false. GLTF standard alpha blend support. Set side DoubleSide. Need shadows. Renderer outputColorSpace = SRGBColorSpace, toneMapping ACES. Need use environment? no. Hemisphere + directional + spot. Need contact shadows? standard shadow map.

Need export only model group. The ground plane in scene perhaps model group included? We can have context group and asset group. Export asset group only. But GLTF needs visible. all. Maybe include platform, road, shelter etc.

Potential issue GLTFExporter with CanvasTexture using document canvas will work, but toBlob maybe. yes.

Need provide camera reset maybe button. Need responsive. Need maybe drag orbit. Need use importmap. Ensure crossorigin.

Let's write code robust.

Need add all visual elements to assetRoot. Use makeBox with cast receive. Materials palette: frame dark navy #17324a roof #24475e wood #b97845, woodDark glass #9cdce5 opacity .28 cyan #42d9e2 white metal.

Create base: platform box 10x0.25x5 at y=-0.15? top at -0.025. road strip beyond z 2.2 maybe separate. If export asset includes road huge? Use context root not exported? Asset includes road strip 10x4 maybe okay. But user asks bus stop, export asset with platform and road curb. Could export all.

Set ground base dimensions 10 x 6, center z=0.5, top y=0.0. Road strip at z=3.0 depth 2.5, y=-.05. But platform only z -1 to 2? Let's set platform depth 5.2 center z=-0.4 => range -3 to 2.2. road strip range 2.2 to 5, center 3.6. curb at z=2.25. This gives context. Need camera looking from positive z road side toward shelter. Sign near curb. Shelter back at z=-1.55, roof depth 2.4 center z=-0.55 => range -1.75 to .65. bench z=-0.2. Sign at x=3.25 z=1.4.

Ground maybe asphalt.

Shelter posts 4 at x -2.1,2.1, z -1.55,0.55, y1.55. each 0.12x3x0.12. Back glass width 4.25 height 2.35 depth .04 center y1.55 z-1.58. Side glass maybe x=-2.12, y1.55, z=-.5, dimensions .04x2.35x1.9. Right side open? Modern shelter can have side panel only left. Roof y3.08, dims 4.65x.18x2.45. Top fascia blue. Under roof light strip maybe emissive mesh at y2.93 z=-.3, width 3.8, depth .06. Could add PointLight? export lights are supported maybe but avoid, emissive material. Bench: seat slats 4, each box 3.35x.09x.12, z from -.35 to .05? Bench facing +z, seat depth .6, slats along x. center z=-.22. back slats at z=-.64. y .92,1.17,1.42. seat top .65. Frame legs x Β±1.45, etc. Use cylinders? square steel. legs y .32. horizontal supports. Back support frame. Armrests maybe.

Route sign: pole cylinder radius .07 height 3.3 at x3.35 z1.45 y1.65. board frame box 1.35x1.65x.12 at y3.25. Canvas map texture on front face +z. A plane geometry 1.2x1.5 at z1.52? Board center z1.45 depth .12 front z1.51. plane z1.515. Could have board dark with texture exact. Use PlaneGeometry. maybe board frame box dark and plane map. Sign top cyan strip. Maybe route circular icon via canvas. Timetable at x=-3.25 z=1.1, pole and case. Use plane texture. Trash bin cylinder at x=4.0 z=-0.5, y .55, dark with cyan lid. But asset width extends. fine. Curb ramp tactile yellow at z=2.2 maybe.

Bus stop sign perhaps board says: ROUTE 24 CENTRAL AVE downward arrow etc. Canvas draw. Timetable.

Add small accessibility marking maybe.

Lighting: renderer shadow map PCFSoft. Directional at (6,10,8), cast shadow 2048. Ambient hemisphere. Spot maybe. Ground receive. Animation none.

Export: const exporter = new GLTFExporter(); exporter.parse(assetRoot, result => { if result instanceof ArrayBuffer create Blob; else JSON; }, error, {binary:true, onlyVisible:true, trs:false, maxTextureSize:2048}); Need maybe exporter.parse scene with lights? asset only no lights. Great. Could include export button and download name. Need ensure textures loaded? Canvas immediate.

Could add export status. Need include button style.

Need maybe a model info summary.

Could add "Reset view" button.

Need maybe use controls.target.

No user asked specific format, but developer says create in HTML. Provide complete file.

Let's ensure no syntax errors.

Importmap: <script type="importmap"> {"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.166.1/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.166.1/examples/jsm/"}} </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';

Maybe font on canvas uses system.

Function rounded? no.

texture creation: function makeBusSignTexture() { const c=document.createElement('canvas'); c.width=1024;c.height=1400; const ctx=... background #0b263b draw border cyan vertical stripe white logo bus text. const tex=new THREE.CanvasTexture(c); tex.colorSpace=THREE.SRGBColorSpace; tex.anisotropy=4; return tex; } Texture on PlaneGeometry; material map tex, roughness .7. Need maybe canvas texture exported with flipY? GLTF handles.

Timetable texture similarly.

Create group names. Use traverse names maybe.

Helper addBox(parent,size,pos,mat, name). Use geometry each. Could optimize but fine. Cylinder helper.

For bench slats, names.

Add small bus icon perhaps sign.

Road context maybe not export? assetRoot includes all. Maybe road and platform are part of asset and useful. User can hide context? no. Could have assetRoot and contextRoot separate, export assetRoot only. But then exported bus stop floats without ground. Yet GLTF model often includes scene. Better export assetRoot including platform/road. Name root "ModernBusStop". The road strip and platform are part of asset.

Maybe ground is large and could clutter export. But okay.

Potential glTF exporter issue transparent material opacity and depthWrite false okay. Potential glTF exporter issue MeshStandardMaterial map canvas with canvas cross origin no issue. Potential glTF exporter issue CanvasTexture image is HTMLCanvasElement. yes.

Need maybe renderer.setAnimationLoop; controls damping.

Add resize.

Use document.getElementById('viewport')? renderer canvas appended to #app.

Let's compose code.

Need maybe style glass panel in scene? background gradient CSS doesn't show through renderer alpha? renderer clear color. We'll set alpha true and scene.background maybe null. But environment no. Better scene.background Color #dfe8ed. Add fog. CSS UI.

Model details:

  • platform concrete with tile lines maybe add tiles as thin boxes? Could create 12 tiles individually; adds visual. But platform one slab and yellow tactile strip.
  • road dark asphalt.
  • curb concrete.
  • yellow tactile paving at z=2.05 x -2 to 2 maybe.
  • white lane line? road context maybe.

Shelter: Frame posts maybe 0.14. Roof top dark with blue edge. Add solar panels? A modern bus stop often solar roof. Could add 2 blue solar panel rectangles on roof with grid lines. But geometry on top maybe visually nice. Yet user asks bench and route sign, extra okay. Solar panels could clutter. Maybe add 2 dark blue rectangular panels at y3.20, z=-.6, x positions -1.35 and .55, size 1.6x.04x1.35, rotated? Roof horizontal. Add grid thin lines. This makes modern. But roof itself maybe dark. Use roof dark navy and panels slightly lighter. Add cyan rim. Could add small hanging timetable? no.

Shelter back: Glass panel and horizontal metal rails. Bench visible.

Bench wood slats with dark metal underframe. Maybe cushion? no.

Sign: Pole and board. Also small downward arrow sign? texture includes.

Timetable: Case at x=-3.3,z=1.15, pole. panel 0.75x1.05 with texture.

Bin: Cylinder body and lid, maybe dark.

Lighting under roof: emissive strip.

Could add stop ID "STOP 24" in canvas.

Need maybe "modern" through sleek design.

Let's ensure camera sees sign and shelter. camera (8.8,6.4,10.5), target (0,1.2,0.2).

Need maybe axes. no.

Let's draft answer with "Save as bus-stop.html". Then code.

We need not mention can't host. But maybe provide instructions.

Let's make code concise but complete. Need ensure exported file download: const blob = new Blob([result], {type:'model/gltf-binary'}); const url = URL.createObjectURL(blob); a.download='modern-bus-stop.glb'; a.click(); setTimeout revoke. Some browsers require append anchor. do.

If result not ArrayBuffer, JSON blob.

Button disabled during export. status.

Need export only assetRoot. assetRoot.updateMatrixWorld(true);

Potential issue GLTFExporter doesn't export texture if canvas has willReadFrequently no. Potential issue GLTFExporter needs FileReader browser yes.

Maybe add export model with animations none.

Let's write.

Save this as bus-stop.html and open it in a modern browser. It includes an orbitable 3D preview and an Export GLB button.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Modern Bus Stop β€” GLB Asset Creator</title>

  <style>
    * {
      box-sizing: border-box;
    }

    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0;
      overflow: hidden;
      font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
        "Segoe UI", sans-serif;
      background: #dfe8ed;
    }

    #app {
      position: fixed;
      inset: 0;
    }

    #app canvas {
      display: block;
      width: 100%;
      height: 100%;
    }

    .panel {
      position: fixed;
      z-index: 10;
      top: 20px;
      left: 20px;
      width: min(360px, calc(100vw - 40px));
      padding: 18px;
      color: #17324a;
      background: rgba(255, 255, 255, 0.88);
      border: 1px solid rgba(23, 50, 74, 0.12);
      border-radius: 16px;
      box-shadow: 0 14px 40px rgba(30, 54, 70, 0.16);
      backdrop-filter: blur(12px);
    }

    .eyebrow {
      margin-bottom: 4px;
      color: #278a98;
      font-size: 11px;
      font-weight: 800;
      letter-spacing: 0.16em;
      text-transform: uppercase;
    }

    h1 {
      margin: 0 0 7px;
      font-size: 23px;
      line-height: 1.15;
      letter-spacing: -0.03em;
    }

    .description {
      margin: 0 0 16px;
      color: #587080;
      font-size: 13px;
      line-height: 1.5;
    }

    .actions {
      display: flex;
      gap: 9px;
      flex-wrap: wrap;
    }

    button {
      min-height: 40px;
      padding: 0 15px;
      border: 0;
      border-radius: 10px;
      font: inherit;
      font-size: 13px;
      font-weight: 750;
      cursor: pointer;
      transition: transform 120ms ease, box-shadow 120ms ease, opacity 120ms ease;
    }

    button:hover {
      transform: translateY(-1px);
    }

    button:active {
      transform: translateY(0);
    }

    button:disabled {
      cursor: wait;
      opacity: 0.65;
      transform: none;
    }

    #exportButton {
      color: #fff;
      background: linear-gradient(135deg, #167f8d, #14536e);
      box-shadow: 0 6px 16px rgba(22, 112, 135, 0.25);
    }

    #resetButton {
      color: #28465a;
      background: #e5ecef;
    }

    #status {
      min-height: 18px;
      margin-top: 12px;
      color: #587080;
      font-size: 12px;
    }

    .hint {
      position: fixed;
      z-index: 10;
      right: 18px;
      bottom: 16px;
      padding: 8px 11px;
      color: rgba(23, 50, 74, 0.7);
      background: rgba(255, 255, 255, 0.7);
      border-radius: 9px;
      font-size: 11px;
      pointer-events: none;
    }

    @media (max-width: 600px) {
      .panel {
        top: 12px;
        left: 12px;
        width: calc(100vw - 24px);
        padding: 14px;
      }

      h1 {
        font-size: 20px;
      }

      .hint {
        display: none;
      }
    }
  </style>

  <script type="importmap">
    {
      "imports": {
        "three": "https://cdn.jsdelivr.net/npm/three@0.166.1/build/three.module.js",
        "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.166.1/examples/jsm/"
      }
    }
  </script>
</head>

<body>
  <div id="app"></div>

  <section class="panel">
    <div class="eyebrow">Procedural City Asset</div>
    <h1>Modern Bus Stop</h1>
    <p class="description">
      A sleek, low-poly transit shelter with a wooden bench, glass enclosure,
      solar roof, route sign, timetable, and urban furniture.
    </p>

    <div class="actions">
      <button id="exportButton" type="button">Export GLB</button>
      <button id="resetButton" type="button">Reset View</button>
    </div>

    <div id="status" aria-live="polite">Ready to export.</div>
  </section>

  <div class="hint">Drag to orbit Β· Scroll to zoom Β· Right-drag to pan</div>

  <script type="module">
    import * as THREE from "three";
    import { OrbitControls } from "three/addons/controls/OrbitControls.js";
    import { GLTFExporter } from "three/addons/exporters/GLTFExporter.js";

    const app = document.getElementById("app");
    const exportButton = document.getElementById("exportButton");
    const resetButton = document.getElementById("resetButton");
    const status = document.getElementById("status");

    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0xdfe8ed);
    scene.fog = new THREE.Fog(0xdfe8ed, 18, 38);

    const camera = new THREE.PerspectiveCamera(
      42,
      window.innerWidth / window.innerHeight,
      0.1,
      100
    );

    const initialCameraPosition = new THREE.Vector3(8.8, 6.4, 10.5);
    const initialTarget = new THREE.Vector3(0, 1.25, 0.2);

    camera.position.copy(initialCameraPosition);

    const renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: false,
      powerPreference: "high-performance"
    });

    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.outputColorSpace = THREE.SRGBColorSpace;
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1.05;
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    app.appendChild(renderer.domElement);

    const controls = new OrbitControls(camera, renderer.domElement);
    controls.target.copy(initialTarget);
    controls.enableDamping = true;
    controls.dampingFactor = 0.06;
    controls.minDistance = 5;
    controls.maxDistance = 25;
    controls.maxPolarAngle = Math.PI * 0.48;

    // Lighting
    const hemisphere = new THREE.HemisphereLight(0xeaf8ff, 0x59666b, 2.1);
    scene.add(hemisphere);

    const sun = new THREE.DirectionalLight(0xfff4df, 3.2);
    sun.position.set(7, 11, 8);
    sun.castShadow = true;
    sun.shadow.mapSize.set(2048, 2048);
    sun.shadow.camera.left = -10;
    sun.shadow.camera.right = 10;
    sun.shadow.camera.top = 10;
    sun.shadow.camera.bottom = -10;
    sun.shadow.camera.near = 1;
    sun.shadow.camera.far = 35;
    sun.shadow.normalBias = 0.025;
    scene.add(sun);

    const fill = new THREE.DirectionalLight(0x9ed8ef, 1.1);
    fill.position.set(-7, 5, -5);
    scene.add(fill);

    // Exportable asset root
    const assetRoot = new THREE.Group();
    assetRoot.name = "Modern_Bus_Stop";
    scene.add(assetRoot);

    const M = {
      frame: new THREE.MeshStandardMaterial({
        color: 0x18374b,
        roughness: 0.36,
        metalness: 0.72
      }),
      roof: new THREE.MeshStandardMaterial({
        color: 0x24475d,
        roughness: 0.48,
        metalness: 0.48
      }),
      roofPanel: new THREE.MeshStandardMaterial({
        color: 0x173c58,
        roughness: 0.28,
        metalness: 0.58
      }),
      steel: new THREE.MeshStandardMaterial({
        color: 0x758790,
        roughness: 0.3,
        metalness: 0.85
      }),
      darkSteel: new THREE.MeshStandardMaterial({
        color: 0x273740,
        roughness: 0.38,
        metalness: 0.78
      }),
      concrete: new THREE.MeshStandardMaterial({
        color: 0xcbd4d5,
        roughness: 0.92,
        metalness: 0
      }),
      concreteDark: new THREE.MeshStandardMaterial({
        color: 0x9da9ab,
        roughness: 0.95,
        metalness: 0
      }),
      asphalt: new THREE.MeshStandardMaterial({
        color: 0x39464c,
        roughness: 1,
        metalness: 0
      }),
      tactile: new THREE.MeshStandardMaterial({
        color: 0xe6b84f,
        roughness: 0.78,
        metalness: 0.05
      }),
      wood: new THREE.MeshStandardMaterial({
        color: 0xb97743,
        roughness: 0.74,
        metalness: 0
      }),
      woodDark: new THREE.MeshStandardMaterial({
        color: 0x83502f,
        roughness: 0.8,
        metalness: 0
      }),
      glass: new THREE.MeshStandardMaterial({
        color: 0x9adce2,
        roughness: 0.08,
        metalness: 0.05,
        transparent: true,
        opacity: 0.27,
        depthWrite: false,
        side: THREE.DoubleSide
      }),
      cyan: new THREE.MeshStandardMaterial({
        color: 0x42dce2,
        roughness: 0.32,
        metalness: 0.18,
        emissive: 0x0b5961,
        emissiveIntensity: 0.25
      }),
      white: new THREE.MeshStandardMaterial({
        color: 0xf4f7f5,
        roughness: 0.6,
        metalness: 0.04
      }),
      rubber: new THREE.MeshStandardMaterial({
        color: 0x202a30,
        roughness: 0.9,
        metalness: 0
      }),
      lamp: new THREE.MeshStandardMaterial({
        color: 0xdff8ff,
        roughness: 0.2,
        metalness: 0,
        emissive: 0x9eefff,
        emissiveIntensity: 1.6
      })
    };

    function addBox(parent, name, size, position, material, castShadow = true) {
      const mesh = new THREE.Mesh(
        new THREE.BoxGeometry(size[0], size[1], size[2]),
        material
      );
      mesh.name = name;
      mesh.position.set(position[0], position[1], position[2]);
      mesh.castShadow = castShadow;
      mesh.receiveShadow = true;
      parent.add(mesh);
      return mesh;
    }

    function addCylinder(
      parent,
      name,
      radiusTop,
      radiusBottom,
      height,
      position,
      material,
      radialSegments = 12
    ) {
      const mesh = new THREE.Mesh(
        new THREE.CylinderGeometry(
          radiusTop,
          radiusBottom,
          height,
          radialSegments
        ),
        material
      );
      mesh.name = name;
      mesh.position.set(position[0], position[1], position[2]);
      mesh.castShadow = true;
      mesh.receiveShadow = true;
      parent.add(mesh);
      return mesh;
    }

    function addPlane(parent, name, width, height, position, material) {
      const mesh = new THREE.Mesh(
        new THREE.PlaneGeometry(width, height),
        material
      );
      mesh.name = name;
      mesh.position.set(position[0], position[1], position[2]);
      mesh.receiveShadow = true;
      parent.add(mesh);
      return mesh;
    }

    function createCanvasTexture(canvas) {
      const texture = new THREE.CanvasTexture(canvas);
      texture.colorSpace = THREE.SRGBColorSpace;
      texture.anisotropy = Math.min(8, renderer.capabilities.getMaxAnisotropy());
      texture.needsUpdate = true;
      return texture;
    }

    function createBusStopTexture() {
      const canvas = document.createElement("canvas");
      canvas.width = 1024;
      canvas.height = 1400;
      const ctx = canvas.getContext("2d");

      ctx.fillStyle = "#0b263b";
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      ctx.fillStyle = "#42dce2";
      ctx.fillRect(0, 0, 26, canvas.height);
      ctx.fillRect(30, 34, 964, 54);

      // Bus pictogram
      ctx.fillStyle = "#f5fbfc";
      ctx.beginPath();
      ctx.roundRect(142, 118, 290, 222, 28);
      ctx.fill();

      ctx.fillStyle = "#42dce2";
      ctx.beginPath();
      ctx.roundRect(169, 145, 186, 62, 15);
      ctx.fill();

      ctx.fillStyle = "#f5fbfc";
      ctx.fillRect(168, 205, 187, 34);

      ctx.fillStyle = "#0b263b";
      ctx.beginPath();
      ctx.arc(245, 330, 29, 0, Math.PI * 2);
      ctx.arc(379, 330, 29, 0, Math.PI * 2);
      ctx.fill();

      // Route information
      ctx.fillStyle = "#f5fbfc";
      ctx.font = "800 88px Arial, sans-serif";
      ctx.fillText("BUS 24", 540, 225);

      ctx.fillStyle = "#42dce2";
      ctx.font = "700 31px Arial, sans-serif";
      ctx.letterSpacing = "4px";
      ctx.fillText("CENTRAL AVE", 540, 310);

      ctx.fillStyle = "#f5fbfc";
      ctx.font = "700 29px Arial, sans-serif";
      ctx.fillText("STOP 0248", 540, 379);

      ctx.fillStyle = "#a9c3cb";
      ctx.font = "24px Arial, sans-serif";
      ctx.fillText("DOWN TOWN", 540, 444);
      ctx.fillText("A11   B15", 540, 483);

      ctx.strokeStyle = "#42dce2";
      ctx.lineWidth = 5;
      ctx.strokeRect(30, 520, 964, 370);

      ctx.fillStyle = "#42dce2";
      ctx.beginPath();
      ctx.moveTo(344, 578);
      ctx.lineTo(680, 578);
      ctx.moveTo(680, 578);
      ctx.lineTo(680, 835);
      ctx.stroke();

      ctx.fillStyle = "#f5fbfc";
      ctx.font = "800 30px Arial, sans-serif";
      ctx.fillText("NEXUS", 540, 635);

      ctx.fillStyle = "#a9c3cb";
      ctx.font = "25px Arial, sans-serif";
      ctx.fillText("10 Min", 540, 687);
      ctx.fillText("24 Min", 540, 730);
      ctx.fillText("48 Min", 540, 773);

      ctx.fillStyle = "#42dce2";
      ctx.fillRect(540, 804, 448, 12);
      ctx.fillStyle = "#f5fbfc";
      ctx.font = "700 25px Arial, sans-serif";
      ctx.fillText("12:48 PM", 540, 842);

      ctx.fillStyle = "#f5fbfc";
      ctx.font = "700 23px Arial, sans-serif";
      ctx.fillText("MEETING POINT", 540, 910);
      ctx.fillText("MONβ€”FRI", 540, 953);

      ctx.fillStyle = "#42dce2";
      ctx.fillRect(540, 977, 164, 17);
      ctx.fillStyle = "#f5fbfc";
      ctx.font = "700 23px Arial, sans-serif";
      ctx.fillText("24", 540, 1010);

      ctx.fillStyle = "#a9c3cb";
      ctx.font = "22px Arial, sans-serif";
      ctx.fillText("ROUTE INFORMATION", 540, 1070);
      ctx.fillText("DEPARTURES", 540, 1123);

      const times = [
        ["12:48", "12 min"],
        ["13:08", "24 min"],
        ["13:28", "48 min"],
        ["13:48", "60 min"]
      ];

      times.forEach((row, index) => {
        const y = 1165 + index * 55;
        ctx.fillStyle = index === 0 ? "#42dce2" : "#f5fbfc";
        ctx.fillRect(540, y - 17, 310, 31);
        ctx.fillStyle = "#1d3c50";
        ctx.font = "800 30px Arial, sans-serif";
        ctx.fillText(row[0], 540, y + 7);
        ctx.fillStyle = "#a9c3cb";
        ctx.font = "22px Arial, sans-serif";
        ctx.fillText(row[1], 855, y + 7);
      });

      ctx.fillStyle = "#42dce2";
      ctx.fillRect(540, 1286, 284, 12);
      ctx.fillStyle = "#f5fbfc";
      ctx.font = "700 22px Arial, sans-serif";
      ctx.fillText("NEXT DEPARTURES", 540, 1323);

      return createCanvasTexture(canvas);
    }

    function createTimetableTexture() {
      const canvas = document.createElement("canvas");
      canvas.width = 512;
      canvas.height = 700;
      const ctx = canvas.getContext("2d");

      ctx.fillStyle = "#f4f7f5";
      ctx.fillRect(0, 0, 512, 700);

      ctx.fillStyle = "#167f8d";
      ctx.fillRect(0, 0, 512, 108);
      ctx.fillStyle = "#ffffff";
      ctx.font = "800 41px Arial, sans-serif";
      ctx.fillText("ROUTE 24", 32, 57);

      ctx.fillStyle = "#23465a";
      ctx.font = "700 27px Arial, sans-serif";
      ctx.fillText("CENTRAL AVE", 32, 91);

      ctx.strokeStyle = "#c7d4d7";
      ctx.lineWidth = 3;
      for (let y = 145; y < 650; y += 58) {
        ctx.beginPath();
        ctx.moveTo(32, y);
        ctx.lineTo(480, y);
        ctx.stroke();
      }

      const rows = [
        ["12:48", "12 min", "Central"],
        ["13:08", "24 min", "Central"],
        ["13:28", "48 min", "Central"],
        ["13:48", "60 min", "Central"],
        ["14:08", "72 min", "Central"]
      ];

      rows.forEach((row, index) => {
        const y = 169 + index * 68;
        ctx.fillStyle = index === 0 ? "#42dce2" : "#f4f7f5";
        ctx.fillRect(26, y - 25, 460, 51);
        ctx.fillStyle = "#23465a";
        ctx.font = "800 31px Arial, sans-serif";
        ctx.fillText(row[0], 42, y + 6);
        ctx.fillStyle = "#587080";
        ctx.font = "24px Arial, sans-serif";
        ctx.fillText(row[1], 128, y + 6);
        ctx.fillStyle = "#7a909c";
        ctx.font = "22px Arial, sans-serif";
        ctx.fillText(row[2], 425, y + 6);
      });

      ctx.fillStyle = "#167f8d";
      ctx.fillRect(26, 655, 460, 13);
      ctx.fillStyle = "#ffffff";
      ctx.font = "700 23px Arial, sans-serif";
      ctx.fillText("MEETING POINT", 42, 688);

      ctx.fillStyle = "#42dce2";
      ctx.fillRect(42, 713, 428, 7);
      ctx.fillStyle = "#ffffff";
      ctx.font = "700 22px Arial, sans-serif";
      ctx.fillText("10 MIN", 42, 746);

      return createCanvasTexture(canvas);
    }

    // Ground and road
    const context = new THREE.Group();
    context.name = "Urban_Context";
    assetRoot.add(context);

    addBox(
      context,
      "Sidewalk",
      [10, 0.24, 5.2],
      [0, -0.13, -0.4],
      M.concrete
    );

    addBox(
      context,
      "Road",
      [10, 0.08, 3.1],
      [0, -0.055, 3.65],
      M.asphalt,
      false
    );

    addBox(
      context,
      "Curb",
      [10, 0.22, 0.34],
      [0, 0.035, 2.28],
      M.concreteDark
    );

    // Expansion joints
    for (let x = -4; x <= 4; x += 2) {
      addBox(
        context,
        "Sidewalk Expansion Joint",
        [0.018, 0.008, 4.8],
        [x, 0.006, -0.4],
        M.concreteDark,
        false
      );
    }

    // Tactile warning paving near the curb
    addBox(
      context,
      "Tactile Paving",
      [4.2, 0.025, 0.65],
      [0, 0.018, 1.98],
      M.tactile,
      false
    );

    for (let x = -1.85; x <= 1.85; x += 0.3) {
      addBox(
        context,
        "Tactile Raised Dot",
        [0.055, 0.012, 0.52],
        [x, 0.035, 1.98],
        M.tactile,
        false
      );
    }

    // Shelter structural frame
    const shelter = new THREE.Group();
    shelter.name = "Shelter";
    assetRoot.add(shelter);

    const postXs = [-2.08, 2.08];
    const postZs = [-1.52, 0.52];

    for (const x of postXs) {
      for (const z of postZs) {
        addBox(
          shelter,
          "Shelter Post",
          [0.14, 3.02, 0.14],
          [x, 1.55, z],
          M.frame
        );

        addBox(
          shelter,
          "Post Foot",
          [0.28, 0.1, 0.28],
          [x, 0.055, z],
          M.darkSteel
        );
      }
    }

    // Upper frame rails
    addBox(
      shelter,
      "Back Upper Rail",
      [4.3, 0.12, 0.12],
      [0, 2.98, -1.52],
      M.frame
    );

    addBox(
      shelter,
      "Front Upper Rail",
      [4.3, 0.12, 0.12],
      [0, 2.98, 0.52],
      M.frame
    );

    addBox(
      shelter,
      "Left Upper Rail",
      [0.12, 0.12, 2.1],
      [-2.08, 2.98, -0.5],
      M.frame
    );

    addBox(
      shelter,
      "Right Upper Rail",
      [0.12, 0.12, 2.1],
      [2.08, 2.98, -0.5],
      M.frame
    );

    // Rear glass panel
    addBox(
      shelter,
      "Rear Glass Panel",
      [4.16, 2.48, 0.045],
      [0, 1.62, -1.56],
      M.glass,
      false
    );

    // Left glass panel
    addBox(
      shelter,
      "Left Glass Panel",
      [0.045, 2.48, 1.92],
      [-2.12, 1.62, -0.5],
      M.glass,
      false
    );

    // Slim vertical mullions
    for (const x of [-0.68, 0.68]) {
      addBox(
        shelter,
        "Rear Glass Mullion",
        [0.055, 2.5, 0.075],
        [x, 1.62, -1.51],
        M.steel
      );
    }

    // Roof
    addBox(
      shelter,
      "Roof Slab",
      [4.65, 0.18, 2.45],
      [0, 3.08, -0.5],
      M.roof
    );

    addBox(
      shelter,
      "Roof Blue Fascia",
      [4.52, 0.09, 2.32],
      [0, 3.19, -0.5],
      M.cyan
    );

    addBox(
      shelter,
      "Roof Front Lip",
      [4.52, 0.16, 0.12],
      [0, 3.04, 0.68],
      M.frame
    );

    // Solar panels
    for (const x of [-1.35, 0.55]) {
      addBox(
        shelter,
        "Solar Panel",
        [1.55, 0.045, 1.35],
        [x, 3.215, -0.55],
        M.roofPanel,
        false
      );

      for (let z = -1.12; z <= 0.02; z += 0.34) {
        addBox(
          shelter,
          "Solar Panel Grid Line",
          [1.45, 0.012, 0.018],
          [x, 3.243, z],
          M.cyan,
          false
        );
      }
    }

    // Under-roof light strip
    addBox(
      shelter,
      "Light Strip",
      [3.7, 0.055, 0.09],
      [0, 2.91, -0.28],
      M.lamp,
      false
    );

    // Bench
    const bench = new THREE.Group();
    bench.name = "Bench";
    shelter.add(bench);

    // Seat slats
    for (let i = 0; i < 4; i++) {
      addBox(
        bench,
        "Bench Seat Slat",
        [3.35, 0.095, 0.13],
        [0, 0.64, -0.43 + i * 0.15],
        i === 3 ? M.woodDark : M.wood
      );
    }

    // Back slats
    for (let i = 0; i < 3; i++) {
      addBox(
        bench,
        "Bench Back Slat",
        [3.35, 0.16, 0.095],
        [0, 0.91 + i * 0.25, -0.67],
        i === 2 ? M.woodDark : M.wood
      );
    }

    // Bench frame
    for (const x of [-1.48, 1.48]) {
      addBox(
        bench,
        "Bench Leg",
        [0.11, 0.58, 0.48],
        [x, 0.32, -0.28],
        M.darkSteel
      );

      addBox(
        bench,
        "Bench Back Support",
        [0.1, 0.72, 0.1],
        [x, 1.0, -0.7],
        M.darkSteel
      );

      addBox(
        bench,
        "Bench Armrest",
        [0.09, 0.09, 0.58],
        [x, 0.98, -0.23],
        M.darkSteel
      );

      addBox(
        bench,
        "Bench Armrest Support",
        [0.08, 0.35, 0.08],
        [x, 0.79, -0.23],
        M.darkSteel
      );
    }

    addBox(
      bench,
      "Bench Seat Frame",
      [3.38, 0.09, 0.09],
      [0, 0.56, -0.43],
      M.darkSteel
    );

    addBox(
      bench,
      "Bench Back Frame",
      [3.38, 0.09, 0.09],
      [0, 0.84, -0.67],
      M.darkSteel
    );

    // Route sign
    const sign = new THREE.Group();
    sign.name = "Route Sign";
    assetRoot.add(sign);

    addCylinder(
      sign,
      "Route Sign Pole",
      0.075,
      0.09,
      3.3,
      [3.3, 1.65, 1.45],
      M.darkSteel,
      12
    );

    addBox(
      sign,
      "Route Sign Base",
      [0.42, 0.1, 0.42],
      [3.3, 0.055, 1.45],
      M.concreteDark
    );

    addBox(
      sign,
      "Route Sign Housing",
      [1.38, 1.68, 0.14],
      [3.3, 3.23, 1.45],
      M.darkSteel
    );

    const busSignMaterial = new THREE.MeshStandardMaterial({
      map: createBusStopTexture(),
      roughness: 0.68,
      metalness: 0.04
    });

    addPlane(
      sign,
      "Route Sign Face",
      1.24,
      1.54,
      [3.3, 3.23, 1.526],
      busSignMaterial
    );

    // Timetable case
    const timetable = new THREE.Group();
    timetable.name = "Timetable Case";
    assetRoot.add(timetable);

    addCylinder(
      timetable,
      "Timetable Pole",
      0.055,
      0.065,
      1.4,
      [-3.28, 0.7, 1.12],
      M.steel,
      10
    );

    addBox(
      timetable,
      "Timetable Case Frame",
      [0.86, 1.16, 0.13],
      [-3.28, 1.92, 1.12],
      M.darkSteel
    );

    const timetableMaterial = new THREE.MeshStandardMaterial({
      map: createTimetableTexture(),
      roughness: 0.72,
      metalness: 0.02
    });

    addPlane(
      timetable,
      "Timetable Face",
      0.76,
      1.05,
      [-3.28, 1.92, 1.191],
      timetableMaterial
    );

    // Trash bin
    const bin = new THREE.Group();
    bin.name = "Trash Bin";
    assetRoot.add(bin);

    addCylinder(
      bin,
      "Bin Body",
      0.34,
      0.29,
      0.83,
      [4.08, 0.43, -0.52],
      M.darkSteel,
      12
    );

    addCylinder(
      bin,
      "Bin Lid",
      0.38,
      0.38,
      0.11,
      [4.08, 0.9, -0.52],
      M.frame,
      12
    );

    addBox(
      bin,
      "Bin Opening",
      [0.38, 0.07, 0.12],
      [4.08, 0.96, -0.35],
      M.cyan
    );

    // Small stop ID plaque under the roof
    addBox(
      shelter,
      "Stop ID Plaque",
      [0.72, 0.22, 0.06],
      [0.85, 2.7, 0.61],
      M.cyan
    );

    addBox(
      shelter,
      "Stop ID Plaque Inset",
      [0.58, 0.1, 0.018],
      [0.85, 2.7, 0.647],
      M.white
    );

    // Keep all asset meshes discoverable and consistently named.
    assetRoot.traverse((object) => {
      if (object.isMesh) {
        object.castShadow = object.castShadow !== false;
        object.receiveShadow = true;
      }
    });

    // Camera reset
    function resetView() {
      camera.position.copy(initialCameraPosition);
      controls.target.copy(initialTarget);
      controls.update();
    }

    resetButton.addEventListener("click", resetView);

    // GLB export
    exportButton.addEventListener("click", async () => {
      exportButton.disabled = true;
      status.textContent = "Building GLB…";

      try {
        assetRoot.updateMatrixWorld(true);

        const exporter = new GLTFExporter();
        const result = await exporter.parseAsync(assetRoot, {
          binary: true,
          onlyVisible: true,
          trs: false,
          maxTextureSize: 2048
        });

        let blob;
        let filename;

        if (result instanceof ArrayBuffer) {
          blob = new Blob([result], {
            type: "model/gltf-binary"
          });
          filename = "modern-bus-stop.glb";
        } else {
          blob = new Blob([JSON.stringify(result, null, 2)], {
            type: "model/gltf+json"
          });
          filename = "modern-bus-stop.gltf";
        }

        const url = URL.createObjectURL(blob);
        const anchor = document.createElement("a");
        anchor.href = url;
        anchor.download = filename;
        document.body.appendChild(anchor);
        anchor.click();
        anchor.remove();

        setTimeout(() => URL.revokeObjectURL(url), 1500);

        status.textContent = `Exported ${filename}`;
      } catch (error) {
        console.error(error);
        status.textContent = "Export failed. See the browser console for details.";
      } finally {
        exportButton.disabled = false;
      }
    });

    // Resize handling
    window.addEventListener("resize", () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    });

    // Render loop
    renderer.setAnimationLoop(() => {
      controls.update();
      renderer.render(scene, camera);
    });
  </script>
</body>
</html>

The exported modern-bus-stop.glb contains the shelter, bench, glass panels, solar roof, route sign, timetable, bin, paving, and surrounding display environment.

[ Prompt: 113.5 t/s | Generation: 165.2 t/s ]

Exiting...

[ Prompt: 113.5 t/s | Generation: 165.2 t/s ] - Generated with full GPU offloading on an NVIDIA RTX PRO 6000 Blackwell Server Edition using MTP (draft-n-max: 2). GGUF: Qwen3.5-4B-GLB-3D-Coder-MTP.BF16.gguf

a b

llama.cpp

LLM inference in C/C++ β€” https://github.com/ggml-org/llama.cpp

MTP-repackaged and quantized using llama.cpp by β€” prithivMLmods.

Downloads last month
-
Safetensors
Model size
5B params
Tensor type
F32
Β·
BF16
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for prithivMLmods/Qwen3.5-4B-GLB-3D-Coder-MTP-Repacked

Finetuned
Qwen/Qwen3.5-4B
Quantized
(3)
this model

Collections including prithivMLmods/Qwen3.5-4B-GLB-3D-Coder-MTP-Repacked