Drop to ground.

This commit is contained in:
Lubos Lenco 2016-07-18 12:31:31 +02:00
parent 0792bd6901
commit 91fa10b970
5 changed files with 202 additions and 3 deletions

View file

@ -25,7 +25,7 @@ class Root {
cam.world = Resource.getWorld(Main.projectScene, resource.world_ref);
// Physics
physics = new PhysicsWorld();
physics = new PhysicsWorld(resource.gravity);
Eg.addNodeTrait(sceneNode, physics);
App.notifyOnRender(render);

View file

@ -32,7 +32,7 @@ class PhysicsWorld extends Trait {
static inline var timeStep = 1 / 60;
static inline var fixedStep = 1 / 60;
public function new() {
public function new(gravity:Array<Float> = null) {
super();
rbMap = new Map();
@ -49,7 +49,8 @@ class PhysicsWorld extends Trait {
var solver = BtSequentialImpulseConstraintSolver.create();
world = BtDiscreteDynamicsWorld.create(dispatcher, broadphase, solver, collisionConfiguration);
world.ptr.setGravity(BtVector3.create(0, 0, -9.81).value);
if (gravity == null) gravity = [0, 0, -9.81];
world.ptr.setGravity(BtVector3.create(gravity[0], gravity[1], gravity[2]).value);
notifyOnUpdate(update);
}

View file

@ -2221,6 +2221,8 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
self.ExportWorlds()
self.output.world_ref = scene.world.name
self.output.gravity = [scene.gravity[0], scene.gravity[1], scene.gravity[2]]
self.ExportObjects(scene)
self.cb_postprocess()

View file

@ -0,0 +1,193 @@
# http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Object/Drop_to_ground
import bpy
from bpy.props import *
import bmesh
from random import seed, uniform
import math
import mathutils
from mathutils import *
def transform_ground_to_world(sc, ground):
tmpMesh = ground.to_mesh(sc, True, 'PREVIEW')
tmpMesh.transform(ground.matrix_world)
tmp_ground = bpy.data.objects.new('tmpGround', tmpMesh)
sc.objects.link(tmp_ground)
sc.update()
return tmp_ground
def get_lowest_world_co_from_mesh(ob, mat_parent=None):
bme = bmesh.new()
bme.from_mesh(ob.data)
mat_to_world = ob.matrix_world.copy()
if mat_parent:
mat_to_world = mat_parent * mat_to_world
lowest = None
# bme.verts.index_update()
for v in bme.verts:
if not lowest:
lowest = v
if (mat_to_world * v.co).z < (mat_to_world * lowest.co).z:
lowest = v
lowest_co = mat_to_world * lowest.co
bme.free()
return lowest_co
def drop_objects(self, context, ground, obs, use_origin, offset, drop_random):
# Random distribution
if drop_random:
halfX = ground.dimensions.x / 2
halfY = ground.dimensions.y / 2
for ob in obs:
# if spherical is True:
# ob.matrix_world = Matrix.Translation((0, 0, 100))
# else:
ob.location = (
ground.location.x + uniform(-halfX, halfX),
ground.location.y + uniform(-halfY, halfY),
ground.location.z + 1000)
# if spherical is True:
# ground.matrix_world.translation = ((0, 0, 0))
tmp_ground = transform_ground_to_world(context.scene, ground)
down = Vector((0, 0, -10000))
mat_original = ground.matrix_world.copy()
for ob in obs:
if use_origin:
lowest_world_co = ob.location
else:
lowest_world_co = get_lowest_world_co_from_mesh(ob)
if not lowest_world_co:
continue
# if spherical is True:
# e = Euler(
# (uniform(0, math.pi * 2),
# uniform(0, math.pi * 2),
# uniform(0, math.pi * 2)),
# 'XYZ')
# mat_rot = e.to_matrix().to_4x4()
# ground.matrix_world = mat_rot * mat_original
was_hit, hit_location, hit_normal, hit_index = \
tmp_ground.ray_cast(lowest_world_co, lowest_world_co + down)
if hit_index is -1:
continue
to_ground_vec = hit_location - lowest_world_co
ob.matrix_world *= Matrix.Translation(to_ground_vec)
ob.location.z += offset
# if spherical is True:
# ob.matrix_world = mat_rot * ob.matrix_world
ground.matrix_world = mat_original
bpy.ops.object.select_all(action='DESELECT')
tmp_ground.select = True
bpy.ops.object.delete('EXEC_DEFAULT')
for ob in obs:
ob.select = True
ground.select = True
bpy.context.scene.objects.active = ground
class OBJECT_OT_drop_to_ground(bpy.types.Operator):
bl_idname = "object.drop_on_active"
bl_label = "Drop to Ground"
bl_options = {'REGISTER', 'UNDO'}
bl_description = "Drop selected objects on active object"
use_origin = BoolProperty(
name="Use Center",
description="Drop to objects origins",
default=False)
drop_random = BoolProperty(
name="Random",
description="Drop to random point",
default=False)
offset = FloatProperty(
name="Margin",
description="Offset from the ground",
default=0.0)
@classmethod
def poll(cls, context):
return len(context.selected_objects) >= 2
def execute(self, context):
ground = context.object
obs = context.selected_objects
obs.remove(ground)
drop_objects(self, context, ground, obs, self.use_origin, self.offset, self.drop_random)
return {'FINISHED'}
# http://blenderartists.org/forum/showthread.php?229346-AddOn-Duplicate-Multiple-Linked
def duplicate_object(context, numCopies, transVec, doParent):
activeObj = context.active_object
dupCopies = []
dupCopies.append(activeObj)
while numCopies > 0:
bpy.ops.object.duplicate_move_linked(OBJECT_OT_duplicate={"linked":True, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":transVec, "release_confirm":False})
dupCopies.append(context.active_object)
numCopies -= 1
if doParent:
groupName = activeObj.name + "_Copies"
bpy.ops.object.add(type='EMPTY')
groupEmpty = context.active_object
groupEmpty.name = groupName
for i in dupCopies:
bpy.data.objects[i.name].select = True
bpy.data.objects[groupEmpty.name].select = True
bpy.ops.object.parent_set(type="OBJECT")
else:
for i in dupCopies:
bpy.data.objects[i.name].select = True
class OBJECT_OT_multi_duplicate(bpy.types.Operator):
bl_idname = "object.multi_duplicate"
bl_label = "Duplicate Multiple Linked"
bl_options = {"REGISTER", "UNDO"}
num_copies = bpy.props.IntProperty(name="Number of Copies:", default=1, description="Number of copies", min=1, max=5000, subtype="NONE")
xyz_offset = bpy.props.FloatVectorProperty(name="XYZ Offset:", default=(0.0,0.0,0.0), min=-1000, max=1000, description="XYZ Offset")
do_parent = bpy.props.BoolProperty(name="Parent under Empty", default=True)
@classmethod
def poll(cls, context):
ob = context.object
if ob == None:
return False
elif ob.select:
return True
return False
def execute(self, context):
duplicate_object(context, self.num_copies, self.xyz_offset, self.do_parent)
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
class ArmToolsPanel(bpy.types.Panel):
bl_label = "Armory Tools"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
def draw(self, context):
self.layout.operator("object.drop_on_active")
self.layout.operator("object.multi_duplicate")
def register():
bpy.utils.register_class(OBJECT_OT_drop_to_ground)
bpy.utils.register_class(OBJECT_OT_multi_duplicate)
bpy.utils.register_class(ArmToolsPanel)
def unregister():
bpy.utils.unregister_class(OBJECT_OT_drop_to_ground)
bpy.utils.unregister_class(OBJECT_OT_multi_duplicate)
bpy.utils.unregister_class(ArmToolsPanel)

View file

@ -7,6 +7,7 @@ import traits_animation
import traits_params
import traits
import props
import lib.drop_to_ground
import bpy
import utils
@ -24,6 +25,7 @@ def register():
traits_animation.register()
traits_params.register()
traits.register()
lib.drop_to_ground.register()
# Start server
user_preferences = bpy.context.user_preferences
@ -45,6 +47,7 @@ def unregister():
traits_params.unregister()
traits.unregister()
props.unregister()
lib.drop_to_ground.unregister()
# Stop server
register.p.terminate()