Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'object_cloud_gen.py')
-rw-r--r--object_cloud_gen.py674
1 files changed, 0 insertions, 674 deletions
diff --git a/object_cloud_gen.py b/object_cloud_gen.py
deleted file mode 100644
index 9d9ee1e2..00000000
--- a/object_cloud_gen.py
+++ /dev/null
@@ -1,674 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Cloud Generator",
- "author": "Nick Keeline(nrk)",
- "version": (0,7),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "Tool Shelf ",
- "description": "Creates Volumetric Clouds",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Object/Cloud_Gen",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22015&group_id=153&atid=469",
- "category": "Object"}
-
-"""
-Place this file in the .blender/scripts/addons dir
-You have to activated the script in the "Add-Ons" tab (user preferences).
-The functionality can then be accessed via the Tool shelf when objects
-are selected
-
-Rev 0 initial release
-Rev 0.1 added scene to create_mesh per python api change.
-Rev 0.2 Added Point Density turbulence and fixed degenerate
-Rev 0.3 Fixed bug in degenerate
-Rev 0.4 updated for api change/changed to new apply modifier technique
-Rev 0.5 made particle count equation with radius so radius increases with cloud volume
-Rev 0.6 added poll function to operator, fixing crash with no selected objects
-Rev 0.7 added particles option and Type of Cloud wanted selector
-"""
-
-import bpy
-import mathutils
-from math import *
-from bpy.props import *
-
-
-# This routine takes an object and deletes all of the geometry in it
-# and adds a bounding box to it.
-# It will add or subtract the bound box size by the variable sizeDifference.
-def makeObjectIntoBoundBox(object, sizeDifference):
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object
- object.select = True
-
- # Go into Edit Mode
- bpy.ops.object.mode_set(mode='EDIT')
-
- mesh = object.data
- verts = mesh.vertices
-
- #Set the max and min verts to the first vertex on the list
- maxVert = [verts[0].co[0], verts[0].co[1], verts[0].co[2]]
- minVert = [verts[0].co[0], verts[0].co[1], verts[0].co[2]]
-
- #Create Max and Min Vertex array for the outer corners of the box
- for vert in verts:
- #Max vertex
- if vert.co[0] > maxVert[0]:
- maxVert[0] = vert.co[0]
- if vert.co[1] > maxVert[1]:
- maxVert[1] = vert.co[1]
- if vert.co[2] > maxVert[2]:
- maxVert[2] = vert.co[2]
-
- #Min Vertex
- if vert.co[0] < minVert[0]:
- minVert[0] = vert.co[0]
- if vert.co[1] < minVert[1]:
- minVert[1] = vert.co[1]
- if vert.co[2] < minVert[2]:
- minVert[2] = vert.co[2]
-
- #Add the size difference to the max size of the box
- maxVert[0] = maxVert[0] + sizeDifference
- maxVert[1] = maxVert[1] + sizeDifference
- maxVert[2] = maxVert[2] + sizeDifference
-
- #subtract the size difference to the min size of the box
- minVert[0] = minVert[0] - sizeDifference
- minVert[1] = minVert[1] - sizeDifference
- minVert[2] = minVert[2] - sizeDifference
-
- #Create arrays of verts and faces to be added to the mesh
- addVerts = []
-
- #X high loop
- addVerts.append([maxVert[0], maxVert[1], maxVert[2]])
- addVerts.append([maxVert[0], maxVert[1], minVert[2]])
- addVerts.append([maxVert[0], minVert[1], minVert[2]])
- addVerts.append([maxVert[0], minVert[1], maxVert[2]])
-
- #x low loop
- addVerts.append([minVert[0], maxVert[1], maxVert[2]])
- addVerts.append([minVert[0], maxVert[1], minVert[2]])
- addVerts.append([minVert[0], minVert[1], minVert[2]])
- addVerts.append([minVert[0], minVert[1], maxVert[2]])
-
- # Make the faces of the bounding box.
- addFaces = []
-
- # Draw a box on paper and number the vertices.
- # Use right hand rule to come up with number orders for faces on
- # the box (with normals pointing out).
- addFaces.append([0, 3, 2, 1])
- addFaces.append([4, 5, 6, 7])
- addFaces.append([0, 1, 5, 4])
- addFaces.append([1, 2, 6, 5])
- addFaces.append([2, 3, 7, 6])
- addFaces.append([0, 4, 7, 3])
-
- # Delete all geometry from the object.
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.delete(type='ALL')
-
- # Must be in object mode for from_pydata to work
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Add the mesh data.
- mesh.from_pydata(addVerts, [], addFaces)
-
- # Update the mesh
- mesh.update()
-
-
-def applyScaleRotLoc(scene, obj):
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object
- obj.select = True
- scene.objects.active = obj
-
- #bpy.ops.object.rotation_apply()
- bpy.ops.object.location_apply()
- bpy.ops.object.scale_apply()
-
-
-def totallyDeleteObject(scene, obj):
- #To Do this section to be updated when
- #Ability to completely delet objects added to blender
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object and delete it.
- obj.select = True
- scene.objects.active = obj
-
- # Delete all material slots in obj
- for i in range(len(obj.material_slots)):
- #textureSlots = cloudMaterial.texture_slots
- obj.active_material_index = i - 1
- bpy.ops.object.material_slot_remove()
-
- #bpy.ops.object.parent_clear(type='CLEAR')
-
- # Delete the Main Object
- bpy.ops.object.delete()
- #bpy.data.objects.remove(obj)
-
-
-def makeParent(parentobj, childobj, scene):
-
- applyScaleRotLoc(scene, parentobj)
-
- applyScaleRotLoc(scene, childobj)
-
- childobj.parent = parentobj
-
- #childobj.location = childobj.location - parentobj.location
-
-
-def addNewObject(scene, name, copyobj):
- '''
- Add an object and do other silly stuff.
- '''
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Create a new object.
- ob_new = bpy.data.objects.new(name, mesh)
- tempme = copyobj.data
- ob_new.data = tempme.copy()
- ob_new.scale = copyobj.scale
- ob_new.location = copyobj.location
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- return ob_new
-
-
-def combineObjects(scene, combined, listobjs):
- # scene is the current scene
- # combined is the object we want to combine everything into
- # listobjs is the list of objects to stick into combined
-
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the new object.
- combined.select = True
- scene.objects.active = combined
-
- # Add data
- if (len(listobjs) > 0):
- for i in listobjs:
- # Add a modifier
- bpy.ops.object.modifier_add(type='BOOLEAN')
-
- union = combined.modifiers
- union[0].name = "AddEmUp"
- union[0].object = i
- union[0].operation = 'UNION'
-
- # Apply modifier
- bpy.ops.object.modifier_apply(apply_as='DATA', modifier=union[0].name)
-
-
-# Returns True if we want to degenerate
-# and False if we want to generate a new cloud.
-def degenerateCloud(obj):
- if not obj:
- return False
-
- if "CloudMember" in obj:
- if obj["CloudMember"] != None:
- if obj.parent:
- if "CloudMember" not in obj.parent:
- return False
-
- else:
- return True
-
- return False
-
-
-class VIEW3D_PT_tools_cloud(bpy.types.Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'TOOLS'
-
- bl_label = "Cloud Generator"
- bl_context = "objectmode"
-
- def draw(self, context):
- active_obj = context.active_object
- layout = self.layout
- col = layout.column(align=True)
-
- degenerate = degenerateCloud(active_obj)
-
- if active_obj and degenerate:
-
- col.operator("cloud.generate_cloud", text="DeGenerate")
-
- elif active_obj is None:
-
- col.label(text="Select one or more")
- col.label(text="objects to generate")
- col.label(text="a cloud.")
-
- elif "CloudMember" in active_obj:
-
- col.label(text="Must select")
- col.label(text="bound box")
-
- elif active_obj and active_obj.type == 'MESH':
-
- col.operator("cloud.generate_cloud", text="Generate Cloud")
-
- col.prop(context.scene, "cloudparticles")
- col.prop(context.scene, "cloud_type")
- else:
- col.label(text="Select one or more")
- col.label(text="objects to generate")
- col.label(text="a cloud.")
-
-cloudTypes = []
-
-cloudTypes.append(("0","Stratus","Generate Stratus_foggy Cloud"))
-cloudTypes.append(("1","Cumulous","Generate Cumulous_puffy Cloud"))
-cloudTypes.append(("2","Cirrus","Generate Cirrus_wispy Cloud"))
-#cloudTypes.append(("3","Nimbus","Generate Nimbus Cloud"))
-
-
-bpy.types.Scene.cloudparticles = BoolProperty(
- name="Particles",
- description="Generate Cloud as Particle System",
- default=False)
-
-bpy.types.Scene.cloud_type = EnumProperty(
- name="Type",
- description="Select the type of cloud to create with material settings",
- items = cloudTypes, default = '0')
-
-class GenerateCloud(bpy.types.Operator):
- bl_idname = "cloud.generate_cloud"
- bl_label = "Generate Cloud"
- bl_description = "Create a Cloud."
- bl_register = True
- bl_undo = True
-
- @classmethod
- def poll(cls, context):
- if not context.active_object:
- return False
- else:
- return (context.active_object.type=='MESH')
-
- def execute(self, context):
- # Make variable that is the current .blend file main data blocks
- blend_data = context.blend_data
-
- # Make variable that is the active object selected by user
- active_object = context.active_object
-
- # Make variable scene that is current scene
- scene = context.scene
-
- # Parameters the user may want to change:
- # Number of points this number is multiplied by the volume to get
- # the number of points the scripts will put in the volume.
- numOfPoints = 1.0
- maxNumOfPoints = 100000
- scattering = 2.5
- pointDensityRadiusFactor = 1.0
- densityScale = 1.5
-
- # Should we degnerate?
- degenerate = degenerateCloud(active_object)
-
- if degenerate:
- # Degenerate Cloud
- mainObj = active_object
-
- cloudMembers = active_object.children
-
- createdObjects = []
- definitionObjects = []
- for member in cloudMembers:
- applyScaleRotLoc(scene, member)
- if (member["CloudMember"] == "CreatedObj"):
- createdObjects.append(member)
- else:
- definitionObjects.append(member)
-
- for defObj in definitionObjects:
- #Delete cloudmember data from objects
- if "CloudMember" in defObj:
- del(defObj["CloudMember"])
-
- for createdObj in createdObjects:
- totallyDeleteObject(scene, createdObj)
-
- # Delete the blend_data object
- totallyDeleteObject(scene, mainObj)
-
- # Select all of the left over boxes so people can immediately
- # press generate again if they want.
- for eachMember in definitionObjects:
- eachMember.draw_type = 'SOLID'
- eachMember.select = True
- #scene.objects.active = eachMember
-
- #TODO Delete this when render bug caused by degenerate is fixed.
- self.report({'WARNING'}, "Please save file exit and reenter blender before rendering to clean memory and prevent crash")
-
- else:
- # Generate Cloud
-
- ###############Create Combined Object bounds##################
- # Make a list of all Selected objects.
- selectedObjects = bpy.context.selected_objects
- if not selectedObjects:
- selectedObjects = [bpy.context.active_object]
-
- # Create a new object bounds
- bounds = addNewObject(scene,
- "CloudBounds",
- selectedObjects[0])
-
- bounds.draw_type = 'BOUNDS'
- bounds.hide_render = False
-
- # Just add a Definition Property designating this
- # as the blend_data object.
- bounds["CloudMember"] = "MainObj"
-
- # Since we used iteration 0 to copy with object we
- # delete it off the list.
- firstObject = selectedObjects[0]
- del selectedObjects[0]
-
- # Apply location Rotation and Scale to all objects involved.
- applyScaleRotLoc(scene, bounds)
- for each in selectedObjects:
- applyScaleRotLoc(scene, each)
-
- # Let's combine all of them together.
- combineObjects(scene, bounds, selectedObjects)
-
- # Let's add some property info to the objects.
- for selObj in selectedObjects:
- selObj["CloudMember"] = "DefinitioinObj"
- selObj.name = "DefinitioinObj"
- selObj.draw_type = 'WIRE'
- selObj.hide_render = True
- makeParent(bounds, selObj, scene)
-
- # Do the same to the 1. object since it is no longer in list.
- firstObject["CloudMember"] = "DefinitioinObj"
- firstObject.name = "DefinitioinObj"
- firstObject.draw_type = 'WIRE'
- firstObject.hide_render = True
- makeParent(bounds, firstObject, scene)
-
- ###############Create Cloud for putting Cloud Mesh############
- # Create a new object cloud.
- cloud = addNewObject(scene, "CloudMesh", bounds)
- cloud["CloudMember"] = "CreatedObj"
- cloud.draw_type = 'WIRE'
- cloud.hide_render = True
-
- makeParent(bounds, cloud, scene)
-
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.subdivide(number_cuts=2, fractal=0, smoothness=1)
- bpy.ops.object.location_apply()
- bpy.ops.mesh.vertices_smooth(repeat=20)
- bpy.ops.mesh.tris_convert_to_quads()
- bpy.ops.mesh.faces_shade_smooth()
- bpy.ops.object.editmode_toggle()
-
- ###############Create Particles in cloud obj##################
- # Turn off gravity.
- scene.use_gravity = False
-
- # Set time to 0.
- scene.frame_current = 0
-
- # Add a new particle system.
- bpy.ops.object.particle_system_add()
-
- #Particle settings setting it up!
- cloudParticles = cloud.particle_systems.active
- cloudParticles.name = "CloudParticles"
- cloudParticles.settings.frame_start = 0
- cloudParticles.settings.frame_end = 0
- cloudParticles.settings.emit_from = 'VOLUME'
- cloudParticles.settings.draw_method = 'DOT'
- cloudParticles.settings.render_type = 'NONE'
- cloudParticles.settings.normal_factor = 0
- cloudParticles.settings.distribution = 'RAND'
- cloudParticles.settings.physics_type = 'NO'
-
- ####################Create Volume Material####################
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object.
- bounds.select = True
- scene.objects.active = bounds
-
- # Turn bounds object into a box.
- makeObjectIntoBoundBox(bounds, .6)
-
- # Delete all material slots in bounds object.
- for i in range(len(bounds.material_slots)):
- bounds.active_material_index = i - 1
- bpy.ops.object.material_slot_remove()
-
- # Add a new material.
- cloudMaterial = blend_data.materials.new("CloudMaterial")
- bpy.ops.object.material_slot_add()
- bounds.material_slots[0].material = cloudMaterial
-
- # Set Up the Cloud Material
- cloudMaterial.name = "CloudMaterial"
- cloudMaterial.type = 'VOLUME'
- mVolume = cloudMaterial.volume
- mVolume.scattering = scattering
- mVolume.density = 0
- mVolume.density_scale = densityScale
- mVolume.transmission_color = [3, 3, 3]
- mVolume.step_size = 0.1
- mVolume.use_light_cache = True
- mVolume.cache_resolution = 75
-
- # Add a texture
- vMaterialTextureSlots = cloudMaterial.texture_slots
- cloudtex = blend_data.textures.new("CloudTex", type='CLOUDS')
- cloudtex.noise_type = 'HARD_NOISE'
- cloudtex.noise_scale = 2
- mtex = cloudMaterial.texture_slots.add()
- mtex.texture = cloudtex
- mtex.texture_coords = 'ORCO'
- mtex.use_map_color_diffuse = True
-
- # Add a force field to the points.
- cloudField = bounds.field
- cloudField.type = 'TEXTURE'
- cloudField.strength = 2
- cloudField.texture = cloudtex
-
- # Set time
- #for i in range(12):
- # scene.current_frame = i
- # scene.update()
- scene.frame_current = 1
-
- #bpy.ops.ptcache.bake(bake=False)
-
- # Add a Point Density texture
- pDensity = blend_data.textures.new("CloudPointDensity", 'POINT_DENSITY')
-
- mtex = cloudMaterial.texture_slots.add()
- mtex.texture = pDensity
- mtex.texture_coords = 'GLOBAL'
- mtex.use_map_density = True
- mtex.use_rgb_to_intensity = True
- mtex.texture_coords = 'GLOBAL'
-
- pDensity.point_density.vertex_cache_space = 'WORLD_SPACE'
- pDensity.point_density.use_turbulence = True
- pDensity.point_density.noise_basis = 'VORONOI_F2'
- pDensity.point_density.turbulence_depth = 3
-
- pDensity.use_color_ramp = True
- pRamp = pDensity.color_ramp
- #pRamp.use_interpolation = 'LINEAR'
- pRampElements = pRamp.elements
- #pRampElements[1].position = .9
- #pRampElements[1].color = [.18,.18,.18,.8]
- bpy.ops.texture.slot_move(type='UP')
-
-
- # Estimate the number of particles for the size of bounds.
- volumeBoundBox = (bounds.dimensions[0] * bounds.dimensions[1]* bounds.dimensions[2])
- numParticles = int((2.4462 * volumeBoundBox + 430.4) * numOfPoints)
- if numParticles > maxNumOfPoints:
- numParticles = maxNumOfPoints
- if numParticles < 10000:
- numParticles = int(numParticles + 15 * volumeBoundBox)
- print(numParticles)
-
- # Set the number of particles according to the volume
- # of bounds.
- cloudParticles.settings.count = numParticles
-
- pDensity.point_density.radius = (.00013764 * volumeBoundBox + .3989) * pointDensityRadiusFactor
-
- # Set time to 1.
- scene.frame_current = 1
-
- if not scene.cloudparticles:
- ###############Create CloudPnts for putting points in#########
- # Create a new object cloudPnts
- cloudPnts = addNewObject(scene, "CloudPoints", bounds)
- cloudPnts["CloudMember"] = "CreatedObj"
- cloudPnts.draw_type = 'WIRE'
- cloudPnts.hide_render = True
-
- makeParent(bounds, cloudPnts, scene)
-
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.select_all(action='SELECT')
-
- bpy.ops.mesh.delete(type='ALL')
-
- meshPnts = cloudPnts.data
-
- listCloudParticles = cloudParticles.particles
-
- listMeshPnts = []
- for pTicle in listCloudParticles:
- listMeshPnts.append(pTicle.location)
-
- # Must be in object mode fro from_pydata to work.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Add in the mesh data.
- meshPnts.from_pydata(listMeshPnts, [], [])
-
- # Update the mesh.
- meshPnts.update()
-
- # Add a modifier.
- bpy.ops.object.modifier_add(type='DISPLACE')
-
- cldPntsModifiers = cloudPnts.modifiers
- cldPntsModifiers[0].name = "CloudPnts"
- cldPntsModifiers[0].texture = cloudtex
- cldPntsModifiers[0].texture_coords = 'OBJECT'
- cldPntsModifiers[0].texture_coordinate_object = cloud
- cldPntsModifiers[0].strength = -1.4
-
- # Apply modifier
- bpy.ops.object.modifier_apply(apply_as='DATA', modifier=cldPntsModifiers[0].name)
-
- pDensity.point_density.point_source = 'OBJECT'
- pDensity.point_density.object = cloudPnts
-
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object.
- cloud.select = True
- scene.objects.active = cloud
-
- bpy.ops.object.particle_system_remove()
-
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- else:
-
- pDensity.point_density.point_source = 'PARTICLE_SYSTEM'
- pDensity.point_density.object = cloud
- pDensity.point_density.particle_system = cloudParticles
-
- if scene.cloud_type == '1': # Cumulous
- print("Cumulous")
- mVolume.density_scale = 2.22
- pDensity.point_density.turbulence_depth = 10
- pDensity.point_density.turbulence_strength = 6.3
- pDensity.point_density.turbulence_scale = 2.9
- pRampElements[1].position = .606
- pDensity.point_density.radius = pDensity.point_density.radius + .1
-
- elif scene.cloud_type == '2': # Cirrus
- print("Cirrus")
- pDensity.point_density.turbulence_strength = 22
- mVolume.transmission_color = [3.5, 3.5, 3.5]
- mVolume.scattering = .13
-
- # Select the object.
- bounds.select = True
- scene.objects.active = bounds
-
- return {'FINISHED'}
-
-
-def register():
- pass
-
-
-def unregister():
- pass
-
-
-if __name__ == "__main__":
- register()