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 #ifndef __UTIL_TRANSFORM_H__ 00020 #define __UTIL_TRANSFORM_H__ 00021 00022 #ifndef __KERNEL_GPU__ 00023 #include <string.h> 00024 #endif 00025 00026 #include "util_math.h" 00027 #include "util_types.h" 00028 00029 CCL_NAMESPACE_BEGIN 00030 00031 typedef struct Transform { 00032 float4 x, y, z, w; /* rows */ 00033 00034 #ifndef __KERNEL_GPU__ 00035 float4 operator[](int i) const { return *(&x + i); } 00036 float4& operator[](int i) { return *(&x + i); } 00037 #endif 00038 } Transform; 00039 00040 __device_inline float3 transform(const Transform *t, const float3 a) 00041 { 00042 float4 b = make_float4(a.x, a.y, a.z, 1.0f); 00043 float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b)); 00044 float w = dot(t->w, b); 00045 00046 return (w != 0.0f)? c/w: make_float3(0.0f, 0.0f, 0.0f); 00047 } 00048 00049 __device_inline float3 transform_direction(const Transform *t, const float3 a) 00050 { 00051 float4 b = make_float4(a.x, a.y, a.z, 0.0f); 00052 float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b)); 00053 00054 return c; 00055 } 00056 00057 #ifndef __KERNEL_GPU__ 00058 00059 __device_inline void print_transform(const char *label, const Transform& t) 00060 { 00061 print_float4(label, t.x); 00062 print_float4(label, t.y); 00063 print_float4(label, t.z); 00064 print_float4(label, t.w); 00065 printf("\n"); 00066 } 00067 00068 __device_inline Transform transform_transpose(const Transform a) 00069 { 00070 Transform t; 00071 00072 t.x.x = a.x.x; t.x.y = a.y.x; t.x.z = a.z.x; t.x.w = a.w.x; 00073 t.y.x = a.x.y; t.y.y = a.y.y; t.y.z = a.z.y; t.y.w = a.w.y; 00074 t.z.x = a.x.z; t.z.y = a.y.z; t.z.z = a.z.z; t.z.w = a.w.z; 00075 t.w.x = a.x.w; t.w.y = a.y.w; t.w.z = a.z.w; t.w.w = a.w.w; 00076 00077 return t; 00078 } 00079 00080 __device_inline Transform operator*(const Transform a, const Transform b) 00081 { 00082 Transform c = transform_transpose(b); 00083 Transform t; 00084 00085 t.x = make_float4(dot(a.x, c.x), dot(a.x, c.y), dot(a.x, c.z), dot(a.x, c.w)); 00086 t.y = make_float4(dot(a.y, c.x), dot(a.y, c.y), dot(a.y, c.z), dot(a.y, c.w)); 00087 t.z = make_float4(dot(a.z, c.x), dot(a.z, c.y), dot(a.z, c.z), dot(a.z, c.w)); 00088 t.w = make_float4(dot(a.w, c.x), dot(a.w, c.y), dot(a.w, c.z), dot(a.w, c.w)); 00089 00090 return t; 00091 } 00092 00093 __device_inline Transform make_transform(float a, float b, float c, float d, 00094 float e, float f, float g, float h, 00095 float i, float j, float k, float l, 00096 float m, float n, float o, float p) 00097 { 00098 Transform t; 00099 00100 t.x.x = a; t.x.y = b; t.x.z = c; t.x.w = d; 00101 t.y.x = e; t.y.y = f; t.y.z = g; t.y.w = h; 00102 t.z.x = i; t.z.y = j; t.z.z = k; t.z.w = l; 00103 t.w.x = m; t.w.y = n; t.w.z = o; t.w.w = p; 00104 00105 return t; 00106 } 00107 00108 __device_inline Transform transform_translate(float3 t) 00109 { 00110 return make_transform( 00111 1, 0, 0, t.x, 00112 0, 1, 0, t.y, 00113 0, 0, 1, t.z, 00114 0, 0, 0, 1); 00115 } 00116 00117 __device_inline Transform transform_translate(float x, float y, float z) 00118 { 00119 return transform_translate(make_float3(x, y, z)); 00120 } 00121 00122 __device_inline Transform transform_scale(float3 s) 00123 { 00124 return make_transform( 00125 s.x, 0, 0, 0, 00126 0, s.y, 0, 0, 00127 0, 0, s.z, 0, 00128 0, 0, 0, 1); 00129 } 00130 00131 __device_inline Transform transform_scale(float x, float y, float z) 00132 { 00133 return transform_scale(make_float3(x, y, z)); 00134 } 00135 00136 __device_inline Transform transform_perspective(float fov, float n, float f) 00137 { 00138 Transform persp = make_transform( 00139 1, 0, 0, 0, 00140 0, 1, 0, 0, 00141 0, 0, f / (f - n), -f*n / (f - n), 00142 0, 0, 1, 0); 00143 00144 float inv_angle = 1.0f/tanf(0.5f*fov); 00145 00146 Transform scale = transform_scale(inv_angle, inv_angle, 1); 00147 00148 return scale * persp; 00149 } 00150 00151 __device_inline Transform transform_rotate(float angle, float3 axis) 00152 { 00153 float s = sinf(angle); 00154 float c = cosf(angle); 00155 float t = 1.f - c; 00156 00157 axis = normalize(axis); 00158 00159 return make_transform( 00160 axis.x*axis.x*t + c, 00161 axis.x*axis.y*t - s*axis.z, 00162 axis.x*axis.z*t + s*axis.y, 00163 0.0f, 00164 00165 axis.y*axis.x*t + s*axis.z, 00166 axis.y*axis.y*t + c, 00167 axis.y*axis.z*t - s*axis.x, 00168 0.0f, 00169 00170 axis.z*axis.x*t - s*axis.y, 00171 axis.z*axis.y*t + s*axis.x, 00172 axis.z*axis.z*t + c, 00173 0.0f, 00174 00175 0.0f, 0.0f, 0.0f, 1.0f); 00176 } 00177 00178 __device_inline Transform transform_euler(float3 euler) 00179 { 00180 return 00181 transform_rotate(euler.x, make_float3(1.0f, 0.0f, 0.0f)) * 00182 transform_rotate(euler.y, make_float3(0.0f, 1.0f, 0.0f)) * 00183 transform_rotate(euler.z, make_float3(0.0f, 0.0f, 1.0f)); 00184 } 00185 00186 __device_inline Transform transform_orthographic(float znear, float zfar) 00187 { 00188 return transform_scale(1.0f, 1.0f, 1.0f / (zfar-znear)) * 00189 transform_translate(0.0f, 0.0f, -znear); 00190 } 00191 00192 __device_inline Transform transform_identity() 00193 { 00194 return transform_scale(1.0f, 1.0f, 1.0f); 00195 } 00196 00197 __device_inline bool operator==(const Transform& A, const Transform& B) 00198 { 00199 return memcmp(&A, &B, sizeof(Transform)) == 0; 00200 } 00201 00202 __device_inline bool operator!=(const Transform& A, const Transform& B) 00203 { 00204 return !(A == B); 00205 } 00206 00207 __device_inline float3 transform_get_column(const Transform *t, int column) 00208 { 00209 return make_float3(t->x[column], t->y[column], t->z[column]); 00210 } 00211 00212 __device_inline void transform_set_column(Transform *t, int column, float3 value) 00213 { 00214 t->x[column] = value.x; 00215 t->y[column] = value.y; 00216 t->z[column] = value.z; 00217 } 00218 00219 Transform transform_inverse(const Transform& a); 00220 00221 __device_inline bool transform_uniform_scale(const Transform& tfm, float& scale) 00222 { 00223 /* the epsilon here is quite arbitrary, but this function is only used for 00224 surface area and bump, where we except it to not be so sensitive */ 00225 Transform ttfm = transform_transpose(tfm); 00226 float eps = 1e-7f; 00227 00228 float sx = len(float4_to_float3(tfm.x)); 00229 float sy = len(float4_to_float3(tfm.y)); 00230 float sz = len(float4_to_float3(tfm.z)); 00231 float stx = len(float4_to_float3(ttfm.x)); 00232 float sty = len(float4_to_float3(ttfm.y)); 00233 float stz = len(float4_to_float3(ttfm.z)); 00234 00235 if(fabsf(sx - sy) < eps && fabsf(sx - sz) < eps && 00236 fabsf(sx - stx) < eps && fabsf(sx - sty) < eps && 00237 fabsf(sx - stz) < eps) { 00238 scale = sx; 00239 return true; 00240 } 00241 00242 return false; 00243 } 00244 00245 __device_inline bool transform_negative_scale(const Transform& tfm) 00246 { 00247 float3 c0 = transform_get_column(&tfm, 0); 00248 float3 c1 = transform_get_column(&tfm, 1); 00249 float3 c2 = transform_get_column(&tfm, 2); 00250 00251 return (dot(cross(c0, c1), c2) < 0.0f); 00252 } 00253 00254 __device_inline Transform transform_clear_scale(const Transform& tfm) 00255 { 00256 Transform ntfm = tfm; 00257 00258 transform_set_column(&ntfm, 0, normalize(transform_get_column(&ntfm, 0))); 00259 transform_set_column(&ntfm, 1, normalize(transform_get_column(&ntfm, 1))); 00260 transform_set_column(&ntfm, 2, normalize(transform_get_column(&ntfm, 2))); 00261 00262 return ntfm; 00263 } 00264 00265 #endif 00266 00267 CCL_NAMESPACE_END 00268 00269 #endif /* __UTIL_TRANSFORM_H__ */ 00270