diff --git a/object_cloud_gen.py b/object_cloud_gen.py
new file mode 100644
index 0000000000000000000000000000000000000000..3a245c3a513d011905d3791b6f187eed3f0c5997
--- /dev/null
+++ b/object_cloud_gen.py
@@ -0,0 +1,624 @@
+# ##### 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.1',
+    'blender': (2, 5, 3),
+    'location': 'Tool Shelf ',
+    'description': 'Creates Volumetric Clouds',
+    'url': 'http://wiki.blender.org/index.php/Extensions:2.5/Py/' \
+        'Scripts/Object/Cloud_Gen',
+    '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.
+"""
+
+import bpy
+import mathutils
+from math import *
+from bpy.props import *
+
+# Deselect All
+bpy.ops.object.select_all(action='DESELECT')
+
+
+# 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.selected = True
+
+    # Go into Edit Mode
+    bpy.ops.object.mode_set(mode='EDIT')
+
+    mesh = object.data
+    verts = mesh.verts
+
+    #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.selected = True
+    scene.objects.active = obj
+
+    #bpy.ops.object.rotation_apply()
+    bpy.ops.object.location_apply()
+    bpy.ops.object.scale_apply()
+
+
+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.selected = 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.selected = 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
+                # Can't use bpy.ops.object.modifier_apply because poll fails.
+                combined.data = combined.create_mesh(scene,
+                    apply_modifiers=True,
+                    settings='PREVIEW')
+                combined.modifiers.remove(union[0])
+
+
+# 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:
+                return True
+
+            else:
+                del(obj["CloudMember"])
+
+    return False
+
+
+class View3DPanel(bpy.types.Panel):
+    bl_space_type = 'VIEW_3D'
+    bl_region_type = 'TOOLS'
+
+
+class VIEW3D_PT_tools_cloud(View3DPanel):
+    bl_label = "Cloud Generator"
+    bl_context = "objectmode"
+
+    def draw(self, context):
+        active_obj = context.active_object
+
+        degenerate = degenerateCloud(active_obj)
+
+        if active_obj and degenerate:
+            layout = self.layout
+
+            col = layout.column(align=True)
+            col.operator("cloud.generate_cloud", text="DeGenerate")
+
+        elif active_obj and active_obj.type == 'MESH':
+            layout = self.layout
+
+            col = layout.column(align=True)
+            col.operator("cloud.generate_cloud", text="Generate Cloud")
+
+        else:
+            layout = self.layout
+
+            col = layout.column(align=True)
+            col.label(text="Select one or more")
+            col.label(text="objects to generate")
+            col.label(text="a cloud.")
+
+classes = [VIEW3D_PT_tools_cloud]
+
+
+def register():
+    register = bpy.types.register
+    for cls in classes:
+        register(cls)
+
+
+def unregister():
+    unregister = bpy.types.unregister
+    for cls in classes:
+        unregister(cls)
+
+if __name__ == "__main__":
+    register()
+
+
+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
+
+    def execute(self, context):
+        # Make variable that is the current .blend file main data blocks
+        main = context.main
+
+        # 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
+
+        if active_object and active_object.type == 'MESH':
+            # 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 = 35
+            maxNumOfPoints = 100000
+            scattering = 3
+            pointDensityRadius = 0.4
+
+            # Should we degnerate?
+            degenerate = degenerateCloud(active_object)
+
+            if degenerate:
+                # Degenerate Cloud
+                if active_object["CloudMember"] == "MainObj":
+                    mainObj = active_object
+
+                else:
+                    mainObj = active_object.parent
+
+                cloudMembers = active_object.children
+
+                # Find the created objects children of main and delete.
+                createdObjFound = False
+
+                createdObjects = []
+                i = 0
+                for member in cloudMembers:
+                    applyScaleRotLoc(scene, member)
+
+                    if (member["CloudMember"] == "CreatedObj"):
+                        createdObjects.append(member)
+                        del cloudMembers[i]
+
+                    # @todo check if it wouldn't be better to remove this
+                    # in the first place (see del() in degenerateCloud)
+                    member["CloudMember"] = None
+                    i += 1
+
+                for createdObj in createdObjects:
+                    # Deselect All
+                    bpy.ops.object.select_all(action='DESELECT')
+
+                    # Select the object and delete it.
+                    createdObj.selected = True
+                    scene.objects.active = createdObj
+                    bpy.ops.object.delete()
+
+                # Delete the main object
+                # Deselect All
+                bpy.ops.object.select_all(action='DESELECT')
+
+                # Select the object and delete it.
+                mainObj.selected = True
+                scene.objects.active = mainObj
+
+                # Delete all material slots in mainObj object
+                for i in range(len(mainObj.material_slots)):
+                    mainObj.active_material_index = i - 1
+                    bpy.ops.object.material_slot_remove()
+
+                # Delete the Main Object
+                bpy.ops.object.delete()
+
+                # Select all of the left over boxes so people can immediately
+                # press generate again if they want.
+                for eachMember in cloudMembers:
+                    eachMember.max_draw_type = 'SOLID'
+                    eachMember.selected = True
+                    scene.objects.active = eachMember
+
+            else:
+                # Generate Cloud
+
+                ###############Create Combined Object bounds##################
+                # Make a list of all Selected objects.
+                selectedObjects = bpy.context.selected_objects
+
+                # Create a new object bounds
+                if len(selectedObjects) == 0:
+                    bounds = addNewObject(scene,
+                        "CloudBounds",
+                        [])
+
+                else:
+                    bounds = addNewObject(scene,
+                        "CloudBounds",
+                        selectedObjects[0])
+
+                bounds.max_draw_type = 'BOUNDS'
+                bounds.restrict_render = False
+
+                # Just add a Definition Property designating this
+                # as the main 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.max_draw_type = 'WIRE'
+                    selObj.restrict_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.max_draw_type = 'WIRE'
+                firstObject.restrict_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.max_draw_type = 'WIRE'
+                cloud.restrict_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.active_particle_system
+                cloudParticles.name = "CloudParticles"
+                cloudParticles.settings.start = 0
+                cloudParticles.settings.end = 0
+                cloudParticles.settings.emit_from = 'VOLUME'
+                cloudParticles.settings.draw_as = 'DOT'
+                cloudParticles.settings.ren_as = 'NONE'
+                cloudParticles.settings.normal_factor = 0
+                cloudParticles.settings.distribution = 'RAND'
+
+                ####################Create Volume Material####################
+                # Deselect All
+                bpy.ops.object.select_all(action='DESELECT')
+
+                # Select the object.
+                bounds.selected = True
+                scene.objects.active = bounds
+
+                # Turn bounds object into a box.
+                makeObjectIntoBoundBox(bounds, .2)
+
+                # 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 = main.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 = 1
+                mVolume.transmission_color = [3, 3, 3]
+                mVolume.step_size = 0.1
+                mVolume.light_cache = True
+                mVolume.cache_resolution = 75
+
+                # Add a texture
+                vMaterialTextureSlots = cloudMaterial.texture_slots
+                cloudtex = main.textures.new("CloudTex")
+                cloudMaterial.add_texture(cloudtex, 'ORCO')
+                cloudtex.type = 'CLOUDS'
+                cloudtex.noise_type = 'HARD_NOISE'
+                cloudtex.noise_size = 2
+
+                # Add a texture
+                cloudPointDensity = main.textures.new("CloudPointDensity")
+                cloudPointDensity.type = 'POINT_DENSITY'
+                cloudMaterial.add_texture(cloudPointDensity, 'ORCO')
+                pDensity = vMaterialTextureSlots[1].texture
+                vMaterialTextureSlots[1].map_density = True
+                vMaterialTextureSlots[1].rgb_to_intensity = True
+                vMaterialTextureSlots[1].texture_coordinates = 'GLOBAL'
+                pDensity.pointdensity.radius = pointDensityRadius
+                pDensity.pointdensity.vertices_cache = 'WORLD_SPACE'
+                pDensity.use_color_ramp = True
+                pRamp = pDensity.color_ramp
+                pRamp.interpolation = 'LINEAR'
+                pRampElements = pRamp.elements
+                #pRampElements[1].position = .9
+                #pRampElements[1].color = [.18,.18,.18,.8]
+
+                # Estimate the number of particles for the size of bounds.
+                numParticles = int(bounds.dimensions[0] * bounds.dimensions[1]
+                    * bounds.dimensions[2]) * numOfPoints
+                if numParticles > maxNumOfPoints:
+                    numParticles = maxNumOfPoints
+                print(numParticles)
+
+                # Set the number of particles according to the volume
+                # of bounds.
+                cloudParticles.settings.amount = numParticles
+
+                # Set time to 1.
+                scene.frame_current = 1
+
+                ###############Create CloudPnts for putting points in#########
+                # Create a new object cloudPnts
+                cloudPnts = addNewObject(scene, "CloudPoints", bounds)
+                cloudPnts["CloudMember"] = "CreatedObj"
+                cloudPnts.max_draw_type = 'WIRE'
+                cloudPnts.restrict_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_coordinates = 'OBJECT'
+                cldPntsModifiers[0].texture_coordinate_object = cloud
+                cldPntsModifiers[0].strength = -1.4
+
+                # Apply modifier
+                # Can't use bpy.ops.object.modifier_apply because poll fails.
+                cloudPnts.data = cloudPnts.create_mesh(scene,
+                    apply_modifiers=True,
+                    settings='PREVIEW')
+                cloudPnts.modifiers.remove(cldPntsModifiers[0])
+
+                pDensity.pointdensity.point_source = 'OBJECT'
+                pDensity.pointdensity.object = cloudPnts
+
+                # Deselect All
+                bpy.ops.object.select_all(action='DESELECT')
+
+                # Select the object.
+                cloud.selected = True
+                scene.objects.active = cloud
+
+                bpy.ops.object.particle_system_remove()
+
+                # Deselect All
+                bpy.ops.object.select_all(action='DESELECT')
+
+                # Select the object.
+                bounds.selected = True
+                scene.objects.active = bounds
+
+                # 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()
+                #bpy.ops.ptcache.bake_all(bake=False)
+
+            #self.report({'WARNING'}, "Generating Cloud")
+
+        return {'FINISHED'}
+
+bpy.types.register(GenerateCloud)
+
+if __name__ == "__main__":
+    bpy.ops.cloud.generate_cloud()