venkat112/venkat_glb_creation
0
1// Code Generator2// Generates Node.js (Three.js) or Blender Python code from scene graph3 4export class CodeGenerator {5 generateNodeJS(sceneGraph, sceneData) {6 let code = `// GLB Generation Code (Three.js + GLTFExporter)7// Generated automatically from scene description8// Run: npm install three @gltf-transform/core @gltf-transform/functions9 10import * as THREE from 'three';11import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';12import { Document, NodeIO } from '@gltf-transform/core';13import { dedup, resample, draco } from '@gltf-transform/functions';14import fs from 'fs';15 16const scene = new THREE.Scene();17const sceneData = ${JSON.stringify(sceneData, null, 2)};18 19// Environment setup20scene.background = new THREE.Color(${this.colorToThreeJS(sceneData.lighting?.color || [1, 1, 1])});21scene.fog = ${sceneData.effects?.fog ? `new THREE.FogExp2(${this.colorToThreeJS([0.8, 0.8, 0.9])}, 0.05)` : 'null'};22 23// Create ground24function createGround() {25 const groundGeometry = new THREE.PlaneGeometry(${sceneData.ground?.size || 20}, ${sceneData.ground?.size || 20});26 const groundMaterial = new THREE.MeshStandardMaterial({27 color: ${this.colorToThreeJS(sceneData.ground?.color || [0.5, 0.5, 0.5])},28 roughness: ${sceneData.ground?.roughness || 0.8},29 metalness: ${sceneData.ground?.metallic || 0.0}30 });31 const ground = new THREE.Mesh(groundGeometry, groundMaterial);32 ground.rotation.x = -Math.PI / 2;33 scene.add(ground);34 return ground;35}36 37// Create object helper38function createObject(objData) {39 let geometry, material, mesh;40 41 switch(objData.type) {42 case 'cube':43 geometry = new THREE.BoxGeometry(44 objData.size || 1,45 objData.size || 1,46 objData.size || 147 );48 break;49 case 'sphere':50 geometry = new THREE.SphereGeometry(51 objData.radius || 0.5,52 32,53 3254 );55 break;56 case 'cylinder':57 geometry = new THREE.CylinderGeometry(58 objData.radius || 0.5,59 objData.radius || 0.5,60 objData.size || 1,61 3262 );63 break;64 case 'cone':65 geometry = new THREE.ConeGeometry(66 objData.radius || 0.5,67 objData.size || 1,68 3269 );70 break;71 case 'plane':72 geometry = new THREE.PlaneGeometry(73 objData.size || 10,74 objData.size || 1075 );76 break;77 default:78 geometry = new THREE.BoxGeometry(1, 1, 1);79 }80 81 const color = objData.color || [0.8, 0.8, 0.8, 1];82 material = new THREE.MeshStandardMaterial({83 color: new THREE.Color(color[0], color[1], color[2]),84 roughness: objData.roughness || 0.5,85 metalness: objData.metallic || 0.0,86 transparent: color[3] < 1,87 opacity: color[3] || 188 });89 90 if (objData.emission) {91 material.emissive = new THREE.Color(92 objData.emission[0],93 objData.emission[1],94 objData.emission[2]95 );96 material.emissiveIntensity = objData.emissionStrength || 1.0;97 }98 99 mesh = new THREE.Mesh(geometry, material);100 mesh.position.set(101 objData.location[0] || 0,102 objData.location[1] || 0,103 objData.location[2] || 0104 );105 mesh.rotation.set(106 objData.rotation[0] || 0,107 objData.rotation[1] || 0,108 objData.rotation[2] || 0109 );110 mesh.scale.set(111 objData.scale[0] || 1,112 objData.scale[1] || 1,113 objData.scale[2] || 1114 );115 mesh.name = objData.name || 'Object';116 117 scene.add(mesh);118 return mesh;119}120 121// Create avatar122function createAvatar(avatarData) {123 const group = new THREE.Group();124 group.name = avatarData.name || 'Avatar';125 126 // Simple humanoid from primitives127 const torso = new THREE.Mesh(128 new THREE.CylinderGeometry(0.25, 0.25, 0.8, 32),129 new THREE.MeshStandardMaterial({ color: 0xffccaa })130 );131 torso.position.y = 1.0;132 group.add(torso);133 134 const head = new THREE.Mesh(135 new THREE.SphereGeometry(0.18, 32, 32),136 new THREE.MeshStandardMaterial({ color: 0xffccaa })137 );138 head.position.y = 1.9;139 group.add(head);140 141 // Arms142 const leftArm = new THREE.Mesh(143 new THREE.BoxGeometry(0.2, 0.4, 0.2),144 new THREE.MeshStandardMaterial({ color: 0xffccaa })145 );146 leftArm.position.set(-0.45, 1.3, 0);147 group.add(leftArm);148 149 const rightArm = new THREE.Mesh(150 new THREE.BoxGeometry(0.2, 0.4, 0.2),151 new THREE.MeshStandardMaterial({ color: 0xffccaa })152 );153 rightArm.position.set(0.45, 1.3, 0);154 group.add(rightArm);155 156 // Legs157 const leftLeg = new THREE.Mesh(158 new THREE.BoxGeometry(0.25, 0.75, 0.25),159 new THREE.MeshStandardMaterial({ color: 0x4444ff })160 );161 leftLeg.position.set(-0.18, 0.5, 0);162 group.add(leftLeg);163 164 const rightLeg = new THREE.Mesh(165 new THREE.BoxGeometry(0.25, 0.75, 0.25),166 new THREE.MeshStandardMaterial({ color: 0x4444ff })167 );168 rightLeg.position.set(0.18, 0.5, 0);169 group.add(rightLeg);170 171 group.position.set(172 avatarData.position[0] || 0,173 avatarData.position[1] || 0,174 avatarData.position[2] || 0175 );176 group.scale.set(177 avatarData.scale || 1,178 avatarData.scale || 1,179 avatarData.scale || 1180 );181 182 scene.add(group);183 return group;184}185 186// Create lights187function createLights(lightingData) {188 if (lightingData.lights) {189 lightingData.lights.forEach(light => {190 let lightObj;191 switch(light.type) {192 case 'SUN':193 case 'DIRECTIONAL':194 lightObj = new THREE.DirectionalLight(195 new THREE.Color(light.color || lightingData.color || [1, 1, 1]),196 light.energy || 1197 );198 lightObj.position.set(199 light.location[0] || 10,200 light.location[1] || -10,201 light.location[2] || 10202 );203 break;204 case 'POINT':205 lightObj = new THREE.PointLight(206 new THREE.Color(light.color || lightingData.color || [1, 1, 1]),207 light.energy || 50,208 100209 );210 lightObj.position.set(211 light.location[0] || 0,212 light.location[1] || 0,213 light.location[2] || 2214 );215 break;216 case 'SPOT':217 lightObj = new THREE.SpotLight(218 new THREE.Color(light.color || lightingData.color || [1, 1, 1]),219 light.energy || 50220 );221 lightObj.position.set(222 light.location[0] || 0,223 light.location[1] || 0,224 light.location[2] || 2225 );226 break;227 default:228 lightObj = new THREE.AmbientLight(229 new THREE.Color(lightingData.color || [1, 1, 1]),230 lightingData.ambient_strength || 0.3231 );232 }233 scene.add(lightObj);234 });235 }236 237 // Ambient light238 const ambientLight = new THREE.AmbientLight(239 new THREE.Color(lightingData.color || [1, 1, 1]),240 lightingData.ambient_strength || 0.3241 );242 scene.add(ambientLight);243}244 245// Create camera246function createCamera(cameraData) {247 const camera = new THREE.PerspectiveCamera(248 cameraData.fov || 50,249 16 / 9,250 0.1,251 1000252 );253 camera.position.set(254 cameraData.position[0] || 4,255 cameraData.position[1] || -4,256 cameraData.position[2] || 2.2257 );258 camera.rotation.set(259 cameraData.rotation[0] || 1.05,260 cameraData.rotation[1] || 0,261 cameraData.rotation[2] || 0.78262 );263 return camera;264}265 266// Build scene267console.log('Building scene...');268createGround();269sceneData.objects?.forEach(obj => createObject(obj));270if (sceneData.avatar?.present) {271 createAvatar(sceneData.avatar);272}273createLights(sceneData.lighting);274const camera = createCamera(sceneData.camera);275 276// Export to GLB277console.log('Exporting to GLB...');278const exporter = new GLTFExporter();279const options = {280 binary: true,281 includeCustomExtensions: true282};283 284exporter.parse(285 scene,286 (result) => {287 fs.writeFileSync('scene.glb', Buffer.from(result));288 console.log('GLB file saved as scene.glb');289 },290 (error) => {291 console.error('Export error:', error);292 }293);294`;295 296 return code;297 }298 299 generateBlenderPython(sceneGraph, sceneData) {300 let code = `# Blender Python Script for GLB Generation301# Generated automatically from scene description302# Run: blender --background --python this_script.py303 304import bpy305import json306import mathutils307 308def clear_scene():309 bpy.ops.wm.read_factory_settings(use_empty=True)310 311def make_pbr_material(name, base_color=(1,1,1,1), roughness=0.5, metallic=0.0, emission=None, emission_strength=1.0):312 mat = bpy.data.materials.new(name)313 mat.use_nodes = True314 nodes = mat.node_tree.nodes315 links = mat.node_tree.links316 nodes.clear()317 318 output = nodes.new(type="ShaderNodeOutputMaterial")319 principled = nodes.new(type="ShaderNodeBsdfPrincipled")320 principled.inputs['Base Color'].default_value = base_color321 principled.inputs['Roughness'].default_value = roughness322 principled.inputs['Metallic'].default_value = metallic323 324 if emission:325 principled.inputs['Emission'].default_value = (*emission[:3], 1.0)326 principled.inputs['Emission Strength'].default_value = emission_strength327 328 links.new(principled.outputs['BSDF'], output.inputs['Surface'])329 return mat330 331def create_object(obj_data):332 typ = obj_data.get('type', 'cube')333 location = obj_data.get('location', [0, 0, 0])334 rotation = obj_data.get('rotation', [0, 0, 0])335 scale = obj_data.get('scale', [1, 1, 1])336 name = obj_data.get('name', 'Object')337 338 if typ == 'cube':339 bpy.ops.mesh.primitive_cube_add(size=obj_data.get('size', 1), location=location)340 elif typ == 'sphere':341 bpy.ops.mesh.primitive_uv_sphere_add(radius=obj_data.get('radius', 0.5), location=location)342 elif typ == 'cylinder':343 bpy.ops.mesh.primitive_cylinder_add(vertices=32, radius=obj_data.get('radius', 0.5), 344 depth=obj_data.get('size', 1), location=location)345 elif typ == 'cone':346 bpy.ops.mesh.primitive_cone_add(vertices=32, radius1=obj_data.get('radius', 0.5),347 depth=obj_data.get('size', 1), location=location)348 elif typ == 'plane':349 bpy.ops.mesh.primitive_plane_add(size=obj_data.get('size', 10), location=location)350 else:351 bpy.ops.mesh.primitive_cube_add(size=1, location=location)352 353 obj = bpy.context.object354 obj.name = name355 obj.rotation_euler = rotation356 obj.scale = scale357 358 # Apply material359 color = obj_data.get('color', [0.8, 0.8, 0.8, 1])360 mat = make_pbr_material(361 f"mat_{name}",362 base_color=tuple(color),363 roughness=obj_data.get('roughness', 0.5),364 metallic=obj_data.get('metallic', 0.0),365 emission=obj_data.get('emission'),366 emission_strength=obj_data.get('emissionStrength', 1.0)367 )368 obj.data.materials.append(mat)369 370 return obj371 372def create_avatar(avatar_data):373 # Simple humanoid from primitives374 bpy.ops.mesh.primitive_cylinder_add(vertices=32, radius=0.25, depth=0.8, location=(0, 0, 1.0))375 torso = bpy.context.object376 torso.name = f"{avatar_data.get('name', 'Avatar')}_Torso"377 378 bpy.ops.mesh.primitive_uv_sphere_add(radius=0.18, location=(0, 0, 1.9))379 head = bpy.context.object380 head.name = f"{avatar_data.get('name', 'Avatar')}_Head"381 382 # Arms and legs (simplified)383 bpy.ops.mesh.primitive_cube_add(size=0.2, location=(-0.45, 0, 1.3))384 left_arm = bpy.context.object385 left_arm.scale[1] = 2.0386 left_arm.name = f"{avatar_data.get('name', 'Avatar')}_L_Arm"387 388 bpy.ops.mesh.primitive_cube_add(size=0.2, location=(0.45, 0, 1.3))389 right_arm = bpy.context.object390 right_arm.scale[1] = 2.0391 right_arm.name = f"{avatar_data.get('name', 'Avatar')}_R_Arm"392 393 bpy.ops.mesh.primitive_cube_add(size=0.25, location=(-0.18, 0, 0.5))394 left_leg = bpy.context.object395 left_leg.scale[2] = 1.5396 left_leg.name = f"{avatar_data.get('name', 'Avatar')}_L_Leg"397 398 bpy.ops.mesh.primitive_cube_add(size=0.25, location=(0.18, 0, 0.5))399 right_leg = bpy.context.object400 right_leg.scale[2] = 1.5401 right_leg.name = f"{avatar_data.get('name', 'Avatar')}_R_Leg"402 403 # Join all parts404 bpy.ops.object.select_all(action='DESELECT')405 for part in [torso, head, left_arm, right_arm, left_leg, right_leg]:406 part.select_set(True)407 bpy.context.view_layer.objects.active = torso408 bpy.ops.object.join()409 410 avatar = bpy.context.object411 avatar.name = avatar_data.get('name', 'Avatar')412 avatar.location = avatar_data.get('position', [0, 0, 0])413 avatar.scale = [avatar_data.get('scale', 1.0)] * 3414 415 mat = make_pbr_material("AvatarMat", base_color=(1, 0.8, 0.6, 1))416 avatar.data.materials.append(mat)417 418 return avatar419 420def create_lights(lighting_data):421 if lighting_data.get('lights'):422 for light in lighting_data['lights']:423 light_type = light.get('type', 'POINT')424 location = light.get('location', [0, 0, 2])425 energy = light.get('energy', 50)426 color = light.get('color', lighting_data.get('color', [1, 1, 1]))427 428 if light_type == 'SUN':429 bpy.ops.object.light_add(type='SUN', location=location)430 sun = bpy.context.object431 sun.data.energy = energy432 sun.data.color = color433 elif light_type == 'POINT':434 bpy.ops.object.light_add(type='POINT', location=location)435 point = bpy.context.object436 point.data.energy = energy437 point.data.color = color438 elif light_type == 'SPOT':439 bpy.ops.object.light_add(type='SPOT', location=location)440 spot = bpy.context.object441 spot.data.energy = energy442 spot.data.color = color443 444 # Ambient light445 bpy.context.scene.world.use_nodes = True446 world_nodes = bpy.context.scene.world.node_tree.nodes447 world_nodes['Background'].inputs['Strength'].default_value = lighting_data.get('ambient_strength', 0.3)448 world_nodes['Background'].inputs['Color'].default_value = (*lighting_data.get('color', [1, 1, 1]), 1)449 450def create_camera(camera_data):451 bpy.ops.object.camera_add(location=camera_data.get('position', [4, -4, 2.2]))452 cam = bpy.context.object453 cam.rotation_euler = camera_data.get('rotation', [1.05, 0, 0.78])454 bpy.context.scene.camera = cam455 cam.data.lens = 50456 cam.data.sensor_width = 36457 458# Scene data459scene_data = ${JSON.stringify(sceneData, null, 2)}460 461# Clear and build scene462clear_scene()463 464# Ground465if scene_data.get('ground'):466 ground = scene_data['ground']467 bpy.ops.mesh.primitive_plane_add(size=ground.get('size', 20), location=(0, 0, 0))468 ground_obj = bpy.context.object469 ground_obj.name = "Ground"470 mat = make_pbr_material(471 "GroundMat",472 base_color=tuple(ground.get('color', [0.5, 0.5, 0.5, 1])),473 roughness=ground.get('roughness', 0.8),474 metallic=ground.get('metallic', 0.0)475 )476 ground_obj.data.materials.append(mat)477 478# Objects479if scene_data.get('objects'):480 for obj_data in scene_data['objects']:481 create_object(obj_data)482 483# Avatar484if scene_data.get('avatar') and scene_data['avatar'].get('present'):485 create_avatar(scene_data['avatar'])486 487# Lighting488if scene_data.get('lighting'):489 create_lights(scene_data['lighting'])490 491# Camera492if scene_data.get('camera'):493 create_camera(scene_data['camera'])494 495# Scene settings496bpy.context.scene.render.engine = 'CYCLES'497bpy.context.scene.cycles.device = 'CPU'498 499# Export GLB500output_path = 'scene.glb'501export_kwargs = {502 "filepath": output_path,503 "export_format": "GLB",504 "export_apply": True,505 "export_texcoords": True,506 "export_normals": True,507 "export_materials": "EXPORT",508 "export_colors": True,509 "export_extras": True,510}511 512bpy.ops.export_scene.gltf(**export_kwargs)513print(f"Exported: {output_path}")514`;515 516 return code;517 }518 519 colorToThreeJS(color) {520 if (Array.isArray(color) && color.length >= 3) {521 return `0x${Math.floor(color[0] * 255).toString(16).padStart(2, '0')}${Math.floor(color[1] * 255).toString(16).padStart(2, '0')}${Math.floor(color[2] * 255).toString(16).padStart(2, '0')}`;522 }523 return '0xffffff';524 }525}526 527 