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 00021 #include "mesh.h" 00022 #include "scene.h" 00023 #include "shader.h" 00024 00025 #include "util_foreach.h" 00026 #include "util_progress.h" 00027 00028 CCL_NAMESPACE_BEGIN 00029 00030 bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& progress) 00031 { 00032 /* verify if we have a displacement shader */ 00033 bool has_displacement = false; 00034 00035 if(mesh->displacement_method != Mesh::DISPLACE_BUMP) { 00036 foreach(uint sindex, mesh->used_shaders) 00037 if(scene->shaders[sindex]->has_displacement) 00038 has_displacement = true; 00039 } 00040 00041 if(!has_displacement) 00042 return false; 00043 00044 /* setup input for device task */ 00045 vector<bool> done(mesh->verts.size(), false); 00046 device_vector<uint4> d_input; 00047 uint4 *d_input_data = d_input.resize(mesh->verts.size()); 00048 size_t d_input_offset = 0; 00049 00050 for(size_t i = 0; i < mesh->triangles.size(); i++) { 00051 Mesh::Triangle t = mesh->triangles[i]; 00052 Shader *shader = scene->shaders[mesh->shader[i]]; 00053 00054 if(!shader->has_displacement) 00055 continue; 00056 00057 for(int j = 0; j < 3; j++) { 00058 if(done[t.v[j]]) 00059 continue; 00060 00061 done[t.v[j]] = true; 00062 00063 /* set up object, primitive and barycentric coordinates */ 00064 /* when used, non-instanced convention: object = -object-1; */ 00065 int object = ~0; /* todo */ 00066 int prim = mesh->tri_offset + i; 00067 float u, v; 00068 00069 if(j == 0) { 00070 u = 1.0f; 00071 v = 0.0f; 00072 } 00073 else if(j == 1) { 00074 u = 0.0f; 00075 v = 1.0f; 00076 } 00077 else { 00078 u = 0.0f; 00079 v = 0.0f; 00080 } 00081 00082 /* back */ 00083 uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v)); 00084 d_input_data[d_input_offset++] = in; 00085 } 00086 } 00087 00088 if(d_input_offset == 0) 00089 return false; 00090 00091 /* run device task */ 00092 device_vector<float3> d_output; 00093 d_output.resize(d_input.size()); 00094 00095 device->mem_alloc(d_input, MEM_READ_ONLY); 00096 device->mem_copy_to(d_input); 00097 device->mem_alloc(d_output, MEM_WRITE_ONLY); 00098 00099 DeviceTask task(DeviceTask::SHADER); 00100 task.shader_input = d_input.device_pointer; 00101 task.shader_output = d_output.device_pointer; 00102 task.shader_eval_type = SHADER_EVAL_DISPLACE; 00103 task.shader_x = 0; 00104 task.shader_w = d_input.size(); 00105 00106 device->task_add(task); 00107 device->task_wait(); 00108 00109 device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float3)); 00110 device->mem_free(d_input); 00111 device->mem_free(d_output); 00112 00113 if(progress.get_cancel()) 00114 return false; 00115 00116 /* read result */ 00117 done.clear(); 00118 done.resize(mesh->verts.size(), false); 00119 int k = 0; 00120 00121 float3 *offset = (float3*)d_output.data_pointer; 00122 00123 for(size_t i = 0; i < mesh->triangles.size(); i++) { 00124 Mesh::Triangle t = mesh->triangles[i]; 00125 Shader *shader = scene->shaders[mesh->shader[i]]; 00126 00127 if(!shader->has_displacement) 00128 continue; 00129 00130 for(int j = 0; j < 3; j++) { 00131 if(!done[t.v[j]]) { 00132 done[t.v[j]] = true; 00133 mesh->verts[t.v[j]] += offset[k++]; 00134 } 00135 } 00136 } 00137 00138 /* for displacement method both, we only need to recompute the face 00139 * normals, as bump mapping in the shader will already alter the 00140 * vertex normal, so we start from the non-displaced vertex normals 00141 * to avoid applying the perturbation twice. */ 00142 mesh->attributes.remove(Attribute::STD_FACE_NORMAL); 00143 mesh->add_face_normals(); 00144 00145 if(mesh->displacement_method == Mesh::DISPLACE_TRUE) { 00146 mesh->attributes.remove(Attribute::STD_VERTEX_NORMAL); 00147 mesh->add_vertex_normals(); 00148 } 00149 00150 return true; 00151 } 00152 00153 CCL_NAMESPACE_END 00154