Browse Source

Merge branch 'dev' of github.com:mrdoob/three.js into Blender_extra_vertex_groups

tschw 10 years ago
parent
commit
0b3411ecf6

+ 2 - 2
examples/webgl_animation_cloth.html

@@ -187,7 +187,7 @@
 				clothTexture.wrapS = clothTexture.wrapT = THREE.RepeatWrapping;
 				clothTexture.anisotropy = 16;
 
-				var clothMaterial = new THREE.MeshPhongMaterial( { alphaTest: 0.5, color: 0xffffff, specular: 0x030303, emissive: 0x111111, shiness: 10, map: clothTexture, side: THREE.DoubleSide } );
+				var clothMaterial = new THREE.MeshPhongMaterial( { alphaTest: 0.5, color: 0xffffff, specular: 0x030303, emissive: 0x111111, shininess: 10, map: clothTexture, side: THREE.DoubleSide } );
 
 				// cloth geometry
 				clothGeometry = new THREE.ParametricGeometry( clothFunction, cloth.w, cloth.h );
@@ -241,7 +241,7 @@
 				// poles
 
 				var poleGeo = new THREE.BoxGeometry( 5, 375, 5 );
-				var poleMat = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shiness: 100 } );
+				var poleMat = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shininess: 100 } );
 
 				var mesh = new THREE.Mesh( poleGeo, poleMat );
 				mesh.position.x = -125;

+ 9 - 59
examples/webgl_shaders_ocean2.html

@@ -40,7 +40,9 @@
 		<script src="js/Ocean.js"></script>
 
 		<script>
-			var stats;
+			var stats = new Stats();
+			document.body.appendChild( stats.domElement );
+
 			var lastTime = (new Date()).getTime();
 
 			var types = { 'float': 'half-float', 'half-float': 'float' };
@@ -48,59 +50,7 @@
 			if (!(hash in types)) hash = 'half-float';
 
 			document.getElementById('type-status').innerHTML = hash;
-			document.getElementById('change-type').innerHTML =
-				'<a href="#" onclick="return change(\'' + types[hash] + '\')">' + types[hash] + '</a>';
-
-			var WINDOW = {
-				ms_Width: 0,
-				ms_Height: 0,
-				ms_Callbacks: {
-					70: "WINDOW.ToggleFullScreen()",		// Toggle fullscreen
-				},
-
-				Initialize: function () {
-					this.UpdateSize();
-
-					stats = new Stats();
-					document.body.appendChild( stats.domElement );
-
-					// Create callbacks from keyboard
-					document.onkeydown = function (inEvent) { WINDOW.CallAction(inEvent.keyCode); };
-					window.onresize = function (inEvent) {
-						WINDOW.UpdateSize();
-						WINDOW.ResizeCallback(WINDOW.ms_Width, WINDOW.ms_Height);
-					};
-				},
-				UpdateSize: function () {
-					this.ms_Width = window.outerWidth;
-					this.ms_Height = window.outerHeight - 4;
-				},
-				CallAction: function (inId) {
-					if (inId in this.ms_Callbacks) {
-						eval(this.ms_Callbacks[inId]);
-						return false;
-					}
-				},
-				ToggleFullScreen: function () {
-					if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement) {
-						if (document.documentElement.requestFullscreen)
-							document.documentElement.requestFullscreen();
-						else if (document.documentElement.mozRequestFullScreen)
-							document.documentElement.mozRequestFullScreen();
-						else if (document.documentElement.webkitRequestFullscreen)
-							document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
-					}
-					else {
-						if (document.cancelFullScreen)
-							document.cancelFullScreen();
-						else if (document.mozCancelFullScreen)
-							document.mozCancelFullScreen();
-						else if (document.webkitCancelFullScreen)
-							document.webkitCancelFullScreen();
-					}
-				},
-				ResizeCallback: function (inWidth, inHeight) { },
-			};
+			document.getElementById('change-type').innerHTML = '<a href="#" onclick="return change(\'' + types[hash] + '\')">' + types[hash] + '</a>';
 
 			var lastTime = (new Date()).getTime();
 
@@ -129,7 +79,7 @@
 
 					this.ms_Scene = new THREE.Scene();
 
-					this.ms_Camera = new THREE.PerspectiveCamera(55.0, WINDOW.ms_Width / WINDOW.ms_Height, 0.5, 300000);
+					this.ms_Camera = new THREE.PerspectiveCamera(55.0, window.innerWidth / window.innerHeight, 0.5, 300000);
 					this.ms_Camera.position.set(450, 350, 450);
 					this.ms_Camera.lookAt(new THREE.Vector3());
 
@@ -246,12 +196,12 @@
 				}
 			};
 
-			WINDOW.Initialize();
-
 			DEMO.Initialize();
 
-			WINDOW.ResizeCallback = function (inWidth, inHeight) { DEMO.Resize(inWidth, inHeight); };
-			DEMO.Resize(WINDOW.ms_Width, WINDOW.ms_Height);
+			window.addEventListener( 'resize', function () {
+				DEMO.Resize(window.innerWidth, window.innerHeight);
+			} );
+			DEMO.Resize(window.innerWidth, window.innerHeight);
 
 			var render = function () {
 

+ 6 - 6
src/core/BufferGeometry.js

@@ -316,8 +316,6 @@ THREE.BufferGeometry.prototype = {
 		var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
 		var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
 
-		var hasFaceVertexNormals = faces[ 0 ] && faces[ 0 ].vertexNormals.length === 3;
-
 		var positions = new Float32Array( faces.length * 3 * 3 );
 		this.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
 
@@ -365,11 +363,13 @@ THREE.BufferGeometry.prototype = {
 			positions[ i3 + 7 ] = c.y;
 			positions[ i3 + 8 ] = c.z;
 
-			if ( hasFaceVertexNormals === true ) {
+			var vertexNormals = face.vertexNormals;
+
+			if ( vertexNormals.length === 3 ) {
 
-				var na = face.vertexNormals[ 0 ];
-				var nb = face.vertexNormals[ 1 ];
-				var nc = face.vertexNormals[ 2 ];
+				var na = vertexNormals[ 0 ];
+				var nb = vertexNormals[ 1 ];
+				var nc = vertexNormals[ 2 ];
 
 				normals[ i3     ] = na.x;
 				normals[ i3 + 1 ] = na.y;

+ 19 - 1
utils/exporters/blender/addons/io_three/__init__.py

@@ -312,6 +312,10 @@ def restore_export_settings(properties, settings):
     properties.option_geometry_type = settings.get(
         constants.GEOMETRY_TYPE,
         constants.EXPORT_OPTIONS[constants.GEOMETRY_TYPE])
+
+    properties.option_index_type = settings.get(
+        constants.INDEX_TYPE,
+        constants.EXPORT_OPTIONS[constants.INDEX_TYPE])
     ## }
 
     ## Materials {
@@ -435,6 +439,7 @@ def set_settings(properties):
         constants.EXTRA_VGROUPS: properties.option_extra_vgroups,
         constants.APPLY_MODIFIERS: properties.option_apply_modifiers,
         constants.GEOMETRY_TYPE: properties.option_geometry_type,
+        constants.INDEX_TYPE: properties.option_index_type,
 
         constants.MATERIALS: properties.option_materials,
         constants.UVS: properties.option_uv_coords,
@@ -576,6 +581,17 @@ class ExportThree(bpy.types.Operator, ExportHelper):
         default=constants.EXPORT_OPTIONS[constants.APPLY_MODIFIERS]
     )
 
+    index_buffer_types = [
+        (constants.NONE,) * 3,
+        (constants.UINT_16,) * 3,
+        (constants.UINT_32,) * 3]
+
+    option_index_type = EnumProperty(
+        name="Index Buffer",
+        description="Index buffer type that will be used for BufferGeometry objects.",
+        items=index_buffer_types,
+        default=constants.EXPORT_OPTIONS[constants.INDEX_TYPE])
+
     option_scale = FloatProperty(
         name="Scale",
         description="Scale vertices",
@@ -614,7 +630,7 @@ class ExportThree(bpy.types.Operator, ExportHelper):
         name="Type",
         description="Geometry type",
         items=_geometry_types()[1:],
-        default=constants.GEOMETRY)
+        default=constants.EXPORT_OPTIONS[constants.GEOMETRY_TYPE])
 
     option_export_scene = BoolProperty(
         name="Scene",
@@ -781,6 +797,8 @@ class ExportThree(bpy.types.Operator, ExportHelper):
         row = layout.row()
         row.prop(self.properties, 'option_geometry_type')
 
+        row = layout.row()
+        row.prop(self.properties, 'option_index_type')
         ## }
 
         layout.separator()

+ 11 - 2
utils/exporters/blender/addons/io_three/constants.py

@@ -48,6 +48,11 @@ APPLY_MODIFIERS = 'applyModifiers'
 COLORS = 'colors'
 MIX_COLORS = 'mixColors'
 EXTRA_VGROUPS = 'extraVertexGroups'
+INDEX = 'index'
+DRAW_CALLS = 'offsets'
+DC_START = 'start'
+DC_COUNT = 'count'
+DC_INDEX = 'index'
 SCALE = 'scale'
 COMPRESSION = 'compression'
 MAPS = 'maps'
@@ -78,6 +83,7 @@ GLOBAL = 'global'
 BUFFER_GEOMETRY = 'BufferGeometry'
 GEOMETRY = 'geometry'
 GEOMETRY_TYPE = 'geometryType'
+INDEX_TYPE = 'indexType'
 
 CRITICAL = 'critical'
 ERROR = 'error'
@@ -90,6 +96,10 @@ MSGPACK = 'msgpack'
 
 PACK = 'pack'
 
+FLOAT_32 = 'Float32Array'
+UINT_16 = 'Uint16Array'
+UINT_32 = 'Uint32Array'
+
 INFLUENCES_PER_VERTEX = 'influencesPerVertex'
 
 EXPORT_OPTIONS = {
@@ -100,6 +110,7 @@ EXPORT_OPTIONS = {
     APPLY_MODIFIERS: True,
     COLORS: False,
     EXTRA_VGROUPS: '',
+    INDEX_TYPE: UINT_16,
     MATERIALS: False,
     FACE_MATERIALS: False,
     SCALE: 1,
@@ -189,8 +200,6 @@ NORMAL = 'normal'
 ITEM_SIZE = 'itemSize'
 ARRAY = 'array'
 
-FLOAT_32 = 'Float32Array'
-
 VISIBLE = 'visible'
 CAST_SHADOW = 'castShadow'
 RECEIVE_SHADOW = 'receiveShadow'

+ 4 - 1
utils/exporters/blender/addons/io_three/exporter/api/material.py

@@ -384,7 +384,10 @@ def _valid_textures(material, strict_use=True):
             in_use = texture.use
         else:
             in_use = True
-        if texture.texture.type != IMAGE or not in_use:
+        if not in_use:
+            continue
+        if not texture.texture or texture.texture.type != IMAGE:
+            logger.warning("Unable to export non-image texture %s", texture)
             continue
         logger.debug("Valid texture found %s", texture)
         yield texture

+ 3 - 0
utils/exporters/blender/addons/io_three/exporter/api/object.py

@@ -330,6 +330,8 @@ def extract_mesh(obj, options, recalculate=False):
     """
     logger.debug('object.extract_mesh(%s, %s)', obj, options)
     apply_modifiers = options.get(constants.APPLY_MODIFIERS, True)
+    if apply_modifiers:
+        bpy.ops.object.mode_set(mode='OBJECT')
     mesh_node = obj.to_mesh(context.scene, apply_modifiers, RENDER)
 
     # transfer the geometry type to the extracted mesh
@@ -350,6 +352,7 @@ def extract_mesh(obj, options, recalculate=False):
                      original_mesh.name,
                      mesh_node.name)
 
+        bpy.ops.object.mode_set(mode='OBJECT')
         obj.select = True
         bpy.context.scene.objects.active = obj
         logger.info('Applying triangulation to %s', obj.data.name)

+ 97 - 7
utils/exporters/blender/addons/io_three/exporter/geometry.py

@@ -241,7 +241,8 @@ class Geometry(base_classes.BaseNode):
                       constants.NORMALS, constants.BONES,
                       constants.SKIN_WEIGHTS,
                       constants.SKIN_INDICES, constants.NAME,
-                      constants.INFLUENCES_PER_VERTEX]
+                      constants.INFLUENCES_PER_VERTEX,
+                      constants.INDEX]
 
         data = {}
         anim_components = [constants.MORPH_TARGETS, constants.ANIMATION]
@@ -294,6 +295,10 @@ class Geometry(base_classes.BaseNode):
 
         data[constants.METADATA].update(self.metadata)
 
+        draw_calls = self.get(constants.DRAW_CALLS)
+        if draw_calls is not None:
+            data[constants.DRAW_CALLS] = draw_calls
+
         return data
 
     def _buffer_geometry_metadata(self, metadata):
@@ -308,7 +313,7 @@ class Geometry(base_classes.BaseNode):
             metadata[key] = len(array)/size
 
     def _geometry_metadata(self, metadata):
-        """Three.Geometry metadat
+        """Three.Geometry metadata
 
         :rtype: dict
 
@@ -354,12 +359,15 @@ class Geometry(base_classes.BaseNode):
                 constants.METADATA: self.metadata
             })
         else:
+            geometry_data = data
             if self.options.get(constants.EMBED_GEOMETRY, True):
-                data[constants.DATA] = {
-                    constants.ATTRIBUTES: component_data
-                }
-            else:
-                data[constants.ATTRIBUTES] = component_data
+                data[constants.DATA] = geometry_data = {}
+
+            geometry_data[constants.ATTRIBUTES] = component_data
+            draw_calls = self.get(constants.DRAW_CALLS)
+            if draw_calls is not None:
+                geometry_data[constants.DRAW_CALLS] = draw_calls
+
             data[constants.METADATA] = self.metadata
             data[constants.NAME] = self[constants.NAME]
 
@@ -373,6 +381,7 @@ class Geometry(base_classes.BaseNode):
         option_normals = self.options.get(constants.NORMALS)
         option_uvs = self.options.get(constants.UVS)
         option_extra_vgroups = self.options.get(constants.EXTRA_VGROUPS)
+        option_index_type = self.options.get(constants.INDEX_TYPE)
 
         pos_tuple = (constants.POSITION, options_vertices,
                      api.mesh.buffer_position, 3)
@@ -420,6 +429,87 @@ class Geometry(base_classes.BaseNode):
                     constants.ARRAY: array
                 }
 
+        if option_index_type != constants.NONE:
+
+            assert(not (self.get(constants.INDEX) or
+                        self.get(constants.DRAW_CALLS)))
+
+            indices_per_face = 3
+            index_threshold  = 0xffff - indices_per_face
+            if option_index_type == constants.UINT_32:
+                index_threshold = 0x7fffffff - indices_per_face
+
+            attrib_data_in, attrib_data_out, attrib_keys = [], [], []
+
+            i = 0
+            for key, entry in self[constants.ATTRIBUTES].items():
+
+                item_size = entry[constants.ITEM_SIZE]
+
+                attrib_keys.append(key)
+                attrib_data_in.append( (entry[constants.ARRAY], item_size) )
+                attrib_data_out.append( ([], i, i + item_size) )
+                i += item_size
+
+            index_data, draw_calls = [], []
+            indexed, flush_req, base_vertex = {}, False, 0
+
+            assert(len(attrib_data_in) > 0)
+            array, item_size = attrib_data_in[0]
+            i, n = 0, len(array) / item_size
+            while i < n:
+
+                vertex_data = ()
+                for array, item_size in attrib_data_in:
+                    vertex_data += tuple(
+                            array[i * item_size : (i + 1) * item_size])
+
+                vertex_index = indexed.get(vertex_data)
+
+                if vertex_index is None:
+
+                    vertex_index = len(indexed)
+                    flush_req = vertex_index >= index_threshold
+
+                    indexed[vertex_data] = vertex_index
+                    for array, i_from, i_to in attrib_data_out:
+                        array.extend(vertex_data[i_from : i_to])
+
+                index_data.append(vertex_index)
+
+                i += 1
+                if i == n:
+                    flush_req = len(draw_calls) > 0
+                    assert(i % indices_per_face == 0)
+
+                if flush_req and i % indices_per_face == 0:
+                    start, count = 0, len(index_data)
+                    if draw_calls:
+                        prev = draw_calls[-1]
+                        start = prev[constants.DC_START] + prev[constants.DC_COUNT]
+                        count -= start
+                    draw_calls.append({
+                        constants.DC_START: start,
+                        constants.DC_COUNT: count,
+                        constants.DC_INDEX: base_vertex
+                    })
+                    base_vertex += len(indexed)
+                    indexed.clear()
+                    flush_req = False
+
+            for i, key in enumerate(attrib_keys):
+                array = attrib_data_out[i][0]
+                self[constants.ATTRIBUTES][key][constants.ARRAY] = array
+
+            self[constants.ATTRIBUTES][constants.INDEX] = {
+                constants.ITEM_SIZE: 3,
+                constants.TYPE: option_index_type,
+                constants.ARRAY: index_data
+            }
+            if (draw_calls):
+                logger.info("draw_calls = %s", repr(draw_calls))
+                self[constants.DRAW_CALLS] = draw_calls
+
 
     def _parse_geometry(self):
         """Parse the geometry to Three.Geometry specs"""