void update_object_orientation(void) { static int mx = 0, my = 0, last_mouse_x = 0, last_mouse_y = 0; static int arcball = 0; IF_FAILED(init); if(!disable_mouse) { if(!arcball && input_get_mousebtn_state(MOUSE_LEFTBTN)) { arcball = 1; input_get_mouse_position(&mx, &my); last_mouse_x = mx; last_mouse_y = my; } else if(arcball && !input_get_mousebtn_state(MOUSE_LEFTBTN)) { arcball = 0; return; } if(arcball) { input_get_mouse_position(&mx, &my); if(mx < 0) mx = 0; else if(mx > window_width) mx = window_width; if(my < 0) my = 0; else if(my > window_height) my = window_height; if(last_mouse_x != mx || last_mouse_y != my) { // получаем вектора вращения виртуальной сферы vector3f v1 = compute_sphere_vector(last_mouse_x, last_mouse_y); vector3f v2 = compute_sphere_vector(mx, my); // угол вращения rot_angle = RAD_TO_DEG(math_acosf(math_min(1.0f, vec3f_dot(v1, v2)))); matrix3f rotmat3, model3, rotmodel3; mat4_submat(rotmat3, 3, 3, rotmat); mat4_submat(model3, 3, 3, modelmat); mat3_mult2(rotmodel3, rotmat3, model3); // получаем ось вращения (переводим её в систему координат объекта) rot_axis = mat3_mult_vec3(rotmodel3, vec3f_norm(vec3f_cross(v1, v2))); // домножаем матрицу вращения mat4_rotate_axis_mult(rotmat, rot_angle, rot_axis); last_mouse_x = mx; last_mouse_y = my; } } } }
float perlin_noise_3d(vector3f pos) { int x = math_fast_floorf(pos.x); int y = math_fast_floorf(pos.y); int z = math_fast_floorf(pos.z); pos.x -= x; pos.y -= y; pos.z -= z; x &= 255; y &= 255; z &= 255; float u = fade(pos.x), v = fade(pos.y), w = fade(pos.z); int gi000 = perm[ x + perm[ y + perm[z] ] ] % 12; int gi001 = perm[ x + perm[ y + perm[z + 1] ] ] % 12; int gi010 = perm[ x + perm[ y + 1 + perm[z] ] ] % 12; int gi011 = perm[ x + perm[ y + 1 + perm[z + 1] ] ] % 12; int gi100 = perm[ x + 1 + perm[ y + perm[z] ] ] % 12; int gi101 = perm[ x + 1 + perm[ y + perm[z + 1] ] ] % 12; int gi110 = perm[ x + 1 + perm[ y + 1 + perm[z] ] ] % 12; int gi111 = perm[ x + 1 + perm[ y + 1 + perm[z + 1] ] ] % 12; float n000 = vec3f_dot(grad3[gi000], vec3f(pos.x, pos.y, pos.z)); float n100 = vec3f_dot(grad3[gi100], vec3f(pos.x - 1.0f, pos.y, pos.z)); float n010 = vec3f_dot(grad3[gi010], vec3f(pos.x, pos.y - 1.0f, pos.z)); float n110 = vec3f_dot(grad3[gi110], vec3f(pos.x - 1.0f, pos.y - 1.0f, pos.z)); float n001 = vec3f_dot(grad3[gi001], vec3f(pos.x, pos.y, pos.z - 1.0f)); float n101 = vec3f_dot(grad3[gi101], vec3f(pos.x - 1.0f, pos.y, pos.z - 1.0f)); float n011 = vec3f_dot(grad3[gi011], vec3f(pos.x, pos.y - 1.0f, pos.z - 1.0f)); float n111 = vec3f_dot(grad3[gi111], vec3f(pos.x - 1.0f, pos.y - 1.0f, pos.z - 1.0f)); float nx00 = math_mix(n000, n100, u); float nx01 = math_mix(n001, n101, u); float nx10 = math_mix(n010, n110, u); float nx11 = math_mix(n011, n111, u); float nxy0 = math_mix(nx00, nx10, v); float nxy1 = math_mix(nx01, nx11, v); float nxyz = math_mix(nxy0, nxy1, w); return nxyz; }
/** * Apply an infinitesimal rotation w*dt to a direction cosine matrix A. * An orthonormalization step is added to prevent rounding errors. * * Without the normalization, this would be a simple matrix multiplication: * * return mat3_matmul( A, (mat3f) { * 1, -w.z, w.y, * w.z, 1, -w.x, * -w.y, w.x, 1 * }; */ static mat3f dcm_integrate(mat3f A, vec3f w, float dt) { w = vec3f_scale(w, dt); // Calculate the new x and y axes. z is calculated later. // vec3f x = vec3f_matmul(A, (vec3f){ 1, w.z, -w.y } ); vec3f y = vec3f_matmul(A, (vec3f){ -w.z, 1, w.x } ); // Orthonormalization // // First we compute the dot product of the x and y rows of the matrix, which // is supposed to be zero, so the result is a measure of how much the X and Y // rows are rotating toward each other // float error = vec3f_dot(x, y); // We apportion half of the error each to the x and y rows, and approximately // rotate the X and Y rows in the opposite direction by cross coupling: // vec3f xo, yo, zo; xo = vec3f_sub(x, vec3f_scale(y, 0.5 * error)); yo = vec3f_sub(y, vec3f_scale(x, 0.5 * error)); // Scale them to unit length and take a cross product for the Z axis // xo = vec3f_norm(xo); yo = vec3f_norm(yo); zo = vec3f_cross(xo, yo); return (mat3f) { xo.x, yo.x, zo.x, xo.y, yo.y, zo.y, xo.z, yo.z, zo.z }; }
float simplex_noise_3d(vector3f pos) { const float F3 = 1.0f / 3.0f; const float G3 = 1.0f / 6.0f; float s = (pos.x + pos.y + pos.z) * F3; int i = math_fast_floorf(pos.x + s); int j = math_fast_floorf(pos.y + s); int k = math_fast_floorf(pos.z + s); float t = (i + j + k) * G3; float X0 = i - t; float Y0 = j - t; float Z0 = k - t; float x0 = pos.x - X0; float y0 = pos.y - Y0; float z0 = pos.z - Z0; int i1, i2, j1, j2, k1, k2; if(x0 >= y0) { if(y0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } else if(x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } } else { if(y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; } else if(x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; } else { i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } } float x1 = x0 - i1 + G3; float y1 = y0 - j1 + G3; float z1 = z0 - k1 + G3; float x2 = x0 - i2 + 2.0f * G3; float y2 = y0 - j2 + 2.0f * G3; float z2 = z0 - k2 + 2.0f * G3; float x3 = x0 - 1.0f + 3.0f * G3; float y3 = y0 - 1.0f + 3.0f * G3; float z3 = z0 - 1.0f + 3.0f * G3; int ii = i & 255; int jj = j & 255; int kk = k & 255; int gi0 = perm[ii + perm[jj + perm[kk ]]] % 12; int gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]] % 12; int gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]] % 12; int gi3 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1 ]]] % 12; float n0 = 0.0f, n1 = 0.0f, n2 = 0.0f, n3 = 0.0f; float t0 = 0.6f - x0*x0 - y0*y0 - z0*z0; if(t0 < 0.0f) { n0 = 0.0f; } else { t0 *= t0; n0 = t0 * t0 * vec3f_dot(grad3[gi0], vec3f(x0, y0, z0)); } float t1 = 0.6f - x1*x1 - y1*y1 - z1*z1; if(t1 < 0.0f) { n1 = 0.0f; } else { t1 *= t1; n1 = t1 * t1 * vec3f_dot(grad3[gi1], vec3f(x1, y1, z1)); } float t2 = 0.6f - x2*x2 - y2*y2 - z2*z2; if(t2 < 0.0f) { n2 = 0.0f; } else { t2 *= t2; n2 = t2 * t2 * vec3f_dot(grad3[gi2], vec3f(x2, y2, z2)); } float t3 = 0.6f - x3*x3 - y3*y3 - z3*z3; if(t3 < 0.0f) { n3 = 0.0f; } else { t3 *= t3; n3 = t3 * t3 * vec3f_dot(grad3[gi3], vec3f(x3, y3, z3)); } return 32.0f * (n0 + n1 + n2 + n3); //return 16.0f * (n0 + n1 + n2 + n3) + 1.0f; }