初始化项目,由ModelHub XC社区提供模型
Model: megamindbrian/josiefied-qwen-spatial-engine Source: Original Platform
This commit is contained in:
39
.gitattributes
vendored
Normal file
39
.gitattributes
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||
*.arrow filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
||||
*.ftz filter=lfs diff=lfs merge=lfs -text
|
||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||
*.h5 filter=lfs diff=lfs merge=lfs -text
|
||||
*.joblib filter=lfs diff=lfs merge=lfs -text
|
||||
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
||||
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
||||
*.model filter=lfs diff=lfs merge=lfs -text
|
||||
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
||||
*.npy filter=lfs diff=lfs merge=lfs -text
|
||||
*.npz filter=lfs diff=lfs merge=lfs -text
|
||||
*.onnx filter=lfs diff=lfs merge=lfs -text
|
||||
*.ot filter=lfs diff=lfs merge=lfs -text
|
||||
*.parquet filter=lfs diff=lfs merge=lfs -text
|
||||
*.pb filter=lfs diff=lfs merge=lfs -text
|
||||
*.pickle filter=lfs diff=lfs merge=lfs -text
|
||||
*.pkl filter=lfs diff=lfs merge=lfs -text
|
||||
*.pt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pth filter=lfs diff=lfs merge=lfs -text
|
||||
*.rar filter=lfs diff=lfs merge=lfs -text
|
||||
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
||||
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
||||
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
||||
*.tar filter=lfs diff=lfs merge=lfs -text
|
||||
*.tflite filter=lfs diff=lfs merge=lfs -text
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.wasm filter=lfs diff=lfs merge=lfs -text
|
||||
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.zst filter=lfs diff=lfs merge=lfs -text
|
||||
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
||||
josiefied-qwen-f16.gguf filter=lfs diff=lfs merge=lfs -text
|
||||
josiefied-qwen-q4_k_m.gguf filter=lfs diff=lfs merge=lfs -text
|
||||
josiefied-qwen-spatial-engine.gguf filter=lfs diff=lfs merge=lfs -text
|
||||
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
||||
209
README.md
Normal file
209
README.md
Normal file
@@ -0,0 +1,209 @@
|
||||
---
|
||||
base_model: Goekdeniz-Guelmez/Josiefied-Qwen2.5-0.5B-Instruct-abliterated-v1
|
||||
library_name: peft
|
||||
pipeline_tag: text-generation
|
||||
tags:
|
||||
- base_model:adapter:Goekdeniz-Guelmez/Josiefied-Qwen2.5-0.5B-Instruct-abliterated-v1
|
||||
- lora
|
||||
- sft
|
||||
- transformers
|
||||
- trl
|
||||
---
|
||||
|
||||
# Model Card for Model ID
|
||||
|
||||
<!-- Provide a quick summary of what the model is/does. -->
|
||||
|
||||
|
||||
|
||||
## Model Details
|
||||
|
||||
### Model Description
|
||||
|
||||
<!-- Provide a longer summary of what this model is. -->
|
||||
|
||||
|
||||
|
||||
- **Developed by:** [More Information Needed]
|
||||
- **Funded by [optional]:** [More Information Needed]
|
||||
- **Shared by [optional]:** [More Information Needed]
|
||||
- **Model type:** [More Information Needed]
|
||||
- **Language(s) (NLP):** [More Information Needed]
|
||||
- **License:** [More Information Needed]
|
||||
- **Finetuned from model [optional]:** [More Information Needed]
|
||||
|
||||
### Model Sources [optional]
|
||||
|
||||
<!-- Provide the basic links for the model. -->
|
||||
|
||||
- **Repository:** [More Information Needed]
|
||||
- **Paper [optional]:** [More Information Needed]
|
||||
- **Demo [optional]:** [More Information Needed]
|
||||
|
||||
## Uses
|
||||
|
||||
<!-- Address questions around how the model is intended to be used, including the foreseeable users of the model and those affected by the model. -->
|
||||
|
||||
### Direct Use
|
||||
|
||||
<!-- This section is for the model use without fine-tuning or plugging into a larger ecosystem/app. -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
### Downstream Use [optional]
|
||||
|
||||
<!-- This section is for the model use when fine-tuned for a task, or when plugged into a larger ecosystem/app -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
### Out-of-Scope Use
|
||||
|
||||
<!-- This section addresses misuse, malicious use, and uses that the model will not work well for. -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
## Bias, Risks, and Limitations
|
||||
|
||||
<!-- This section is meant to convey both technical and sociotechnical limitations. -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
### Recommendations
|
||||
|
||||
<!-- This section is meant to convey recommendations with respect to the bias, risk, and technical limitations. -->
|
||||
|
||||
Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.
|
||||
|
||||
## How to Get Started with the Model
|
||||
|
||||
Use the code below to get started with the model.
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
## Training Details
|
||||
|
||||
### Training Data
|
||||
|
||||
<!-- This should link to a Dataset Card, perhaps with a short stub of information on what the training data is all about as well as documentation related to data pre-processing or additional filtering. -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
### Training Procedure
|
||||
|
||||
<!-- This relates heavily to the Technical Specifications. Content here should link to that section when it is relevant to the training procedure. -->
|
||||
|
||||
#### Preprocessing [optional]
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
|
||||
#### Training Hyperparameters
|
||||
|
||||
- **Training regime:** [More Information Needed] <!--fp32, fp16 mixed precision, bf16 mixed precision, bf16 non-mixed precision, fp16 non-mixed precision, fp8 mixed precision -->
|
||||
|
||||
#### Speeds, Sizes, Times [optional]
|
||||
|
||||
<!-- This section provides information about throughput, start/end time, checkpoint size if relevant, etc. -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
## Evaluation
|
||||
|
||||
<!-- This section describes the evaluation protocols and provides the results. -->
|
||||
|
||||
### Testing Data, Factors & Metrics
|
||||
|
||||
#### Testing Data
|
||||
|
||||
<!-- This should link to a Dataset Card if possible. -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
#### Factors
|
||||
|
||||
<!-- These are the things the evaluation is disaggregating by, e.g., subpopulations or domains. -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
#### Metrics
|
||||
|
||||
<!-- These are the evaluation metrics being used, ideally with a description of why. -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
### Results
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
#### Summary
|
||||
|
||||
|
||||
|
||||
## Model Examination [optional]
|
||||
|
||||
<!-- Relevant interpretability work for the model goes here -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
## Environmental Impact
|
||||
|
||||
<!-- Total emissions (in grams of CO2eq) and additional considerations, such as electricity usage, go here. Edit the suggested text below accordingly -->
|
||||
|
||||
Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700).
|
||||
|
||||
- **Hardware Type:** [More Information Needed]
|
||||
- **Hours used:** [More Information Needed]
|
||||
- **Cloud Provider:** [More Information Needed]
|
||||
- **Compute Region:** [More Information Needed]
|
||||
- **Carbon Emitted:** [More Information Needed]
|
||||
|
||||
## Technical Specifications [optional]
|
||||
|
||||
### Model Architecture and Objective
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
### Compute Infrastructure
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
#### Hardware
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
#### Software
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
## Citation [optional]
|
||||
|
||||
<!-- If there is a paper or blog post introducing the model, the APA and Bibtex information for that should go in this section. -->
|
||||
|
||||
**BibTeX:**
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
**APA:**
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
## Glossary [optional]
|
||||
|
||||
<!-- If relevant, include terms and calculations in this section that can help readers understand the model or model card. -->
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
## More Information [optional]
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
## Model Card Authors [optional]
|
||||
|
||||
[More Information Needed]
|
||||
|
||||
## Model Card Contact
|
||||
|
||||
[More Information Needed]
|
||||
### Framework versions
|
||||
|
||||
- PEFT 0.19.1
|
||||
BIN
__pycache__/draco_glb.cpython-314.pyc
Normal file
BIN
__pycache__/draco_glb.cpython-314.pyc
Normal file
Binary file not shown.
48
adapter_config.json
Normal file
48
adapter_config.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"alora_invocation_tokens": null,
|
||||
"alpha_pattern": {},
|
||||
"arrow_config": null,
|
||||
"auto_mapping": null,
|
||||
"base_model_name_or_path": "Goekdeniz-Guelmez/Josiefied-Qwen2.5-0.5B-Instruct-abliterated-v1",
|
||||
"bias": "none",
|
||||
"corda_config": null,
|
||||
"ensure_weight_tying": false,
|
||||
"eva_config": null,
|
||||
"exclude_modules": null,
|
||||
"fan_in_fan_out": false,
|
||||
"inference_mode": true,
|
||||
"init_lora_weights": true,
|
||||
"layer_replication": null,
|
||||
"layers_pattern": null,
|
||||
"layers_to_transform": null,
|
||||
"loftq_config": {},
|
||||
"lora_alpha": 32,
|
||||
"lora_bias": false,
|
||||
"lora_dropout": 0.05,
|
||||
"lora_ga_config": null,
|
||||
"megatron_config": null,
|
||||
"megatron_core": "megatron.core",
|
||||
"modules_to_save": null,
|
||||
"peft_type": "LORA",
|
||||
"peft_version": "0.19.1",
|
||||
"qalora_group_size": 16,
|
||||
"r": 16,
|
||||
"rank_pattern": {},
|
||||
"revision": null,
|
||||
"target_modules": [
|
||||
"up_proj",
|
||||
"o_proj",
|
||||
"gate_proj",
|
||||
"q_proj",
|
||||
"k_proj",
|
||||
"v_proj",
|
||||
"down_proj"
|
||||
],
|
||||
"target_parameters": null,
|
||||
"task_type": "CAUSAL_LM",
|
||||
"trainable_token_indices": null,
|
||||
"use_bdlora": null,
|
||||
"use_dora": false,
|
||||
"use_qalora": false,
|
||||
"use_rslora": false
|
||||
}
|
||||
3
adapter_model.safetensors
Normal file
3
adapter_model.safetensors
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fd64aa770679f8f37664c816ce7f7889192c543ad55d8320267e0afd8b23ed90
|
||||
size 35237104
|
||||
236
altman-vision.py
Normal file
236
altman-vision.py
Normal file
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# On a headless Linux box pyrender needs an offscreen GL backend (EGL); without
|
||||
# this the OffscreenRenderer cannot create a context. Must run before importing
|
||||
# pyrender. A desktop session (DISPLAY set) is left untouched.
|
||||
if platform.system() == "Linux" and not os.environ.get("DISPLAY"):
|
||||
os.environ.setdefault("PYOPENGL_PLATFORM", "egl")
|
||||
|
||||
import numpy as np
|
||||
import trimesh
|
||||
import pyrender
|
||||
from PIL import Image
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
from draco_glb import load_glb_scene
|
||||
|
||||
|
||||
def rotation_matrix_x(angle_rad):
|
||||
c = np.cos(angle_rad)
|
||||
s = np.sin(angle_rad)
|
||||
|
||||
return np.array([
|
||||
[1, 0, 0, 0],
|
||||
[0, c, -s, 0],
|
||||
[0, s, c, 0],
|
||||
[0, 0, 0, 1]
|
||||
])
|
||||
|
||||
|
||||
def look_at(camera_position, target, up=np.array([0.0, 0.0, 1.0])):
|
||||
forward = target - camera_position
|
||||
f_norm = np.linalg.norm(forward)
|
||||
|
||||
# Avoid zero-length forward vectors
|
||||
if f_norm < 1e-6:
|
||||
forward = np.array([0.0, -1.0, 0.0])
|
||||
else:
|
||||
forward = forward / f_norm
|
||||
|
||||
right = np.cross(forward, up)
|
||||
r_norm = np.linalg.norm(right)
|
||||
|
||||
# Handle the case where forward points straight up/down
|
||||
if r_norm < 1e-6:
|
||||
alternative_up = np.array([1.0, 0.0, 0.0])
|
||||
right = np.cross(forward, alternative_up)
|
||||
right = right / max(np.linalg.norm(right), 1e-6)
|
||||
else:
|
||||
right = right / r_norm
|
||||
|
||||
true_up = np.cross(right, forward)
|
||||
true_up = true_up / max(np.linalg.norm(true_up), 1e-6)
|
||||
|
||||
pose = np.eye(4)
|
||||
pose[:3, 0] = right
|
||||
pose[:3, 1] = true_up
|
||||
pose[:3, 2] = -forward
|
||||
pose[:3, 3] = camera_position
|
||||
|
||||
return pose
|
||||
|
||||
|
||||
def compute_bounds(scene):
|
||||
mins = np.array([np.inf, np.inf, np.inf])
|
||||
maxs = np.array([-np.inf, -np.inf, -np.inf])
|
||||
|
||||
for geom in scene.geometry.values():
|
||||
if len(geom.vertices) == 0:
|
||||
continue
|
||||
verts = np.asarray(geom.vertices)
|
||||
if not np.isfinite(verts).all():
|
||||
continue
|
||||
mins = np.minimum(mins, verts.min(axis=0))
|
||||
maxs = np.maximum(maxs, verts.max(axis=0))
|
||||
|
||||
# Fallback if no valid geometry was found
|
||||
if np.any(np.isinf(mins)) or np.any(np.isinf(maxs)):
|
||||
return np.zeros(3), np.ones(3), 1.0
|
||||
|
||||
center = (mins + maxs) * 0.5
|
||||
extents = maxs - mins
|
||||
|
||||
# Enforce a non-zero norm baseline
|
||||
extents_norm = np.linalg.norm(extents)
|
||||
radius = max(extents_norm * 0.5, 0.001)
|
||||
|
||||
return center, extents, radius
|
||||
|
||||
|
||||
def trimesh_to_pyrender(scene):
|
||||
render_scene = pyrender.Scene(
|
||||
bg_color=[255, 255, 255, 255],
|
||||
ambient_light=[0.25, 0.25, 0.25]
|
||||
)
|
||||
|
||||
for name, geom in scene.geometry.items():
|
||||
if len(geom.vertices) == 0:
|
||||
print(f"Skipping empty mesh: {name}")
|
||||
continue
|
||||
|
||||
verts = np.asarray(geom.vertices)
|
||||
if not np.isfinite(verts).all():
|
||||
print(f"Skipping invalid mesh: {name}")
|
||||
continue
|
||||
|
||||
try:
|
||||
# Explicitly force trimesh to generate flat normals ahead of time
|
||||
# This ensures pyrender never triggers its stateful eigenvalue calculation
|
||||
geom.fix_normals()
|
||||
|
||||
# Construct manual pyrender material mapping to bypass trimesh parsing
|
||||
material = pyrender.MetallicRoughnessMaterial(
|
||||
doubleSided=True,
|
||||
baseColorFactor=[0.7, 0.7, 0.7, 1.0],
|
||||
metallicFactor=0.2,
|
||||
roughnessFactor=0.8
|
||||
)
|
||||
|
||||
# Build primitive tracking geometry manually
|
||||
primitive = pyrender.Primitive(
|
||||
positions=verts,
|
||||
indices=np.asarray(geom.faces, dtype=np.uint32),
|
||||
normals=np.asarray(geom.vertex_normals),
|
||||
material=material,
|
||||
mode=pyrender.GLTF.TRIANGLES
|
||||
)
|
||||
|
||||
mesh = pyrender.Mesh(primitives=[primitive], name=name)
|
||||
render_scene.add(mesh)
|
||||
|
||||
except Exception as e:
|
||||
# Fallback to direct raw primitives if the normal engine still complains
|
||||
try:
|
||||
primitive = pyrender.Primitive(
|
||||
positions=verts,
|
||||
indices=np.asarray(geom.faces, dtype=np.uint32),
|
||||
material=material,
|
||||
mode=pyrender.GLTF.TRIANGLES
|
||||
)
|
||||
mesh = pyrender.Mesh(primitives=[primitive], name=name)
|
||||
render_scene.add(mesh)
|
||||
except Exception as inner_e:
|
||||
print(f"❌ Failed to render mesh {name}: {inner_e}")
|
||||
|
||||
return render_scene
|
||||
|
||||
|
||||
def add_raymond_lights(scene):
|
||||
light_positions = [
|
||||
[5, 5, 10],
|
||||
[-5, 5, 10],
|
||||
[0, -5, 10]
|
||||
]
|
||||
|
||||
for pos in light_positions:
|
||||
light = pyrender.DirectionalLight(
|
||||
color=np.ones(3),
|
||||
intensity=3.0
|
||||
)
|
||||
|
||||
pose = np.eye(4)
|
||||
pose[:3, 3] = pos
|
||||
|
||||
scene.add(light, pose=pose)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--model", required=True)
|
||||
parser.add_argument("--output", default="render.png")
|
||||
parser.add_argument("--width", type=int, default=1024)
|
||||
parser.add_argument("--height", type=int, default=1024)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
model_path = Path(args.model)
|
||||
|
||||
if not model_path.exists():
|
||||
raise FileNotFoundError(model_path)
|
||||
|
||||
trimesh_scene = load_glb_scene(model_path)
|
||||
|
||||
center, extents, radius = compute_bounds(trimesh_scene)
|
||||
|
||||
scene = trimesh_to_pyrender(trimesh_scene)
|
||||
|
||||
add_raymond_lights(scene)
|
||||
|
||||
fov_y = np.radians(45.0)
|
||||
|
||||
desired_fill = 0.75
|
||||
|
||||
distance = radius / np.tan((fov_y * desired_fill) / 2.0)
|
||||
|
||||
angle_deg = 30.0
|
||||
angle_rad = np.radians(angle_deg)
|
||||
|
||||
horizontal_distance = distance * np.cos(angle_rad)
|
||||
vertical_offset = distance * np.sin(angle_rad)
|
||||
|
||||
camera_position = center + np.array([
|
||||
horizontal_distance,
|
||||
-horizontal_distance,
|
||||
vertical_offset
|
||||
])
|
||||
|
||||
camera_pose = look_at(camera_position, center)
|
||||
|
||||
camera = pyrender.PerspectiveCamera(
|
||||
yfov=fov_y
|
||||
)
|
||||
|
||||
scene.add(camera, pose=camera_pose)
|
||||
|
||||
renderer = pyrender.OffscreenRenderer(
|
||||
viewport_width=args.width,
|
||||
viewport_height=args.height
|
||||
)
|
||||
|
||||
color, depth = renderer.render(scene)
|
||||
|
||||
Image.fromarray(color).save(args.output)
|
||||
|
||||
renderer.delete()
|
||||
|
||||
print(f"Saved: {args.output}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
146
blender-vision.py
Normal file
146
blender-vision.py
Normal file
@@ -0,0 +1,146 @@
|
||||
# blender_render_script.py
|
||||
import bpy
|
||||
import os
|
||||
import math
|
||||
from array import array
|
||||
from mathutils import Vector
|
||||
|
||||
# NOTE: this script runs inside Blender's bundled Python, which usually has
|
||||
# neither PIL nor numpy, so the 2x2 grid is assembled with Blender's own image
|
||||
# API instead.
|
||||
|
||||
# These will be replaced by the main script before running
|
||||
MODEL_PATH = r"{{MODEL_PATH}}"
|
||||
OUTPUT_GRID_PATH = r"{{OUTPUT_GRID_PATH}}"
|
||||
|
||||
# ====================== BLENDER RENDER LOGIC ======================
|
||||
# Start from a clean scene. open_mainfile("") raises, so just delete the
|
||||
# default cube/camera/light instead.
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
bpy.ops.object.delete()
|
||||
|
||||
# Import GLB (Blender's glTF importer handles KHR_draco_mesh_compression)
|
||||
bpy.ops.import_scene.gltf(filepath=MODEL_PATH)
|
||||
|
||||
# Select meshes and compute bounds
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
for obj in bpy.data.objects:
|
||||
if obj.type == 'MESH':
|
||||
obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
|
||||
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS')
|
||||
|
||||
# Calculate scene bounds
|
||||
min_pt = Vector((float('inf'),) * 3)
|
||||
max_pt = Vector((-float('inf'),) * 3)
|
||||
|
||||
for obj in bpy.data.objects:
|
||||
if obj.type == 'MESH':
|
||||
for vert in obj.data.vertices:
|
||||
world_coord = obj.matrix_world @ vert.co
|
||||
min_pt = Vector((min(min_pt.x, world_coord.x), min(min_pt.y, world_coord.y), min(min_pt.z, world_coord.z)))
|
||||
max_pt = Vector((max(max_pt.x, world_coord.x), max(max_pt.y, world_coord.y), max(max_pt.z, world_coord.z)))
|
||||
|
||||
center = (min_pt + max_pt) / 2
|
||||
extents = max_pt - min_pt
|
||||
max_dim = max(extents.x, extents.y, extents.z) or 1.0
|
||||
|
||||
print(f"Blender bounds → Center: {center} | Max Dim: {max_dim:.3f}")
|
||||
|
||||
# Scene settings
|
||||
scene = bpy.context.scene
|
||||
scene.render.resolution_x = 512
|
||||
scene.render.resolution_y = 512
|
||||
scene.render.image_settings.file_format = 'PNG'
|
||||
# EEVEE was renamed BLENDER_EEVEE_NEXT in Blender 4.2+; pick whatever this build
|
||||
# actually offers so the script works across versions.
|
||||
engine_options = scene.render.bl_rna.properties['engine'].enum_items.keys()
|
||||
if 'BLENDER_EEVEE_NEXT' in engine_options:
|
||||
scene.render.engine = 'BLENDER_EEVEE_NEXT'
|
||||
elif 'BLENDER_EEVEE' in engine_options:
|
||||
scene.render.engine = 'BLENDER_EEVEE'
|
||||
scene.eevee.taa_render_samples = 64
|
||||
scene.render.film_transparent = True
|
||||
|
||||
# Add sunlight
|
||||
light = bpy.data.lights.new(name="Sun", type='SUN')
|
||||
light.energy = 5.0
|
||||
light_node = bpy.data.objects.new("Sun", light)
|
||||
bpy.context.collection.objects.link(light_node)
|
||||
light_node.rotation_euler = (math.radians(45), 0, math.radians(30))
|
||||
|
||||
# Camera
|
||||
cam_data = bpy.data.cameras.new(name='Camera')
|
||||
cam = bpy.data.objects.new('Camera', cam_data)
|
||||
bpy.context.collection.objects.link(cam)
|
||||
scene.camera = cam
|
||||
|
||||
distance = max_dim * 2.5
|
||||
|
||||
views = [
|
||||
("front", 8, 0),
|
||||
("side", 5, 90),
|
||||
("top", 75, 45),
|
||||
("angle", -12, 35),
|
||||
]
|
||||
|
||||
temp_dir = os.path.dirname(OUTPUT_GRID_PATH)
|
||||
image_paths = []
|
||||
|
||||
for i, (name, pitch, yaw) in enumerate(views):
|
||||
pitch_rad = math.radians(pitch)
|
||||
yaw_rad = math.radians(yaw)
|
||||
|
||||
dx = distance * math.cos(pitch_rad) * math.sin(yaw_rad)
|
||||
dy = -distance * math.cos(pitch_rad) * math.cos(yaw_rad)
|
||||
dz = distance * math.sin(pitch_rad)
|
||||
|
||||
cam.location = center + Vector((dx, dy, dz))
|
||||
direction = center - cam.location
|
||||
cam.rotation_euler = direction.to_track_quat('-Z', 'Y').to_euler()
|
||||
|
||||
output = os.path.join(temp_dir, f"view_{i}.png")
|
||||
scene.render.filepath = output
|
||||
bpy.ops.render.render(write_still=True)
|
||||
image_paths.append(output)
|
||||
print(f"Rendered view: {name}")
|
||||
|
||||
# Create 2x2 grid using only Blender's image API (no PIL/numpy required).
|
||||
GRID = 1024
|
||||
bg = (30 / 255.0, 30 / 255.0, 35 / 255.0, 1.0)
|
||||
dest = array('f', list(bg) * (GRID * GRID))
|
||||
|
||||
# (screen-space top-left x, top-left y) for each tile; Blender images are stored
|
||||
# bottom-up, so convert the y origin accordingly.
|
||||
placements = [(0, 0), (512, 0), (0, 512), (512, 512)]
|
||||
|
||||
for path, (px, py) in zip(image_paths, placements):
|
||||
img = bpy.data.images.load(path)
|
||||
sw, sh = img.size
|
||||
src = array('f', [0.0] * (sw * sh * 4))
|
||||
img.pixels.foreach_get(src)
|
||||
|
||||
base_row = GRID - py - sh # bottom-up row of the tile's bottom edge
|
||||
for sr in range(sh):
|
||||
grid_row = base_row + sr
|
||||
if grid_row < 0 or grid_row >= GRID:
|
||||
continue
|
||||
d0 = (grid_row * GRID + px) * 4
|
||||
s0 = sr * sw * 4
|
||||
dest[d0:d0 + sw * 4] = src[s0:s0 + sw * 4]
|
||||
bpy.data.images.remove(img)
|
||||
|
||||
grid_img = bpy.data.images.new("grid", width=GRID, height=GRID, alpha=True)
|
||||
grid_img.pixels.foreach_set(dest)
|
||||
grid_img.filepath_raw = OUTPUT_GRID_PATH
|
||||
grid_img.file_format = 'PNG'
|
||||
grid_img.save()
|
||||
print(f"✅ Blender 4-view grid saved → {OUTPUT_GRID_PATH}")
|
||||
|
||||
# Cleanup temp view files
|
||||
for p in image_paths:
|
||||
try:
|
||||
os.remove(p)
|
||||
except:
|
||||
pass
|
||||
17
chat_template.jinja
Normal file
17
chat_template.jinja
Normal file
@@ -0,0 +1,17 @@
|
||||
{%- for message in messages %}
|
||||
{%- if message.role == 'system' %}
|
||||
{{- '<|im_start|>system\n' }}
|
||||
{{- 'You are Illustrious, a zero-prose compiler converting text to 3D coordinate streams. Output ONLY raw tokens. No commentary.\n' }}
|
||||
{{- 'Schema: [identity][x,y,z,rx,ry,rz,scale,modifiers]\n' }}
|
||||
{{- 'Identity: Accepts geometric primitives (sphere, box, cylinder, etc.) OR any lowercase asset noun (pillar, chair, tree) natively.\n' }}
|
||||
{{- 'Metrics & Operators: fw/fd/fh=footprints. -%=CSG cut, @0=root, @N=anchor, "@0,@1"=midpoint, @idx=index loop, sym=mirror.\n' }}
|
||||
{{- 'Layout Rule: If structural placement is implied (e.g., "holding up", "between"), use explicit relative anchors or coordinates. Use sequential index loops (fw*@idx) ONLY for unlinked asset lists/clutter.\n' }}
|
||||
{{- 'User: Two stone pillars holding up a heavy steel crossbeam mesh across the top. Assistant: [pillar][-4,0,0,0,0,0,1][pillar][4,0,0,0,0,0,1][crossbeam][0,0,fh,@0,@1,1]\n' }}
|
||||
{{- 'User: clutter: rock, barrel, crate. Assistant: [rock][0,0,0,0,0,0,1][barrel][fw*@idx,fd*@idx,0,0,0,0,1][crate][fw*@idx,fd*@idx,0,0,0,0,1]<|im_end|>\n' }}
|
||||
{%- else %}
|
||||
{{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>\n' }}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{%- if add_generation_prompt %}
|
||||
{{- '<|im_start|>assistant\n' }}
|
||||
{%- endif %}
|
||||
242
dataset/sme-altman-complex.json
Normal file
242
dataset/sme-altman-complex.json
Normal file
@@ -0,0 +1,242 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A wooden picnic table with two long benches running parallel on its left and right sides."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[picnic table][0,0,0,0,0,0,[2.5,1.2,0.2]][bench][sym(fw),0,-hh,0,0,0,[1.8,0.4,0.3]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A watchtower standing on top of a broad stone platform."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stone platform][0,0,0,0,0,0,[4,4,0.5]][watchtower][0,0,fh,0,0,0,2.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A small campfire directly in front of a wooden cabin."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden cabin][0,0,0,0,0,0,2.5][campfire][0,fd,0,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A lighthouse with a rotating beacon sphere hovering above its roof."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[lighthouse][0,0,0,0,0,0,3.0][beacon sphere][0,0,2fh,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A castle gate flanked by two defensive towers positioned a moderate distance apart."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[tower][-3fw,0,0,0,0,0,2.0][tower][3fw,0,0,0,0,0,2.0][castle gate][@0,@1][0,0,0,0,0,0,[2,0.5,2]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A large boulder with a tiny bird perched on top of it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[boulder][0,0,0,0,0,0,2.0][bird][0,0,fh,0,0,0,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Three streetlights lined up along a road at equal spacing."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[streetlight][0,0,0,0,0,0,1.0][streetlight][fd*@idx,0,0,0,0,0,1.0][streetlight][fd*@idx,0,0,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A satellite dish mounted on the right side of a communication building."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[communication building][0,0,0,0,0,0,2.0][satellite dish][fw,0,hh,0,45,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A decorative fountain centered in a courtyard with four flower planters symmetrically placed around it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[fountain][0,0,0,0,0,0,1.5][flower planter][sym(2fw),0,0,0,0,0,0.5][flower planter][0,sym(2fd),0,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A cargo crate with a warning beacon attached to its upper left corner."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cargo crate][0,0,0,0,0,0,1.0][warning beacon][-hw,0,fh,0,0,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A suspension bridge supported by two massive towers with the roadway spanning between them."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[bridge tower][-4fw,0,0,0,0,0,3.0][bridge tower][4fw,0,0,0,0,0,3.0][bridge roadway][@0,@1][0,0,hh,0,0,0,[8,0.5,0.2]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A treasure chest partially hidden behind a giant rock."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[giant rock][0,0,0,0,0,0,2.5][treasure chest][hw,-hd,hh,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A floating crystal hovering high above an ancient pedestal."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[ancient pedestal][0,0,0,0,0,0,1.2][floating crystal][0,0,2fh,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A train engine with two passenger cars directly behind it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[train engine][0,0,0,0,90,0,1.5][passenger car][0,-fd,0,0,90,0,1.2][passenger car][0,-fd*@idx,0,0,90,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A giant tree with a wooden treehouse attached halfway up its trunk."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[giant tree][0,0,0,0,0,0,4.0][treehouse][fw,0,hh,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A stone altar with two torches standing on either side."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stone altar][0,0,0,0,0,0,[2,1,1]][torch][sym(fw),0,fh,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A submarine resting beneath the ocean surface with a buoy floating directly above it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[submarine][0,0,0,0,90,0,2.0][buoy][0,0,2fh,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A large warehouse and a security booth positioned near its front-left corner."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[warehouse][0,0,0,0,0,0,4.0][security booth][-fw,fd,0,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A radar tower with four antenna dishes mounted around its upper section."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[radar tower][0,0,0,0,0,0,3.0][antenna dish][sym(fw),0,fh,0,0,0,0.3][antenna dish][0,sym(fd),fh,0,90,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A ceremonial stone circle with a glowing crystal suspended exactly in the middle above the stones."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stone pillar][-fw,0,0,0,0,0,1.0][stone pillar][fw,0,0,0,0,0,1.0][stone pillar][0,-fd,0,0,0,0,1.0][stone pillar][0,fd,0,0,0,0,1.0][glowing crystal][@0,@1][0,0,2fh,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
242
dataset/sme-altman-gimble.json
Normal file
242
dataset/sme-altman-gimble.json
Normal file
@@ -0,0 +1,242 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Determine the volume scale properties for an antique amphora vessel."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.15,0.15,0.95,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Determine the volume scale properties for a giant squid statue."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.85,0.90,0.25,90,180,45,6.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Determine the volume scale properties for a medieval trebuchet."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.75,0.55,0.40,0,90,0,5.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Determine the volume scale properties for a crystal obelisk. Include volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.10,0.10,0.98,0,0,0,4.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Calculate the volume scale data for a ceremonial gong."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.65,0.65,0.10,90,0,0,2.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate volume scale values for a weathered ship anchor."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.25,0.20,0.85,0,0,0,1.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Provide the volume scale properties of a giant mushroom."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.60,0.60,0.90,0,0,180,3.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Evaluate volume scale for a grandfather clock."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.20,0.15,0.95,0,0,0,2.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Determine the volume scale characteristics of a crescent moon monument."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.70,0.85,0.20,90,45,90,5.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Compute volume scale values for a stone gargoyle."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.45,0.65,0.55,15,180,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate volume scale information for a nautical buoy."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.35,0.35,0.95,0,0,0,1.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Determine the volume scale data for a carnival hot air balloon."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.50,0.50,0.98,0,0,0,8.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Calculate volume scale values for an ancient sarcophagus."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.90,0.55,0.15,90,0,0,2.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Provide volume scale properties for a spiral seashell."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.65,0.80,0.35,45,270,180,0.35]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Determine the volume scale characteristics of a giant tuning fork."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.20,0.25,0.95,0,0,0,3.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate volume scale information for a decorative samovar."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.30,0.30,0.90,0,0,0,0.9]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Calculate volume scale values for a giant horseshoe."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.85,0.85,0.15,90,0,180,2.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Determine the volume scale properties of a pagoda tower."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.25,0.25,0.98,0,0,0,7.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Provide volume scale data for a dragon skull relic."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.75,0.60,0.40,30,180,15,2.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate the volume scale values for a giant chess knight piece."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[0.45,0.70,0.90,0,270,0,1.8]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
242
dataset/sme-altman-positional.json
Normal file
242
dataset/sme-altman-positional.json
Normal file
@@ -0,0 +1,242 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A weather vane mounted directly above a barn roof."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[barn roof][0,0,0,0,0,0,2.0][weather vane][0,0,fh,0,0,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A scarecrow standing a few paces in front of a cornfield."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cornfield][0,0,0,0,0,0,3.0][scarecrow][0,3fd,0,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A mailbox positioned off to the front-right of a country road."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[country road][0,0,0,0,0,0,[1,8,0.1]][mailbox][fw,fd,0,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A crow peeking out from behind a gravestone."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[gravestone][0,0,0,0,0,0,1.0][crow][hw,-hd,hh,0,0,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A lantern hanging underneath a wooden porch."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden porch][0,0,0,0,0,0,2.0][lantern][0,0,-fh,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A fishing boat floating far away from a dock."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[dock][0,0,0,0,0,0,2.0][fishing boat][0,4fd,0,0,0,0,1.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A park bench directly to the left of a drinking fountain."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[drinking fountain][0,0,0,0,0,0,1.0][park bench][-fw,0,0,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A squirrel perched on top of a tree stump."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[tree stump][0,0,0,0,0,0,1.0][squirrel][0,0,fh,0,0,0,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A wagon parked directly behind a farmhouse."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[farmhouse][0,0,0,0,0,0,2.5][wagon][0,-fd,0,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A windmill standing alongside a grain silo."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[grain silo][0,0,0,0,0,0,2.0][windmill][2fw,0,0,0,0,0,2.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A cat curled up beneath a wooden chair."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden chair][0,0,0,0,0,0,1.0][cat][0,0,-fh,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A chalkboard mounted on the rear wall behind a teacher's desk."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[teacher desk][0,0,0,0,0,0,1.5][chalkboard][0,-fd,fh,0,0,0,1.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A coffee mug resting on the right edge of an office desk."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[office desk][0,0,0,0,0,0,2.0][coffee mug][fw,0,fh,0,0,0,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A lifeguard chair way off to the left of a swimming pool."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[swimming pool][0,0,0,0,0,0,[5,8,0.5]][lifeguard chair][-4fw,0,0,0,0,0,1.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A beach umbrella hovering over a lounge chair."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[lounge chair][0,0,0,0,0,0,1.0][beach umbrella][0,0,2fh,0,0,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A seagull gliding far above a lighthouse."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[lighthouse][0,0,0,0,0,0,3.0][seagull][0,0,4fh,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A backpack tucked slightly behind a camping tent."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[camping tent][0,0,0,0,0,0,1.5][backpack][hw,-hd,hh,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A telescope standing diagonally back-left from an observatory dome."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[observatory dome][0,0,0,0,0,0,2.5][telescope][-fw,-fd,0,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A knight statue guarding the forefront of a castle entrance."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[castle entrance][0,0,0,0,0,0,3.0][knight statue][0,fd,0,0,0,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A treasure map spread out underneath a compass."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[compass][0,0,0,0,0,0,0.3][treasure map][0,0,-fh,0,0,0,[1.5,1.5,0.05]]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
242
dataset/sme-altman-rooms.json
Normal file
242
dataset/sme-altman-rooms.json
Normal file
@@ -0,0 +1,242 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A grandfather clock consisting of a tall rectangular cabinet, a circular clock face mounted near the top front, and a pendulum sphere hanging beneath it inside the lower body."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[clock cabinet][0,0,0,0,0,0,[1,1,4]][clock face][0,hd,fh*0.75,90,0,0,0.4][pendulum sphere][0,0,hh,0,0,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A pirate ship with a long hull, three vertical mast cylinders rising from the deck, and triangular sails attached midway up each mast."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[ship hull][0,0,0,0,0,0,[5,1.5,1]][mast cylinder][0,0,fh,0,0,0,[0.15,0.15,3]][mast cylinder][fd,0,fh,0,0,0,[0.15,0.15,3]][mast cylinder][-fd,0,fh,0,0,0,[0.15,0.15,3]][sail mesh][0,0,fh*0.5,0,0,0,[1,0.1,1.5]][sail mesh][fd,0,fh*0.5,0,0,0,[1,0.1,1.5]][sail mesh][-fd,0,fh*0.5,0,0,0,[1,0.1,1.5]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A gas station canopy supported by four corner pillars, with two fuel pumps directly underneath the center."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[canopy roof][0,0,0,0,0,0,[6,4,0.2]][support pillar][sym(hw),sym(hd),-fh,0,0,0,[0.2,0.2,3]][fuel pump][-hw*0.4,0,-hh,0,0,0,0.5][fuel pump][hw*0.4,0,-hh,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A locomotive engine with a smokestack rising from the front top section, and two headlight spheres mounted on either side of the nose."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[locomotive body][0,0,0,0,0,0,[4,1.5,2]][smokestack][0,hd,fh,0,0,0,[0.3,0.3,1]][headlight sphere][sym(hw*0.5),fd,hh,0,0,0,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A treasure chest with a rounded lid sitting on top, and two decorative metal handles attached to the left and right sides."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[treasure chest base][0,0,0,0,0,0,[2,1.2,1]][rounded lid][0,0,fh,0,0,0,[1,1,0.5]][metal handle][sym(fw),0,hh,90,0,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A castle gatehouse with two guard towers standing on both outer sides and a banner hanging above the central entrance."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[gatehouse][0,0,0,0,0,0,[3,2,3]][guard tower][sym(2fw),0,0,0,0,0,1.5][banner][0,hd,fh*0.6,0,0,0,[1.2,0.05,0.8]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A laboratory workstation with a microscope positioned on the back left corner, and three sample vials lined up across the front edge."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[lab workstation][0,0,0,0,0,0,[3,2,1]][microscope][-fw+0.3,-fd+0.3,fh,0,0,0,0.6][sample vial][-fw*0.5,fd,fh,0,0,0,0.1][sample vial][0,fd,fh,0,0,0,0.1][sample vial][fw*0.5,fd,fh,0,0,0,0.1]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A wizard hat cone with a circular brim torus wrapped around the bottom and a glowing jewel embedded on the front."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wizard hat cone][0,0,0,0,0,0,[1,1,2]][hat brim torus][0,0,-hh,90,0,0,1.2][glowing jewel][0,hd,hh,0,0,0,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A drawbridge platform with two heavy chains rising diagonally upward toward support points on either side."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[drawbridge platform][0,0,0,0,0,0,[4,1,0.2]][chain cable][sym(hw),-fd,fh,45,0,0,[0.05,0.05,2.5]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A snowman made from a large lower sphere, a medium sphere resting on top, a smaller head sphere above that, and a carrot cone sticking from the front."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[lower snow sphere][0,0,0,0,0,0,1.5][middle snow sphere][0,0,fh,0,0,0,1.0][head snow sphere][0,0,2fh,0,0,0,0.7][carrot cone][0,hd,2fh,0,90,0,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A medieval battering ram with four wheels underneath and a peaked roof shelter centered above."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[battering ram body][0,0,0,0,90,0,[4,1,1]][wheel][sym(hw),sym(hd),-hh,90,0,0,0.3][roof shelter][0,0,fh,0,0,0,[1.2,1.2,0.8]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A vending machine with a transparent display window occupying the upper front half and a dispensing tray recessed near the bottom."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[vending machine][0,0,0,0,0,0,[1.5,1,3]][display window][0,hd,fh*0.5,0,0,0,[0.8,0.05,1.2]][dispensing tray][0,hd,-hh*0.5,0,0,0,[-0.5,0.2,-0.2]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A helicopter fuselage with a long tail boom extending behind it, a main rotor on top, and a tail rotor mounted at the rear end."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[helicopter fuselage][0,0,0,0,0,0,[3,1.5,1.5]][tail boom][0,-fd*2,0,0,0,0,[0.2,3,0.2]][main rotor][0,0,fh,0,0,0,[3,0.1,0.1]][tail rotor][0,-fd*3,0,90,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A jukebox cabinet with a glowing arch mounted over the top front and two speaker circles embedded low on both sides."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[jukebox cabinet][0,0,0,0,0,0,[2,1,3]][glowing arch][0,hd,fh,0,0,0,[1.2,0.1,0.8]][speaker circle][sym(hw*0.6),hd,-hh*0.3,90,0,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A fountain basin with a central statue rising from the middle and four water jets surrounding it at equal distances."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[fountain basin][0,0,0,0,0,0,[4,4,0.5]][central statue][0,0,fh,0,0,0,1.2][water jet][hw,0,fh,0,0,0,0.1][water jet][-hw,0,fh,0,0,0,0.1][water jet][0,hd,fh,0,0,0,0.1][water jet][0,-hd,fh,0,0,0,0.1]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A king's throne with two lion sculptures sitting on the armrests and a crown emblem centered high on the backrest."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[royal throne][0,0,0,0,0,0,[2,2,3]][lion sculpture][sym(hw),0,hh,0,0,0,0.4][crown emblem][0,0,fh,0,0,0,0.25]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A space capsule with three landing legs folded outward beneath the body and a communication antenna protruding from the top."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[space capsule][0,0,0,0,0,0,1.5][landing leg][hw,0,-hh,30,0,0,0.5][landing leg][-hw,0,-hh,-30,0,0,0.5][landing leg][0,-hd,-hh,0,30,0,0.5][antenna][0,0,fh,0,0,0,[0.05,0.05,0.8]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A record player base with a circular platter centered on top and a tonearm extending inward from the right side."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[record player base][0,0,0,0,0,0,[3,2,0.5]][record platter][0,0,fh,90,0,0,0.8][tonearm][fw,0,fh,0,-45,0,[0.8,0.05,0.05]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A giant mushroom with a thick stem cylinder supporting a wide cap overhead, and several tiny mushrooms clustered around the base."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[mushroom stem][0,0,0,0,0,0,[0.8,0.8,3]][mushroom cap][0,0,fh,0,0,0,[3,3,1]][tiny mushroom][hw,0,0,0,0,0,0.2][tiny mushroom][-hw,0,0,0,0,0,0.2][tiny mushroom][0,hd,0,0,0,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A ceremonial altar block with two candles standing at the front corners, a sacred book resting in the center, and a floating halo ring suspended above."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[ceremonial altar][0,0,0,0,0,0,[3,2,1]][candle][-hw,fd,fh,0,0,0,0.25][candle][hw,fd,fh,0,0,0,0.25][sacred book][0,0,fh,0,0,0,[0.8,0.6,0.1]][halo ring][0,0,2fh,90,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
242
dataset/sme-altman-terrain.json
Normal file
242
dataset/sme-altman-terrain.json
Normal file
@@ -0,0 +1,242 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A tranquil alpine meadow terrain with a crystal lake resting far ahead, and a solitary pine tree standing near the shoreline."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[alpine meadow terrain][0,0,0,0,0,0,[25,25,0.2],noise=0.2][crystal lake][0,4fd,0,0,0,0,[8,6,0.1]][solitary pine tree][0,-fd,0,0,0,0,3.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A rolling hillside terrain with a winding dirt path leading toward the front, and a wooden fence running alongside the right edge of the trail."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[rolling hillside terrain][0,0,0,0,0,0,[20,20,2],noise=0.5][dirt path][0,fd,0,0,0,0,[1,8,0.05]][wooden fence][fw,0,0,0,0,0,[0.2,8,0.8]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A flowering valley terrain with a giant cherry blossom tree in the center and a small picnic blanket spread directly beneath it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[flowering valley terrain][0,0,0,0,0,0,[18,18,1],noise=0.3][giant cherry blossom tree][0,0,0,0,0,0,5.0][picnic blanket][0,0,-hh,0,0,0,[1.5,1.5,0.02]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A coastal cliff terrain overlooking the sea with a lighthouse perched on the front-right edge and a seagull gliding high above it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[coastal cliff terrain][0,0,0,0,0,0,[25,20,4],noise=0.7][lighthouse][fw,fd,0,0,0,0,4.0][seagull][0,0,4fh,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A snowy tundra terrain with a frozen pond near the center and a wooden cabin tucked slightly behind it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[snowy tundra terrain][0,0,0,0,0,0,[20,20,0.3],noise=0.2][frozen pond][0,0,0,0,0,0,[5,4,0.05]][wooden cabin][hw,-hd,hh,0,0,0,2.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A lush rainforest terrain with a waterfall cascading from a rocky cliff far ahead and a pool resting directly underneath it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[rainforest terrain][0,0,0,0,0,0,[30,30,3],noise=0.8][rock cliff][0,4fd,0,0,0,0,[8,2,6]][waterfall][0,0,0,0,0,0,[2,0.2,5]][pool][0,0,-fh,0,0,0,[5,3,0.1]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A golden wheat field terrain with a rustic windmill standing far to the left and a dirt road stretching toward it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[golden wheat field terrain][0,0,0,0,0,0,[25,25,0.1]][rustic windmill][-4fw,0,0,0,0,0,4.0][dirt road][-fd,0,0,0,0,0,[1,10,0.05]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A tropical beach terrain with a curved palm tree near the shoreline and a hammock suspended beside it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[tropical beach terrain][0,0,0,0,0,0,[30,15,0.1]][curved palm tree][0,fd,0,0,0,15,3.5][hammock][fw,0,hh,0,0,0,[2,0.5,0.2]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A canyon terrain with a narrow rope bridge spanning between two stone pillars and a traveler standing at one end."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[canyon terrain][0,0,0,0,0,0,[30,30,5],noise=0.9][stone pillar][-3fw,0,0,0,0,0,3.0][stone pillar][3fw,0,0,0,0,0,3.0][rope bridge][@0,@1][0,0,fh,0,0,0,[6,0.3,0.1]][traveler][-fw,0,fh,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A lavender field terrain with a stone well in the center and a wooden bucket resting beside it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[lavender field terrain][0,0,0,0,0,0,[18,18,0.1]][stone well][0,0,0,0,0,0,1.5][wooden bucket][fw,0,0,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A river valley terrain with a small arched bridge crossing the water and wildflowers growing along both sides."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[river valley terrain][0,0,0,0,0,0,[25,25,1],noise=0.4][river][0,0,0,0,0,0,[2,15,0.05]][arched bridge][0,0,fh,0,0,0,[3,1,0.5]][wildflowers][sym(fw),0,0,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A misty moor terrain with a lonely standing stone near the center and a raven perched on top."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[misty moor terrain][0,0,0,0,0,0,[20,20,0.5],noise=0.3][standing stone][0,0,0,0,0,0,2.0][raven][0,0,fh,0,0,0,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A mountain lake terrain with a wooden dock extending out over the water and a canoe tied to its right side."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[mountain lake terrain][0,0,0,0,0,0,[25,25,0.2]][wooden dock][0,fd,0,0,0,0,[1,5,0.1]][canoe][fw,0,0,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A sunflower field terrain with a scarecrow standing in the middle and a crow perched on its shoulder."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[sunflower field terrain][0,0,0,0,0,0,[20,20,0.1]][scarecrow][0,0,0,0,0,0,2.0][crow][hw,0,fh*0.5,0,0,0,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A rugged volcanic terrain with a glowing lava pool near the front and a blackened rock arch rising behind it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[volcanic terrain][0,0,0,0,0,0,[30,30,3],noise=1.0][lava pool][0,fd,0,0,0,0,[6,4,0.1]][rock arch][0,-fd,0,0,0,0,[5,1,4]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A peaceful orchard terrain with rows of fruit trees and a wooden cart parked along the front edge."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[orchard terrain][0,0,0,0,0,0,[25,25,0.1]][fruit tree][-fw,0,0,0,0,0,2.5][fruit tree][0,0,0,0,0,0,2.5][fruit tree][fw,0,0,0,0,0,2.5][wooden cart][0,fd,0,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A forest clearing terrain with a stone campfire ring at the center and four log seats arranged around it."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[forest clearing terrain][0,0,0,0,0,0,[18,18,0.2]][campfire ring][0,0,0,0,0,0,1.0][log seat][hw,0,0,0,0,0,0.8][log seat][-hw,0,0,0,0,0,0.8][log seat][0,hd,0,0,0,0,0.8][log seat][0,-hd,0,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A dramatic fjord terrain with steep cliffs on both sides and a sailing boat drifting through the center channel."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[fjord terrain][0,0,0,0,0,0,[35,20,6],noise=0.9][cliff wall][-4fw,0,0,0,0,0,[3,20,6]][cliff wall][4fw,0,0,0,0,0,[3,20,6]][sailing boat][0,0,0,0,0,0,1.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A meadow terrain at sunset with a lone gazebo near the center and climbing vines wrapping around its posts."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[sunset meadow terrain][0,0,0,0,0,0,[20,20,0.1]][gazebo][0,0,0,0,0,0,2.5][climbing vines][0,0,0,0,0,0,1.0,noise=0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A serene garden terrain with a koi pond in the middle, a stone lantern along the shore, and a curved footbridge arching across the water."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[garden terrain][0,0,0,0,0,0,[15,15,0.1]][koi pond][0,0,0,0,0,0,[5,4,0.1]][stone lantern][fw,0,0,0,0,0,0.8][curved footbridge][0,0,fh,0,0,0,[3,1,0.5]]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
170
dataset/sme-gemini-combos.json
Normal file
170
dataset/sme-gemini-combos.json
Normal file
@@ -0,0 +1,170 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An elongated sphere with fuzzy stuff on top, with two smaller flat spheres on the side about 20% the size of the first sphere, and a rounded cone in the middle front, and a depressed skinny moon underneath about 15% tall and 50% wide for a mouth, and 2 depressed spheres equally spaced divets for eyes."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[elongated sphere][0,0,0,0,0,0,[1,1,1.5]][fuzzy sphere][0,0,fh,0,0,0,[1,1,0.2],noise=0.3][flat sphere][sym(fw),0,hh,0,0,0,0.2][rounded cone][0,hd,hh,0,0,0,0.25][skinny crescent][0,hd+0.05,hh*0.5,0,0,0,[-0.5,1,-0.15]][depressed sphere][sym(hw*0.4),hd,hh*1.2,0,0,0,-0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A table, a plate on top of the table, and a cup next to the plate."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden table][0,0,0,0,0,0,1.2][ceramic plate][0,0,fh,0,0,0,0.25][coffee cup][@1][fw,0,0,0,0,0,0.12]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An elephant at the center, a mouse way off to the right 10 units away, and a bird hovering 5 units directly above the elephant."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[large elephant][0,0,0,0,0,0,3.0][tiny mouse][abs][10.0,0,0,0,0,0,0.1][flying bird][@0][0,0,fh+5.0,0,0,0,0.25]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A couch on the left, a chair on the right, and a small rug placed right between them."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[couch][-4fw,0,0,0,0,0,2.0][chair][4fw,0,0,0,0,0,0.8][small rug][@0,@1][0,0,0,0,0,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A box with a ball floating over it, a capsule buried deep under, and another cylinder topled over face down far to the left."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden box][0,0,0,0,0,0,1.0][floating ball][0,0,fh+0.5,0,0,0,0.3][buried capsule][0,0,-fh-0.5,0,0,0,0.4][toppled cylinder][-4fw,0,0,90,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A giant pillar with a torus wrapped around it at the vertical center, looking sideways left."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[giant pillar][0,0,0,0,0,0,[1,1,3]][wrapped torus][0,0,hh,0,-90,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A small cube that is tightly packed against the front profile of a massive block, flanked by tiny spheres on the sides."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[massive block][0,0,0,0,0,0,3.0][small cube][0,fd,0,0,0,0,0.2][tiny sphere][@0][sym(fw),0,hh,0,0,0,0.1]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A row of four boxes lined up one after another starting from the center."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden box][0,0,0,0,0,0,1.0][wooden box][fw*@idx,0,0,0,0,0,1.0][wooden box][fw*@idx,0,0,0,0,0,1.0][wooden box][fw*@idx,0,0,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A main sphere with a small capsule sticking out of its front-right diagonal face, slanted slightly."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[main sphere][0,0,0,0,0,0,1.0][small capsule][hw,hd+0.1,0,0,0,45,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A table at the origin, a book resting on top of the table, a coffee mug sitting directly on top of the book, and an absolute override chair shifted 5 units up in the air away from everything."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden table][0,0,0,0,0,0,1.2][resting book][0,0,fh,0,0,0,0.25][coffee mug][0,0,fh,0,0,0,0.12][high chair][abs][0,0,5.0,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A car base with two pairs of wheels on both sides equally spaced along the bottom width profiles."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[car base][0,0,0,0,0,0,[2,1,0.5]][rubber wheel][sym(hw*0.5),-hd,-hh,0,90,0,0.3][rubber wheel][sym(hw*0.5),hd,-hh,0,90,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A hollowed divet in a flat plane serving as a pool basin, with a tiny ladder perched on the right edge."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[flat plane][0,0,0,0,0,0,[4,4,0.1]][pool basin][0,0,0,0,0,0,[-1,1,-0.1]][tiny ladder][@0][fw,0,fh,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A tree trunk cylinder, a giant green ball canopy sitting on top of the trunk, and a small fruit sphere hanging directly underneath the canopy."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden trunk][0,0,0,0,0,0,[0.2,0.2,2]][green canopy][0,0,fh,0,0,0,3.0][fruit sphere][0,0,-fh,0,0,0,0.1]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A pillar on the far left, another matching pillar far to the right, and a heavy ceiling slab between them resting on their tops."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[left pillar][-4fw,0,0,0,0,0,3.0][right pillar][4fw,0,0,0,0,0,3.0][heavy ceiling slab][@0,@1][0,0,fh,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
98
dataset/sme-gemini-complex.json
Normal file
98
dataset/sme-gemini-complex.json
Normal file
@@ -0,0 +1,98 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A standard monitor screen box with two small speakers flanking its outer left and right sides."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[monitor screen][0,0,0,0,0,0,[1.5,0.1,1.0]][small speaker][sym(fw),0,hh,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A house roof crescent perched on the right edge of a massive stone foundation slab."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stone foundation][0,0,0,0,0,0,[4,4,1]][roof crescent][fw,0,fh,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An archway frame consisting of a post cylinder on the left, a post cylinder on the right, and a curved torus section resting right between them."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[left post][-3fw,0,0,0,0,0,2.0][right post][3fw,0,0,0,0,0,2.0][curved archway][@0,@1][0,0,fh,90,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A target bullseye board with a concentric smaller sphere encased completely within its interior volume."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[bullseye board][0,0,0,90,0,0,[2,2,0.1]][inner sphere][0,0,0,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A high-precision laser array where three emitting tubes line them up in a row staring way ahead forward."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[emitting tube][0,0,0,0,90,0,0.5][emitting tube][fw*@idx,0,0,0,90,0,0.5][emitting tube][fw*@idx,0,0,0,90,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A giant central statue, a stone path leading out from in front of it, and a tiny signpost perched on the right edge of that path."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[giant statue][0,0,0,0,0,0,4.0][stone path][0,4fd,0,0,0,0,[1,4,0.1]][tiny signpost][fw,0,fh,0,0,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A smooth landscape plane with an absolute coordinate platform shifted 5 units up, and a drone capsule hovering over that platform."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[landscape plane][0,0,0,0,0,0,[10,10,0.1]][override platform][abs][0,0,5.0,0,0,0,1.0][drone capsule][0,0,fh+0.5,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A large crate box with a spiky protective shield wrapping around it tightly."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[large crate][0,0,0,0,0,0,1.5][spiky shield][0,0,0,0,0,0,1.2,noise=0.4]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
242
dataset/sme-gemini-gimble.json
Normal file
242
dataset/sme-gemini-gimble.json
Normal file
@@ -0,0 +1,242 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Analyze a standard taxidermy narwhal skull with its tusk for its baseline 3D composition and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[narwhal skull][0.2,0.1,0.7,90,0,0,2.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Instantiate an architectural model of a multi-tiered gothic cathedral spire and calculate its volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[gothic spire][0.1,0.1,0.8,0,0,0,4.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Spawn a heavy blacksmithing anvil with a single horn to determine its layout orientation and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[blacksmith anvil][0.6,0.3,0.1,0,0,0,0.6]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Render an antique glass apothecary carboy filled with fluid to assess its orientation properties and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[apothecary carboy][0.4,0.4,0.2,0,0,90,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate a standard fiberglass wind turbine blade asset and establish its structural volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[turbine blade][0.05,0.9,0.05,-90,0,0,15.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Place an ancient stone Moai monolithic statue from Easter Island and evaluate its center of mass volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[moai statue][0.3,0.3,0.4,0,0,0,4.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Model a heavy deep-sea diving helmet made of brass and copper to configure its center of gravity and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[diving helmet][0.35,0.35,0.3,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Synthesize a full-sized fiberglass cello case shell for proper spatial alignment based on its internal volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cello case][0.3,0.2,0.5,0,0,0,1.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Introduce a vintage coin-operated arcade upright cabinet into the scene and compute its structural volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[arcade cabinet][0.3,0.3,0.4,0,0,0,1.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Create a model of a classic acoustic guitar body shell and extract its liquid-displacement profile and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[guitar body][0.4,0.15,0.45,0,0,90,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate a replica of an ancient Egyptian limestone sarcophagus for placement considering its rigid volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[egyptian sarcophagus][0.3,0.5,0.2,90,0,0,2.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Load a standard metal scuba diving oxygen cylinder tank to configure its physics constraints and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[scuba tank][0.15,0.15,0.7,-90,0,0,0.7]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Instantiate a classic wide-brimmed Mexican mariachi sombrero hat asset to check its equilibrium properties and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[sombrero hat][0.45,0.45,0.1,0,0,0,0.6]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Spawn a cast-iron kettlebell weight into the physics environment and define its heavy-bottomed volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[iron kettlebell][0.4,0.4,0.2,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Render a large, porous ocean brain coral specimen to calculate its fluid dispersion dynamics and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[brain coral][0.33,0.33,0.34,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Model a commercial concrete parking lot bumper block asset to analyze its sliding friction and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[parking bumper][0.15,0.7,0.15,0,90,0,1.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Place an antique wooden grandfather clock cabinet to balance its pendulum frame using its external volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[grandfather clock][0.25,0.15,0.6,0,0,0,2.1]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate a replica of an medieval executioner's steel battle axe asset and set its top-heavy volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[battle axe][0.2,0.7,0.1,-90,0,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Synthesize a professional ceramic toilet bowl fixture assembly to evaluate its hollow water capacity and volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[toilet fixture][0.3,0.4,0.3,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Spawn an industrial heavy-duty gas-powered chainsaw tool asset and measure its complex motor casing volume scale."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[industrial chainsaw][0.2,0.6,0.2,0,90,0,0.9]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
146
dataset/sme-gemini-multiples.json
Normal file
146
dataset/sme-gemini-multiples.json
Normal file
@@ -0,0 +1,146 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Two stone pillars holding up a heavy steel crossbeam mesh across the top."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stone pillar][-3fw,0,0,0,0,0,1.5][stone pillar][3fw,0,0,0,0,0,1.5][heavy steel crossbeam][@0,@1][0,0,fh,0,0,0,[6.2,0.4,0.2]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A row of five stone columns spaced out evenly along the platform layout using an iteration counter."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stone column][0,0,0,0,0,0,2.0][stone column][fw*@idx,0,0,0,0,0,2.0][stone column][fw*@idx,0,0,0,0,0,2.0][stone column][fw*@idx,0,0,0,0,0,2.0][stone column][fw*@idx,0,0,0,0,0,2.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A brick archway bridging a left obelisk and a right obelisk frame."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[left obelisk][-4fw,0,0,0,0,0,[0.8,0.8,3.0]][right obelisk][4fw,0,0,0,0,0,[0.8,0.8,3.0]][brick archway][@0,@1][0,0,fh,0,0,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A high-fidelity mechanical component featuring a cylinder shaft that has a sharp uniform taper along its vertical tracking axis."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cylinder shaft][0,0,0,0,0,0,[0.5,0.5,3.0],taper=(z,0.2)]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A stone pedestal block at world center with a generic artifact sphere snapped flush to its top outer crust surface profile."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stone pedestal][abs][0,0,0,0,0,0,[1,1,1.5]][artifact sphere][0,0,0,0,0,0,0.4,surf]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A carved marble pillar detailing an ornate structural helix layout twisted ninety degrees around the primary vertical footprint."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[marble pillar][0,0,0,0,0,0,[0.6,0.6,4.0],twist=(z,90)]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A massive foundation layout block with two small decorative capsules symmetrically mirrored along its outer flank walls."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[massive foundation][0,0,0,0,0,0,[4,2,1]][decorative capsule][sym(fw+0.2),0,hh,0,90,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A hollowed circular concrete drainage pipe carved directly out of a solid bedrock masonry cube segment using an explicit subtraction layer."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[solid bedrock][0,0,0,0,0,0,[2,2,2]][drainage pipe][0,0,0,90,0,0,[0.8,0.8,2.2],-%]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A defensive parapet wall assembly flanking a central guard tower cylinder node layout."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[guard tower][0,0,0,0,0,0,[1.5,1.5,4.0]][parapet wall][sym(fw+1.5),0,0,0,0,0,[2,0.4,2]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A custom weapon handle shaft featuring a parallel capsule segment wrapped cleanly in a high-amplitude grip displacement texture mapping."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[weapon handle][0,0,0,0,0,0,[0.2,0.2,1.2],noise=0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An absolute coordinate beacon sphere positioned 12 units high away from a sprawling procedural canyon field layout canvas edge."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[canyon terrain][0,0,0,0,0,0,[30,30,3],noise=0.65][beacon sphere][abs][0,0,12.0,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A target bullseye board setup with a smaller concentric target cylinder loop encased completely inside its volume median vector tracker."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[target board][0,0,0,90,0,0,[1.5,1.5,0.1]][target loop][0,0,0,90,0,0,[0.5,0.5,0.12]]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
242
dataset/sme-gemini-negatives.json
Normal file
242
dataset/sme-gemini-negatives.json
Normal file
@@ -0,0 +1,242 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "can you order me a pepperoni pizza"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[pepperoni pizza]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "hello is anyone there"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "make it look cool"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "an elephant"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[large elephant][0,0,0,0,0,0,3.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "a futuristic cyberpunk skyscraper"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cyberpunk skyscraper][0,0,0,0,0,0,[1,1,40.0]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "a red balloon"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[red balloon][0,0,0,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "what is the meaning of life"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "draw a quick circle"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[drawn circle][0,0,0,0,0,0,[1,0.01,1]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "can you generate a python script to parse data"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "a generic soda can"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[soda can][0,0,0,0,0,0,[0.06,0.06,0.12]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "some text that i am writing right now"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "a long snake resting on a rock"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[large rock][0,0,0,0,0,0,1.5][long snake][0,0,fh,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "delete everything in the scene view"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "a giant custom mechanical mech suit"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[giant mechanical mech suit][0,0,0,0,0,0,3.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "go forward by ten steps"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "a simple donut"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[glazed donut][0,0,0,0,0,0,0.12]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "where are my keys"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "a wooden stick"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden stick][0,0,0,0,0,0,[0.03,0.03,1.5]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "make it look bright and sunny"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "a flying saucer spaceship hovering above the ground plane"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[flying saucer][abs][0,0,3.0,0,0,0,[6,6,0.9]]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
458
dataset/sme-gemini-nouns.json
Normal file
458
dataset/sme-gemini-nouns.json
Normal file
@@ -0,0 +1,458 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "spawn a car, tree, house, and a dog"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[car][tree][house][dog]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "give me some starter models: couch, television, plant, rug, table"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[couch][television][plant][rug][table]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "i want to build a forest scene. throw in rocks, boulders, pine trees, bushes, logs, and mushrooms"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[rocks][boulders][pine_trees][bushes][logs][mushrooms]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "can I get a sword, shield, helmet, and armor"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[sword][shield][helmet][armor]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "add a computer, keyboard, mouse, mug, desk"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[computer][keyboard][mouse][mug][desk]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "dump a bunch of beach items like sand, ocean, towel, umbrella, crab, seashell"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[sand][ocean][towel][umbrella][crab][seashell]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "street assets: lamp, bench, fire_hydrant, car, bicycle"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[lamp][bench][fire_hydrant][car][bicycle]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "let's start with a base character body, hair, shirt, pants, shoes"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[body][hair][shirt][pants][shoes]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "add some space stuff: astronaut, rocket, planet, moon, asteroid, satellite"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[astronaut][rocket][planet][moon][asteroid][satellite]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "can you drop a burger, fries, drink, and ketchup into the viewport"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[burger][fries][drink][ketchup]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "kitchen assets needed: stove, fridge, microwave, sink, pan, plate, fork"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stove][fridge][microwave][sink][pan][plate][fork]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "i'm making a graveyard scene, load up a tombstone, coffin, skeleton, gate, fence, ghost"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[tombstone][coffin][skeleton][gate][fence][ghost]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "load up standard testing shapes: cube, sphere, cylinder, torus, cone"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cube][sphere][cylinder][torus][cone]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "spawn a cat, bird, fish, hamster"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cat][bird][fish][hamster]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "dungeon room starters: torch, chest, spikes, door, key, barrel"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[torch][chest][spikes][door][key][barrel]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "gimme a guitar, drum, piano, microphone, amplifier"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[guitar][drum][piano][microphone][amplifier]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "city skyline assets: building, road, traffic_light, billboard"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[building][road][traffic_light][billboard]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "add a hat, glasses, jacket, backpack"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[hat][glasses][jacket][backpack]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "playground models: swing, slide, sandbox, bench"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[playground ground plane][0,0,0,0,0,0,1.0][playground swing][fw*@idx,fd*@idx,0,0,0,0,2.5][children slide][fw*@idx,fd*@idx,0,0,0,0,2.0][wooden sandbox][fw*@idx,fd*@idx,0,0,0,0,1.5][park bench][fw*@idx,fd*@idx,0,0,0,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "put a phone, wallet, watch, coin on the layout grid"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[layout grid][0,0,0,0,0,0,1.0][smart phone][hw*@idx,hd*@idx,0,0,0,10,0.15][leather wallet][hw*@idx,hd*@idx,0,0,0,20,0.1][wrist watch][hw*@idx,hd*@idx,0,0,0,30,0.04][metal coin][hw*@idx,hd*@idx,0,0,0,40,0.03]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "spawn tools: hammer, screwdriver, wrench, pliers"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[tool box][0,0,0,0,0,0,1.0][steel hammer][fw*@idx,0,hh*@idx,0,15*@idx,0,0.3][manual screwdriver][fw*@idx,0,hh*@idx,0,15*@idx,0,0.2][metal wrench][fw*@idx,0,hh*@idx,0,15*@idx,0,0.25][metal pliers][fw*@idx,0,hh*@idx,0,15*@idx,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "fruit collection: apple, banana, orange, grape, pear"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[fruit bowl][0,0,0,0,0,0,1.0][red apple][hw*@idx,hd*@idx,hh*@idx,0,0,0,0.08][ripe banana][hw*@idx,hd*@idx,hh*@idx,0,0,0,0.15][juicy orange][hw*@idx,hd*@idx,hh*@idx,0,0,0,0.09][green grape][hw*@idx,hd*@idx,hh*@idx,0,0,0,0.02][fresh pear][hw*@idx,hd*@idx,hh*@idx,0,0,0,0.1]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "desk assets: laptop, mouse, keyboard, notebook, lamp"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden desk][0,0,0,0,0,0,1.2][modern laptop][fw*@idx,fd*@idx,0,0,0,12*@idx,0.4][optical mouse][fw*@idx,fd*@idx,0,0,0,12*@idx,0.1][slim keyboard][fw*@idx,fd*@idx,0,0,0,12*@idx,0.45][paper notebook][fw*@idx,fd*@idx,0,0,0,12*@idx,0.25][desk lamp][fw*@idx,fd*@idx,0,0,0,12*@idx,0.35]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "breakfast array: plate, cup, fork, knife, spoon, napkin"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[dining surface][0,0,0,0,0,0,1.0][ceramic plate][hw*@idx,hd*@idx,0,0,0,60*@idx,0.25][coffee cup][hw*@idx,hd*@idx,0,0,0,60*@idx,0.1][metal fork][hw*@idx,hd*@idx,0,0,0,60*@idx,0.18][butter knife][hw*@idx,hd*@idx,0,0,0,60*@idx,0.2][metal spoon][hw*@idx,hd*@idx,0,0,0,60*@idx,0.18][paper napkin][hw*@idx,hd*@idx,0,0,0,60*@idx,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "camping gear list: tent, backpack, sleeping_bag, stove, flashlight"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[campsite ground][0,0,0,0,0,0,1.0][camping tent][fw*@idx,fd*@idx,0,0,0,0,2.0-0.2*@idx][travel backpack][fw*@idx,fd*@idx,0,0,0,0,0.6-0.06*@idx][warm sleeping_bag][fw*@idx,fd*@idx,0,0,0,0,1.8-0.18*@idx][portable stove][fw*@idx,fd*@idx,0,0,0,0,0.3-0.03*@idx][bright flashlight][fw*@idx,fd*@idx,0,0,0,0,0.2-0.02*@idx]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "kitchen counters: blender, toaster, microwave, kettle"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[kitchen counter][0,0,0,0,0,0,1.0][food blender][fw*@idx,0,0,0,0,0,0.35][bread toaster][fw*@idx,0,0,0,0,0,0.25][microwave oven][fw*@idx,0,0,0,0,0,0.5][water kettle][fw*@idx,0,0,0,0,0,0.25]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "bar materials: bottle, glass, shaker, jigger, strainer"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[bar counter][0,0,0,0,0,0,1.0][glass bottle][0,fd*@idx,hh*@idx,0,0,30*@idx,0.3][drinking glass][0,fd*@idx,hh*@idx,0,0,30*@idx,0.12][drink shaker][0,fd*@idx,hh*@idx,0,0,30*@idx,0.25][double jigger][0,fd*@idx,hh*@idx,0,0,30*@idx,0.08][bar strainer][0,fd*@idx,hh*@idx,0,0,30*@idx,0.12]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "living room group: sofa, armchair, coffee_table, rug, television"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[display console][0,0,0,0,0,0,1.0][comfy sofa][fw*@idx,fd*@idx,0,0,0,15*@idx,2.0][cozy armchair][fw*@idx,fd*@idx,0,0,0,15*@idx,0.8][wooden coffee_table][fw*@idx,fd*@idx,0,0,0,15*@idx,1.0][wool rug][fw*@idx,fd*@idx,0,0,0,15*@idx,1.8][flat television][fw*@idx,fd*@idx,0,0,0,15*@idx,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "bathroom set: soap, toothbrush, toothpaste, cup, razor"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[sink counter][0,0,0,0,0,0,1.0][scented soap][hw*@idx,hd*@idx,0,0,0,45*@idx,0.1][plastic toothbrush][hw*@idx,hd*@idx,0,0,0,45*@idx,0.18][mint toothpaste][hw*@idx,hd*@idx,0,0,0,45*@idx,0.15][rinse cup][hw*@idx,hd*@idx,0,0,0,45*@idx,0.1][shaving razor][hw*@idx,hd*@idx,0,0,0,45*@idx,0.14]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "streetscape objects: mailbox, fire_hydrant, lamppost, trash_can"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[street curb][0,0,0,0,0,0,1.0][metal mailbox][fw*@idx,0,0,0,0,0,1.2][fire_hydrant][fw*@idx,0,0,0,0,0,0.7][tall lamppost][fw*@idx,0,0,0,0,0,3.5][outdoor trash_can][fw*@idx,0,0,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "musical instruments: guitar, violin, flute, drum, trumpet"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stage floor][0,0,0,0,0,0,1.0][acoustic guitar][fw*@idx,fd*@idx,hh*@idx,0,0,0,1.0][wooden violin][fw*@idx,fd*@idx,hh*@idx,0,0,0,0.6][silver flute][fw*@idx,fd*@idx,hh*@idx,0,0,0,0.65][snare drum][fw*@idx,fd*@idx,hh*@idx,0,0,0,0.4][brass trumpet][fw*@idx,fd*@idx,hh*@idx,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "fitness bundle: dumbbell, kettlebell, mat, roller"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[gym floor][0,0,0,0,0,0,1.0][heavy dumbbell][fw*@idx,fd*@idx,0,0,0,90*@idx,0.25][cast_iron kettlebell][fw*@idx,fd*@idx,0,0,0,90*@idx,0.3][yoga mat][fw*@idx,fd*@idx,0,0,0,90*@idx,1.8][foam roller][fw*@idx,fd*@idx,0,0,0,90*@idx,0.45]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "garden patch: shovel, rake, pot, shears, watering_can"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[garden terrain][0,0,0,0,0,0,1.0][metal shovel][fw*@idx,fd*@idx,0,0,0,0,1.2-0.06*@idx][steel rake][fw*@idx,fd*@idx,0,0,0,0,1.5-0.075*@idx][clay pot][fw*@idx,fd*@idx,0,0,0,0,0.3-0.015*@idx][pruning shears][fw*@idx,fd*@idx,0,0,0,0,0.25-0.0125*@idx][watering_can][fw*@idx,fd*@idx,0,0,0,0,0.35-0.0175*@idx]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "clothing pile: shirt, pants, jacket, hat, socks"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[clothes hanger][0,0,0,0,0,0,1.0][cotton shirt][hw*@idx,hd*@idx,hh*@idx,10*@idx,10*@idx,0,0.6][denim pants][hw*@idx,hd*@idx,hh*@idx,10*@idx,10*@idx,0,1.0][warm jacket][hw*@idx,hd*@idx,hh*@idx,10*@idx,10*@idx,0,0.8][winter hat][hw*@idx,hd*@idx,hh*@idx,10*@idx,10*@idx,0,0.25][woolen socks][hw*@idx,hd*@idx,hh*@idx,10*@idx,10*@idx,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "stoneware workshop layout: jug, vase, bowl, chalice"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[workshop counter][0,0,0,0,0,0,1.0][clay jug][fw*@idx,fd*@idx,0,0,0,0,0.35][ceramic vase][fw*@idx,fd*@idx,0,0,0,0,0.3][soup bowl][fw*@idx,fd*@idx,0,0,0,0,0.2][royal chalice][fw*@idx,fd*@idx,0,0,0,0,0.25]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "mechanic bench collection: engine_block, alternator, battery, radiator"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[mechanic bench][0,0,0,0,0,0,1.0][engine_block][fw*@idx,0,0,0,0,25*@idx,0.6][alternator][fw*@idx,0,0,0,0,25*@idx,0.2][car battery][fw*@idx,0,0,0,0,25*@idx,0.35][cooling radiator][fw*@idx,0,0,0,0,25*@idx,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "dinner table elements: candle, napkin_ring, wine_bottle, centerpiece"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[dining table][0,0,0,0,0,0,1.0][tall candle][hw*@idx,hd*@idx,0,0,0,0,0.25][napkin_ring][hw*@idx,hd*@idx,0,0,0,0,0.05][wine_bottle][hw*@idx,hd*@idx,0,0,0,0,0.3][floral centerpiece][hw*@idx,hd*@idx,0,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "medieval armory stash: shield, sword, helmet, gauntlet, boots"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[armory crate][0,0,0,0,0,0,1.0][knight shield][fw*@idx,fd*@idx,hh*@idx,0,0,18*@idx,0.7][steel sword][fw*@idx,fd*@idx,hh*@idx,0,0,18*@idx,1.0][iron helmet][fw*@idx,fd*@idx,hh*@idx,0,0,18*@idx,0.3][armored gauntlet][fw*@idx,fd*@idx,hh*@idx,0,0,18*@idx,0.35][leather boots][fw*@idx,fd*@idx,hh*@idx,0,0,18*@idx,0.4]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
170
dataset/sme-gemini-positional.json
Normal file
170
dataset/sme-gemini-positional.json
Normal file
@@ -0,0 +1,170 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A giant box shifted 5 units up higher in the air away from everything."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[giant box][abs][0,0,5.0,0,0,0,3.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A standard cylinder flipped completely backwards and upside down at the origin."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[standard cylinder][0,0,0,-90,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A capsule way off to the right 10 units away in world space."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[long capsule][abs][10.0,0,0,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A tiny miniature sphere facing sideways looking right."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[miniature sphere][0,0,0,0,90,0,0.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A rough spiky mesh primitive toppled over face down at world center."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[spiky mesh][abs][0,0,0,90,0,0,1.0,noise=0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An elongated torus tilted and slanted at a forty five degree angle."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[elongated torus][0,0,0,0,0,45,[1,1,2.0]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A flat squashed crescent base facing away in the opposite direction."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[flat crescent][0,0,0,0,180,0,[1,1,0.2]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A slender skinny cone projecting far ahead along the forward vector."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[slender cone][0,4fd,0,0,0,0,[0.3,0.3,1.0]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An elephant standing directly on top of a red balloon."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[red balloon][0,0,0,0,0,0,0.3][large elephant][0,0,fh,0,0,0,3.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A red balloon squeezed directly underneath an elephant's foot."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[large elephant][0,0,0,0,0,0,3.0][red balloon][0,0,-fh,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An elephant standing on top of a red balloon, shifted half its depth forward so the front of the elephant is centered halfway over the balloon."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[red balloon][0,0,0,0,0,0,0.3][large elephant][0,hd,fh,0,0,0,3.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A red balloon tucked directly underneath an elephant, shifted half its depth backward."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[large elephant][0,0,0,0,0,0,3.0][red balloon][0,-hd,-fh,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A wooden sword piercing a round shield from behind."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[round shield][0,0,0,0,0,0,0.8][wooden sword][0,-hd,0,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A round shield being pierced by a wooden sword from the front."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden sword][0,0,0,0,0,0,1.0][round shield][0,hd,0,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
398
dataset/sme-gemini-rooms.json
Normal file
398
dataset/sme-gemini-rooms.json
Normal file
@@ -0,0 +1,398 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An elongated sphere with fuzzy stuff on top, with two smaller flat spheres on the side about 20% the size of the first sphere, and a rounded cone in the middle front, and a depressed skinny moon underneath about 15% tall and 50% wide for a mouth."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[elongated sphere][0,0,0,0,0,0,[1,1,1.5]][fuzzy sphere][0,0,fh,0,0,0,[1,1,0.2],noise=0.3][flat sphere][sym(fw),0,hh,0,0,0,0.2][rounded cone][0,hd,hh,0,0,0,0.25][skinny crescent][0,hd+0.05,hh*0.5,0,0,0,[-0.5,1,-0.15]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A teddy bear where the torso is a bigger sphere, a slightly smaller head sphere on top, and the two feet capsules stick out straight from the bottom front profile like it is sitting down."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[torso sphere][0,0,0,0,0,0,1.5][head sphere][0,0,fh,0,0,0,1.0][foot capsule][sym(hw*0.6),hd,-hh+0.2,90,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A bathroom containing a bowl shape depressed into a counter block to serve as a sink, a tiny box soap dish tucked in the front right corner, and a cylinder pipe with a flat round shower head sticking out of three fourths up the wall."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[sink counter][0,0,0,0,0,0,[3,2,1]][sink bowl][0,0,hh,0,0,0,[-0.6,0.6,-0.4]][tiny soap dish][fw-0.2,fd-0.2,hh,0,0,0,0.15][shower pipe][0,-bd,hh*1.5,0,0,0,[0.1,0.1,1.5]][shower head][0,-bd+0.3,fh*0.75,90,0,0,[0.4,0.4,0.05]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A bedroom setup with a large mattress block, and a stylized couch placed right in the back left corner of the room layout space."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[large mattress][0,0,0,0,0,0,[2,2.5,0.4]][stylized couch][-4fw,-4fd,0,0,0,0,[1.5,0.8,0.6]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A standard computer desk with a flat monitor screen, and a keyboard arranged directly in front of the screen anchor profile."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[computer desk][0,0,0,0,0,0,[3,1.5,1]][flat monitor screen][0,0,fh,0,0,0,[1.2,0.1,0.8]][computer keyboard][0,-fd,fh,0,0,0,[0.8,0.3,0.02]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A procedural tree with a cylinder trunk that tapers down by half along the vertical Z axis, topped by three separate overlapping foliage spheres."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cylinder trunk][0,0,0,0,0,0,[0.4,0.4,3.0],taper=(z,0.5)][foliage sphere][0,0,fh,0,0,0,1.5][foliage sphere][hw,0,fh-0.5,0,0,0,1.0][foliage sphere][-hw,0,fh-0.5,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A medieval castle tower cylinder with a hollowed out doorway arch at its bottom front base, and a spiky cone roof capping the peak profile."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[castle tower][0,0,0,0,0,0,[1.5,1.5,4.0]][doorway arch][0,hd,0,0,0,0,[-0.4,1,-0.8]][spiky roof cone][0,0,fh,0,0,0,1.7]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A classical sword primitive assembly featuring a long thin blade box, a crossguard cylinder wrapped around its base, and a small sphere pommel underneath."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[blade box][0,0,0,0,0,0,[0.1,0.02,3.0]][crossguard cylinder][0,0,-hh,90,0,0,[0.6,0.1,0.1]][sphere pommel][0,0,-hh-0.2,0,0,0,0.15]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A dining room arrangement featuring a large flat table slab, four chair models arrayed on both sides, and a chandelier torus hanging far above the absolute center."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[large table][0,0,0,0,0,0,[3,1.5,0.1]][dining chair][sym(hw),hd,0,0,0,0,1.0][dining chair][sym(hw),-hd,0,0,0,0,1.0][chandelier torus][abs][0,0,4.0,0,0,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A stylized corkscrew cylinder twisted forty five degrees along the primary Z axis footprint."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[corkscrew cylinder][0,0,0,0,0,0,[0.3,0.3,2.5],twist=(z,45)]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A desktop desk lamp with a base disc cylinder, a long slender neck capsule, and a cone spotlight shell perched on the top forward edge facing down."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[base disc][0,0,0,0,0,0,[0.4,0.4,0.05]][neck capsule][0,0,fh,0,15,0,[0.08,0.08,1.2]][cone spotlight][0,hd,fh,45,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A rowboat crescent shell containing two flat box bench slabs encased completely within its interior longitudinal layout."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[rowboat crescent][0,0,0,90,0,0,[1,3,0.5]][flat bench][0,hd*0.3,0,0,0,0,[0.8,0.2,0.1]][flat bench][0,-hd*0.3,0,0,0,0,[0.8,0.2,0.1]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A modular campfire layout with three logs arranged in a row, and a spiky conical fire primitive sprouting from the crest of the center log structure."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[campfire log][0,0,0,90,0,0,[0.15,0.15,1]][campfire log][fw*@idx,0,0,90,0,0,[0.15,0.15,1]][campfire log][fw*@idx,0,0,90,0,0,[0.15,0.15,1]][spiky fire][@1][0,0,fh,0,0,0,0.8,noise=0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A low poly sci fi gun barrel cylinder that tapers sharply at the muzzle end, with a laser box scope sitting directly on top of the rear framework."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[gun barrel][0,0,0,0,90,0,[0.2,0.2,2.0],taper=(y,0.3)][laser scope][0,-hd*0.5,fh,0,0,0,[0.1,0.4,0.1]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A backyard playground kit containing a swing set frame, and an absolute space sandbox platform shifted 5 units up on a structural deck mountain profile."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[playground frame][0,0,0,0,0,0,2.0][sandbox platform][abs][4.0,4.0,5.0,0,0,0,[3,3,0.2]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A laboratory flask bottle composed of a flat bottom cylinder, an elongated cone midsection stacked on top, and a narrow cylinder neck trailing out the peak."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[bottom cylinder][0,0,0,0,0,0,[1,1,0.2]][cone midsection][0,0,fh,0,0,0,[0.8,0.8,1.2],taper=(z,0.1)][narrow neck][0,0,fh,0,0,0,[0.15,0.15,0.5]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A mechanical wheel capsule with a rough tread pattern noise map applied to its primary rotational contact edge."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wheel capsule][0,0,0,0,90,0,1.0,noise=0.25]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A living room corner detailing a large television monitor screen block, flanked closely on both sides by tall skinny soundbars."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[television panel][0,0,0,0,0,0,[2,0.1,1.2]][skinny soundbar][sym(fw+0.1),0,hh,0,0,0,[0.2,0.2,1.5]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A fountain array with a large circular torus pool base at world origin, and an elongated cone geyser shooting straight up out of the exact center midpoint layout space."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[pool base][0,0,0,90,0,0,2.5][cone geyser][0,0,0,0,0,0,[0.3,0.3,4.0]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A small generic coffee cup cylinder resting near a sprawling office keyboard configuration block context."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[office keyboard][0,0,0,0,0,0,[1.2,0.4,0.05]][coffee cup][2fw,0,0,0,0,0,0.25]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A standard low-poly bedroom spatial layout featuring a blue-and-white striped platform mattress on the far right floor, an orange armchair next to it with a character sitting inside holding a small white sphere primitive, a tiny dark coffee table nearby, a green armchair, a dark gray armchair facing them, a tall wooden desk cabinet against the dark blue accent wall with a desk lamp resting on top, a large dark square dining or working table centered in the rear, an industrial radiator heater sitting on the left wall under a large window pane, and a secondary window on the left side wall."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[striped mattress][abs,2.2,-0.5,0,0,0,-45,[1.0,1.8,0.3]][armchair orange][@0,0,0,fh,0,0,0,[0.9,0.9,0.8]][character][@1,0,0,hh,0,0,0,[0.4,0.4,0.6]][white sphere][@2,0,0,fh,0,0,0,0.15][dark coffee table][@1,-2fd,0,0,0,0,0,[0.5,0.5,0.3]][armchair green][@4,-2fw,0,0,0,0,45,[0.8,0.8,0.9]][armchair gray][@4,-2fw,-2fd,0,0,0,15,[0.8,0.8,0.9]][wooden desk cabinet][@5,0,-3fd,fh,0,0,0,[0.9,0.5,1.2]][desk lamp][@7,0,0,fh,0,0,0,[0.2,0.2,0.35]][dark dining table][@5,-3fw,3fd,0,0,0,0,[1.2,1.2,0.75]][industrial radiator heater][abs,-2.2,1.2,0,0,0,45,[0.2,1.0,0.6]][window pane][wall,left,0,2fh,0,0,0,[1.5,0.05,1.2]][secondary window][wall,back,0,2fh,0,0,0,[1.5,0.05,1.2]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A massive heavy wooden banquet table with a symmetrical pair of high-back dining chairs resting tightly packed against its left and right sides."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wooden banquet table][0,0,0,0,0,0,[2.4,1.2,0.75]][high back dining chair][sym(-fw),0,0,0,0,0,0,[0.5,0.5,1.1]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A high-tech cylindrical laboratory stasis pod standing on top of a square metallic ventilation platform base block."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[ventilation platform base][0,0,0,0,0,0,[1.5,1.5,0.4]][high-tech stasis pod][0,0,fh,0,0,0,0,[0.5,0.5,2.0]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An industrial storage barrel container with an emergency warning cone sitting directly on top of its upper lid surface."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[industrial barrel container][0,0,0,0,0,0,[0.6,0.6,1.0]][warning cone][0,0,fh,0,0,0,0,[0.4,0.4,0.6]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A rectangular stone structural pillars asset block context with a small decorative torus ring molding slightly overlapping inside its upper capital profile."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[stone structural pillars][0,0,0,0,0,0,[0.4,0.4,3.0]][torus ring][0,0,hh,0,0,0,0,[0.5,0.5,0.1]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A plush living room sectional sofa block with a tiny square wooden drink coaster resting in the immediate vicinity of its right armrest."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[plush sectional sofa][0,0,0,0,0,0,[2.2,0.9,0.75]][wooden drink coaster][2fw,0,0,0,0,0,0,[0.2,0.2,0.02]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A master bedroom king-size bed layout featuring a wooden nightstand table separated from the main frame off to its front-left side."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[king size bed][0,0,0,0,0,0,[2.0,2.1,0.6]][wooden nightstand table][-fw,fd,0,0,0,0,0,[0.5,0.5,0.5]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A large rectangular wall-mounted widescreen television panel with a tiny remote control box tucked slightly behind its rear support tracking."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[television panel][0,0,1.2,0,0,0,0,[1.4,0.1,0.8]][remote control][hw,-hd,hh,0,0,0,0.5,[0.2,0.1,0.05]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A heavy industrial metal workbench area featuring a tall vertical drill press assembly standing far away from its main working surface boundaries."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[metal workbench][0,0,0,0,0,0,[1.8,0.8,0.85]][drill press][4fw,0,0,0,0,0,0,[0.5,0.5,1.8]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A wide brick backyard patio fireplace hearth with a decorative spherical stone ornament resting directly behind its primary flue column structure."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[brick fireplace hearth][0,0,0,0,0,0,[1.5,0.8,2.2]][stone ornament][0,-fd,0,0,0,0,1,[0.3,0.3,0.3]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A square electronics workbench grid module with a long protective cylindrical fuse capsule capsule component buried deep under its lower grounding line plane."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[workbench grid][0,0,0,0,0,0,[1.0,1.0,0.1]][fuse capsule][0,0,-4fh,0,0,0,1,[0.05,0.05,0.3]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A flat low-poly office desk assembly layout containing a compact rectangular smartphone unit sitting diagonally back-right from its primary keyboard chassis block."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[keyboard chassis][0,0,0,0,0,0,[0.5,0.2,0.02]][smartphone unit][fw,-fd,0,0,0,0,0,[0.08,0.15,0.01]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A standard desktop monitor screen displaying complex CAD graphics with an external modular webcam sensor block hovering over its top bezel profile frame."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[monitor screen][0,0,0.4,0,0,0,0,[0.6,0.05,0.4]][webcam sensor][0,0,2fh,0,0,0,1,[0.08,0.08,0.05]]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
122
dataset/sme-gemini-rotations.json
Normal file
122
dataset/sme-gemini-rotations.json
Normal file
@@ -0,0 +1,122 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "rotate this bag laying on the side to be standing upright on a desk. Asset ID: handbag_94f. Source bounds: X: 0.82m, Y: 0.35m, Z: 0.41m. Native orientation: Tipped on its side along the X-axis."},
|
||||
{"role": "assistant", "content": "[handbag_94f][0,0,0,0,0,90,1.0]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "place this laptop flat on the kitchen island. Asset ID: laptop_77a. Source bounds: X: 0.03m, Y: 0.32m, Z: 0.24m. Native orientation: Modeled standing completely vertical like a book."},
|
||||
{"role": "assistant", "content": "[laptop_77a][0,0,0,-90,0,0,0.35]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "put this soda can upright near the keyboard. Asset ID: can_cola_02. Source bounds: X: 0.12m, Y: 0.06m, Z: 0.06m. Native orientation: Tipped backward, pointing horizontally along the Z-axis."},
|
||||
{"role": "assistant", "content": "[can_cola_02][0,0,0,90,0,0,0.12]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "drop the desk lamp onto the side table. Asset ID: lamp_office_x. Source bounds: X: 15.0m, Y: 45.0m, Z: 20.0m. Native orientation: Model is upside down with base pointing to sky, scaled in centimeters."},
|
||||
{"role": "assistant", "content": "[lamp_office_x][0,0,0,180,0,0,0.45]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "slide the acoustic guitar into the corner stand. Asset ID: guitar_gibson. Source bounds: X: 0.15m, Y: 1.05m, Z: 0.42m. Native orientation: Intentionally modeled flat on its back like a floor asset."},
|
||||
{"role": "assistant", "content": "[guitar_gibson][0,0,0,-90,0,0,1.05]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "stand the tall floor vase up next to the armchair. Asset ID: vase_ceramic_h. Source bounds: X: 0.88m, Y: 0.32m, Z: 0.31m. Native orientation: Tipped horizontally along the main X-axis."},
|
||||
{"role": "assistant", "content": "[vase_ceramic_h][0,0,0,0,0,-90,0.88]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "place this coffee mug facing handle-right onto the saucer. Asset ID: mug_porcelain. Source bounds: X: 0.09m, Y: 0.12m, Z: 0.09m. Native orientation: Inverted upside down."},
|
||||
{"role": "assistant", "content": "[mug_porcelain][0,0,0,180,90,0,0.12]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "mount this flat screen TV flush against the living room wall. Asset ID: tv_samsung_65. Source bounds: X: 1.45m, Y: 0.08m, Z: 0.83m. Native orientation: Laying flat face-up like a coffee table."},
|
||||
{"role": "assistant", "content": "[tv_samsung_65][0,0,0,90,0,0,1.45]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "stand this computer tower up under the workstation. Asset ID: pc_case_atx. Source bounds: X: 480.0m, Y: 210.0m, Z: 500.0m. Native orientation: Tipped on its right panel face down, modeled in raw millimeters."},
|
||||
{"role": "assistant", "content": "[pc_case_atx][0,0,0,0,0,-90,0.5]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "put the water bottle straight up in the cup holder. Asset ID: hydro_flask_32. Source bounds: X: 0.09m, Y: 0.25m, Z: 0.09m. Native orientation: Tipped at an odd forward 45 degree angle."},
|
||||
{"role": "assistant", "content": "[hydro_flask_32][0,0,0,-45,0,0,0.25]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "set this office chair down facing away from the wall. Asset ID: chair_herman_m. Source bounds: X: 0.65m, Y: 0.65m, Z: 1.05m. Native orientation: Perfectly oriented upright but needs a turn."},
|
||||
{"role": "assistant", "content": "[chair_herman_m][0,0,0,0,180,0,1.05]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "align this keyboard straight on the desk mat. Asset ID: kbd_mechanical. Source bounds: X: 0.14m, Y: 0.44m, Z: 0.04m. Native orientation: Rotated weirdly at a diagonal 45 degrees on the Z-axis baseline."},
|
||||
{"role": "assistant", "content": "[kbd_mechanical][0,0,0,0,-45,0,0.44]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "place this modern bookshelf flush against the master wall. Asset ID: shelf_ikea_bil. Source bounds: X: 0.28m, Y: 0.80m, Z: 2.02m. Native orientation: Spined horizontally on its back side like a low bench."},
|
||||
{"role": "assistant", "content": "[shelf_ikea_bil][0,0,0,90,0,0,2.02]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "stand this skateboard up on its tail wheel against the garage wall. Asset ID: skateboard_deck. Source bounds: X: 0.78m, Y: 0.20m, Z: 0.10m. Native orientation: Dropped entirely flat on its wheels parallel to ground."},
|
||||
{"role": "assistant", "content": "[skateboard_deck][0,0,0,90,0,0,0.78]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "set this picture frame upright on the shelf mantlepiece. Asset ID: frame_photo_8x10. Source bounds: X: 0.25m, Y: 0.20m, Z: 0.02m. Native orientation: Face down flat on the canvas surface."},
|
||||
{"role": "assistant", "content": "[frame_photo_8x10][0,0,0,-90,0,0,0.25]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "stand this tall cleaning broom up inside the storage closet. Asset ID: broom_bristle. Source bounds: X: 1.42m, Y: 0.25m, Z: 0.08m. Native orientation: Spread horizontally across the deck floor surface."},
|
||||
{"role": "assistant", "content": "[broom_bristle][0,0,0,0,0,90,1.42]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "put the heavy dumbbell rack flat on the gym gym mat floor. Asset ID: rack_weights. Source bounds: X: 0.65m, Y: 1.20m, Z: 0.85m. Native orientation: Tipped cleanly onto its back frame profile."},
|
||||
{"role": "assistant", "content": "[rack_weights][0,0,0,-90,0,0,1.20]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "place this desktop microphone upright right next to the screen setup. Asset ID: mic_yeti. Source bounds: X: 0.12m, Y: 0.12m, Z: 0.25m. Native orientation: Perfectly positioned straight vertically inside source file data."},
|
||||
{"role": "assistant", "content": "[mic_yeti][0,0,0,0,0,0,0.25]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "stand the long surf board straight up against the patio beam structure. Asset ID: surfboard_long. Source bounds: X: 2.45m, Y: 0.55m, Z: 0.07m. Native orientation: Floating completely horizontal like it is running on a wave crest."},
|
||||
{"role": "assistant", "content": "[surfboard_long][0,0,0,90,0,0,2.45]"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "set this speaker monitor up right side up on the desktop stands. Asset ID: speaker_studio_monitor. Source bounds: X: 0.18m, Y: 0.30m, Z: 0.22m. Native orientation: Flipped exactly upside down inside the export layer."},
|
||||
{"role": "assistant", "content": "[speaker_studio_monitor][0,0,0,180,0,0,0.30]"}
|
||||
]
|
||||
}
|
||||
]
|
||||
242
dataset/sme-gemini-scenes.json
Normal file
242
dataset/sme-gemini-scenes.json
Normal file
@@ -0,0 +1,242 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Looking at the scene from a frontal perspective, place a flat ground terrain, a tall box wall standing upright at the back, and a small sphere sitting dead center on the floor right in front of the wall."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[flat terrain][0,0,0,0,0,0,1.0][tall wall][0,hd,-hh,0,0,0,[fw,0.1,fh]][small sphere][0,0,0,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From a top-down bird's-eye view, layout a square courtyard using four box walls arranged in a perfect square outline around the origin, matching each other's outer depth and width footprints."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[courtyard wall][0,fd,0,0,0,0,[fw,0.2,fh]][courtyard wall][0,-fd,0,0,0,0,[fw,0.2,fh]][courtyard wall][-fw,0,0,0,0,90,[fw,0.2,fh]][courtyard wall][fw,0,0,0,0,90,[fw,0.2,fh]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Imagine viewing the scene from directly behind. Place a main cylinder pillar at the center, then drop a small tracking sphere flush against its rear surface facing the observer."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cylinder pillar][0,0,0,0,0,0,1.0][tracking sphere][0,-hd,0,0,0,0,0.2,surf]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "In a side profile view from the right, create a long horizontal capsule pipe stretching along the Y-axis, with a box support bracket clamped directly beneath its frontmost edge."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[capsule pipe][0,0,0,0,90,0,[0.5,0.5,fd]][support bracket][0,hd,-hh,0,0,0,[0.8,0.8,0.8]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From an isometric high angle, layout a three-step staircase using three sequential boxes that increment both forward along the Y-axis and upward along the Z-axis using iteration indices."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[staircase step][0,fd*@idx,fh*@idx,0,0,0,1.0][staircase step][0,fd*@idx,fh*@idx,0,0,0,1.0][staircase step][0,fd*@idx,fh*@idx,0,0,0,1.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Looking straight down from the ceiling, position a central circular torus ring, and place two small button spheres mirrored symmetrically on both the left and right outer flanks."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[torus ring][0,0,0,0,0,0,2.0][button sphere][sym(hw+0.5),0,0,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From a worm's-eye view looking straight up from underground, place a massive flat box ceiling slab, and suspend a sharp cone pointing straight down at the camera from the ceiling's absolute center surface."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[ceiling slab][0,0,fh,0,0,0,[fw,fd,0.2]][sharp cone][0,0,-hh,0,180,0,1.0,surf]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Setting up a frontal perspective frame, place a low wide defensive box wall, and use a negative scale cylinder to punch a clean circular arch tunnel directly through its center base."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[defensive wall][0,0,0,0,0,0,[5,0.5,2.0]][tunnel cylinder][0,0,-hh,90,0,0,[0.8,0.8,-1.0]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Behind the main structure, take the first two spawned pillars, find their exact spatial midpoint vector, and float a glowing marker sphere directly above that center space."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cylinder pillar][-3,2,0,0,0,0,1.0][cylinder pillar][3,2,0,0,0,0,1.0][glowing sphere][@0,@1][0,0,fh+1,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From a steep cross-section view from the left, slice a hollow cylinder open by positioning an absolute coordinate space override box that masks out the entire front hemisphere."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[hollow cylinder][0,0,0,0,0,0,2.0][override box][abs][0,1,0,0,0,0,[4,2,4],-%]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From a three-quarter overhead perspective, build a tapering tower by stacking three boxes where each higher step progressively deforms inwards using a taper modifier on the vertical axis."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[tower base][0,0,0,0,0,0,[2,2,2]][tower middle][0,0,fh,0,0,0,[2,2,2],taper(z,0.7)][tower top][0,0,fh,0,0,0,[2,2,2],taper(z,0.4)]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Looking from a high front-left angle, place an organic twisted pillar by generating a cylinder that undergoes a progressive helical deformation along its vertical build line."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[twisted pillar][0,0,0,0,0,0,[0.5,0.5,4.0],twist(z,180)]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Using a strict plan-view layout (top-down), construct a long structural crescent archway curving along the horizontal plane, anchored by two square box blocks at its absolute tips."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[crescent archway][0,0,0,90,0,0,3.0][anchor box][-hw,0,-hh,0,0,0,0.5][anchor box][hw,0,-hh,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From a close-up frontal macro angle, place a smooth capsule capsule base, then layer a high-frequency noise displacement attribute over its outer shell to simulate a rough, weathered stone texture."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[smooth capsule][0,0,0,0,0,0,1.0,noise(0.4)]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From a direct overhead satellite perspective, drop a large circular terrain patch, then scatter three small boulder spheres tracking linearly outwards along the positive X-axis using step counters."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[circular terrain][0,0,0,0,0,0,5.0][boulder sphere][fw*@idx,0,0,0,0,0,0.3][boulder sphere][fw*@idx,0,0,0,0,0,0.3][boulder sphere][fw*@idx,0,0,0,0,0,0.3]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From a rear-view observation deck perspective, place a wide horizon glass pane using a thin box, then center a heavy structural support torus directly around its midpoint line."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[wide glass pane][0,3,0,0,0,0,[6,0.1,2.0]][support torus][@0][0,0,0,0,90,0,1.2]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Looking up from a low roadside gutter perspective, establish a high-altitude absolute coordinate anchor, and hang an expansive highway bridge box spanning the entire top field of view."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[highway bridge][abs][0,0,10.0,0,0,0,[20,4,0.5]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From a strict frontal elevation diagram view, align a flat foundation box, snap a cone roof directly onto its top surface boundary, and verify zero overlapping intersection gaps."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[foundation box][0,0,0,0,0,0,[2,2,1]][cone roof][0,0,hh,0,0,0,1.0,surf]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Viewing the scene from an oblique right-side vantage, project a cylinder forward along the Y-axis, then slide a secondary hollow matching sleeve cylinder around it using a subtraction mask."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[main cylinder][0,0,0,90,0,0,[1,1,4]][sleeve cylinder][0,0,0,90,0,0,[1.2,1.2,2]][sleeve cylinder][0,0,0,90,0,0,[0.9,0.9,2.2],-%]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "From a true bird's-eye orthographic layout, instantiate a multi-anchor assembly by bridging two distant custom meshes together with a long, narrow connecting box walkway centered perfectly between them."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[custom mesh][-5,5,0,0,0,0,1.0][custom mesh][5,-5,0,0,0,0,1.0][walkway box][@0,@1][0,0,0,0,0,45,[1,8,0.2]]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
242
dataset/sme-gemini-terrain.json
Normal file
242
dataset/sme-gemini-terrain.json
Normal file
@@ -0,0 +1,242 @@
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A vast mountain terrain landscape with a tiny pine tree sitting exactly at the absolute coordinate origin."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[mountain terrain][0,0,0,0,0,0,[20,20,5],noise=0.8][tiny pine_tree][abs][0,0,0,0,0,0,0.25]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A flat grassy field terrain with a row of three street lamps lined up one after another starting from the center front surface."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[grassy terrain][0,0,0,0,0,0,[15,15,0.1]][street lamp][0,fd,0,0,0,0,3.0][street lamp][fw*@idx,0,0,0,0,0,3.0][street lamp][fw*@idx,0,0,0,0,0,3.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A rugged desert terrain with a massive boulder rock placed far to the left, and an absolute override car shifted 10 units out along the positive X axis."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[desert terrain][0,0,0,0,0,0,[30,30,2],noise=0.4][massive rock][-4fw,0,0,0,0,0,4.0][override car][abs][10.0,0,0,0,0,0,1.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A park scene terrain containing a wooden bench in the middle front, with a huge oak tree sprouting from the crest directly behind that bench."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[park terrain][0,0,0,0,0,0,[10,10,0.1]][wooden bench][0,hd,0,0,0,0,1.2][huge oak tree][0,-fd,0,0,0,0,6.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A village landscape terrain featuring a large stone church house at the center, flanked directly on its left and right sides by long sections of fence walls."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[village terrain][0,0,0,0,0,0,[40,40,0.5]][stone church][0,0,0,0,0,0,12.0][long fence][sym(fw),0,0,0,0,0,2.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A small island terrain with a lighthouse cylinder structure standing on its peak vertical ceiling, looking sideways right."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[island terrain][0,0,0,0,0,0,[8,8,3],noise=0.6][lighthouse tower][0,0,fh,0,90,0,[1,1,4.0]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A smooth landscape plane with an absolute coordinate platform shifted 5 units up, and a flying drone capsule hovering over that platform plane."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[smooth terrain][0,0,0,0,0,0,[50,50,0.1]][absolute platform][abs][0,0,5.0,0,0,0,1.5][flying drone][0,0,fh+0.5,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A dense forest terrain setup featuring a central campfire structure cone, surrounded completely by four distinct pine trees on the diagonal front and back perimeter profiles."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[forest terrain][0,0,0,0,0,0,[25,25,0.2]][campfire structure][0,0,0,0,0,0,0.5,noise=0.3][pine tree][fw,fd,0,0,0,0,3.5][pine tree][-fw,fd,0,0,0,0,3.5][pine tree][fw,-fd,0,0,0,0,3.5][pine tree][-fw,-fd,0,0,0,0,3.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "An outdoor cemetery terrain with a stone tombstone box near the middle front, and an old dead tree peeking out from behind it, tucked slightly back and scaled down by half."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cemetery terrain][0,0,0,0,0,0,[12,12,0.1]][stone tombstone][0,hd,0,0,0,0,[0.6,0.2,0.8]][old dead tree][hw,-hd,hh,0,0,0,2.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A simple rolling hills terrain with a lone wooden cabin house standing at the origin center profile, flipped backwards and upside down."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[hills terrain][0,0,0,0,0,0,[20,20,1.5],noise=0.55][wooden cabin][0,0,0,-90,0,0,4.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A street scene terrain with an absolute disconnect truck asset positioned 15 units out along the longitudinal Y axis, facing sideways looking left."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[street terrain][0,0,0,0,0,0,[30,10,0.1]][diesel truck][abs][0,15.0,0,0,-90,0,4.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A low poly stylized mountain terrain path with a small crescent bridge arch spanning right between a rock on the left and a rock on the right."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[mountain terrain][0,0,0,0,0,0,[35,15,4.0],noise=0.7][large rock][-3fw,0,0,0,0,0,2.5][large rock][3fw,0,0,0,0,0,2.5][crescent bridge][@1,@2][0,0,0,0,0,0,1.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A flat concrete square courtyard terrain with a generic sculpture sphere encased completely within an architectural torus loop matching its absolute center vector."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[courtyard terrain][0,0,0,0,0,0,[15,15,0.1]][torus loop][0,0,0,90,0,0,2.0][sculpture sphere][0,0,0,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A high elevation mountain peak terrain that tapers sharply along the vertical axis, with a cross signpost capsule protruding directly out of its apex peek normal vector."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[mountain terrain][0,0,0,0,0,0,[10,10,8.0],taper=(z,0.1)][signpost capsule][0,0,fh+0.1,0,0,0,0.5]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A quiet garden terrain with a flower plant sitting near the front edge of a central stone well cylinder layout structure."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[garden terrain][0,0,0,0,0,0,[10,10,0.1]][stone well][0,0,0,0,0,0,[1.2,1.2,0.8]][flower plant][0,-fd,0,0,0,0,0.4]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A highway strip terrain with four identical barricade boxes lined up one after another in a row starting far to the left profile away from the main lane."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[highway terrain][0,0,0,0,0,0,[4,40,0.1]][barricade box][-4fw,0,0,0,0,0,0.8][barricade box][fw*@idx,0,0,0,0,0,0.8][barricade box][fw*@idx,0,0,0,0,0,0.8][barricade box][fw*@idx,0,0,0,0,0,0.8]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A rocky cavern terrain floor with an inverted dome sphere divet carved directly out of the center map space to create a deep circular fire pit crater mesh layout."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[cavern terrain][0,0,0,0,0,0,[20,20,1.0],noise=0.3][inverted sphere][0,0,0,0,0,0,[-1,1,-0.3]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A farm patch terrain layout space with a tractor vehicle parked tightly packed against the rear surface profile of a massive red barn house block asset."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[farm terrain][0,0,0,0,0,0,[30,30,0.1]][red barn house][0,0,0,0,0,0,[4,3,3.0]][tractor vehicle][0,-fd,0,0,0,0,2.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A wavy sand dune desert terrain with a single palm tree primitive tilted and slanted at a forty five degree angle near the center profile."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[sand terrain][0,0,0,0,0,0,[25,25,1.8],noise=0.55][palm tree][0,0,0,0,0,45,4.0]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "A clean courtyard paving terrain with a rectangular bench resting a short distance to the right of an ornate fountain basin statue mesh centerpiece asset."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[courtyard terrain][0,0,0,0,0,0,[16,16,0.1]][ornate fountain][0,0,0,0,0,0,2.2][rectangular bench][2fw,0,0,0,0,0,0.75]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
205
draco_glb.py
Normal file
205
draco_glb.py
Normal file
@@ -0,0 +1,205 @@
|
||||
"""Draco-aware GLB/glTF loader.
|
||||
|
||||
trimesh (and therefore pyrender) cannot decode meshes compressed with the
|
||||
``KHR_draco_mesh_compression`` extension on its own. When it encounters such a
|
||||
file it silently returns geometry whose vertex positions are all zero, which
|
||||
renders as a blank image. A large share of GLB files exported by modern tools
|
||||
(Blender, gltfpack, RealityCapture, photogrammetry pipelines, etc.) are
|
||||
Draco-compressed, so this is the most common reason a "simple" GLB shows up
|
||||
empty.
|
||||
|
||||
This module decodes the Draco buffers with :mod:`DracoPy` and rebuilds a normal
|
||||
:class:`trimesh.Scene` (vertices, faces, normals, UVs and the base-color
|
||||
texture) so the rest of a rendering pipeline can stay unchanged. Files that are
|
||||
not Draco-compressed fall back to a plain :func:`trimesh.load`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
import json
|
||||
import struct
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import trimesh
|
||||
|
||||
|
||||
DRACO_EXT = "KHR_draco_mesh_compression"
|
||||
|
||||
|
||||
def _parse_glb(path: Path):
|
||||
"""Return ``(gltf_json, binary_chunk)`` for a .glb, or ``(None, None)``."""
|
||||
data = Path(path).read_bytes()
|
||||
if len(data) < 12 or data[:4] != b"glTF":
|
||||
return None, None
|
||||
|
||||
total_len = struct.unpack("<I", data[8:12])[0]
|
||||
offset = 12
|
||||
gltf_json = None
|
||||
bin_chunk = b""
|
||||
|
||||
while offset < total_len:
|
||||
chunk_len = struct.unpack("<I", data[offset:offset + 4])[0]
|
||||
chunk_tag = data[offset + 4:offset + 8]
|
||||
body = data[offset + 8:offset + 8 + chunk_len]
|
||||
if chunk_tag == b"JSON":
|
||||
gltf_json = json.loads(body)
|
||||
elif chunk_tag == b"BIN\x00":
|
||||
bin_chunk = body
|
||||
offset += 8 + chunk_len
|
||||
|
||||
return gltf_json, bin_chunk
|
||||
|
||||
|
||||
def _is_draco_glb(path: Path) -> bool:
|
||||
gltf, _ = _parse_glb(path)
|
||||
if gltf is None:
|
||||
return False
|
||||
return DRACO_EXT in (gltf.get("extensionsUsed") or [])
|
||||
|
||||
|
||||
def _buffer_view_bytes(gltf, bin_chunk, view_index):
|
||||
view = gltf["bufferViews"][view_index]
|
||||
start = view.get("byteOffset", 0)
|
||||
return bin_chunk[start:start + view["byteLength"]]
|
||||
|
||||
|
||||
def _node_matrix(node):
|
||||
"""Resolve a glTF node's local transform (matrix or TRS) to a 4x4 matrix."""
|
||||
if "matrix" in node:
|
||||
# glTF stores matrices column-major.
|
||||
return np.array(node["matrix"], dtype=np.float64).reshape(4, 4).T
|
||||
|
||||
matrix = np.eye(4)
|
||||
if "scale" in node:
|
||||
matrix[:3, :3] = matrix[:3, :3] @ np.diag(node["scale"])
|
||||
if "rotation" in node:
|
||||
x, y, z, w = node["rotation"]
|
||||
rot = np.array([
|
||||
[1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w)],
|
||||
[2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w)],
|
||||
[2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y)],
|
||||
])
|
||||
matrix[:3, :3] = rot @ matrix[:3, :3]
|
||||
if "translation" in node:
|
||||
matrix[:3, 3] = node["translation"]
|
||||
return matrix
|
||||
|
||||
|
||||
def _load_material_image(gltf, bin_chunk, material_index):
|
||||
"""Return a PIL image for a material's base-color texture, or ``None``."""
|
||||
if material_index is None:
|
||||
return None
|
||||
try:
|
||||
from PIL import Image
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
try:
|
||||
material = gltf["materials"][material_index]
|
||||
pbr = material.get("pbrMetallicRoughness", {})
|
||||
tex_info = pbr.get("baseColorTexture")
|
||||
if tex_info is None:
|
||||
return None
|
||||
texture = gltf["textures"][tex_info["index"]]
|
||||
image = gltf["images"][texture["source"]]
|
||||
if "bufferView" not in image:
|
||||
return None
|
||||
raw = _buffer_view_bytes(gltf, bin_chunk, image["bufferView"])
|
||||
return Image.open(io.BytesIO(raw)).convert("RGB")
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _decode_draco_primitive(gltf, bin_chunk, primitive):
|
||||
import DracoPy
|
||||
|
||||
draco = primitive["extensions"][DRACO_EXT]
|
||||
comp = _buffer_view_bytes(gltf, bin_chunk, draco["bufferView"])
|
||||
mesh = DracoPy.decode(comp)
|
||||
|
||||
vertices = np.asarray(mesh.points, dtype=np.float64).reshape(-1, 3)
|
||||
faces = np.asarray(mesh.faces, dtype=np.int64).reshape(-1, 3)
|
||||
|
||||
normals = None
|
||||
raw_normals = getattr(mesh, "normals", None)
|
||||
if raw_normals is not None and len(raw_normals) == len(vertices):
|
||||
normals = np.asarray(raw_normals, dtype=np.float64).reshape(-1, 3)
|
||||
|
||||
uv = None
|
||||
raw_uv = getattr(mesh, "tex_coord", None)
|
||||
if raw_uv is not None and len(raw_uv) == len(vertices):
|
||||
uv = np.asarray(raw_uv, dtype=np.float64).reshape(-1, 2)
|
||||
|
||||
visual = None
|
||||
image = _load_material_image(gltf, bin_chunk, primitive.get("material"))
|
||||
if image is not None and uv is not None:
|
||||
material = trimesh.visual.material.PBRMaterial(baseColorTexture=image)
|
||||
visual = trimesh.visual.TextureVisuals(uv=uv, material=material)
|
||||
|
||||
geom = trimesh.Trimesh(
|
||||
vertices=vertices,
|
||||
faces=faces,
|
||||
vertex_normals=normals,
|
||||
visual=visual,
|
||||
process=False,
|
||||
)
|
||||
return geom
|
||||
|
||||
|
||||
def _load_draco_scene(path: Path) -> trimesh.Scene:
|
||||
gltf, bin_chunk = _parse_glb(path)
|
||||
scene = trimesh.Scene()
|
||||
|
||||
# Pre-decode each mesh's primitives once.
|
||||
decoded_meshes = []
|
||||
for mesh in gltf.get("meshes", []):
|
||||
geoms = []
|
||||
for primitive in mesh["primitives"]:
|
||||
if DRACO_EXT in (primitive.get("extensions") or {}):
|
||||
geoms.append(_decode_draco_primitive(gltf, bin_chunk, primitive))
|
||||
decoded_meshes.append(geoms)
|
||||
|
||||
nodes = gltf.get("nodes", [])
|
||||
scene_nodes = (gltf.get("scenes") or [{}])[gltf.get("scene", 0)].get(
|
||||
"nodes", list(range(len(nodes)))
|
||||
)
|
||||
|
||||
counter = {"n": 0}
|
||||
|
||||
def add_node(node_index, parent_matrix):
|
||||
node = nodes[node_index]
|
||||
matrix = parent_matrix @ _node_matrix(node)
|
||||
if "mesh" in node:
|
||||
for geom in decoded_meshes[node["mesh"]]:
|
||||
name = f"draco_{counter['n']}"
|
||||
counter["n"] += 1
|
||||
scene.add_geometry(geom, node_name=name, transform=matrix)
|
||||
for child in node.get("children", []):
|
||||
add_node(child, matrix)
|
||||
|
||||
for node_index in scene_nodes:
|
||||
add_node(node_index, np.eye(4))
|
||||
|
||||
if len(scene.geometry) == 0:
|
||||
raise RuntimeError("Draco GLB contained no decodable geometry")
|
||||
|
||||
return scene
|
||||
|
||||
|
||||
def load_glb_scene(path) -> trimesh.Scene:
|
||||
"""Load ``path`` into a :class:`trimesh.Scene`, decoding Draco if needed.
|
||||
|
||||
Always returns a Scene (a lone mesh is wrapped in one) so callers can treat
|
||||
the result uniformly.
|
||||
"""
|
||||
path = Path(path)
|
||||
|
||||
if path.suffix.lower() == ".glb" and _is_draco_glb(path):
|
||||
return _load_draco_scene(path)
|
||||
|
||||
loaded = trimesh.load(path, force="scene", process=False, maintain_order=True)
|
||||
if isinstance(loaded, trimesh.Scene):
|
||||
return loaded
|
||||
return trimesh.Scene([loaded])
|
||||
54
grammar.bnf
Normal file
54
grammar.bnf
Normal file
@@ -0,0 +1,54 @@
|
||||
# Root: Handles empty arrays, loose lists, or coordinate blocks
|
||||
root ::= (block_sequence | empty_scene)? ws?
|
||||
|
||||
empty_scene ::= "[]"
|
||||
|
||||
block_sequence ::= block (ws_or_nl* block)*
|
||||
|
||||
# A block is a raw tag name or a fully positioned layout primitive
|
||||
block ::= primitive (anchor? vector)?
|
||||
|
||||
primitive ::= "[" [a-zA-Z0-9_-]+ "]"
|
||||
|
||||
anchor ::= "[abs]" | "[@" [0-9]+ ("," ws? "@" [0-9]+)* "]"
|
||||
|
||||
# Vector strings support flat numbers, expressions, nested matrices, or config parameters
|
||||
# Enforces a valid item before and after every comma to break on double commas ,,
|
||||
vector ::= "[" value ("," ws? value)* "]"
|
||||
|
||||
value ::= nested_array | parameter_assignment | expression | attribute | signed_num | boolean_flag | variable
|
||||
|
||||
# Captures matrices like [1,1,1.5] or [-0.6,0.6,-0.4] cleanly
|
||||
nested_array ::= "[" value ("," ws? value)* "]"
|
||||
|
||||
# Captures both taper=(z,0.5) and functional variations like taper(z,0.7) or noise(0.4)
|
||||
parameter_assignment ::= [a-zA-Z_-]+ "=(" ws? [xyz] ws? "," ws? signed_num ws? ")" | [a-zA-Z_-]+ "(" ws? [xyz] ws? "," ws? num ws? ")" | [a-zA-Z_-]+ "(" num ")"
|
||||
|
||||
# Expressions handle explicit signs directly adjacent to implicit multi-variables
|
||||
expression ::= term (op term)*
|
||||
|
||||
# Fully parses 'fw * 4', implicit coefficients like '-4fw', '-4fd', or solo variables
|
||||
# FIX: Added sign? variable to cleanly handle prefixed variables like -fd or -hh
|
||||
term ::= variable ("*" (variable | signed_num))? | signed_num variable? | sign? variable | "sym(" ws? expression ws? ")"
|
||||
variable ::= "fw" | "hw" | "fd" | "hd" | "fh" | "hh" | "bd" | "bh" | "@idx" | "@" [0-9]+
|
||||
|
||||
boolean_flag ::= "surf" | "-%"
|
||||
|
||||
# Layout modifier keywords or attributes
|
||||
attribute ::= "noise=" signed_num | "mesh" | "surf" | "-%"
|
||||
|
||||
# STRICT number definition - only one sign character allowed total
|
||||
positive_num ::= [0-9]+ ("." [0-9]+)?
|
||||
negative_num ::= "-" [0-9]+ ("." [0-9]+)?
|
||||
num ::= positive_num | negative_num
|
||||
|
||||
# FIX: Changed to sign? positive_num to allow things like +5 or -5 without doubling up a negative_num's minus sign
|
||||
signed_num ::= sign? positive_num | negative_num
|
||||
|
||||
# SINGLE sign only - completely kills any '--' variants instantly
|
||||
sign ::= "+" | "-"
|
||||
|
||||
op ::= "+" | "-" | "*" | "/"
|
||||
|
||||
ws ::= [ \t]+
|
||||
ws_or_nl ::= [ \t\r\n]+
|
||||
67
grammar.gbnf
Normal file
67
grammar.gbnf
Normal file
@@ -0,0 +1,67 @@
|
||||
# Root: Handles empty arrays, loose lists, or coordinate blocks
|
||||
root ::= (block-sequence | empty-scene)? ws?
|
||||
|
||||
empty-scene ::= "[]"
|
||||
|
||||
block-sequence ::= block (ws-or-nl+ block)*
|
||||
|
||||
# A block is a raw tag name or a fully positioned layout primitive
|
||||
block ::= primitive (anchor? vector)?
|
||||
|
||||
primitive ::= "[" [a-zA-Z0-9_-]+ "]"
|
||||
|
||||
anchor ::= "[abs]" | "[@" digits ("," ws? "@" digits)* "]"
|
||||
|
||||
# Vector strings support flat numbers, expressions, nested matrices, or config parameters
|
||||
vector ::= "[" value ("," ws? value)* "]"
|
||||
|
||||
value ::= nested-array | parameter-assignment | expression | attribute | signed-num | boolean-flag | variable
|
||||
|
||||
# Captures matrices like [1,1,1.5] or [-0.6,0.6,-0.4] cleanly
|
||||
nested-array ::= "[" value ("," ws? value)* "]"
|
||||
|
||||
# Layout modifier keywords or attributes
|
||||
attribute ::= "noise=" signed-num | "mesh" | "surf" | "-%"
|
||||
|
||||
# Fixed: Explicitly wrapped multi-line assignment alternates in parentheses
|
||||
parameter-assignment ::= (
|
||||
tag-name "=(" ws? [xyz] ws? "," ws? signed-num ws? ")"
|
||||
| tag-name "(" ws? [xyz] ws? "," ws? num ws? ")"
|
||||
| tag-name "(" num ")"
|
||||
)
|
||||
|
||||
# Expressions handle explicit signs directly adjacent to implicit multi-variables
|
||||
expression ::= term (op term)*
|
||||
|
||||
# Fix: Explicitly wrapped the multi-line term rule alternates in parentheses to resolve the parsing error
|
||||
term ::= (
|
||||
variable multiplication-suffix?
|
||||
| signed-num variable?
|
||||
| sign? variable
|
||||
| "sym(" ws? expression ws? ")"
|
||||
)
|
||||
|
||||
multiplication-suffix ::= "*" (variable | signed-num)
|
||||
|
||||
variable ::= "fw" | "hw" | "fd" | "hd" | "fh" | "hh" | "bd" | "bh" | "@idx" | "@" digits
|
||||
|
||||
boolean-flag ::= "surf" | "-%"
|
||||
|
||||
# STRICT number definition - only one sign character allowed total
|
||||
positive-num ::= digits ("." digits)?
|
||||
negative-num ::= "-" digits ("." digits)?
|
||||
num ::= positive-num | negative-num
|
||||
|
||||
# Allows things like +5 or -5 without doubling up a negative_num's minus sign
|
||||
signed-num ::= sign? positive-num | negative-num
|
||||
|
||||
# SINGLE sign only - completely kills any '--' variants instantly
|
||||
sign ::= "+" | "-"
|
||||
|
||||
op ::= "+" | "-" | "*" | "/"
|
||||
|
||||
# Explicit named primitives to ensure perfect alignment with the GBNF compiler loop
|
||||
tag-name ::= [a-zA-Z_-]+
|
||||
digits ::= [0-9]+
|
||||
ws ::= [ \t]+
|
||||
ws-or-nl ::= [ \t\r\n]+
|
||||
511
grok-vision.py
Normal file
511
grok-vision.py
Normal file
@@ -0,0 +1,511 @@
|
||||
import argparse
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# pyrender needs an offscreen GL backend (EGL) on a headless Linux box. Must be
|
||||
# set before pyrender is imported (it is imported lazily further down). A
|
||||
# desktop session (DISPLAY set) is left untouched.
|
||||
if platform.system() == "Linux" and not os.environ.get("DISPLAY"):
|
||||
os.environ.setdefault("PYOPENGL_PLATFORM", "egl")
|
||||
|
||||
import numpy as np
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
from draco_glb import load_glb_scene
|
||||
|
||||
|
||||
def angled_camera_pose(center, radius):
|
||||
"""A 3/4 view pose looking at ``center`` (Z is treated as the up axis).
|
||||
|
||||
Looking straight down a model's main axis (the old behaviour) often shows
|
||||
only a featureless silhouette, so frame it from an elevated corner instead.
|
||||
"""
|
||||
if radius < 1e-6:
|
||||
radius = 1.0
|
||||
|
||||
distance = radius * 2.2
|
||||
azimuth = np.radians(35.0)
|
||||
elevation = np.radians(25.0)
|
||||
|
||||
offset = np.array([
|
||||
distance * np.cos(elevation) * np.sin(azimuth),
|
||||
-distance * np.cos(elevation) * np.cos(azimuth),
|
||||
distance * np.sin(elevation),
|
||||
])
|
||||
eye = center + offset
|
||||
|
||||
forward = center - eye
|
||||
forward = forward / np.linalg.norm(forward)
|
||||
|
||||
up = np.array([0.0, 0.0, 1.0])
|
||||
if abs(np.dot(forward, up)) > 0.99:
|
||||
up = np.array([0.0, 1.0, 0.0])
|
||||
|
||||
right = np.cross(forward, up)
|
||||
right = right / np.linalg.norm(right)
|
||||
true_up = np.cross(right, forward)
|
||||
|
||||
pose = np.eye(4)
|
||||
pose[:3, 0] = right
|
||||
pose[:3, 1] = true_up
|
||||
pose[:3, 2] = -forward
|
||||
pose[:3, 3] = eye
|
||||
return pose
|
||||
|
||||
|
||||
def load_flat_mesh(path):
|
||||
import trimesh
|
||||
|
||||
print("Loading scene...")
|
||||
|
||||
# load_glb_scene transparently decodes KHR_draco_mesh_compression, which a
|
||||
# plain trimesh.load cannot do (it would return all-zero vertices).
|
||||
loaded = load_glb_scene(path)
|
||||
|
||||
print(f"Loaded object type: {type(loaded)}")
|
||||
|
||||
if isinstance(loaded, trimesh.Trimesh):
|
||||
return loaded
|
||||
|
||||
if not isinstance(loaded, trimesh.Scene):
|
||||
raise RuntimeError(
|
||||
f"Unsupported object type: {type(loaded)}"
|
||||
)
|
||||
|
||||
print(f"Scene geometries: {len(loaded.geometry)}")
|
||||
|
||||
if len(loaded.geometry) == 0:
|
||||
raise RuntimeError(
|
||||
"Scene contains no geometry"
|
||||
)
|
||||
|
||||
# New trimesh versions
|
||||
if hasattr(loaded, "to_mesh"):
|
||||
try:
|
||||
print("Using Scene.to_mesh()")
|
||||
mesh = loaded.to_mesh()
|
||||
|
||||
if mesh is not None and not mesh.is_empty:
|
||||
return mesh
|
||||
except Exception as e:
|
||||
print(f"Scene.to_mesh failed: {e}")
|
||||
|
||||
# Fallback
|
||||
try:
|
||||
print("Using dump(concatenate=True)")
|
||||
mesh = loaded.dump(concatenate=True)
|
||||
|
||||
if mesh is not None and not mesh.is_empty:
|
||||
return mesh
|
||||
except Exception as e:
|
||||
print(f"dump(concatenate=True) failed: {e}")
|
||||
|
||||
# Nuclear option: manually bake transforms
|
||||
print("Manually baking scene graph...")
|
||||
|
||||
meshes = []
|
||||
|
||||
for node_name in loaded.graph.nodes_geometry:
|
||||
|
||||
try:
|
||||
transform, geom_name = loaded.graph[node_name]
|
||||
|
||||
geom = loaded.geometry[geom_name].copy()
|
||||
|
||||
if transform is not None:
|
||||
geom.apply_transform(transform)
|
||||
|
||||
meshes.append(geom)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Failed node {node_name}: {e}")
|
||||
|
||||
if not meshes:
|
||||
raise RuntimeError(
|
||||
"No mesh data extracted from scene"
|
||||
)
|
||||
|
||||
mesh = trimesh.util.concatenate(meshes)
|
||||
|
||||
return mesh
|
||||
|
||||
|
||||
def repair_mesh(mesh):
|
||||
print("\nRepairing mesh...")
|
||||
|
||||
try:
|
||||
mesh.remove_unreferenced_vertices()
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
mesh.merge_vertices()
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
mesh.remove_duplicate_faces()
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
mesh.remove_degenerate_faces()
|
||||
except:
|
||||
pass
|
||||
|
||||
# Remove NaN/Inf vertices
|
||||
try:
|
||||
valid = np.isfinite(mesh.vertices).all(axis=1)
|
||||
|
||||
if not valid.all():
|
||||
removed = (~valid).sum()
|
||||
print(
|
||||
f"Removed {removed} invalid vertices"
|
||||
)
|
||||
|
||||
mesh.update_vertices(valid)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Vertex cleanup failed: {e}")
|
||||
|
||||
try:
|
||||
mesh.fix_normals()
|
||||
except:
|
||||
pass
|
||||
|
||||
return mesh
|
||||
|
||||
|
||||
def center_and_scale(mesh, target_size=5.0):
|
||||
|
||||
bounds = mesh.bounds
|
||||
|
||||
vmin = bounds[0]
|
||||
vmax = bounds[1]
|
||||
|
||||
extents = vmax - vmin
|
||||
|
||||
center = (vmin + vmax) * 0.5
|
||||
|
||||
mesh.apply_translation(-center)
|
||||
|
||||
largest = float(np.max(extents))
|
||||
|
||||
if largest > 1e-12:
|
||||
scale = target_size / largest
|
||||
|
||||
mesh.apply_scale(scale)
|
||||
|
||||
print(
|
||||
f"Scale factor: {scale:.6f}"
|
||||
)
|
||||
|
||||
return mesh
|
||||
|
||||
|
||||
def print_diagnostics(mesh):
|
||||
|
||||
print("\n===== MESH INFO =====")
|
||||
|
||||
print(
|
||||
f"Vertices: {len(mesh.vertices):,}"
|
||||
)
|
||||
|
||||
print(
|
||||
f"Faces: {len(mesh.faces):,}"
|
||||
)
|
||||
|
||||
print(
|
||||
f"Empty: {mesh.is_empty}"
|
||||
)
|
||||
|
||||
print(
|
||||
f"Watertight: {mesh.is_watertight}"
|
||||
)
|
||||
|
||||
print(
|
||||
f"Bounds:\n{mesh.bounds}"
|
||||
)
|
||||
|
||||
print(
|
||||
f"Extents: {mesh.extents}"
|
||||
)
|
||||
|
||||
print(
|
||||
f"Centroid: {mesh.centroid}"
|
||||
)
|
||||
|
||||
try:
|
||||
print(
|
||||
f"Volume: {mesh.volume}"
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
print("=====================\n")
|
||||
|
||||
|
||||
def export_debug_render(mesh):
|
||||
try:
|
||||
import pyrender
|
||||
from PIL import Image
|
||||
|
||||
scene = pyrender.Scene(
|
||||
bg_color=[30, 30, 30, 255],
|
||||
ambient_light=[0.5, 0.5, 0.5]
|
||||
)
|
||||
|
||||
material = (
|
||||
pyrender.MetallicRoughnessMaterial(
|
||||
metallicFactor=0.0,
|
||||
roughnessFactor=0.8,
|
||||
baseColorFactor=[
|
||||
0.85,
|
||||
0.85,
|
||||
0.85,
|
||||
1.0
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
render_mesh = (
|
||||
pyrender.Mesh.from_trimesh(
|
||||
mesh,
|
||||
material=material,
|
||||
smooth=False
|
||||
)
|
||||
)
|
||||
|
||||
scene.add(render_mesh)
|
||||
|
||||
bbox = mesh.bounds
|
||||
|
||||
center = bbox.mean(axis=0)
|
||||
|
||||
radius = np.linalg.norm(
|
||||
bbox[1] - bbox[0]
|
||||
)
|
||||
|
||||
if radius < 0.001:
|
||||
radius = 1.0
|
||||
|
||||
camera = pyrender.PerspectiveCamera(
|
||||
yfov=np.pi / 3.0
|
||||
)
|
||||
|
||||
pose = angled_camera_pose(center, radius * 0.5)
|
||||
|
||||
scene.add(camera, pose=pose)
|
||||
|
||||
light = pyrender.DirectionalLight(
|
||||
color=np.ones(3),
|
||||
intensity=8.0
|
||||
)
|
||||
|
||||
scene.add(light, pose=pose)
|
||||
|
||||
renderer = (
|
||||
pyrender.OffscreenRenderer(
|
||||
1024,
|
||||
1024
|
||||
)
|
||||
)
|
||||
|
||||
color, depth = renderer.render(scene)
|
||||
|
||||
Image.fromarray(color).save(
|
||||
"debug_render.png"
|
||||
)
|
||||
|
||||
print(
|
||||
"Saved debug_render.png"
|
||||
)
|
||||
|
||||
renderer.delete()
|
||||
|
||||
except Exception as e:
|
||||
print(
|
||||
f"Debug render failed: {e}"
|
||||
)
|
||||
|
||||
|
||||
def launch_viewer(mesh):
|
||||
|
||||
import pyrender
|
||||
|
||||
scene = pyrender.Scene(
|
||||
bg_color=[20, 20, 25, 255],
|
||||
ambient_light=[0.5, 0.5, 0.5]
|
||||
)
|
||||
|
||||
material = (
|
||||
pyrender.MetallicRoughnessMaterial(
|
||||
metallicFactor=0.0,
|
||||
roughnessFactor=0.9,
|
||||
baseColorFactor=[
|
||||
0.85,
|
||||
0.85,
|
||||
0.85,
|
||||
1.0
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
render_mesh = (
|
||||
pyrender.Mesh.from_trimesh(
|
||||
mesh,
|
||||
material=material,
|
||||
smooth=False
|
||||
)
|
||||
)
|
||||
|
||||
scene.add(render_mesh)
|
||||
|
||||
bbox = mesh.bounds
|
||||
|
||||
center = bbox.mean(axis=0)
|
||||
|
||||
radius = np.linalg.norm(
|
||||
bbox[1] - bbox[0]
|
||||
)
|
||||
|
||||
if radius < 0.001:
|
||||
radius = 1.0
|
||||
|
||||
camera = pyrender.PerspectiveCamera(
|
||||
yfov=np.pi / 3.0
|
||||
)
|
||||
|
||||
pose = angled_camera_pose(center, radius * 0.5)
|
||||
|
||||
scene.add(camera, pose=pose)
|
||||
|
||||
light = pyrender.DirectionalLight(
|
||||
color=np.ones(3),
|
||||
intensity=8.0
|
||||
)
|
||||
|
||||
scene.add(light, pose=pose)
|
||||
|
||||
print(
|
||||
f"Viewer center: {center}"
|
||||
)
|
||||
|
||||
print(
|
||||
f"Viewer radius: {radius}"
|
||||
)
|
||||
|
||||
pyrender.Viewer(
|
||||
scene,
|
||||
viewport_size=(1400, 900),
|
||||
use_raymond_lighting=True,
|
||||
point_size=2.0
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="GLB Debug Viewer"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--model",
|
||||
required=True
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--visualize",
|
||||
action="store_true"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--export-obj"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
model_path = Path(args.model)
|
||||
|
||||
if not model_path.exists():
|
||||
print(
|
||||
f"File not found: {model_path}",
|
||||
file=sys.stderr
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
import trimesh
|
||||
|
||||
mesh = load_flat_mesh(
|
||||
model_path
|
||||
)
|
||||
|
||||
mesh = repair_mesh(
|
||||
mesh
|
||||
)
|
||||
|
||||
print_diagnostics(
|
||||
mesh
|
||||
)
|
||||
|
||||
mesh = center_and_scale(
|
||||
mesh,
|
||||
target_size=5.0
|
||||
)
|
||||
|
||||
export_debug_render(
|
||||
mesh
|
||||
)
|
||||
|
||||
if args.export_obj:
|
||||
|
||||
export_path = Path(
|
||||
args.export_obj
|
||||
)
|
||||
|
||||
export_path.parent.mkdir(
|
||||
parents=True,
|
||||
exist_ok=True
|
||||
)
|
||||
|
||||
mesh.export(export_path)
|
||||
|
||||
print(
|
||||
f"Exported OBJ: {export_path}"
|
||||
)
|
||||
|
||||
if args.visualize:
|
||||
|
||||
try:
|
||||
launch_viewer(mesh)
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print(
|
||||
f"Pyrender failed: {e}"
|
||||
)
|
||||
|
||||
print(
|
||||
"Trying trimesh viewer..."
|
||||
)
|
||||
|
||||
mesh.show()
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print(
|
||||
f"\nFATAL ERROR: {e}",
|
||||
file=sys.stderr
|
||||
)
|
||||
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
3
josiefied-qwen-f16.gguf
Normal file
3
josiefied-qwen-f16.gguf
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:26372bdf846091e929e4cf2d61280e7676fc221cc84229c969fdf25356c96d7d
|
||||
size 1266427872
|
||||
3
josiefied-qwen-q4_k_m.gguf
Normal file
3
josiefied-qwen-q4_k_m.gguf
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:23492bc16013ad621642e9ab971c2993879d450eea1567eb987fde50e3d8a628
|
||||
size 491402208
|
||||
3
josiefied-qwen-spatial-engine.gguf
Normal file
3
josiefied-qwen-spatial-engine.gguf
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:974ce5b6157081c4beb91778bab4dcd292be2322182633b46efe22cabe705220
|
||||
size 35216512
|
||||
148
model-convert.py
Normal file
148
model-convert.py
Normal file
@@ -0,0 +1,148 @@
|
||||
import bpy
|
||||
# from import_bsp import MD3
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# bpy.context.window.cursor_warp(10, 10)
|
||||
# current_file_name = bpy.path.basename(file_path)
|
||||
bpy.ops.object.select_all(action="SELECT")
|
||||
bpy.ops.object.delete()
|
||||
# bpy.ops.render.view_show('INVOKE_DEFAULT')
|
||||
|
||||
# usage:
|
||||
|
||||
print(f'Starting {sys.argv[4]}...')
|
||||
|
||||
extname = '.map'
|
||||
if ".map" in sys.argv[4]:
|
||||
bpy.ops.import_scene.id_map(filepath=sys.argv[4])
|
||||
elif ".bsp" in sys.argv[4]:
|
||||
extname = '.bsp'
|
||||
bpy.ops.import_scene.id3_bsp(
|
||||
filepath=sys.argv[4],
|
||||
preset="BRUSHES",
|
||||
vert_map_packing="Keep"
|
||||
)
|
||||
elif ".obj" in sys.argv[4]:
|
||||
extname = '.obj'
|
||||
bpy.ops.wm.obj_import(filepath=sys.argv[4])
|
||||
|
||||
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
# https://github.com/SomaZ/Blender_BSP_Importer/blob/main/import_bsp/UI.py#L362
|
||||
# bpy.ops.export_scene.id3_md3(
|
||||
# filepath = file,
|
||||
# preset = "MATERIALS",
|
||||
# only_selected = True,
|
||||
# limits = "LEGACY",
|
||||
# start_frame = 0,
|
||||
# end_frame = 0,
|
||||
# individual = False # use model space coordinates instead of world space
|
||||
# )
|
||||
|
||||
try:
|
||||
bpy.ops.export_scene.id3_md3(
|
||||
filepath = sys.argv[4].replace(extname, '.md3'),
|
||||
preset = "MATERIALS",
|
||||
only_selected = False,
|
||||
limits = "STUPID",
|
||||
start_frame = 0,
|
||||
end_frame = 0,
|
||||
individual = False # use model space coordinates instead of world space
|
||||
)
|
||||
except RuntimeError as err:
|
||||
if not "Model exceeds MD3 bounds" in str(err):
|
||||
raise RuntimeError
|
||||
except Exception as err:
|
||||
if not "BSP format not supported" in str(err):
|
||||
raise err
|
||||
|
||||
for ob in bpy.data.objects:
|
||||
ob.scale = (0.5,0.5,0.5)
|
||||
bpy.ops.object.transform_apply(scale=True)
|
||||
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
try:
|
||||
bpy.ops.export_scene.id3_md3(
|
||||
filepath = sys.argv[4].replace(extname, '-half.md3'),
|
||||
preset = "MATERIALS",
|
||||
only_selected = False,
|
||||
limits = "STUPID",
|
||||
start_frame = 0,
|
||||
end_frame = 0,
|
||||
individual = False # use model space coordinates instead of world space
|
||||
)
|
||||
except RuntimeError as err:
|
||||
if not "Model exceeds MD3 bounds" in str(err):
|
||||
raise err
|
||||
except Exception as err:
|
||||
if not "BSP format not supported" in str(err):
|
||||
raise err
|
||||
|
||||
for ob in bpy.data.objects:
|
||||
ob.scale = (0.25,0.25,0.25)
|
||||
bpy.ops.object.transform_apply(scale=True)
|
||||
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
# MD3.ExportMD3(
|
||||
# sys.argv[4].replace(extname, '-quarter.md3'),
|
||||
# bpy.data.objects,
|
||||
# range(0, 1),
|
||||
# False,
|
||||
# True,
|
||||
# 100000,
|
||||
# 1024)
|
||||
|
||||
try:
|
||||
bpy.ops.export_scene.id3_md3(
|
||||
filepath = sys.argv[4].replace(extname, '-quarter.md3'),
|
||||
preset = "MATERIALS",
|
||||
only_selected = False,
|
||||
limits = "STUPID",
|
||||
start_frame = 0,
|
||||
end_frame = 0,
|
||||
individual = False # use model space coordinates instead of world space
|
||||
)
|
||||
except RuntimeError as err:
|
||||
if not "Model exceeds MD3 bounds" in str(err):
|
||||
raise err
|
||||
except Exception as err:
|
||||
if not "BSP format not supported" in str(err):
|
||||
raise err
|
||||
|
||||
|
||||
for ob in bpy.data.objects:
|
||||
ob.scale = (0.125,0.125,0.125)
|
||||
bpy.ops.object.transform_apply(scale=True)
|
||||
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
try:
|
||||
bpy.ops.export_scene.id3_md3(
|
||||
filepath = sys.argv[4].replace(extname, '-eigth.md3'),
|
||||
preset = "MATERIALS",
|
||||
only_selected = False,
|
||||
limits = "STUPID",
|
||||
start_frame = 0,
|
||||
end_frame = 0,
|
||||
individual = False # use model space coordinates instead of world space
|
||||
)
|
||||
except RuntimeError as err:
|
||||
if not "Model exceeds MD3 bounds" in str(err):
|
||||
raise err
|
||||
except Exception as err:
|
||||
if not "BSP format not supported" in str(err):
|
||||
raise err
|
||||
|
||||
|
||||
# bpy.ops.wm.revert_mainfile()
|
||||
|
||||
print(f'Done {sys.argv[4]}...')
|
||||
# bpy.ops.wm.call_menu(name="FILE_quit")
|
||||
# bpy.ops.file.reset_recent()
|
||||
bpy.ops.wm.window_close()
|
||||
bpy.ops.wm.quit_blender()
|
||||
sys.exit()
|
||||
421
model-vision.py
Normal file
421
model-vision.py
Normal file
@@ -0,0 +1,421 @@
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import platform
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
# Clear any legacy or conflicting PyOpenGL/pyrender configuration keys instantly
|
||||
for env_key in ["PYOPENGL_PLATFORM", "PYRENDER_BACKEND", "PYOPENGL_FORCE_NO_EGL"]:
|
||||
if env_key in os.environ:
|
||||
del os.environ[env_key]
|
||||
|
||||
import torch
|
||||
import trimesh
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
from transformers import AutoProcessor, AutoModel, AutoModelForImageTextToText
|
||||
|
||||
from huggingface_hub import hf_hub_download
|
||||
from llama_cpp import Llama
|
||||
from llama_cpp.llama_chat_format import MoondreamChatHandler # Handles the vision projection layer
|
||||
from llama_cpp.llama_chat_format import Llava15ChatHandler # or Llava16ChatHandler
|
||||
from llama_cpp.llama_chat_format import MTMDChatHandler
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
from draco_glb import load_glb_scene
|
||||
|
||||
|
||||
# --- Global Engine State ---
|
||||
processor = None
|
||||
model = None
|
||||
|
||||
# Variables for the specific files needed
|
||||
GGUF_REPO_PATH = "ggml-org/SmolVLM2-2.2B-Instruct-GGUF"
|
||||
GGUF_MODEL_PATH = "SmolVLM2-2.2B-Instruct-Q4_K_M.gguf"
|
||||
GGUF_MMPROJ_PATH = "mmproj-SmolVLM2-2.2B-Instruct-Q8_0.gguf"
|
||||
GGUF_ORIGINAL_PATH = "HuggingFaceTB/SmolVLM2-2.2B-Instruct"
|
||||
|
||||
model_id = "HuggingFaceTB/SmolVLM-Instruct"
|
||||
HF_CACHE_DIR = "hf_cache"
|
||||
CREDENTIALS_FILE = Path("~/.credentials/huggingface-provider.json").expanduser()
|
||||
|
||||
|
||||
|
||||
processor = None
|
||||
model = None
|
||||
device = None
|
||||
dtype = None
|
||||
|
||||
|
||||
|
||||
def get_token():
|
||||
if CREDENTIALS_FILE.exists():
|
||||
with open(CREDENTIALS_FILE, 'r', encoding='utf-8') as f:
|
||||
return json.load(f).get("ACCESS_TOKEN", "").strip()
|
||||
return None
|
||||
|
||||
HF_TOKEN = get_token()
|
||||
if HF_TOKEN:
|
||||
os.environ["HF_TOKEN"] = HF_TOKEN
|
||||
|
||||
# ==================== REPAIR & EXTRACTION LOGIC ====================
|
||||
def compute_scene_bounds(scene):
|
||||
mins = np.array([np.inf, np.inf, np.inf])
|
||||
maxs = np.array([-np.inf, -np.inf, -np.inf])
|
||||
|
||||
for geom in scene.geometry.values():
|
||||
if len(geom.vertices) == 0:
|
||||
continue
|
||||
verts = np.asarray(geom.vertices)
|
||||
if not np.isfinite(verts).all():
|
||||
continue
|
||||
mins = np.minimum(mins, verts.min(axis=0))
|
||||
maxs = np.maximum(maxs, verts.max(axis=0))
|
||||
|
||||
if np.any(np.isinf(mins)) or np.any(np.isinf(maxs)):
|
||||
return np.zeros(3), np.ones(3), 1.0
|
||||
|
||||
center = (mins + maxs) * 0.5
|
||||
extents = maxs - mins
|
||||
extents_norm = np.linalg.norm(extents)
|
||||
radius = max(extents_norm * 0.5, 0.001)
|
||||
|
||||
return center, extents, radius
|
||||
|
||||
def build_camera_transform(center, distance, pitch_deg, yaw_deg):
|
||||
"""Computes layout look-at camera tracking matrices matching Blender metrics."""
|
||||
pitch = np.radians(pitch_deg)
|
||||
yaw = np.radians(yaw_deg)
|
||||
|
||||
dx = distance * np.cos(pitch) * np.sin(yaw)
|
||||
dy = -distance * np.cos(pitch) * np.cos(yaw)
|
||||
dz = distance * np.sin(pitch)
|
||||
|
||||
cam_pos = center + np.array([dx, dy, dz])
|
||||
|
||||
forward = center - cam_pos
|
||||
f_norm = np.linalg.norm(forward)
|
||||
if f_norm < 1e-6:
|
||||
forward = np.array([0.0, -1.0, 0.0])
|
||||
else:
|
||||
forward = forward / f_norm
|
||||
|
||||
world_up = np.array([0.0, 0.0, 1.0])
|
||||
right = np.cross(forward, world_up)
|
||||
r_norm = np.linalg.norm(right)
|
||||
|
||||
if r_norm < 1e-6:
|
||||
alternative_up = np.array([1.0, 0.0, 0.0])
|
||||
right = np.cross(forward, alternative_up)
|
||||
right /= max(np.linalg.norm(right), 1e-6)
|
||||
else:
|
||||
right = right / r_norm
|
||||
|
||||
true_up = np.cross(right, forward)
|
||||
true_up /= max(np.linalg.norm(true_up), 1e-6)
|
||||
|
||||
pose = np.eye(4)
|
||||
pose[:3, 0] = right
|
||||
pose[:3, 1] = true_up
|
||||
pose[:3, 2] = -forward
|
||||
pose[:3, 3] = cam_pos
|
||||
return pose
|
||||
|
||||
|
||||
def build_view_pose(center, distance, pitch_deg, yaw_deg):
|
||||
"""Computes camera look-at transformation matrix targets using yaw and pitch.
|
||||
|
||||
Coordinates map pitch and yaw directly to match standard Blender tracking metrics.
|
||||
"""
|
||||
# Map coordinates to align with standard pitch/yaw angle frames
|
||||
pitch = np.radians(pitch_deg)
|
||||
yaw = np.radians(yaw_deg)
|
||||
|
||||
# Calculate spherical offsets relative to target scene center bounding boxes
|
||||
dx = distance * np.cos(pitch) * np.sin(yaw)
|
||||
dy = -distance * np.cos(pitch) * np.cos(yaw)
|
||||
dz = distance * np.sin(pitch)
|
||||
|
||||
camera_position = center + np.array([dx, dy, dz])
|
||||
|
||||
# Compute look-at forward vector (-Z is forward in camera space)
|
||||
forward = center - camera_position
|
||||
f_norm = np.linalg.norm(forward)
|
||||
if f_norm < 1e-6:
|
||||
forward = np.array([0.0, -1.0, 0.0])
|
||||
else:
|
||||
forward = forward / f_norm
|
||||
|
||||
# Calculate right vector using standard world-up vector (+Z is world-up)
|
||||
world_up = np.array([0.0, 0.0, 1.0])
|
||||
right = np.cross(forward, world_up)
|
||||
r_norm = np.linalg.norm(right)
|
||||
|
||||
if r_norm < 1e-6:
|
||||
alternative_up = np.array([1.0, 0.0, 0.0])
|
||||
right = np.cross(forward, alternative_up)
|
||||
right /= max(np.linalg.norm(right), 1e-6)
|
||||
else:
|
||||
right = right / r_norm
|
||||
|
||||
# Re-orthogonalize the true camera up vector
|
||||
true_up = np.cross(right, forward)
|
||||
true_up /= max(np.linalg.norm(true_up), 1e-6)
|
||||
|
||||
# Assemble transformation matrix
|
||||
pose = np.eye(4)
|
||||
pose[:3, 0] = right
|
||||
pose[:3, 1] = true_up
|
||||
pose[:3, 2] = -forward # Camera looks down its native -Z axis
|
||||
pose[:3, 3] = camera_position
|
||||
|
||||
return pose
|
||||
|
||||
|
||||
|
||||
def render_model_to_2d(file_path: str, output_image_path: str = "model_preview.png"):
|
||||
if not os.path.exists(file_path):
|
||||
raise FileNotFoundError(f"Asset target not found: {file_path}")
|
||||
|
||||
print(f"🎬 Processing Engine: {os.path.basename(file_path)}")
|
||||
|
||||
# Safely unpack Draco-compressed scene metrics via custom loader layer
|
||||
trimesh_scene = load_glb_scene(file_path)
|
||||
center, extents, radius = compute_scene_bounds(trimesh_scene)
|
||||
|
||||
print(f"📐 Scene Center: {np.round(center, 3)} | Calculated Radius: {round(radius, 3)}")
|
||||
|
||||
# Keep a non-zero fill baseline bounding track distance factor
|
||||
distance = radius * 2.5
|
||||
|
||||
# Direct port of Blender angle vectors tracking metrics
|
||||
view_angles = [
|
||||
{"name": "Front Elevated", "pitch": 8, "yaw": 0},
|
||||
{"name": "Side Profile", "pitch": 5, "yaw": 90},
|
||||
{"name": "High Angle Top", "pitch": 75, "yaw": 45},
|
||||
{"name": "Low Pitch Angle", "pitch": -12, "yaw": 35},
|
||||
]
|
||||
|
||||
captured_images = []
|
||||
|
||||
for view in view_angles:
|
||||
try:
|
||||
# Re-initialize a clean perspective transformation frame copy
|
||||
view_scene = trimesh_scene.copy()
|
||||
|
||||
# Build look-at matrix relative to bounding centers
|
||||
cam_pose = build_view_pose(center, distance, view["pitch"], view["yaw"])
|
||||
|
||||
# Direct scene-graph property update for the active camera node
|
||||
view_scene.camera_transform = cam_pose
|
||||
view_scene.camera.resolution = [512, 512]
|
||||
|
||||
# Pure software vector-to-raster dump (completely bypasses PyOpenGL and driver checks)
|
||||
png_bytes = view_scene.save_image(background=[30, 30, 35, 255])
|
||||
|
||||
from io import BytesIO
|
||||
img = Image.open(BytesIO(png_bytes)).convert("RGB")
|
||||
captured_images.append(img)
|
||||
except Exception as e:
|
||||
print(f"⚠️ View '{view['name']}' software save backup failure: {e}")
|
||||
captured_images.append(Image.new('RGB', (512, 512), (50, 50, 60)))
|
||||
|
||||
# Coalesce the views array into a unified 2x2 layout canvas sheet matrix
|
||||
grid = Image.new('RGB', (1024, 1024), (30, 30, 35))
|
||||
grid.paste(captured_images[0], (0, 0))
|
||||
grid.paste(captured_images[1], (512, 0))
|
||||
grid.paste(captured_images[2], (0, 512))
|
||||
grid.paste(captured_images[3], (512, 512))
|
||||
|
||||
grid.save(output_image_path)
|
||||
print(f"✅ Successfully rendered asset sheet layout -> {output_image_path}")
|
||||
return output_image_path
|
||||
|
||||
|
||||
|
||||
def analyze_image_locally(image_path: str):
|
||||
global processor, model, device, dtype
|
||||
|
||||
if not os.path.exists(image_path):
|
||||
print(f"Error: Target image missing: {image_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Lazy Initialization
|
||||
if model is None or processor is None:
|
||||
if torch.cuda.is_available():
|
||||
device = "cuda"
|
||||
dtype = torch.bfloat16
|
||||
attn_impl = "flash_attention_2"
|
||||
elif torch.backends.mps.is_available():
|
||||
device = "mps"
|
||||
dtype = torch.float16
|
||||
attn_impl = None
|
||||
else:
|
||||
device = "cpu"
|
||||
dtype = torch.float32
|
||||
attn_impl = None
|
||||
print("Running on CPU...")
|
||||
|
||||
print(f"Loading SmolVLM on {device}...")
|
||||
|
||||
processor = AutoProcessor.from_pretrained(
|
||||
model_id,
|
||||
cache_dir=HF_CACHE_DIR,
|
||||
token=HF_TOKEN
|
||||
)
|
||||
|
||||
model = AutoModelForImageTextToText.from_pretrained( # ← Updated class
|
||||
model_id,
|
||||
torch_dtype=dtype,
|
||||
_attn_implementation=attn_impl,
|
||||
cache_dir=HF_CACHE_DIR,
|
||||
token=HF_TOKEN,
|
||||
# device_map="auto", # Good for low VRAM
|
||||
).to(device)
|
||||
|
||||
if device == "cpu":
|
||||
num_cores = os.cpu_count() or 4
|
||||
torch.set_num_threads(max(1, num_cores // 2))
|
||||
try:
|
||||
model = torch.compile(model)
|
||||
print("Model compiled.")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raw_image = Image.open(image_path).convert("RGB")
|
||||
|
||||
messages = [{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "image"},
|
||||
{"type": "text", "text": "Categorize the image with descriptive adjectives and nouns. Respond quickly with only the whitespace delimited list of words."}
|
||||
]
|
||||
}]
|
||||
|
||||
prompt = processor.apply_chat_template(messages, add_generation_prompt=True)
|
||||
|
||||
inputs = processor(text=prompt, images=raw_image, return_tensors="pt").to(device)
|
||||
|
||||
if "pixel_values" in inputs:
|
||||
inputs["pixel_values"] = inputs["pixel_values"].to(dtype)
|
||||
|
||||
print("Running inference...")
|
||||
with torch.no_grad():
|
||||
generated_ids = model.generate(
|
||||
**inputs,
|
||||
max_new_tokens=120,
|
||||
do_sample=False,
|
||||
temperature=0.0,
|
||||
)
|
||||
|
||||
generated_ids_trimmed = [
|
||||
out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
|
||||
]
|
||||
answer = processor.batch_decode(generated_ids_trimmed, skip_special_tokens=True)[0].strip()
|
||||
|
||||
print("\n--- LOCAL VISION ANALYSIS ---")
|
||||
print(answer)
|
||||
return answer
|
||||
|
||||
|
||||
def analyze_image_gguf(image_path: str):
|
||||
global model
|
||||
|
||||
if not os.path.exists(image_path):
|
||||
print(f"Error: Image missing: {image_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if model is None:
|
||||
print("Loading SmolVLM GGUF on CPU (optimized for i7)...")
|
||||
num_cores = os.cpu_count() or 4
|
||||
optimal_threads = max(1, num_cores // 2)
|
||||
|
||||
# Download model + mmproj
|
||||
local_model_path = hf_hub_download(
|
||||
repo_id=GGUF_REPO_PATH,
|
||||
filename=GGUF_MODEL_PATH,
|
||||
cache_dir=HF_CACHE_DIR,
|
||||
token=HF_TOKEN
|
||||
)
|
||||
|
||||
local_mmproj_path = hf_hub_download(
|
||||
repo_id=GGUF_REPO_PATH,
|
||||
filename=GGUF_MMPROJ_PATH,
|
||||
cache_dir=HF_CACHE_DIR,
|
||||
token=HF_TOKEN
|
||||
)
|
||||
|
||||
# Use the correct chat handler for SmolVLM / Moondream-style models
|
||||
chat_handler = MTMDChatHandler(
|
||||
clip_model_path=local_mmproj_path,
|
||||
verbose=False
|
||||
)
|
||||
|
||||
model = Llama(
|
||||
model_path=local_model_path,
|
||||
chat_handler=chat_handler,
|
||||
n_ctx=2048,
|
||||
n_threads=optimal_threads,
|
||||
n_gpu_layers=0, # CPU only
|
||||
verbose=False,
|
||||
)
|
||||
|
||||
# Better prompt for SmolVLM + force image inclusion
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "Categorize the image with descriptive adjectives and nouns. Respond quickly with only the whitespace delimited list of words."},
|
||||
#{"type": "image", "image": os.path.abspath(image_path)},
|
||||
{"type": "image_url", "image_url": {"url": f"file://{os.path.abspath(image_path)}"}}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
print("Running GGUF VLM inference...")
|
||||
response = model.create_chat_completion(
|
||||
messages=messages,
|
||||
max_tokens=100,
|
||||
temperature=0.1, # Slight temp helps small models
|
||||
top_p=0.9,
|
||||
)
|
||||
|
||||
raw_content = response["choices"][0]["message"]["content"]
|
||||
answer = raw_content.strip() if raw_content else "No output."
|
||||
|
||||
print("\n--- LOCAL VISION ANALYSIS ---")
|
||||
print(answer)
|
||||
|
||||
try:
|
||||
model.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return answer
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Cross-Platform 3D Asset Validation Engine")
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument("--model", type=str, help="Path to target 3D asset (.glb/.obj/.fbx/.stl)")
|
||||
group.add_argument("--image", type=str, help="Path to pre-existing verification canvas image")
|
||||
parser.add_argument("--output", type=str, default="model_preview.png", help="Output collage path location")
|
||||
parser.add_argument("--analyze", type=lambda x: (str(x).lower() == 'true'), default=False, help="Use vision LLM to describe model")
|
||||
|
||||
args = parser.parse_args()
|
||||
target_image = args.image
|
||||
|
||||
if args.model:
|
||||
try:
|
||||
target_image = render_model_to_2d(args.model, args.output)
|
||||
except Exception as e:
|
||||
print(f"❌ Structural script runtime evaluation failure: {e}", file=sys.stderr)
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
if target_image and args.analyze:
|
||||
analyze_image_gguf(target_image)
|
||||
106
model-vision2.py
Normal file
106
model-vision2.py
Normal file
@@ -0,0 +1,106 @@
|
||||
import os
|
||||
import math
|
||||
import bpy
|
||||
|
||||
def render_model_to_grid(model_path, output_path):
|
||||
# Clear default scene items
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
bpy.ops.object.delete()
|
||||
|
||||
# Import the asset
|
||||
ext = os.path.splitext(model_path)[1].lower()
|
||||
if ext in ['.glb', '.gltf']:
|
||||
bpy.ops.import_scene.gltf(filepath=model_path)
|
||||
elif ext == '.obj':
|
||||
bpy.ops.wm.obj_import(filepath=model_path)
|
||||
elif ext == '.fbx':
|
||||
bpy.ops.import_scene.fbx(filepath=model_path)
|
||||
elif ext == '.stl':
|
||||
bpy.ops.wm.stl_import(filepath=model_path)
|
||||
else:
|
||||
raise ValueError(f"Unsupported asset format extension: {ext}")
|
||||
|
||||
# Compute bounding metrics across all imported objects
|
||||
obs = [o for o in bpy.context.scene.objects if o.type == 'MESH']
|
||||
if not obs:
|
||||
raise ValueError("No valid mesh geometry loaded into the layout tree.")
|
||||
|
||||
# Frame geometry bounds
|
||||
for obj in obs:
|
||||
obj.select_set(True)
|
||||
bpy.ops.view3d.camera_to_view_selected()
|
||||
|
||||
# Add a clean camera and tracking point
|
||||
cam_data = bpy.data.cameras.new(name="ValidationCam")
|
||||
cam_obj = bpy.data.objects.new("ValidationCam", cam_data)
|
||||
bpy.context.scene.collection.objects.link(cam_obj)
|
||||
bpy.context.scene.camera = cam_obj
|
||||
|
||||
# Create an anchor target at the origin
|
||||
target = bpy.data.objects.new("Anchor", None)
|
||||
bpy.context.scene.collection.objects.link(target)
|
||||
|
||||
# Add constraint to camera to always track the target origin
|
||||
track = cam_obj.constraints.new(type='TRACK_TO')
|
||||
track.target = target
|
||||
track.track_axis = 'TRACK_NEGATIVE_Z'
|
||||
track.up_axis = 'UP_Y'
|
||||
|
||||
# Light setup
|
||||
light_data = bpy.data.lights.new(name="Sun", type='SUN')
|
||||
light_obj = bpy.data.objects.new("Sun", light_data)
|
||||
bpy.context.scene.collection.objects.link(light_obj)
|
||||
light_data.energy = 3.0
|
||||
|
||||
# Shading options: render flat colors with basic ambient pass
|
||||
bpy.context.scene.render.engine = 'BLENDER_EEVEE_NEXT' if hasattr(bpy.data, "version") and bpy.data.version >= (4, 2) else 'BLENDER_EEVEE'
|
||||
bpy.context.scene.render.resolution_x = 512
|
||||
bpy.context.scene.render.resolution_y = 512
|
||||
|
||||
# View configurations matrix [Pitch, Yaw]
|
||||
views = [
|
||||
{"name": "Front", "p": 5, "y": 0},
|
||||
{"name": "Side", "p": 5, "y": 90},
|
||||
{"name": "Top", "p": 80, "y": 45},
|
||||
{"name": "Angle", "p": -15, "y": 30}
|
||||
]
|
||||
|
||||
from PIL import Image
|
||||
captured_frames = []
|
||||
|
||||
for idx, v in enumerate(views):
|
||||
pitch = math.radians(v["p"])
|
||||
yaw = math.radians(v["y"])
|
||||
dist = 3.5 # Set normalized tracking distance offset
|
||||
|
||||
# Spherical coordinate conversion mechanics
|
||||
cam_obj.location.x = dist * math.cos(pitch) * math.sin(yaw)
|
||||
cam_obj.location.y = -dist * math.cos(pitch) * math.cos(yaw)
|
||||
cam_obj.location.z = dist * math.sin(pitch)
|
||||
|
||||
# Execute render frame save pass
|
||||
tmp_img_path = f"tmp_frame_{idx}.png"
|
||||
bpy.context.scene.render.filepath = os.path.abspath(tmp_img_path)
|
||||
bpy.ops.render.render(write_still=True)
|
||||
captured_frames.append(Image.open(tmp_img_path))
|
||||
os.remove(tmp_img_path)
|
||||
|
||||
# Compile the 2x2 grid collage
|
||||
grid = Image.new('RGB', (1024, 1024), (30, 30, 35))
|
||||
grid.paste(captured_frames[0], (0, 0))
|
||||
grid.paste(captured_frames[1], (512, 0))
|
||||
grid.paste(captured_frames[2], (0, 512))
|
||||
grid.paste(captured_frames[3], (512, 512))
|
||||
grid.save(output_path)
|
||||
print(f"✅ Grid successfully compiled via Blender context -> {output_path}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
argv = sys.argv
|
||||
try:
|
||||
idx = argv.index("--")
|
||||
m_path = argv[idx + 1]
|
||||
out_path = argv[idx + 2]
|
||||
render_model_to_grid(m_path, out_path)
|
||||
except (ValueError, IndexError):
|
||||
print("Missing argument bindings passed to background wrapper script.")
|
||||
361
objaverse-download.py
Normal file
361
objaverse-download.py
Normal file
@@ -0,0 +1,361 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
import shutil
|
||||
import argparse
|
||||
import pandas as pd
|
||||
import objaverse.xl as oxl
|
||||
from typing import Dict, Any, Hashable, List
|
||||
import re
|
||||
import pyarrow as pa
|
||||
import pyarrow.parquet as pq
|
||||
|
||||
import pandas as pd
|
||||
import pyarrow.parquet as pq
|
||||
import glob
|
||||
|
||||
# --- Windows Permission Error Fix ---
|
||||
def remove_readonly(func, path, excinfo):
|
||||
os.chmod(path, stat.S_IWRITE)
|
||||
func(path)
|
||||
|
||||
_original_rmtree = shutil.rmtree
|
||||
def patched_rmtree(path, *args, **kwargs):
|
||||
if "onerror" not in kwargs and "onexc" not in kwargs:
|
||||
kwargs["onerror"] = remove_readonly
|
||||
return _original_rmtree(path, *args, **kwargs)
|
||||
shutil.rmtree = patched_rmtree
|
||||
# -------------------------------------
|
||||
|
||||
# Explicit directories
|
||||
CACHE_DIR = os.path.expanduser("~/.objaverse") # Parquet + GitHub cache
|
||||
EXPORT_DIR = os.path.expanduser("~/.objaverse/downloads") # Your clean copies
|
||||
GITHUB_REPOS_DIR = os.path.join(CACHE_DIR, "github", "repos") # Where full repos land
|
||||
|
||||
os.makedirs(CACHE_DIR, exist_ok=True)
|
||||
os.makedirs(EXPORT_DIR, exist_ok=True)
|
||||
os.makedirs(GITHUB_REPOS_DIR, exist_ok=True)
|
||||
|
||||
def handle_found_object(
|
||||
local_path: str,
|
||||
file_identifier: str,
|
||||
sha256: str,
|
||||
metadata: Dict[Hashable, Any]
|
||||
) -> None:
|
||||
"""Called when a matching object is found (runs in worker processes)."""
|
||||
base_name = os.path.basename(file_identifier) or f"{sha256}.glb"
|
||||
destination = os.path.join(EXPORT_DIR, base_name)
|
||||
|
||||
try:
|
||||
shutil.copy2(local_path, destination)
|
||||
print(f"💾 [EXPORTED] {base_name} -> {destination}")
|
||||
except Exception as e:
|
||||
print(f"❌ Copy failed for {base_name}: {e}")
|
||||
|
||||
|
||||
def inspect_schema(github: bool = True, gltf: bool = False, thingiverse: bool = False, smithsonian: bool = False) -> pd.DataFrame:
|
||||
"""Centralized loader that profiles the parquet metadata footer directly,
|
||||
bypassing OXL to audit structural layouts before reading rows into memory."""
|
||||
print(f"📦 Inspecting Objaverse Parquet Registries directly from cache: {CACHE_DIR}")
|
||||
|
||||
# Locate downloaded .parquet annotations files inside the local cache directory structure
|
||||
parquet_files = glob.glob(os.path.join(CACHE_DIR, "**/*.parquet"), recursive=True)
|
||||
|
||||
if not parquet_files:
|
||||
raise FileNotFoundError(f"No parquet registries found in {CACHE_DIR}. Ensure assets have been cached or paths are fully mapped.")
|
||||
|
||||
# Target the primary index file (or loop through them if multi-part)
|
||||
target_parquet = parquet_files[0]
|
||||
|
||||
# --- BYPASSING OXL: READ PARQUET METADATA FOOTER ONLY ---
|
||||
parquet_meta = pq.read_metadata(target_parquet)
|
||||
schema = parquet_meta.schema
|
||||
|
||||
print("\n📊 --- LOCAL CACHE METADATA AUDIT (RAW FOOTER SCRIPT) ---")
|
||||
print(f"Total entries sitting in target registry metadata: {parquet_meta.num_rows:,}")
|
||||
|
||||
# --- PARQUET FILE SCHEMA DUMP ---
|
||||
print("\n🗂️ Complete Parquet Column Schema & Data Types:")
|
||||
for i in range(len(schema)):
|
||||
column_meta = schema.column(i)
|
||||
print(f" • {column_meta.name:<18} : {column_meta.physical_type}")
|
||||
# --------------------------------------------------------
|
||||
|
||||
# Map your custom configuration flags to the string names inside the database
|
||||
allowed_sources = []
|
||||
if github: allowed_sources.append("github")
|
||||
if gltf: allowed_sources.append("sketchfab")
|
||||
if thingiverse: allowed_sources.append("thingiverse")
|
||||
if smithsonian: allowed_sources.append("smithsonian")
|
||||
|
||||
# Complete the full data matrix load only for rows that match the filter parameters
|
||||
print("\n📥 Stream-loading row records matching target filter metrics...")
|
||||
|
||||
# Filter pushdown: PyArrow allows reading specific columns if needed, but here we ingest the file
|
||||
#dataset = pq.ParquetDataset(target_parquet, use_legacy_dataset=False)
|
||||
#df = dataset.read().to_pandas()
|
||||
|
||||
#return df
|
||||
|
||||
|
||||
|
||||
def get_annotations_df(github: bool = True, gltf: bool = False, thingiverse: bool = False, smithsonian: bool = False) -> pd.DataFrame:
|
||||
"""Centralized loader that profiles the dataframe to audit loaded domains and formats."""
|
||||
print(f"📦 Loading Objaverse Parquet Registries (cache: {CACHE_DIR})...")
|
||||
|
||||
# 1. Load the data matrix
|
||||
df = oxl.get_annotations(download_dir=CACHE_DIR)
|
||||
|
||||
# 2. Print an explicit structural audit of what's sitting in memory
|
||||
print("\n📊 --- LOCAL CACHE PERFORMANCE AUDIT ---")
|
||||
print(f"Total entries loaded into master index frame: {len(df):,}")
|
||||
|
||||
# --- NEW: PARQUET FILE SCHEMA DUMP ---
|
||||
print("\n🗂️ Complete Parquet Column Schema & Data Types:")
|
||||
for col, dtype in df.dtypes.items():
|
||||
print(f" • {col:<18} : {dtype}")
|
||||
# -------------------------------------
|
||||
|
||||
print("\nSource Domain Inventory Matrix:")
|
||||
for source_name, count in df["source"].value_counts().items():
|
||||
print(f" • {source_name:<15} : {count:,} records")
|
||||
|
||||
print("\nTop 5 Available File Extension Layouts in Index:")
|
||||
for ext_name, count in df["fileType"].value_counts().head(5).items():
|
||||
print(f" • {str(ext_name).upper():<15} : {count:,} records")
|
||||
print("-----------------------------------------\n")
|
||||
|
||||
# 3. Map your custom CLI flags to the string names inside the "source" column
|
||||
allowed_sources = []
|
||||
if github: allowed_sources.append("github")
|
||||
if gltf: allowed_sources.append("sketchfab")
|
||||
if thingiverse: allowed_sources.append("thingiverse")
|
||||
if smithsonian: allowed_sources.append("smithsonian")
|
||||
|
||||
if allowed_sources:
|
||||
print(f"🎛️ Filtering dataset rows for selected sources: {allowed_sources}")
|
||||
df = df[df["source"].isin(allowed_sources)]
|
||||
else:
|
||||
print("⚠️ No sources explicitly enabled via CLI. Defaulting to all sources.")
|
||||
|
||||
return df
|
||||
|
||||
|
||||
def list_assets(keyword: str, args):
|
||||
"""Parses and lists matching records along with direct source URLs and metadata."""
|
||||
annotations = get_annotations_df(
|
||||
github=args.github,
|
||||
gltf=args.gltf,
|
||||
thingiverse=args.thingiverse,
|
||||
smithsonian=args.smithsonian
|
||||
)
|
||||
print(f"🔍 Searching {len(annotations):,} records for '{keyword}'...")
|
||||
|
||||
keyword_mask = (
|
||||
annotations["fileIdentifier"].str.contains(keyword, case=False, na=False) |
|
||||
annotations["metadata"].astype(str).str.contains(keyword, case=False, na=False)
|
||||
)
|
||||
filtered_df = annotations[keyword_mask]
|
||||
|
||||
print(f"\n🔗 TARGET ASSETS WITH METADATA (Showing Top 20 of {len(filtered_df):,} Matches):")
|
||||
for idx, row in filtered_df.head(20).iterrows():
|
||||
source = row['source']
|
||||
identifier = row['fileIdentifier']
|
||||
|
||||
# Build the source URI
|
||||
if source == 'github':
|
||||
clean_id = identifier.replace("https://github.com/", "").lstrip('/')
|
||||
url = f"https://github.com/{clean_id}"
|
||||
elif source == 'sketchfab':
|
||||
url = f"https://sketchfab.com/3d-models/{identifier}"
|
||||
else:
|
||||
url = f"{source.title()} ID: {identifier}"
|
||||
|
||||
print(f"\n🏷️ [{source.upper()}] {url}")
|
||||
|
||||
# --- NEW: PARSE AND PRINT ANY ADDITIONAL KEYWORDS AND METADATA ---
|
||||
# Look for other common columns available in the Objaverse schema
|
||||
for optional_col in ['sha', 'repo', 'license', 'fileType',
|
||||
'source', 'fileIdentifier', 'sha', 'repo',
|
||||
'search_tags', 'clean_ext']:
|
||||
if optional_col in row and pd.notna(row[optional_col]):
|
||||
print(f" • {optional_col}: {row[optional_col]}")
|
||||
|
||||
for col_name in row.index:
|
||||
if col_name not in optional_col and pd.notna(row[col_name]):
|
||||
print(f" • {col_name}: {row[col_name]}")
|
||||
|
||||
|
||||
# Unpack the raw JSON metadata field to capture deep keywords/tags
|
||||
raw_metadata = row.get('metadata', None)
|
||||
if pd.notna(raw_metadata) and raw_metadata != "":
|
||||
try:
|
||||
# If it's a stringified JSON representation, parse it cleanly
|
||||
if isinstance(raw_metadata, str):
|
||||
meta_dict = json.loads(raw_metadata)
|
||||
else:
|
||||
meta_dict = raw_metadata
|
||||
|
||||
# Format and isolate nested dictionary fields beautifully
|
||||
meta_json = json.dumps(meta_dict, indent=6)
|
||||
print(f" • metadata:\n{meta_json}")
|
||||
except Exception:
|
||||
print(f" • metadata (raw text): {raw_metadata}")
|
||||
# -----------------------------------------------------------------
|
||||
print("-" * 60)
|
||||
|
||||
|
||||
|
||||
|
||||
def clean_and_tokenize(df: pd.DataFrame) -> pd.DataFrame:
|
||||
print("🛠️ Sanitizing file paths and building semantic keyword tokens...")
|
||||
|
||||
# 1. Isolate the actual file names or path segments
|
||||
# Splitting by slashes and picking up meaningful text tokens
|
||||
def extract_keywords(row):
|
||||
path_str = str(row['fileIdentifier'])
|
||||
|
||||
# Pull out everything that looks like a word from the path
|
||||
# This replaces underscores, dashes, and slashes with spaces
|
||||
tokens = re.findall(re.compile(r'[a-zA-Z]{3,}'), path_str)
|
||||
|
||||
# Filter out useless structural junk words from paths and links
|
||||
junk_words = {
|
||||
'https', 'github', 'com', 'blob', 'main', 'master', 'assets',
|
||||
'resources', 'models', 'mesh', 'meshes', 'thingiverse', 'thing',
|
||||
'files', 'fileid', 'raw', 'user', 'repo', 'production', 'download',
|
||||
'stl', 'glb', 'fbx', 'obj', 'ply'
|
||||
}
|
||||
|
||||
# Lowercase everything and deduplicate
|
||||
clean_tokens = [t.lower() for t in tokens if t.lower() not in junk_words]
|
||||
|
||||
# Return as a clean comma-separated string for easy SQL 'LIKE' matches
|
||||
return ",".join(set(clean_tokens))
|
||||
|
||||
# Apply the parser across your dataframe matrix
|
||||
df['search_tags'] = df.apply(extract_keywords, axis=1)
|
||||
|
||||
# 2. Extract clean file extension variants for quick layout engine filtering
|
||||
df['clean_ext'] = df['fileType'].astype(str).str.lower()
|
||||
|
||||
return df
|
||||
|
||||
# --- Usage in your build step ---
|
||||
# df = oxl.get_annotations(download_dir=CACHE_DIR)
|
||||
# df_cleaned = clean_and_tokenize(df)
|
||||
#
|
||||
# # Drop the bulky original columns you don't need in the browser to save space!
|
||||
# df_final = df_cleaned[['source', 'fileIdentifier', 'sha', 'repo', 'search_tags', 'clean_ext']]
|
||||
#
|
||||
# # Write out a clean, optimized Parquet file for your browser engine
|
||||
# table = pa.Table.from_pandas(df_final)
|
||||
# pq.write_table(table, "illustrious_index.parquet", row_group_size=50000, compression="ZSTD")
|
||||
|
||||
|
||||
|
||||
|
||||
def download_assets(keyword: str, sample_count: int, args, format_filter: str = "glb"):
|
||||
"""Isolates and executes the asset download pipeline."""
|
||||
annotations = get_annotations_df(
|
||||
github=args.github,
|
||||
gltf=args.gltf,
|
||||
thingiverse=args.thingiverse,
|
||||
smithsonian=args.smithsonian
|
||||
)
|
||||
|
||||
keyword_mask = (
|
||||
annotations["fileIdentifier"].str.contains(keyword, case=False, na=False) |
|
||||
annotations["metadata"].astype(str).str.contains(keyword, case=False, na=False)
|
||||
)
|
||||
filtered_df = annotations[keyword_mask]
|
||||
|
||||
if format_filter:
|
||||
filtered_df = filtered_df[filtered_df["fileType"] == format_filter.lower()]
|
||||
print(f"🎯 Found {len(filtered_df):,} matching {format_filter.upper()} assets.")
|
||||
else:
|
||||
print(f"🎯 Found {len(filtered_df):,} matching all assets.")
|
||||
|
||||
if len(filtered_df) == 0:
|
||||
return
|
||||
|
||||
download_queue = filtered_df.sample(min(sample_count, match_count)).copy().reset_index(drop=True)
|
||||
print(f"📥 Downloading {len(download_queue)} assets...")
|
||||
|
||||
# Force process=1 context synchronization for Windows process boundaries
|
||||
oxl.download_objects(
|
||||
objects=download_queue,
|
||||
download_dir=CACHE_DIR,
|
||||
handle_found_object=handle_found_object,
|
||||
save_repo_format="files",
|
||||
processes=1
|
||||
)
|
||||
|
||||
print("\n✨ --- DOWNLOAD SUMMARY ---")
|
||||
exported = [f for f in os.listdir(EXPORT_DIR) if f.endswith(('.glb', '.obj', '.gltf', '.fbx'))]
|
||||
if exported:
|
||||
print(f"✅ Exported {len(exported)} files to: {EXPORT_DIR}")
|
||||
for f in sorted(exported)[:10]:
|
||||
print(f" • {f}")
|
||||
else:
|
||||
print("⚠️ No files exported to downloads/ folder.")
|
||||
|
||||
|
||||
|
||||
def enumerate_and_curate(extensions: List[str]):
|
||||
"""
|
||||
Scans the entire database in memory to profile extensions and filter out specific assets,
|
||||
bypassing repository cloning for target extraction.
|
||||
"""
|
||||
annotations = get_annotations_df()
|
||||
print(f"🛠️ Enumerating global database for extensions: {extensions}")
|
||||
|
||||
# Normalize extensions to lowercase
|
||||
extensions = [ext.lower().lstrip('.') for ext in extensions]
|
||||
|
||||
# Direct vectorized filtering across the fileType Series
|
||||
curated_mask = annotations["fileType"].str.lower().isin(extensions)
|
||||
curated_df = annotations[curated_mask]
|
||||
|
||||
print(f"\n📊 --- GLOBAL CURATION SUMMARY ---")
|
||||
print(f"Total matching elements found in index: {len(curated_df):,}")
|
||||
print("\nBreakdown by Source Domain:")
|
||||
print(curated_df["source"].value_counts().to_string())
|
||||
print("\nBreakdown by Format Extension:")
|
||||
print(curated_df["fileType"].value_counts().to_string())
|
||||
|
||||
# Save index reference locally to prevent re-parsing 9.7M rows later
|
||||
manifest_path = os.path.join(CACHE_DIR, "curated_manifest.csv")
|
||||
curated_df[["fileIdentifier", "source", "fileType", "sha256"]].to_csv(manifest_path, index=False)
|
||||
print(f"\n💾 Saved filtered layout index to local disk: {manifest_path}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Objaverse-XL Structural Curation Toolkit")
|
||||
|
||||
# Mutually exclusive controls for operations targeting distinct task execution paths
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument("--query", type=str, help="Search the index and output direct component URLs")
|
||||
group.add_argument("--download", type=str, help="Search the index and execute the multi-process download sequence")
|
||||
group.add_argument("--enumerate-exts", type=str, help="Comma-separated format extensions to map globally (e.g., fbx,obj,glb)")
|
||||
|
||||
parser.add_argument("--limit", type=int, default=2, help="Maximum items to download from the match pool")
|
||||
parser.add_argument("--format", type=str, default=None, help="File layout extension restriction")
|
||||
group.add_argument("--inspect", type=lambda x: (str(x).lower() == 'true'), default=False, help="Just print the parquet schema")
|
||||
|
||||
parser.add_argument("--github", type=lambda x: (str(x).lower() == 'true'), default=True, help="Include GitHub source targets (True/False)")
|
||||
parser.add_argument("--gltf", type=lambda x: (str(x).lower() == 'true'), default=False, help="Include Sketchfab / GLTF source targets (True/False)")
|
||||
parser.add_argument("--thingiverse", type=lambda x: (str(x).lower() == 'true'), default=False, help="Include Thingiverse source targets (True/False)")
|
||||
parser.add_argument("--smithsonian", type=lambda x: (str(x).lower() == 'true'), default=False, help="Include Smithsonian source targets (True/False)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.inspect:
|
||||
inspect_schema()
|
||||
elif args.query:
|
||||
list_assets(keyword=args.query, args=args)
|
||||
elif args.download:
|
||||
download_assets(keyword=args.download, sample_count=args.limit, args=args, format_filter=args.format)
|
||||
elif args.enumerate_exts:
|
||||
ext_list = [e.strip() for e in args.enumerate_exts.split(",")]
|
||||
enumerate_and_curate(extensions=ext_list)
|
||||
13
requirements.txt
Normal file
13
requirements.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
# Dependencies for the standalone GLB renderers (altman/grok/model-vision.py).
|
||||
# The blender-*.py scripts instead run inside Blender's bundled Python.
|
||||
|
||||
trimesh>=4.0
|
||||
pyrender>=0.1.45
|
||||
# pyrender pins PyOpenGL==3.1.0, which crashes when uploading textures on recent
|
||||
# numpy. 3.1.7+ fixes it; install it explicitly after pyrender.
|
||||
PyOpenGL>=3.1.7
|
||||
# Required to decode KHR_draco_mesh_compression GLBs (handled by draco_glb.py).
|
||||
# Without it Draco-compressed models load as all-zero vertices -> a blank image.
|
||||
DracoPy>=1.4
|
||||
Pillow>=9.0
|
||||
numpy>=1.24
|
||||
3
tokenizer.json
Normal file
3
tokenizer.json
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e98bea228083ed69e0de7c82211c0286625f3e246971c4a7e17479cd6b53e2d6
|
||||
size 11422056
|
||||
34
tokenizer_config.json
Normal file
34
tokenizer_config.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"add_prefix_space": false,
|
||||
"backend": "tokenizers",
|
||||
"bos_token": null,
|
||||
"clean_up_tokenization_spaces": false,
|
||||
"eos_token": "<|im_end|>",
|
||||
"errors": "replace",
|
||||
"extra_special_tokens": [
|
||||
"<|im_start|>",
|
||||
"<|im_end|>",
|
||||
"<|object_ref_start|>",
|
||||
"<|object_ref_end|>",
|
||||
"<|box_start|>",
|
||||
"<|box_end|>",
|
||||
"<|quad_start|>",
|
||||
"<|quad_end|>",
|
||||
"<|vision_start|>",
|
||||
"<|vision_end|>",
|
||||
"<|vision_pad|>",
|
||||
"<|image_pad|>",
|
||||
"<|video_pad|>"
|
||||
],
|
||||
"is_local": false,
|
||||
"local_files_only": false,
|
||||
"max_length": null,
|
||||
"model_max_length": 131072,
|
||||
"pad_to_multiple_of": null,
|
||||
"pad_token": "<|im_end|>",
|
||||
"pad_token_type_id": 0,
|
||||
"padding_side": "left",
|
||||
"split_special_tokens": false,
|
||||
"tokenizer_class": "Qwen2Tokenizer",
|
||||
"unk_token": null
|
||||
}
|
||||
Reference in New Issue
Block a user