Updated Blender exporter to be able to export scenes.

Work-in-progress.

So close yet so far. Test scene almost works, just two things are not rotated properly (which means maybe everything will need to be reworked :(
This commit is contained in:
alteredq
2011-03-25 04:39:04 +01:00
parent 0496571235
commit 1859fe4057
8 changed files with 1695 additions and 53 deletions
+47
View File
@@ -0,0 +1,47 @@
/*
* File generated with Blender 2.56 Exporter
* https://github.com/mrdoob/three.js/tree/master/utils/exporters/blender/
*
* vertices: 8
* faces: 6
* normals: 0
* uvs: 0
* colors: 0
* materials: 1
*
*/
var model = {
'version' : 2,
'materials': [ {
"DbgColor" : 0xeeeeee,
"DbgIndex" : 0,
"DbgName" : "Material",
"colorAmbient" : [0.0, 0.0, 0.0],
"colorDiffuse" : [0.6400000190734865, 0.10179081114814892, 0.126246120426746],
"colorSpecular" : [0.5, 0.5, 0.5],
"shading" : "Phong",
"specularCoef" : 50,
"transparency" : 1.0,
"vertexColors" : false
}],
'vertices': [1.000000,-1.000000,-1.000000,1.000000,-1.000000,1.000000,-1.000000,-1.000000,1.000000,-1.000000,-1.000000,-1.000000,1.000000,1.000000,-1.000000,0.999999,1.000000,1.000001,-1.000000,1.000000,1.000000,-1.000000,1.000000,-1.000000],
'morphTargets': [],
'normals': [],
'colors': [],
'uvs': [[]],
'faces': [3,0,1,2,3,0,3,4,7,6,5,0,3,0,4,5,1,0,3,1,5,6,2,0,3,2,6,7,3,0,3,4,0,3,7,0],
'end': (new Date).getTime()
}
postMessage( model );
File diff suppressed because one or more lines are too long
+47
View File
@@ -0,0 +1,47 @@
/*
* File generated with Blender 2.56 Exporter
* https://github.com/mrdoob/three.js/tree/master/utils/exporters/blender/
*
* vertices: 4
* faces: 1
* normals: 0
* uvs: 0
* colors: 0
* materials: 1
*
*/
var model = {
'version' : 2,
'materials': [ {
"DbgColor" : 0xeeeeee,
"DbgIndex" : 0,
"DbgName" : "Material.001",
"colorAmbient" : [0.0, 0.0, 0.0],
"colorDiffuse" : [0.14462547517754842, 0.6400000190734865, 0.24541190036254967],
"colorSpecular" : [0.5, 0.5, 0.5],
"shading" : "Phong",
"specularCoef" : 50,
"transparency" : 1.0,
"vertexColors" : false
}],
'vertices': [1.000000,-0.000000,-1.000000,1.000000,0.000000,1.000000,-1.000000,0.000000,1.000000,-1.000000,-0.000000,-1.000000],
'morphTargets': [],
'normals': [],
'colors': [],
'uvs': [[]],
'faces': [3,0,3,2,1,0],
'end': (new Date).getTime()
}
postMessage( model );
Binary file not shown.
+359
View File
@@ -0,0 +1,359 @@
// Converted from: scene.blend
// File generated with Blender 2.56 Exporter
// https://github.com/alteredq/three.js/tree/master/utils/exporters/blender/
var scene = {
"type" : "scene",
"urlBaseType" : "relativeToScene",
"objects" :
{
"Cube.006" : {
"geometry" : "geo_Cube",
"materials" : [ "Material" ],
"position" : [ 10.623673, 3.370784, -0.321692 ],
"rotation" : [ 0.005265, -0.056306, 4.717181 ],
"quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
"scale" : [ 8.310000, 4.930000, 0.120000 ],
"visible" : true
},
"Monkey.018" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ 1.702659, 0.680278, 5.860421 ],
"rotation" : [ 1.413516, 0.081378, -3.204182 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 0.435837, 0.435837, 0.435837 ],
"visible" : true
},
"Monkey.017" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ 0.081295, 0.639505, 5.808783 ],
"rotation" : [ 1.413516, 0.081378, -3.204182 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 0.435837, 0.435837, 0.435837 ],
"visible" : true
},
"Monkey.016" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -1.569030, 0.619385, 5.747240 ],
"rotation" : [ 1.413516, 0.081378, -3.204182 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 0.435837, 0.435837, 0.435837 ],
"visible" : true
},
"Monkey.015" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -3.129120, 0.552267, 5.709269 ],
"rotation" : [ 1.413516, 0.081378, -3.204182 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 0.435837, 0.435837, 0.435837 ],
"visible" : true
},
"Monkey.014" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -6.386331, 0.382167, 3.004400 ],
"rotation" : [ 1.646237, -0.058425, -1.670593 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 0.435837, 0.435837, 0.435837 ],
"visible" : true
},
"Monkey.013" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -6.499331, 0.471640, 1.593073 ],
"rotation" : [ 1.646237, -0.058425, -1.670593 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 0.435837, 0.435837, 0.435837 ],
"visible" : true
},
"Monkey.012" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -6.629794, 0.533840, 0.234131 ],
"rotation" : [ 1.646237, -0.058425, -1.670593 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 0.435837, 0.435837, 0.435837 ],
"visible" : true
},
"Monkey.011" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -6.713673, 0.629835, -1.008146 ],
"rotation" : [ 1.646237, -0.058425, -1.670593 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 0.435837, 0.435837, 0.435837 ],
"visible" : true
},
"Monkey.010" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -2.010442, 1.387332, 24.343616 ],
"rotation" : [ 1.520470, 0.191726, -3.004622 ],
"quaternion": [ -0.587711, 0.550951, 0.566613, 0.173203 ],
"scale" : [ 9.160007, 9.160007, 9.160008 ],
"visible" : true
},
"Monkey.009" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -4.292194, 1.826282, -7.975398 ],
"rotation" : [ 1.594819, 0.080713, -0.213986 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Monkey.008" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ 2.151757, 1.891882, -8.065320 ],
"rotation" : [ 1.594819, 0.080713, -0.213986 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Monkey.007" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -0.712512, 2.115002, -8.097841 ],
"rotation" : [ 1.594819, 0.080713, -0.213986 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Cube.005" : {
"geometry" : "geo_Cube",
"materials" : [ "Material" ],
"position" : [ -1.000975, 1.319482, -8.755547 ],
"rotation" : [ 0.000000, 0.000000, -0.000000 ],
"quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
"scale" : [ 6.130000, 1.690000, 0.070000 ],
"visible" : true
},
"Cube.004" : {
"geometry" : "geo_Cube",
"materials" : [ "Material" ],
"position" : [ 2.484517, 2.724846, 7.486932 ],
"rotation" : [ 0.220417, -0.075224, 0.181029 ],
"quaternion": [ 0.988791, 0.112836, 0.027288, -0.093898 ],
"scale" : [ 0.350000, 3.310000, 0.890000 ],
"visible" : true
},
"Monkey.006" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ 7.724935, 1.694883, -7.123103 ],
"rotation" : [ 1.835590, 0.083161, -2.048913 ],
"quaternion": [ -0.587711, 0.550951, 0.566613, 0.173203 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Monkey.005" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -6.334642, 0.566791, -6.636147 ],
"rotation" : [ 1.327136, -0.032561, -4.135900 ],
"quaternion": [ -0.587711, 0.550951, 0.566613, 0.173203 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Monkey.004" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -5.384042, 0.444915, 6.194087 ],
"rotation" : [ 0.991213, 0.181430, -5.246078 ],
"quaternion": [ -0.587711, 0.550951, 0.566613, 0.173203 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Monkey.003" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ 3.147747, 1.014840, 4.230884 ],
"rotation" : [ 1.719311, -0.307044, -3.355401 ],
"quaternion": [ -0.587711, 0.550951, 0.566613, 0.173203 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Monkey.002" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -2.668043, 3.008879, 2.153389 ],
"rotation" : [ 1.881970, 0.457870, 4.066133 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Cube.003" : {
"geometry" : "geo_Cube",
"materials" : [ "Material" ],
"position" : [ -3.031251, 0.702044, 1.943665 ],
"rotation" : [ -1.300741, -1.330343, 3.282723 ],
"quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
"scale" : [ 1.781142, 0.231142, 0.361142 ],
"visible" : true
},
"Monkey.001" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ 1.245307, 0.620196, -0.137285 ],
"rotation" : [ 2.339869, -0.286025, -1.394760 ],
"quaternion": [ -0.587711, 0.550951, 0.566613, 0.173203 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Monkey" : {
"geometry" : "geo_Monkey",
"materials" : [ "Material.002" ],
"position" : [ -0.282500, 1.813606, -4.272932 ],
"rotation" : [ 0.646062, -0.219349, -0.010569 ],
"quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Cube.002" : {
"geometry" : "geo_Cube",
"materials" : [ "Material" ],
"position" : [ 0.042212, 5.536832, -0.199037 ],
"rotation" : [ 0.000000, 0.000000, -0.000000 ],
"quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Cube.001" : {
"geometry" : "geo_Cube",
"materials" : [ "Material" ],
"position" : [ -0.395497, 1.009696, -3.944532 ],
"rotation" : [ 0.000000, 0.000000, -0.000000 ],
"quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
},
"Plane" : {
"geometry" : "geo_Plane",
"materials" : [ "Material.001" ],
"position" : [ 0.000000, 0.000000, 0.118260 ],
"rotation" : [ 0.000000, 0.000000, -0.000000 ],
"quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
"scale" : [ 7.922787, 7.922787, 7.922787 ],
"visible" : true
},
"Cube" : {
"geometry" : "geo_Cube",
"materials" : [ "Material" ],
"position" : [ 3.651978, 1.071144, 0.000000 ],
"rotation" : [ 0.220417, -0.075224, 0.181029 ],
"quaternion": [ 0.988791, 0.112836, 0.027288, -0.093898 ],
"scale" : [ 1.000000, 1.000000, 1.000000 ],
"visible" : true
}
},
"geometries" :
{
"geo_Cube" : {
"type" : "ascii_mesh",
"url" : "scene.Cube.js"
},
"geo_Monkey" : {
"type" : "ascii_mesh",
"url" : "scene.Monkey.js"
},
"geo_Plane" : {
"type" : "ascii_mesh",
"url" : "scene.Plane.js"
}
},
"materials" :
{
"Material" : {
"type": "MeshPhongMaterial",
"parameters": { color: 0xa31920, opacity: 1.00, ambient: 0x000000, specular: 0x7f7f7f, shininess: 50.0 }
},
"Material.001" : {
"type": "MeshPhongMaterial",
"parameters": { color: 0x24a33e, opacity: 1.00, ambient: 0x000000, specular: 0x7f7f7f, shininess: 50.0 }
},
"Material.002" : {
"type": "MeshPhongMaterial",
"parameters": { color: 0xa37024, opacity: 1.00, ambient: 0x000000, specular: 0x7f7f7f, shininess: 50.0 }
}
},
"cameras" :
{
"default_camera" : {
"type" : "perspective",
"fov" : 60.000000,
"aspect": 1.333000,
"near" : 1.000000,
"far" : 10000.000000,
"position": [ 0.000000, 0.000000, 10.000000 ],
"target" : [ 0.000000, 0.000000, 0.000000 ]
}
},
"lights" :
{
"default_light": {
"type" : "directional",
"direction" : [ 0.000000, 1.000000, 1.000000 ],
"color" : 0xffffff,
"intensity" : 0.80
}
},
"defaults" :
{
"bgcolor" : [ 0.000000, 0.000000, 0.000000 ],
"bgalpha" : 1.000000,
"camera" : "default_camera"
}
}
postMessage( scene );
+561
View File
@@ -0,0 +1,561 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js webgl - io - scene loader [blender]</title>
<meta charset="utf-8">
<style type="text/css">
body {
background:#000;
color:#fff;
padding:0;
margin:0;
overflow:hidden;
font-family:georgia;
text-align:center;
}
#info {
position: absolute;
top: 0px; width: 100%;
padding: 5px;
font-family: Monospace;
font-size: 13px;
text-align: center;
z-index:100;
}
#progress {
color:red;
top:7em;
width: 100%;
font-size:3em;
font-variant:small-caps;
font-weight:bold;
position:absolute;
z-index:100;
text-align: center;
text-shadow: #000 0px 0px 10px;
display:none;
}
#start {
color:#fff;
text-shadow: #000 0px 0px 2px;
padding:0.1em 0.3em;
width:3em;
text-align: center;
display:none;
}
.shadow {
-moz-box-shadow: 0px 0px 5px #000;
-webkit-box-shadow: 0px 0px 5px #000;
box-shadow: 0px 0px 5px #000;
}
#progressbar {
text-align: center;
background: white;
width: 250px;
height: 10px;
}
#bar {
background:#d00;
width:50px;
height:10px;
}
.enabled {
color: lime!important;
cursor:pointer;
}
.enabled:hover {
text-shadow: #0f0 0px 0px 5px !important;
}
.disabled {
background:gray;
cursor:default;
}
a { color:red }
canvas { pointer-events:none; z-index:10; }
#log { position:absolute; top:0; display:block; text-align:left; z-index:1000; pointer-events:none; }
#scene_explorer {
background:transparent;
color:#fff;
width:200px;
position:absolute;
text-align:left;
top:0px;
z-index:200;
overflow:auto;
}
#section_exp {
background:rgba(0,0,50,0.5);
padding:0.5em 0;
display:none;
}
#scene_explorer h3 {
font-size:1em;
padding:0;
margin:0;
color:orange;
}
#scene_explorer a {
color:#555;
font-weight:bold;
text-decoration:none;
font-size:1.2em;
font-family:Monospace;
}
#scene_explorer a:hover {
background:#555;
color:rgba(0,0,50,1);
}
.part {
display:none;
padding:0 0 0.5em 2em;
}
</style>
</head>
<body>
<div id="info">
<a href="http://github.com/mrdoob/three.js">three.js</a> - scene loader test [blender]
</div>
<div id="scene_explorer">
<a id="plus_exp" href="#">[+]</a>
<div id="section_exp"></div>
</div>
<div id="progress">
<span id="message">Loading ...</span>
<center>
<div id="progressbar" class="shadow"><div id="bar" class="shadow"></div></div>
<div id="start" class="disabled">Start</div>
</center>
</div>
<pre id="log"></pre>
<!--
<script type="text/javascript" src="../build/Three.js"></script>
-->
<script type="text/javascript" src="../src/Three.js"></script>
<script type="text/javascript" src="../src/core/Color.js"></script>
<script type="text/javascript" src="../src/core/Vector2.js"></script>
<script type="text/javascript" src="../src/core/Vector3.js"></script>
<script type="text/javascript" src="../src/core/Vector4.js"></script>
<script type="text/javascript" src="../src/core/Ray.js"></script>
<script type="text/javascript" src="../src/core/Rectangle.js"></script>
<script type="text/javascript" src="../src/core/Matrix3.js"></script>
<script type="text/javascript" src="../src/core/Matrix4.js"></script>
<script type="text/javascript" src="../src/core/Object3D.js"></script>
<script type="text/javascript" src="../src/core/Quaternion.js"></script>
<script type="text/javascript" src="../src/core/Vertex.js"></script>
<script type="text/javascript" src="../src/core/Face3.js"></script>
<script type="text/javascript" src="../src/core/Face4.js"></script>
<script type="text/javascript" src="../src/core/UV.js"></script>
<script type="text/javascript" src="../src/core/Geometry.js"></script>
<script type="text/javascript" src="../src/core/Spline.js"></script>
<script type="text/javascript" src="../src/animation/AnimationHandler.js"></script>
<script type="text/javascript" src="../src/animation/Animation.js"></script>
<script type="text/javascript" src="../src/cameras/Camera.js"></script>
<script type="text/javascript" src="../src/lights/Light.js"></script>
<script type="text/javascript" src="../src/lights/AmbientLight.js"></script>
<script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
<script type="text/javascript" src="../src/lights/PointLight.js"></script>
<script type="text/javascript" src="../src/materials/Material.js"></script>
<script type="text/javascript" src="../src/materials/Mappings.js"></script>
<script type="text/javascript" src="../src/materials/LineBasicMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshBasicMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshLambertMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshPhongMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshDepthMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshNormalMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshShaderMaterial.js"></script>
<script type="text/javascript" src="../src/materials/ParticleBasicMaterial.js"></script>
<script type="text/javascript" src="../src/materials/ParticleCanvasMaterial.js"></script>
<script type="text/javascript" src="../src/materials/ParticleDOMMaterial.js"></script>
<script type="text/javascript" src="../src/materials/Texture.js"></script>
<script type="text/javascript" src="../src/materials/RenderTarget.js"></script>
<script type="text/javascript" src="../src/materials/Uniforms.js"></script>
<script type="text/javascript" src="../src/objects/Particle.js"></script>
<script type="text/javascript" src="../src/objects/ParticleSystem.js"></script>
<script type="text/javascript" src="../src/objects/Line.js"></script>
<script type="text/javascript" src="../src/objects/Mesh.js"></script>
<script type="text/javascript" src="../src/objects/Bone.js"></script>
<script type="text/javascript" src="../src/objects/SkinnedMesh.js"></script>
<script type="text/javascript" src="../src/objects/Ribbon.js"></script>
<script type="text/javascript" src="../src/objects/Sound.js"></script>
<script type="text/javascript" src="../src/objects/LOD.js"></script>
<script type="text/javascript" src="../src/scenes/Scene.js"></script>
<script type="text/javascript" src="../src/scenes/Fog.js"></script>
<script type="text/javascript" src="../src/scenes/FogExp2.js"></script>
<script type="text/javascript" src="../src/renderers/Projector.js"></script>
<script type="text/javascript" src="../src/renderers/DOMRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/WebGLShaders.js"></script>
<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/SoundRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableVertex.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableFace3.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableFace4.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableObject.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
<script type="text/javascript" src="../src/extras/GeometryUtils.js"></script>
<script type="text/javascript" src="../src/extras/ImageUtils.js"></script>
<script type="text/javascript" src="../src/extras/SceneUtils.js"></script>
<script type="text/javascript" src="../src/extras/ShaderUtils.js"></script>
<script type="text/javascript" src="../src/extras/cameras/QuakeCamera.js"></script>
<script type="text/javascript" src="../src/extras/cameras/PathCamera.js"></script>
<script type="text/javascript" src="../src/extras/geometries/Cube.js"></script>
<script type="text/javascript" src="../src/extras/geometries/Cylinder.js"></script>
<script type="text/javascript" src="../src/extras/geometries/Icosahedron.js"></script>
<script type="text/javascript" src="../src/extras/geometries/Lathe.js"></script>
<script type="text/javascript" src="../src/extras/geometries/Plane.js"></script>
<script type="text/javascript" src="../src/extras/geometries/Sphere.js"></script>
<script type="text/javascript" src="../src/extras/geometries/Torus.js"></script>
<script type="text/javascript" src="../src/extras/geometries/TorusKnot.js"></script>
<script type="text/javascript" src="../src/extras/io/Loader.js"></script>
<script type="text/javascript" src="../src/extras/io/JSONLoader.js"></script>
<script type="text/javascript" src="../src/extras/io/BinaryLoader.js"></script>
<script type="text/javascript" src="../src/extras/objects/MarchingCubes.js"></script>
<script type="text/javascript" src="js/Detector.js"></script>
<script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
<script type="text/javascript" src="js/Stats.js"></script>
<script type="text/javascript">
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var container,stats;
var camera, scene, loaded;
var renderer;
var mesh, zmesh, geometry;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
init();
animate();
function $( id ) {
return document.getElementById( id );
}
function handle_update( result, pieces ) {
refreshSceneView( result );
renderer.initWebGLObjects( result.scene );
var m, material, count = 0;
for ( m in result.materials ) {
material = result.materials[ m ];
if ( ! ( material instanceof THREE.MeshFaceMaterial ) ) {
if( !material.program ) {
console.log(m);
renderer.initMaterial( material, result.scene.lights, result.scene.fog );
count += 1;
if( count > pieces ) {
//console.log("xxxxxxxxx");
break;
}
}
}
}
}
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var loadScene = createLoadScene();
scene = loadScene.scene;
camera = loadScene.camera;
renderer = new THREE.WebGLRenderer();
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.domElement.style.position = "relative";
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.right = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
$( "start" ).addEventListener( 'click', onStartClick, false );
var callback_progress = function( progress, result ) {
var bar = 250,
total = progress.total_models + progress.total_textures,
loaded = progress.loaded_models + progress.loaded_textures;
if ( total )
bar = Math.floor( bar * loaded / total );
$( "bar" ).style.width = bar + "px";
count = 0;
for ( var m in result.materials ) count++;
handle_update( result, Math.floor( count/total ) );
}
var callback_sync = function( result ) {
/*
// uncomment to see progressive scene loading
scene = result.scene;
camera = result.currentCamera;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setClearColor( result.bgColor, result.bgAlpha );
*/
//handle_update( result, 1 );
}
var callback_async = function( result ) {
loaded = result;
$( "message" ).style.display = "none";
$( "progressbar" ).style.display = "none";
$( "start" ).style.display = "block";
$( "start" ).className = "enabled";
handle_update( result, 1 );
}
$( "progress" ).style.display = "block";
SceneUtils.loadScene( "obj/blenderscene/scene.js", callback_sync, callback_async, callback_progress );
$( "plus_exp" ).addEventListener( 'click', createToggle( "exp" ), false );
}
function setButtonActive( id ) {
$( "start" ).style.backgroundColor = "green";
}
function onStartClick() {
$( "progress" ).style.display = "none";
scene = loaded.scene;
camera = loaded.currentCamera;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setClearColor( loaded.bgColor, loaded.bgAlpha );
}
function onDocumentMouseMove(event) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}
function createLoadScene() {
var result = {
scene: new THREE.Scene(),
camera: new THREE.Camera( 65, window.innerWidth / window.innerHeight, 1, 1000 )
};
result.camera.position.z = 100;
var object, geometry, material, light, count = 500, range = 200;
material = new THREE.MeshLambertMaterial( { color:0xffffff } );
geometry = new Cube( 5, 5, 5 );
for( var i = 0; i < count; i++ ) {
object = new THREE.Mesh( geometry, material );
object.position.x = ( Math.random() - 0.5 ) * range;
object.position.y = ( Math.random() - 0.5 ) * range;
object.position.z = ( Math.random() - 0.5 ) * range;
object.rotation.x = Math.random() * 6;
object.rotation.y = Math.random() * 6;
object.rotation.z = Math.random() * 6;
object.matrixAutoUpdate = false;
object.updateMatrix();
result.scene.addObject( object );
}
result.scene.matrixAutoUpdate = false;
light = new THREE.PointLight( 0xffffff );
result.scene.addLight( light );
light = new THREE.DirectionalLight( 0x111111 );
light.position.x = 1;
result.scene.addLight( light );
return result;
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * .001;
camera.position.y += ( - mouseY - camera.position.y ) * .001;
renderer.render( scene, camera );
}
function log( text ) {
var e = $("log");
e.innerHTML = text + "<br/>" + e.innerHTML;
}
// Scene explorer user interface
function toggle( id ) {
var scn = $( "section_" + id ).style,
btn = $( "plus_" + id );
if ( scn.display == "block" ) {
scn.display = "none";
btn.innerHTML = "[+]";
}
else {
scn.display = "block";
btn.innerHTML = "[-]";
}
}
function createToggle( label ) { return function() { toggle( label ) } };
function refreshSceneView( result ) {
$( "section_exp" ).innerHTML = generateSceneView( result );
var config = [ "obj", "geo", "mat", "tex", "lit", "cam" ];
for ( var i = 0; i < config.length; i++ )
$( "plus_" + config[i] ).addEventListener( 'click', createToggle( config[i] ), false );
}
function generateSection( label, id, objects ) {
var html = "";
html += "<h3><a id='plus_" + id + "' href='#'>[+]</a> " + label + "</h3>";
html += "<div id='section_" + id + "' class='part'>";
for( var o in objects ) {
html += o + "<br/>";
}
html += "</div>";
return html;
}
function generateSceneView( result ) {
var config = [
[ "Objects", "obj", result.objects ],
[ "Geometries", "geo", result.geometries ],
[ "Materials", "mat", result.materials ],
[ "Textures", "tex", result.textures ],
[ "Lights", "lit", result.lights ],
[ "Cameras", "cam", result.cameras ]
];
var html = "";
for ( var i = 0; i < config.length; i++ )
html += generateSection( config[i][0], config[i][1], config[i][2] );
return html;
}
</script>
</body>
</html>
@@ -35,13 +35,14 @@ class ExportTHREEJS(bpy.types.Operator, ExportHelper):
filename_ext = ".js"
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply modifiers to the exported mesh", default=True)
option_flip_yz = BoolProperty(name="Flip YZ", description="Flip YZ", default=True)
use_normals = BoolProperty(name="Normals", description="Export normals", default=True)
use_colors = BoolProperty(name="Colors", description="Export vertex colors", default=True)
use_uv_coords = BoolProperty(name="UVs", description="Export texture coordinates", default=True)
option_export_scene = BoolProperty(name="Scene", description="Export scene", default=True)
align_types = [("None","None","None"), ("Center","Center","Center"), ("Bottom","Bottom","Bottom"), ("Top","Top","Top")]
align_model = EnumProperty(name="Align model", description="Align model", items=align_types, default="Center")
align_model = EnumProperty(name="Align model", description="Align model", items=align_types, default="None")
@classmethod
def poll(cls, context):
@@ -61,15 +62,24 @@ class ExportTHREEJS(bpy.types.Operator, ExportHelper):
layout = self.layout
row = layout.row()
row.prop(self.properties, "use_modifiers")
row.prop(self.properties, "option_export_scene")
layout.separator()
row = layout.row()
row.prop(self.properties, "option_flip_yz")
layout.separator()
row = layout.row()
row.prop(self.properties, "align_model")
layout.separator()
row = layout.row()
row.prop(self.properties, "use_normals")
row = layout.row()
row.prop(self.properties, "use_colors")
row = layout.row()
row.prop(self.properties, "use_uv_coords")
row = layout.row()
row.prop(self.properties, "align_model")
def menu_func(self, context):
@@ -23,9 +23,8 @@
Blender exporter for Three.js (ASCII JSON format).
TODO
- model alignment
- export scene
- copy used images to folder where exported file goes
- export all selected meshes
- binary format
"""
@@ -42,13 +41,149 @@ import random
# Configuration
# #####################################################
# default colors for debugging (each material gets one distinct color):
DEFAULTS = {
"bgcolor" : [0, 0, 0],
"bgalpha" : 1.0,
"camera" :
{
"name" : "default_camera",
"type" : "perspective",
"near" : 1,
"far" : 10000,
"fov" : 60,
"aspect": 1.333,
"position" : [0, 0, 10],
"target" : [0, 0, 0]
},
"light" :
{
"name" : "default_light",
"type" : "directional",
"direction" : [0,1,1],
"color" : [1,1,1],
"intensity" : 0.8
}
}
# default colors for debugging (each material gets one distinct color):
# white, red, green, blue, yellow, cyan, magenta
COLORS = [0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, 0xeeee00, 0x00eeee, 0xee00ee]
# #####################################################
# Templates
# Templates - scene
# #####################################################
TEMPLATE_SCENE_ASCII = """\
// Converted from: %(fname)s
// File generated with Blender 2.56 Exporter
// https://github.com/alteredq/three.js/tree/master/utils/exporters/blender/
var scene = {
"type" : "scene",
"urlBaseType" : "relativeToScene",
%(sections)s
"defaults" :
{
"bgcolor" : %(bgcolor)s,
"bgalpha" : %(bgalpha)f,
"camera" : %(defcamera)s
}
}
postMessage( scene );
"""
TEMPLATE_SECTION = """
"%s" :
{
%s
},
"""
TEMPLATE_OBJECT = """\
%(object_id)s : {
"geometry" : %(geometry_id)s,
"materials" : [ %(material_id)s ],
"position" : %(position)s,
"rotation" : %(rotation)s,
"quaternion": %(quaternion)s,
"scale" : %(scale)s,
"visible" : true
}"""
TEMPLATE_GEOMETRY = """\
%(geometry_id)s : {
"type" : "ascii_mesh",
"url" : %(model_file)s
}"""
TEMPLATE_TEXTURE = """\
%(texture_id)s : {
"url": %(texture_file)s
}"""
TEMPLATE_MATERIAL_SCENE = """\
%(material_id)s : {
"type": %(type)s,
"parameters": { %(parameters)s }
}"""
TEMPLATE_CAMERA_PERSPECTIVE = """\
%(camera_id)s : {
"type" : "perspective",
"fov" : %(fov)f,
"aspect": %(aspect)f,
"near" : %(near)f,
"far" : %(far)f,
"position": %(position)s,
"target" : %(target)s
}"""
TEMPLATE_CAMERA_ORTHO = """\
%(camera_id)s: {
"type" : "ortho",
"left" : %(left)f,
"right" : %(right)f,
"top" : %(top)f,
"bottom": %(bottom)f,
"near" : %(near)f,
"far" : %(far)f,
"position": %(position)s,
"target" : %(target)s
}"""
TEMPLATE_LIGHT_DIRECTIONAL = """\
%(light_id)s: {
"type" : "directional",
"direction" : %(direction)s,
"color" : %(color)s,
"intensity" : %(intensity).2f
}"""
TEMPLATE_LIGHT_POINT = """\
%(light_id)s: {
"type" : "point",
"position" : %(position)s,
"color" : %(color)s
"intensity" : %(intensity).3f
}"""
TEMPLATE_VEC4 = '[ %f, %f, %f, %f ]'
TEMPLATE_VEC3 = '[ %f, %f, %f ]'
TEMPLATE_VEC2 = '[ %f, %f ]'
TEMPLATE_STRING = '"%s"'
TEMPLATE_HEX = "0x%06x"
# #####################################################
# Templates - model
# #####################################################
TEMPLATE_FILE_ASCII = """\
/*
@@ -98,8 +233,11 @@ TEMPLATE_C = "0x%06x"
# #####################################################
# Utils
# #####################################################
def veckey3(x,y,z):
return round(x, 6), round(y, 6), round(z, 6)
def veckey3d(v):
return round(v.x, 6), round(v.y, 6), round(v.z, 6)
return veckey3(v.x, v.y, v.z)
def veckey2d(v):
return round(v[0], 6), round(v[1], 6)
@@ -107,8 +245,13 @@ def veckey2d(v):
def get_normal_indices(v, normals, mesh):
n = []
mv = mesh.vertices
for i in v:
n.append( normals[veckey3d(mv[i].normal)] )
normal = mv[i].normal
key = veckey3d(normal)
n.append( normals[key] )
return n
def get_uv_indices(face_index, uvs, mesh):
@@ -127,6 +270,24 @@ def get_color_indices(face_index, colors, mesh):
c.append( colors[hexcolor(i)] )
return c
def rgb2int(rgb):
color = (int(rgb[0]*255) << 16) + (int(rgb[1]*255) << 8) + int(rgb[2]*255);
return color
# #####################################################
# Utils - files
# #####################################################
def write_file(fname, content):
out = open(fname, "w")
out.write(content)
out.close()
def ensure_folder_exist(foldername):
"""Create folder (with whole path) if it doesn't exist yet."""
if not os.access(foldername, os.R_OK|os.W_OK|os.X_OK):
os.makedirs(foldername)
# #####################################################
# Alignment
# #####################################################
@@ -231,7 +392,7 @@ def setBit(value, position, on):
mask = ~(1 << position)
return (value & mask)
def generate_face(f, faceIndex, normals, uvs, colors, mesh, use_normals, use_colors, use_uv_coords):
def generate_face(f, faceIndex, normals, uvs, colors, mesh, use_normals, use_colors, use_uv_coords, flipyz):
isTriangle = ( len(f.vertices) == 3 )
if isTriangle:
@@ -315,7 +476,10 @@ def extract_vertex_normals(mesh, use_normals):
for f in mesh.faces:
for v in f.vertices:
key = veckey3d(mesh.vertices[v].normal)
normal = mesh.vertices[v].normal
key = veckey3d(normal)
if key not in normals:
normals[key] = count
count += 1
@@ -327,7 +491,7 @@ def generate_normals(normals, use_normals):
return ""
chunks = []
for key, index in sorted(normals.items(), key=operator.itemgetter(1)):
for key, index in sorted(normals.items(), key = operator.itemgetter(1)):
chunks.append(key)
return ",".join(generate_normal(n) for n in chunks)
@@ -441,7 +605,7 @@ def value2string(v):
return str(v).lower()
return str(v)
def generate_materials(mtl, materials, use_colors):
def generate_materials(mtl, materials, use_colors, draw_type):
"""Generate JS array of materials objects
"""
@@ -458,6 +622,10 @@ def generate_materials(mtl, materials, use_colors):
mtl[m]['DbgColor'] = generate_color(index)
mtl[m]['vertexColors'] = use_colors
if draw_type in [ "BOUNDS", "WIRE" ]:
mtl[m]['wireframe'] = True
mtl[m]['DbgColor'] = 0xff0000
mtl_raw = ",\n".join(['\t"%s" : %s' % (n, value2string(v)) for n,v in sorted(mtl[m].items())])
mtl_string = "\t{\n%s\n\t}" % mtl_raw
mtl_array.append([index, mtl_string])
@@ -505,7 +673,7 @@ def extract_materials(mesh, scene):
return materials
def generate_materials_string(mesh, scene, use_colors):
def generate_materials_string(mesh, scene, use_colors, draw_type):
random.seed(42) # to get well defined color order for debug materials
@@ -522,19 +690,21 @@ def generate_materials_string(mesh, scene, use_colors):
materials = { 'default':0 }
# default dummy materials
mtl = generate_mtl(materials)
# extract real materials from the mesh
mtl.update(extract_materials(mesh, scene))
return generate_materials(mtl, materials, use_colors)
return generate_materials(mtl, materials, use_colors, draw_type)
# #####################################################
# ASCII exporter
# #####################################################
def generate_ascii_model(mesh, scene, use_normals, use_colors, use_uv_coords, align_model):
def generate_ascii_model(mesh, scene, use_normals, use_colors, use_uv_coords, align_model, flipyz, draw_type):
vertices = mesh.vertices[:]
vertices = mesh.vertices[:]
if align_model == 1:
center(vertices)
@@ -547,7 +717,7 @@ def generate_ascii_model(mesh, scene, use_normals, use_colors, use_uv_coords, al
colors, ncolor = extract_vertex_colors(mesh, use_colors)
uvs, nuv = extract_uvs(mesh, use_uv_coords)
mstring, nmaterial = generate_materials_string(mesh, scene, use_colors)
mstring, nmaterial = generate_materials_string(mesh, scene, use_colors, draw_type)
text = TEMPLATE_FILE_ASCII % {
"nvertex" : len(mesh.vertices),
@@ -565,46 +735,49 @@ def generate_ascii_model(mesh, scene, use_normals, use_colors, use_uv_coords, al
"vertices" : ",".join(generate_vertex(v) for v in vertices),
"faces" : ",".join(generate_face(f, i, normals, uvs, colors, mesh, use_normals, use_colors, use_uv_coords) for i, f in enumerate(mesh.faces))
"faces" : ",".join(generate_face(f, i, normals, uvs, colors, mesh, use_normals, use_colors, use_uv_coords, flipyz) for i, f in enumerate(mesh.faces))
}
return text
# #####################################################
# Main
# Utils
# #####################################################
def save(operator, context, filepath="", use_modifiers=True, use_normals=True, use_colors=True, use_uv_coords=True, align_model=1):
def ensure_extension(filepath, extension):
if not filepath.lower().endswith(extension):
filepath += extension
return filepath
def generate_mesh_filename(meshname, filepath):
normpath = os.path.normpath(filepath)
path, ext = os.path.splitext(normpath)
return "%s.%s%s" % (path, meshname, ext)
# #####################################################
# Export single mesh
# #####################################################
def export_mesh(obj, scene, filepath, use_normals, use_colors, use_uv_coords, align_model, flipyz, export_single_model):
"""Export single mesh"""
def rvec3d(v):
return round(v[0], 6), round(v[1], 6), round(v[2], 6)
def rvec2d(v):
return round(v[0], 6), round(v[1], 6)
scene = context.scene
obj = context.object
if not filepath.lower().endswith('.js'):
filepath += '.js'
if not obj:
raise Exception("Error, Select 1 active object")
if scene.objects.active:
bpy.ops.object.mode_set(mode='OBJECT')
if use_modifiers:
mesh = obj.create_mesh(scene, True, 'PREVIEW')
else:
mesh = obj.data
# collapse modifiers into mesh
mesh = obj.create_mesh(scene, True, 'RENDER')
if not mesh:
raise Exception("Error, could not get mesh data from active object")
raise Exception("Error, could not get mesh data from object [%s]" % obj.name)
# that's what Blender's native export_obj.py does
x_rot = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
mesh.transform(x_rot * obj.matrix_world)
# to flip YZ
X_ROT = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
if export_single_model:
mesh.transform(X_ROT * obj.matrix_world)
else:
mesh.transform(X_ROT)
mesh.calc_normals()
faceUV = (len(mesh.uv_textures) > 0)
@@ -627,14 +800,412 @@ def save(operator, context, filepath="", use_modifiers=True, use_normals=True, u
if not active_col_layer:
use_colors = False
text = generate_ascii_model(mesh, scene, use_normals, use_colors, use_uv_coords, align_model)
file = open(filepath, 'w')
file.write(text)
file.close()
text = generate_ascii_model(mesh, scene, use_normals, use_colors, use_uv_coords, align_model, flipyz, obj.draw_type)
write_file(filepath, text)
# remove temp mesh
bpy.data.meshes.remove(mesh)
print("writing", filepath, "done")
# #####################################################
# Export scene
# #####################################################
def generate_vec4(vec):
return TEMPLATE_VEC4 % (vec[0], vec[1], vec[2], vec[3])
if use_modifiers:
bpy.data.meshes.remove(mesh)
def generate_vec3(vec):
return TEMPLATE_VEC3 % (vec[0], vec[1], vec[2])
def generate_vec2(vec):
return TEMPLATE_VEC2 % (vec[0], vec[1])
def generate_hex(number):
return TEMPLATE_HEX % number
def generate_string(s):
return TEMPLATE_STRING % s
def generate_section(label, content):
return TEMPLATE_SECTION % (label, content)
def get_mesh_filename(mesh):
object_id = mesh["data"]["name"]
filename = "%s.js" % sanitize(object_id)
return filename
def generate_material_id_list(materials):
chunks = []
for material in materials:
chunks.append(material.name)
return ",".join(chunks)
def generate_objects(data):
chunks = []
for obj in data["objects"]:
if obj.type == "MESH":
object_id = obj.name
if len(obj.modifiers) > 0:
geo_name = obj.name
else:
geo_name = obj.data.name
geometry_id = "geo_%s" % geo_name
material_id = generate_material_id_list(obj.material_slots)
#position = obj.location
#rotation = obj.rotation_euler
scale = obj.scale
quaternion = obj.rotation_quaternion
position = [obj.location.x, obj.location.z, -obj.location.y]
rotation = [obj.rotation_euler.x, -obj.rotation_euler.y, -obj.rotation_euler.z]
#quaternion = obj.rotation_euler.to_quat()
scale = [obj.scale.x, obj.scale.z, obj.scale.y]
material_string = ""
if material_id:
material_string = generate_string(material_id)
object_string = TEMPLATE_OBJECT % {
"object_id" : generate_string(object_id),
"geometry_id" : generate_string(geometry_id),
"material_id" : material_string,
"position" : generate_vec3(position),
"rotation" : generate_vec3(rotation),
"quaternion" : generate_vec4(quaternion),
"scale" : generate_vec3(scale)
}
chunks.append(object_string)
return ",\n\n".join(chunks)
def generate_geometries(data):
chunks = []
geo_set = set()
for obj in data["objects"]:
if obj.type == "MESH":
if len(obj.modifiers) > 0:
name = obj.name
else:
name = obj.data.name
if name not in geo_set:
geometry_id = "geo_%s" % name
model_filename = os.path.basename(generate_mesh_filename(name, data["filepath"]))
geometry_string = TEMPLATE_GEOMETRY % {
"geometry_id" : generate_string(geometry_id),
"model_file" : generate_string(model_filename)
}
chunks.append(geometry_string)
geo_set.add(name)
return ",\n\n".join(chunks)
def generate_textures_scene(data):
chunks = []
# TODO: extract just textures actually used by some objects in the scene
for img in bpy.data.images:
texture_id = img.name
texture_file = extract_texture_filename(img)
texture_string = TEMPLATE_TEXTURE % {
"texture_id" : generate_string(texture_id),
"texture_file" : generate_string(texture_file)
}
chunks.append(texture_string)
return ",\n\n".join(chunks)
def extract_texture_filename(image):
fn = bpy.path.abspath(image.filepath)
fn = os.path.normpath(fn)
fn_strip = os.path.basename(fn)
return fn_strip
def extract_material_data(m):
world = bpy.context.scene.world
material = { 'name': m.name }
material['colorDiffuse'] = [m.diffuse_intensity * m.diffuse_color[0],
m.diffuse_intensity * m.diffuse_color[1],
m.diffuse_intensity * m.diffuse_color[2]]
material['colorSpecular'] = [m.specular_intensity * m.specular_color[0],
m.specular_intensity * m.specular_color[1],
m.specular_intensity * m.specular_color[2]]
material['colorAmbient'] = [m.ambient * world.ambient_color[0],
m.ambient * world.ambient_color[1],
m.ambient * world.ambient_color[2]]
material['transparency'] = m.alpha
# not sure about mapping values to Blinn-Phong shader
# Blender uses INT from [1,511] with default 0
# http://www.blender.org/documentation/blender_python_api_2_54_0/bpy.types.Material.html#bpy.types.Material.specular_hardness
material["specularCoef"] = m.specular_hardness
material['mapDiffuse'] = ""
material['mapLight'] = ""
material['mapNormal'] = ""
# just take first textures of each, for the moment three.js materials can't handle more
for i in range(len(m.texture_slots)):
ts = m.texture_slots[i]
if ts:
t = ts.texture
if ts.use and t.type == 'IMAGE':
name = t.image.name
if t.use_normal_map:
material['mapNormal'] = name
else:
if not material['mapDiffuse']:
material['mapDiffuse'] = name
else:
material['mapLight'] = name
if material['mapDiffuse'] and material['mapNormal'] and material['mapLight']:
break
if m.specular_intensity > 0.0 and (m.specular_color[0] > 0 or m.specular_color[1] > 0 or m.specular_color[2] > 0):
material['shading'] = "Phong"
else:
material['shading'] = "Lambert"
return material
def generate_material_string(material):
type_map = {
"Lambert" : "MeshLambertMaterial",
"Phong" : "MeshPhongMaterial"
}
material_id = material["name"]
shading = material["shading"]
material_type = type_map.get(shading, "MeshBasicMaterial")
parameters = "color: %s" % generate_hex(rgb2int(material["colorDiffuse"]))
parameters += ", opacity: %.2f" % material["transparency"]
if shading == "Phong":
parameters += ", ambient: %s" % generate_hex(rgb2int(material["colorAmbient"]))
parameters += ", specular: %s" % generate_hex(rgb2int(material["colorSpecular"]))
parameters += ", shininess: %.1f" % material["specularCoef"]
colorMap = material['mapDiffuse']
lightMap = material['mapLight']
normalMap = material['mapNormal']
if colorMap:
parameters += ", map: %s" % generate_string(colorMap)
if lightMap:
parameters += ", lightMap: %s" % generate_string(lightMap)
if normalMap:
parameters += ", normalMap: %s" % generate_string(normalMap)
material_string = TEMPLATE_MATERIAL_SCENE % {
"material_id" : generate_string(material_id),
"type" : generate_string(material_type),
"parameters" : parameters
}
return material_string
def generate_materials_scene(data):
chunks = []
# TODO: extract just materials actually used by some objects in the scene
for m in bpy.data.materials:
material = extract_material_data(m)
material_string = generate_material_string(material)
chunks.append(material_string)
return ",\n\n".join(chunks)
def generate_cameras(data):
cameras = data.get("cameras", [])
if not cameras:
cameras.append(DEFAULTS["camera"])
chunks = []
for camera in cameras:
if camera["type"] == "perspective":
camera_string = TEMPLATE_CAMERA_PERSPECTIVE % {
"camera_id" : generate_string(camera["name"]),
"fov" : camera["fov"],
"aspect" : camera["aspect"],
"near" : camera["near"],
"far" : camera["far"],
"position" : generate_vec3(camera["position"]),
"target" : generate_vec3(camera["target"])
}
elif camera["type"] == "ortho":
camera_string = TEMPLATE_CAMERA_ORTHO % {
"camera_id" : generate_string(camera["name"]),
"left" : camera["left"],
"right" : camera["right"],
"top" : camera["top"],
"bottom" : camera["bottom"],
"near" : camera["near"],
"far" : camera["far"],
"position" : generate_vec3(camera["position"]),
"target" : generate_vec3(camera["target"])
}
chunks.append(camera_string)
return ",\n\n".join(chunks)
def generate_lights(data):
lights = data.get("lights", [])
if not lights:
lights.append(DEFAULTS["light"])
chunks = []
for light in lights:
if light["type"] == "directional":
light_string = TEMPLATE_LIGHT_DIRECTIONAL % {
"light_id" : generate_string(light["name"]),
"direction" : generate_vec3(light["direction"]),
"color" : generate_hex(rgb2int(light["color"])),
"intensity" : light["intensity"]
}
elif light["type"] == "point":
light_string = TEMPLATE_LIGHT_POINT % {
"light_id" : generate_string(light["name"]),
"position" : generate_vec3(light["position"]),
"color" : generate_hex(rgb2int(light["color"])),
"intensity" : light["intensity"]
}
chunks.append(light_string)
return ",\n\n".join(chunks)
def generate_ascii_scene(data):
objects = generate_objects(data)
geometries = generate_geometries(data)
textures = generate_textures_scene(data)
materials = generate_materials_scene(data)
cameras = generate_cameras(data)
lights = generate_lights(data)
sections = [
["objects", objects],
["geometries", geometries],
["textures", textures],
["materials", materials],
["cameras", cameras],
["lights", lights]
]
chunks = []
for label, content in sections:
if content:
chunks.append(generate_section(label, content))
sections_string = "\n".join(chunks)
default_camera = "default_camera"
parameters = {
"fname" : data["source_file"],
"sections" : sections_string,
"bgcolor" : generate_vec3(DEFAULTS["bgcolor"]),
"bgalpha" : DEFAULTS["bgalpha"],
"defcamera" : generate_string(default_camera)
}
text = TEMPLATE_SCENE_ASCII % parameters
return text
def export_scene(scene, filepath, flipyz):
source_file = os.path.basename(bpy.data.filepath)
scene_text = ""
data = {
"scene" : scene,
"objects" : scene.objects,
"source_file" : source_file,
"filepath" : filepath,
"flipyz" : flipyz
}
scene_text += generate_ascii_scene(data)
write_file(filepath, scene_text)
# #####################################################
# Main
# #####################################################
def save(operator, context, filepath = "", option_flip_yz = True, use_normals = True, use_colors = True, use_uv_coords = True, align_model = 0, option_export_scene = True):
filepath = ensure_extension(filepath, '.js')
scene = context.scene
if scene.objects.active:
bpy.ops.object.mode_set(mode='OBJECT')
if option_export_scene:
export_scene(scene, filepath, option_flip_yz)
geo_set = set()
for obj in scene.objects:
if obj.type == "MESH":
# create extra copy of geometry with applied modifiers
# (if they exist)
if len(obj.modifiers) > 0:
name = obj.name
# otherwise can share geometry
else:
name = obj.data.name
if name not in geo_set:
fname = generate_mesh_filename(name, filepath)
export_mesh(obj, scene, fname, use_normals, use_colors, use_uv_coords, 0, option_flip_yz, False)
geo_set.add(name)
else:
obj = context.object
if not obj:
raise Exception("Error, Select 1 active object or select 'export scene'")
export_mesh(obj, scene, filepath, use_normals, use_colors, use_uv_coords, align_model, option_flip_yz, True)
return {'FINISHED'}