Blender V2.61 - r43446

object.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "device.h"
00020 #include "light.h"
00021 #include "mesh.h"
00022 #include "object.h"
00023 #include "scene.h"
00024 
00025 #include "util_foreach.h"
00026 #include "util_map.h"
00027 #include "util_progress.h"
00028 
00029 CCL_NAMESPACE_BEGIN
00030 
00031 /* Object */
00032 
00033 Object::Object()
00034 {
00035     name = "";
00036     mesh = NULL;
00037     tfm = transform_identity();
00038     visibility = ~0;
00039 }
00040 
00041 Object::~Object()
00042 {
00043 }
00044 
00045 void Object::compute_bounds()
00046 {
00047     bounds = mesh->bounds.transformed(&tfm);
00048 }
00049 
00050 void Object::apply_transform()
00051 {
00052     if(!mesh || tfm == transform_identity())
00053         return;
00054     
00055     for(size_t i = 0; i < mesh->verts.size(); i++)
00056         mesh->verts[i] = transform(&tfm, mesh->verts[i]);
00057 
00058     Attribute *attr_fN = mesh->attributes.find(Attribute::STD_FACE_NORMAL);
00059     Attribute *attr_vN = mesh->attributes.find(Attribute::STD_VERTEX_NORMAL);
00060 
00061     Transform ntfm = transform_transpose(transform_inverse(tfm));
00062 
00063     /* we keep normals pointing in same direction on negative scale, notify
00064        mesh about this in it (re)calculates normals */
00065     if(transform_negative_scale(tfm))
00066         mesh->transform_negative_scaled = true;
00067 
00068     if(attr_fN) {
00069         float3 *fN = attr_fN->data_float3();
00070 
00071         for(size_t i = 0; i < mesh->triangles.size(); i++)
00072             fN[i] = transform_direction(&ntfm, fN[i]);
00073     }
00074 
00075     if(attr_vN) {
00076         float3 *vN = attr_vN->data_float3();
00077 
00078         for(size_t i = 0; i < mesh->verts.size(); i++)
00079             vN[i] = transform_direction(&ntfm, vN[i]);
00080     }
00081 
00082     if(bounds.valid()) {
00083         mesh->compute_bounds();
00084         compute_bounds();
00085     }
00086     
00087     tfm = transform_identity();
00088 }
00089 
00090 void Object::tag_update(Scene *scene)
00091 {
00092     if(mesh) {
00093         if(mesh->transform_applied)
00094             mesh->need_update = true;
00095 
00096         foreach(uint sindex, mesh->used_shaders) {
00097             Shader *shader = scene->shaders[sindex];
00098 
00099             if(shader->sample_as_light && shader->has_surface_emission)
00100                 scene->light_manager->need_update = true;
00101         }
00102     }
00103 
00104     scene->mesh_manager->need_update = true;
00105     scene->object_manager->need_update = true;
00106 }
00107 
00108 /* Object Manager */
00109 
00110 ObjectManager::ObjectManager()
00111 {
00112     need_update = true;
00113 }
00114 
00115 ObjectManager::~ObjectManager()
00116 {
00117 }
00118 
00119 void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
00120 {
00121     float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
00122     int i = 0;
00123     map<Mesh*, float> surface_area_map;
00124 
00125     foreach(Object *ob, scene->objects) {
00126         Mesh *mesh = ob->mesh;
00127 
00128         /* compute transformations */
00129         Transform tfm = ob->tfm;
00130         Transform itfm = transform_inverse(tfm);
00131         Transform ntfm = transform_transpose(itfm);
00132 
00133         /* compute surface area. for uniform scale we can do avoid the many
00134            transform calls and share computation for instances */
00135         /* todo: correct for displacement, and move to a better place */
00136         float uniform_scale;
00137         float surface_area = 0.0f;
00138         
00139         if(transform_uniform_scale(tfm, uniform_scale)) {
00140             map<Mesh*, float>::iterator it = surface_area_map.find(mesh);
00141 
00142             if(it == surface_area_map.end()) {
00143                 foreach(Mesh::Triangle& t, mesh->triangles) {
00144                     float3 p1 = mesh->verts[t.v[0]];
00145                     float3 p2 = mesh->verts[t.v[1]];
00146                     float3 p3 = mesh->verts[t.v[2]];
00147 
00148                     surface_area += triangle_area(p1, p2, p3);
00149                 }
00150 
00151                 surface_area_map[mesh] = surface_area;
00152             }
00153             else
00154                 surface_area = it->second;
00155 
00156             surface_area *= uniform_scale;
00157         }
00158         else {
00159             foreach(Mesh::Triangle& t, mesh->triangles) {
00160                 float3 p1 = transform(&tfm, mesh->verts[t.v[0]]);
00161                 float3 p2 = transform(&tfm, mesh->verts[t.v[1]]);
00162                 float3 p3 = transform(&tfm, mesh->verts[t.v[2]]);
00163 
00164                 surface_area += triangle_area(p1, p2, p3);
00165             }
00166         }
00167 
00168         /* pack in texture */
00169         int offset = i*OBJECT_SIZE;
00170 
00171         memcpy(&objects[offset], &tfm, sizeof(float4)*4);
00172         memcpy(&objects[offset+4], &itfm, sizeof(float4)*4);
00173         memcpy(&objects[offset+8], &ntfm, sizeof(float4)*4);
00174         objects[offset+12] = make_float4(surface_area, 0.0f, 0.0f, 0.0f);
00175 
00176         i++;
00177 
00178         if(progress.get_cancel()) return;
00179     }
00180 
00181     device->tex_alloc("__objects", dscene->objects);
00182 }
00183 
00184 void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
00185 {
00186     if(!need_update)
00187         return;
00188     
00189     device_free(device, dscene);
00190 
00191     if(scene->objects.size() == 0)
00192         return;
00193 
00194     /* set object transform matrices, before applying static transforms */
00195     progress.set_status("Updating Objects", "Copying Transformations to device");
00196     device_update_transforms(device, dscene, scene, progress);
00197 
00198     if(progress.get_cancel()) return;
00199 
00200     /* prepare for static BVH building */
00201     /* todo: do before to support getting object level coords? */
00202     if(scene->params.bvh_type == SceneParams::BVH_STATIC) {
00203         progress.set_status("Updating Objects", "Applying Static Transformations");
00204         apply_static_transforms(scene, progress);
00205     }
00206 
00207     if(progress.get_cancel()) return;
00208 
00209     need_update = false;
00210 }
00211 
00212 void ObjectManager::device_free(Device *device, DeviceScene *dscene)
00213 {
00214     device->tex_free(dscene->objects);
00215     dscene->objects.clear();
00216 }
00217 
00218 void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress)
00219 {
00220     /* todo: normals and displacement should be done before applying transform! */
00221     /* todo: create objects/meshes in right order! */
00222 
00223     /* counter mesh users */
00224     map<Mesh*, int> mesh_users;
00225 
00226     foreach(Object *object, scene->objects) {
00227         map<Mesh*, int>::iterator it = mesh_users.find(object->mesh);
00228 
00229         if(it == mesh_users.end())
00230             mesh_users[object->mesh] = 1;
00231         else
00232             it->second++;
00233     }
00234 
00235     if(progress.get_cancel()) return;
00236 
00237     /* apply transforms for objects with single user meshes */
00238     foreach(Object *object, scene->objects) {
00239         if(mesh_users[object->mesh] == 1) {
00240             if(!object->mesh->transform_applied) {
00241                 object->apply_transform();
00242                 object->mesh->transform_applied = true;
00243             }
00244 
00245             if(progress.get_cancel()) return;
00246         }
00247     }
00248 }
00249 
00250 void ObjectManager::tag_update(Scene *scene)
00251 {
00252     need_update = true;
00253     scene->mesh_manager->need_update = true;
00254     scene->light_manager->need_update = true;
00255 }
00256 
00257 CCL_NAMESPACE_END
00258