Blender V2.61 - r43446
|
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