/** * Called every time the cursor moves. It is used to calculate the Camera's direction * in window - the window holding the cursor * in xpos - the xposition of the cursor on the screen * in ypos - the yposition of the curose on the screen */ static void cursor_position_callback(GLFWwindow *window, double xpos, double ypos) { GLfloat quat[] = {0.0f,0.0f,0.0f,0.0f}; //calculate pitch static double previous_ypos = ypos; double position_y_difference = ypos - previous_ypos; previous_ypos = ypos; //calculate yaw static double previous_xpos = xpos; double position_x_difference = xpos - previous_xpos; previous_xpos = xpos; //reduce signal camera.yaw += position_x_difference *camera.signal_amplifier; camera.pitch += position_y_difference *camera.signal_amplifier; //calculate rotation sequence create_versor(quat, camera.pitch, 1.0f, 0.0f, 0.0f); quat_to_mat4(camera.Rpitch.m, quat); create_versor(quat, camera.yaw, 0.0f, 1.0f, 0.0f); quat_to_mat4(camera.Ryaw.m,quat); // mult_quat_quat(camera.resultQuat, camera.quatYaw, camera.quatPitch); // mult_quat_quat(camera.resultQuat, camera.quatYaw, camera.quatPitch); // quat_to_mat4(camera.R.m, camera.resultQuat); }
static void calculateCursorRotations(Cursor *cursor){ GLfloat quat[] = {0.0f,0.0f,0.0f,0.0f}; create_versor(quat, cursor->pitch, 1.0f, 0.0f, 0.0f); quat_to_mat4(cursor->Rpitch.m, quat); create_versor(quat, cursor->yaw, 0.0f, 1.0f, 0.0f); quat_to_mat4(cursor->Ryaw.m, quat); create_versor(quat, cursor->roll, 0.0f, 0.0f, 1.0f); quat_to_mat4(cursor->Rroll.m, quat); }
/* Sync rigid body and object transformations */ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) { RigidBodyOb *rbo = ob->rigidbody_object; /* keep original transform for kinematic and passive objects */ if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE) return; /* use rigid body transform after cache start frame if objects is not being transformed */ if (BKE_rigidbody_check_sim_running(rbw, ctime) && !(ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) { float mat[4][4], size_mat[4][4], size[3]; normalize_qt(rbo->orn); // RB_TODO investigate why quaternion isn't normalized at this point quat_to_mat4(mat, rbo->orn); copy_v3_v3(mat[3], rbo->pos); mat4_to_size(size, ob->obmat); size_to_mat4(size_mat, size); mul_m4_m4m4(mat, mat, size_mat); copy_m4_m4(ob->obmat, mat); } /* otherwise set rigid body transform to current obmat */ else { mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat); } }
GLCamera::GLCamera(float aspect) { near = 0.1f; far = 100.0f; fovy = 67.0f; //aspect = (float)g_gl_width / (float)g_gl_height; this->aspect = aspect; proj_mat = perspective(fovy, this->aspect, near, far); cam_speed = 5.0f; cam_heading_speed = 100.0f; cam_heading = 0.0f; cam_pos = vector3(0.0f, 0.0f, 5.0f); T = identity_mat4().translate( vector3(-cam_pos.v[0], -cam_pos.v[1], -cam_pos.v[2]) ); create_versor(quaternion, -cam_heading, 0.0f, 1.0f, 0.0f); quat_to_mat4(R.m, quaternion); // combine the inverse rotation and transformation to make a view matrix view_mat = R * T; // keep track of some useful vectors that can be used for keyboard movement fwd = vector4(0.0f, 0.0f, -1.0f, 0.0f); rgt = vector4(1.0f, 0.0f, 0.0f, 0.0f); up = vector4(0.0f, 1.0f, 0.0f, 0.0f); cam_yaw = 0.0f; // y-rotation in degrees cam_pitch = 0.0f; cam_roll = 0.0; }
Camera::Camera(int view_mat_location, int proj_mat_location) { this->view_mat_location = view_mat_location; this->proj_mat_location = proj_mat_location; cam_pos = vec3 (0.0f, 0.0f, 5.0f); near = 0.1f; // clipping plane far = 100.0f; // clipping plane fovy = 67.0f; // 67 degrees // aspect ratio aspect = (float)g_gl_width / (float)g_gl_height; proj_mat = perspective (fovy, aspect, near, far); cam_speed = 5.0f; // 1 unit per second cam_heading_speed = 100.0f; // 30 degrees per second cam_heading = 0.0f; // y-rotation in degrees T = translate ( identity_mat4 (), vec3 (-cam_pos.v[0], -cam_pos.v[1], -cam_pos.v[2]) ); create_versor (quaternion, -cam_heading, 0.0f, 1.0f, 0.0f); // convert the quaternion to a rotation matrix (just an array of 16 floats) quat_to_mat4 (R.m, quaternion); // combine the inverse rotation and transformation to make a view matrix view_mat = R * T; fwd = FORWARD; rgt = RIGHT; up = UP; set_view(); set_proj(); reset_control(); }
void skyUpdate(Skybox *sky){ //calculate new sky ngle GLfloat quat[] = {0.0f,0.0f,0.0f,0.0f}; sky->angle += 0.002f; if (sky->angle> 359) sky->angle= 0; create_versor(quat, sky->angle, 0.0f, 1.0f, 0.0f); quat_to_mat4(sky->modelMatrix.m, quat); }
/* don't set windows active in here, is used by renderwin too */ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d) { if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ if (v3d->camera) { BKE_object_where_is_calc(scene, v3d->camera); obmat_to_viewmat(v3d, rv3d, v3d->camera, 0); } else { quat_to_mat4(rv3d->viewmat, rv3d->viewquat); rv3d->viewmat[3][2] -= rv3d->dist; } } else { /* should be moved to better initialize later on XXX */ if (rv3d->viewlock) ED_view3d_lock(rv3d); quat_to_mat4(rv3d->viewmat, rv3d->viewquat); if (rv3d->persp == RV3D_PERSP) rv3d->viewmat[3][2] -= rv3d->dist; if (v3d->ob_centre) { Object *ob = v3d->ob_centre; float vec[3]; copy_v3_v3(vec, ob->obmat[3]); if (ob->type == OB_ARMATURE && v3d->ob_centre_bone[0]) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, v3d->ob_centre_bone); if (pchan) { copy_v3_v3(vec, pchan->pose_mat[3]); mul_m4_v3(ob->obmat, vec); } } translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); } else if (v3d->ob_centre_cursor) { float vec[3]; copy_v3_v3(vec, give_cursor(scene, v3d)); translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); } else { translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]); } } }
void GLCamera::movePitchDown(double elapsed_seconds) { cam_pitch -= cam_heading_speed * elapsed_seconds; float q_pitch[16]; create_versor(q_pitch, cam_pitch, rgt.v[0], rgt.v[1], rgt.v[2]); mult_quat_quat(quaternion, q_pitch, quaternion); // recalc axes to suit new orientation quat_to_mat4(R.m, quaternion); fwd = R * vector4(0.0, 0.0, -1.0, 0.0); rgt = R * vector4(1.0, 0.0, 0.0, 0.0); up = R * vector4(0.0, 1.0, 0.0, 0.0); }
void GLCamera::rollRight(double elapsed_seconds) { cam_roll += cam_heading_speed * elapsed_seconds; float q_roll[16]; create_versor(q_roll, cam_roll, fwd.v[0], fwd.v[1], fwd.v[2]); mult_quat_quat(quaternion, q_roll, quaternion); // recalc axes to suit new orientation quat_to_mat4(R.m, quaternion); fwd = R * vector4(0.0, 0.0, -1.0, 0.0); rgt = R * vector4(1.0, 0.0, 0.0, 0.0); up = R * vector4(0.0, 1.0, 0.0, 0.0); }
void display_render_io_process(struct s_vm* vm, t_display* display) { t_v4 color_io_process; t_v4 color_ambient; t_v3 light_direction; t_mat4 local; t_mat4 translate; t_mat4 rotation; t_quat quat; int i; v4_set(&color_io_process, 0.4f, 0.4f, 1.0f, 0.0f); v4_set(&color_ambient, 0.2f, 0.2f, 0.2f, 1.0f); v3_set(&light_direction, 0, 0, -1.0f); display_mesh_render_start(display->mesh_renderer, MESH_TYPE_VN); display_mesh_set_ambient(display->mesh_renderer, &color_ambient); display_mesh_set_light_direction(display->mesh_renderer, &light_direction); display_mesh_set_diffuse(display->mesh_renderer, &color_io_process); display_mesh_set_projection(display->mesh_renderer, &display->projection_view); mat4_ident(&local); for (i = 0; i < vm->process_count; ++i) { t_process* process = vm->processes[i]; float angle = (float)process->cycle_create + (float)display->frame_last_time ; int index = process->pc; float x = (float) (index % display->memory_stride); float y = (float) (index / display->memory_stride); x = x * DISPLAY_CELL_SIZE + DISPLAY_CELL_SIZE * 0.5f; y = y * DISPLAY_CELL_SIZE + DISPLAY_CELL_SIZE * 0.5f; mat4_ident(&translate); mat4_translate(&translate, x, y, DISPLAY_CELL_SIZE * 0.5f); quat_from_euler(&quat, angle, angle, angle); quat_to_mat4(&quat, &rotation); mat4_mul(&translate, &rotation, &local); display_mesh_set_local(display->mesh_renderer, &local); display_mesh_render(display->process_mesh); } }
void GLCamera::moveYawLeft(double elapsed_seconds) { cam_yaw += getHeadingSpeed() * elapsed_seconds; // create a quaternion representing change in heading (the yaw) float q_yaw[16]; create_versor(q_yaw, cam_yaw, up.v[0], up.v[1], up.v[2]); // add yaw rotation to the camera's current orientation mult_quat_quat(quaternion, q_yaw, quaternion); // recalc axes to suit new orientation quat_to_mat4(R.m, quaternion); fwd = R * vector4(0.0, 0.0, -1.0, 0.0); rgt = R * vector4(1.0, 0.0, 0.0, 0.0); up = R * vector4(0.0, 1.0, 0.0, 0.0); }
void Camera::update() { // update view matrix if (cam_moved) { quat_to_mat4 (R.m, quaternion); // checking for fp errors // printf ("dot fwd . up %f\n", dot (fwd, up)); // printf ("dot rgt . up %f\n", dot (rgt, up)); // printf ("dot fwd . rgt\n %f", dot (fwd, rgt)); cam_pos += vec3 (fwd) * -move.v[2]; cam_pos += vec3 (up) * move.v[1]; cam_pos += vec3 (rgt) * move.v[0]; T = translate (identity_mat4 (), vec3 (cam_pos)); view_mat = inverse (R) * inverse (T); set_view(); } }
void GLCamera::setPosition(vector3 pos) { this->cam_pos = pos; T = identity_mat4().translate(vector3(-cam_pos.v[0], -cam_pos.v[1], -cam_pos.v[2])); T = identity_mat4().translate( vector3(-cam_pos.v[0], -cam_pos.v[1], -cam_pos.v[2]) ); create_versor(quaternion, -cam_heading, 0.0f, 1.0f, 0.0f); quat_to_mat4(R.m, quaternion); // combine the inverse rotation and transformation to make a view matrix view_mat = R * T; // keep track of some useful vectors that can be used for keyboard movement fwd = vector4(0.0f, 0.0f, -1.0f, 0.0f); rgt = vector4(1.0f, 0.0f, 0.0f, 0.0f); up = vector4(0.0f, 1.0f, 0.0f, 0.0f); cam_yaw = 0.0f; // y-rotation in degrees cam_pitch = 0.0f; cam_roll = 0.0; }
void GLCamera::updatePosition(vector3 move) { quat_to_mat4(R.m, quaternion); // checking for fp errors // printf ("dot fwd . up %f\n", dot (fwd, up)); // printf ("dot rgt . up %f\n", dot (rgt, up)); // printf ("dot fwd . rgt\n %f", dot (fwd, rgt)); cam_pos = cam_pos + vector3(fwd) * -move.v[2]; cam_pos = cam_pos + vector3(up) * move.v[1]; cam_pos = cam_pos + vector3(rgt) * move.v[0]; matriz4x4 T = identity_mat4().translate(vector3(cam_pos)); view_mat = R.inverse() * T.inverse(); cam_yaw = 0.0f; cam_pitch = 0.0f; cam_roll = 0.0; }
void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm) { int i; mat4_t rmat; vec3_t pos, scale; quat_t rot; pos = anm_get_node_position(node, tm); rot = anm_get_node_rotation(node, tm); scale = anm_get_node_scaling(node, tm); m4_set_translation(mat, node->pivot.x, node->pivot.y, node->pivot.z); quat_to_mat4(rmat, rot); for(i=0; i<3; i++) { mat[i][0] = rmat[i][0]; mat[i][1] = rmat[i][1]; mat[i][2] = rmat[i][2]; } /* this loop is equivalent to: m4_mult(mat, mat, rmat); */ mat[0][0] *= scale.x; mat[0][1] *= scale.y; mat[0][2] *= scale.z; mat[0][3] += pos.x; mat[1][0] *= scale.x; mat[1][1] *= scale.y; mat[1][2] *= scale.z; mat[1][3] += pos.y; mat[2][0] *= scale.x; mat[2][1] *= scale.y; mat[2][2] *= scale.z; mat[2][3] += pos.z; m4_translate(mat, -node->pivot.x, -node->pivot.y, -node->pivot.z); /* that's basically: pivot * rotation * translation * scaling * -pivot */ }
int main () { // start GL context and O/S window using the GLFW helper library if (!glfwInit ()) { fprintf (stderr, "ERROR: could not start GLFW3\n"); return 1; } // uncomment these lines if on Apple OS X glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* window = glfwCreateWindow (640, 480, "Cube to Sphere", NULL, NULL); if (!window) { fprintf (stderr, "ERROR: could not open window with GLFW3\n"); glfwTerminate(); return 1; } GLFWwindow* window2 = glfwCreateWindow (640, 480, "Just checking", NULL, NULL); if (!window2) { fprintf (stderr, "ERROR: could not open window with GLFW3\n"); glfwTerminate(); return 1; } glfwMakeContextCurrent (window); //start GLEW extension handler glewExperimental = GL_TRUE; glewInit (); // get version info const GLubyte* renderer = glGetString (GL_RENDERER); // get renderer string const GLubyte* version = glGetString (GL_VERSION); // version as a string printf ("Renderer: %s\n", renderer); printf ("OpenGL version supported %s\n", version); //CLGLUtils::init(); boost::compute::context context; try { context = boost::compute::opengl_create_shared_context(); } catch (std::exception e) { std::cerr<<"Failed to initialize a CLGL context"<<e.what()<<std::endl; exit(0); } // tell GL to only draw onto a pixel if the shape is closer to the viewer glEnable (GL_DEPTH_TEST); // enable depth-testing glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" // OTHER STUFF GOES HERE NEXT float points[] = { -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; GLuint vbo; glGenBuffers (1, &vbo); glBindBuffer (GL_ARRAY_BUFFER, vbo); glBufferData (GL_ARRAY_BUFFER, 3 * 36 * sizeof (float), &points, GL_STATIC_DRAW); GLuint vao; glGenVertexArrays (1, &vao); glBindVertexArray (vao); glEnableVertexAttribArray (0); glBindBuffer (GL_ARRAY_BUFFER, vbo); glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL); //Create Cube map GLuint cube_map_texture; create_cube_map ((resource_dir+"negz.jpg").c_str(), (resource_dir+"posz.jpg").c_str(), (resource_dir+"posy.jpg").c_str(), (resource_dir+"negy.jpg").c_str(), (resource_dir+"negx.jpg").c_str(), (resource_dir+"posx.jpg").c_str(), &cube_map_texture); boost::shared_ptr<boost::compute::opengl_texture> cl_cube_map_texture; try { cl_cube_map_texture = boost::shared_ptr<boost::compute::opengl_texture>(new boost::compute::opengl_texture(context,GL_TEXTURE_2D_ARRAY,0,cube_map_texture,boost::compute::memory_object::mem_flags::read_only)); } catch ( const std::exception& e ) { std::cerr << e.what() << std::endl; } const char* vertex_shader = "#version 400\n" "in vec3 vp;" "uniform mat4 P, V;" // "uniform vec3 vertOut;" "out vec3 texcoords;" "vec3 newP;" "void main () {" " texcoords = vp;" // " vertOut = vp;" " gl_Position = P * V * vec4 (vp, 1.0);" "}"; const char* fragment_shader = loadShader(resource_dir+"fragmentShader.frag").c_str(); /*"#version 400\n" "in vec3 texcoords;" "uniform samplerCube cube_texture;" "out vec4 frag_colour;" "vec4 cubeToLatLon(samplerCube cubemap, vec3 inUV) {" "vec3 cubmapTexCoords;" //"cubmapTexCoords.x = inUV.x*sqrt(1 - ( (inUV.y * inUV.y)/2 ) - ( (inUV.z * inUV.z)/2 ) + ( ( (inUV.y * inUV.y) * (inUV.z * inUV.z))/3));" "cubmapTexCoords.x = inUV.x;" //"cubmapTexCoords.y= inUV.y*sqrt(1 - ( (inUV.z * inUV.z)/2 ) - ( (inUV.x * inUV.x)/2 ) + ( ( (inUV.z * inUV.z) * (inUV.x * inUV.x))/3));" "cubmapTexCoords.y = inUV.y;" "cubmapTexCoords.z = inUV.z*sqrt(1 - ( (inUV.x * inUV.x)/2 ) - ( (inUV.y * inUV.y)/2 ) + ( ( (inUV.x * inUV.x) * (inUV.y * inUV.y))/3));" //"cubmapTexCoords.z = inUV.z;" "return texture(cubemap, cubmapTexCoords);" "}" "void main () {" //" frag_colour = texture (cube_texture, texcoords);" " frag_colour = cubeToLatLon (cube_texture, texcoords);" "}";*/ GLuint vs = glCreateShader (GL_VERTEX_SHADER); glShaderSource (vs, 1, &vertex_shader, NULL); glCompileShader (vs); GLuint fs = glCreateShader (GL_FRAGMENT_SHADER); glShaderSource (fs, 1, &fragment_shader, NULL); glCompileShader (fs); GLuint cube_sp = glCreateProgram (); glAttachShader (cube_sp, fs); glAttachShader (cube_sp, vs); glLinkProgram (cube_sp); //*-----------------------------Compile Shaders for second window - square --------*/ glfwMakeContextCurrent(window2); //start GLEW extension handler glewExperimental = GL_TRUE; glewInit (); glEnable (GL_DEPTH_TEST); // enable depth-testing glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" float squarePoints[] = { -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f }; GLfloat texcoords[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; GLuint vbo_square; glGenBuffers (1, &vbo_square); glBindBuffer (GL_ARRAY_BUFFER, vbo_square); glBufferData (GL_ARRAY_BUFFER, 3 * 6 * sizeof (float), &squarePoints, GL_STATIC_DRAW); GLuint texcoords_vbo; glGenBuffers (1, &texcoords_vbo); glBindBuffer (GL_ARRAY_BUFFER, texcoords_vbo); glBufferData (GL_ARRAY_BUFFER, 12 * sizeof (GLfloat), texcoords, GL_STATIC_DRAW); GLuint vao_square; glGenVertexArrays (1, &vao_square); glBindVertexArray (vao_square); glBindBuffer (GL_ARRAY_BUFFER, vbo_square); glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glBindBuffer (GL_ARRAY_BUFFER, texcoords_vbo); glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, NULL); // normalise! glEnableVertexAttribArray (0); glEnableVertexAttribArray (1); GLuint square_sp = create_programme_from_files((resource_dir+"square.vert").c_str(), (resource_dir+"square.frag").c_str()); GLuint tex; assert (load_texture ((resource_dir+"negz.jpg").c_str(), &tex)); //*----------------------------------------------------------------------------------*/ glfwMakeContextCurrent (window); int cube_V_location = glGetUniformLocation (cube_sp, "V"); int cube_P_location = glGetUniformLocation (cube_sp, "P"); //int cube_vertOut = glGetUniformLocation (cube_sp, "vertOut"); /*-------------------------------CREATE GLOBAL CAMERA--------------------------------*/ #define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444 // input variables float near = 0.1f; // clipping plane float far = 100.0f; // clipping plane float fovy = 80.0f; // 67 degrees float aspect = (float)g_gl_width / (float)g_gl_height; // aspect ratio proj_mat = perspective (fovy, aspect, near, far); float cam_speed = 3.0f; // 1 unit per second float cam_heading_speed = 50.0f; // 30 degrees per second float cam_heading = 0.0f; // y-rotation in degrees mat4 T = translate (identity_mat4 (), vec3 (-cam_pos.v[0], -cam_pos.v[1], -cam_pos.v[2])); mat4 R = rotate_y_deg (identity_mat4 (), -cam_heading); versor q = quat_from_axis_deg (-cam_heading, 0.0f, 1.0f, 0.0f); view_mat = R * T; // keep track of some useful vectors that can be used for keyboard movement vec4 fwd (0.0f, 0.0f, -1.0f, 0.0f); vec4 rgt (1.0f, 0.0f, 0.0f, 0.0f); vec4 up (0.0f, 1.0f, 0.0f, 0.0f); /*---------------------------SET RENDERING DEFAULTS---------------------------*/ glUseProgram (cube_sp); glUniformMatrix4fv (cube_V_location, 1, GL_FALSE, R.m); glUniformMatrix4fv (cube_P_location, 1, GL_FALSE, proj_mat.m); // unique model matrix for each sphere mat4 model_mat = identity_mat4 (); glEnable (GL_DEPTH_TEST); // enable depth-testing glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" glEnable (GL_CULL_FACE); // cull face glCullFace (GL_BACK); // cull back face glFrontFace (GL_CCW); // set counter-clock-wise vertex order to mean the front glClearColor (0.2, 0.2, 0.2, 1.0); // grey background to help spot mistakes glViewport (0, 0, g_gl_width, g_gl_height); while (!glfwWindowShouldClose (window) && !glfwWindowShouldClose (window2)) { // update timers static double previous_seconds = glfwGetTime (); double current_seconds = glfwGetTime (); double elapsed_seconds = current_seconds - previous_seconds; previous_seconds = current_seconds; //_update_fps_counter (window); // wipe the drawing surface clear glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // render a sky-box using the cube-map texture glDepthMask (GL_FALSE); glUseProgram (cube_sp); glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_CUBE_MAP, cube_map_texture); glBindVertexArray (vao); glDrawArrays (GL_TRIANGLES, 0, 36); glDepthMask (GL_TRUE); //*---------------------------------Display for second window-------------------*/ glfwMakeContextCurrent (window2); glUseProgram (square_sp); int cubemap_vert = glGetUniformLocation (square_sp, "cubeMap_texcoords"); glEnable (GL_DEPTH_TEST); // enable depth-testing glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" glEnable (GL_CULL_FACE); // cull face glCullFace (GL_BACK); // cull back face glFrontFace (GL_CCW); // set counter-clock-wise vertex order to mean the front glClearColor (0.3, 0.2, 0.3, 1.0); // grey background to help spot mistakes glViewport (0, 0, g_gl_width, g_gl_height); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDepthMask (GL_FALSE); glUseProgram (square_sp); glBindVertexArray (vao_square); glDrawArrays (GL_TRIANGLES, 0, 6); glDepthMask (GL_TRUE); //*------------------------------GO back to cubemap window--------------------*/ glfwMakeContextCurrent (window); // update other events like input handling glfwPollEvents (); // control keys bool cam_moved = false; vec3 move (0.0, 0.0, 0.0); float cam_yaw = 0.0f; // y-rotation in degrees float cam_pitch = 0.0f; float cam_roll = 0.0; if (glfwGetKey (window, GLFW_KEY_A)) { move.v[0] -= cam_speed * elapsed_seconds; cam_moved = true; print(move); } if (glfwGetKey (window, GLFW_KEY_D)) { move.v[0] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_Q)) { move.v[1] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_E)) { move.v[1] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_W)) { move.v[2] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_S)) { move.v[2] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_LEFT)) { cam_yaw += cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_yaw = quat_from_axis_deg ( cam_yaw, up.v[0], up.v[1], up.v[2] ); q = q_yaw * q; } if (glfwGetKey (window, GLFW_KEY_RIGHT)) { cam_yaw -= cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_yaw = quat_from_axis_deg ( cam_yaw, up.v[0], up.v[1], up.v[2] ); q = q_yaw * q; } if (glfwGetKey (window, GLFW_KEY_UP)) { cam_pitch += cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_pitch = quat_from_axis_deg ( cam_pitch, rgt.v[0], rgt.v[1], rgt.v[2] ); q = q_pitch * q; } if (glfwGetKey (window, GLFW_KEY_DOWN)) { cam_pitch -= cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_pitch = quat_from_axis_deg ( cam_pitch, rgt.v[0], rgt.v[1], rgt.v[2] ); q = q_pitch * q; } if (glfwGetKey (window, GLFW_KEY_Z)) { cam_roll -= cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_roll = quat_from_axis_deg ( cam_roll, fwd.v[0], fwd.v[1], fwd.v[2] ); q = q_roll * q; } if (glfwGetKey (window, GLFW_KEY_C)) { cam_roll += cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_roll = quat_from_axis_deg ( cam_roll, fwd.v[0], fwd.v[1], fwd.v[2] ); q = q_roll * q; } // update view matrix if (cam_moved) { cam_heading += cam_yaw; // re-calculate local axes so can move fwd in dir cam is pointing R = quat_to_mat4 (q); fwd = R * vec4 (0.0, 0.0, -1.0, 0.0); rgt = R * vec4 (1.0, 0.0, 0.0, 0.0); up = R * vec4 (0.0, 1.0, 0.0, 0.0); cam_pos = cam_pos + vec3 (fwd) * -move.v[2]; cam_pos = cam_pos + vec3 (up) * move.v[1]; cam_pos = cam_pos + vec3 (rgt) * move.v[0]; mat4 T = translate (identity_mat4 (), vec3 (cam_pos)); view_mat = inverse (R) * inverse (T); //std::cout<<inverse(R).m<<std::endl; // cube-map view matrix has rotation, but not translation glUseProgram (cube_sp); glUniformMatrix4fv (cube_V_location, 1, GL_FALSE, inverse (R).m); } if (GLFW_PRESS == glfwGetKey (window, GLFW_KEY_ESCAPE)) { glfwSetWindowShouldClose (window, 1); } if (GLFW_PRESS == glfwGetKey (window2, GLFW_KEY_ESCAPE)) { glfwSetWindowShouldClose (window2, 1); } // put the stuff we've been drawing onto the display glfwSwapBuffers (window); glfwMakeContextCurrent (window2); glfwSwapBuffers (window2); glfwMakeContextCurrent (window); } // close GL context and any other GLFW resources glfwTerminate(); return 0; }
/* don't set windows active in here, is used by renderwin too */ void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d) { if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ if (v3d->camera) { BKE_object_where_is_calc(scene, v3d->camera); obmat_to_viewmat(rv3d, v3d->camera); } else { quat_to_mat4(rv3d->viewmat, rv3d->viewquat); rv3d->viewmat[3][2] -= rv3d->dist; } } else { bool use_lock_ofs = false; /* should be moved to better initialize later on XXX */ if (rv3d->viewlock & RV3D_LOCKED) ED_view3d_lock(rv3d); quat_to_mat4(rv3d->viewmat, rv3d->viewquat); if (rv3d->persp == RV3D_PERSP) rv3d->viewmat[3][2] -= rv3d->dist; if (v3d->ob_centre) { Object *ob = v3d->ob_centre; float vec[3]; copy_v3_v3(vec, ob->obmat[3]); if (ob->type == OB_ARMATURE && v3d->ob_centre_bone[0]) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, v3d->ob_centre_bone); if (pchan) { copy_v3_v3(vec, pchan->pose_mat[3]); mul_m4_v3(ob->obmat, vec); } } translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); use_lock_ofs = true; } else if (v3d->ob_centre_cursor) { float vec[3]; copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, v3d)); translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); use_lock_ofs = true; } else { translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]); } /* lock offset */ if (use_lock_ofs) { float persmat[4][4], persinv[4][4]; float vec[3]; /* we could calculate the real persmat/persinv here * but it would be unreliable so better to later */ mul_m4_m4m4(persmat, rv3d->winmat, rv3d->viewmat); invert_m4_m4(persinv, persmat); mul_v2_v2fl(vec, rv3d->ofs_lock, rv3d->is_persp ? rv3d->dist : 1.0f); vec[2] = 0.0f; mul_mat3_m4_v3(persinv, vec); translate_m4(rv3d->viewmat, vec[0], vec[1], vec[2]); } /* end lock offset */ } }
void m4_rotate_quat(mat4_t m, quat_t q) { mat4_t rm; quat_to_mat4(rm, q); m4_mult(m, m, rm); }
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) { GroupObject *go; Object *ob=NULL, **oblist=NULL, obcopy, *obcopylist=NULL; DupliObject *dob; ParticleDupliWeight *dw; ParticleSettings *part; ParticleData *pa; ChildParticle *cpa=NULL; ParticleKey state; ParticleCacheKey *cache; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0; float (*obmat)[4], (*oldobmat)[4]; int a, b, counter, hair = 0; int totpart, totchild, totgroup=0 /*, pa_num */; int no_draw_flag = PARS_UNEXIST; if (psys==NULL) return; /* simple preventing of too deep nested groups */ if (level>MAX_DUPLI_RECUR) return; part=psys->part; if (part==NULL) return; if (!psys_check_enabled(par, psys)) return; if (G.rendering == 0) no_draw_flag |= PARS_NO_DISP; ctime = BKE_curframe(scene); /* NOTE: in old animsys, used parent object's timeoffset... */ totpart = psys->totpart; totchild = psys->totchild; BLI_srandom(31415926 + psys->seed); if ((psys->renderdata || part->draw_as==PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { ParticleSimulationData sim= {NULL}; sim.scene= scene; sim.ob= par; sim.psys= psys; sim.psmd= psys_get_modifier(par, psys); /* make sure emitter imat is in global coordinates instead of render view coordinates */ invert_m4_m4(par->imat, par->obmat); /* first check for loops (particle system object used as dupli object) */ if (part->ren_as == PART_DRAW_OB) { if (ELEM(part->dup_ob, NULL, par)) return; } else { /*PART_DRAW_GR */ if (part->dup_group == NULL || part->dup_group->gobject.first == NULL) return; for (go=part->dup_group->gobject.first; go; go=go->next) if (go->ob == par) return; } /* if we have a hair particle system, use the path cache */ if (part->type == PART_HAIR) { if (psys->flag & PSYS_HAIR_DONE) hair= (totchild == 0 || psys->childcache) && psys->pathcache; if (!hair) return; /* we use cache, update totchild according to cached data */ totchild = psys->totchildcache; totpart = psys->totcached; } psys_check_group_weights(part); psys->lattice = psys_get_lattice(&sim); /* gather list of objects or single object */ if (part->ren_as==PART_DRAW_GR) { group_handle_recalc_and_update(scene, par, part->dup_group); if (part->draw & PART_DRAW_COUNT_GR) { for (dw=part->dupliweights.first; dw; dw=dw->next) totgroup += dw->count; } else { for (go=part->dup_group->gobject.first; go; go=go->next) totgroup++; } /* we also copy the actual objects to restore afterwards, since * where_is_object_time will change the object which breaks transform */ oblist = MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list"); obcopylist = MEM_callocN(totgroup*sizeof(Object), "dupgroup copy list"); if (part->draw & PART_DRAW_COUNT_GR && totgroup) { dw = part->dupliweights.first; for (a=0; a<totgroup; dw=dw->next) { for (b=0; b<dw->count; b++, a++) { oblist[a] = dw->ob; obcopylist[a] = *dw->ob; } } } else { go = part->dup_group->gobject.first; for (a=0; a<totgroup; a++, go=go->next) { oblist[a] = go->ob; obcopylist[a] = *go->ob; } } } else { ob = part->dup_ob; obcopy = *ob; } if (totchild==0 || part->draw & PART_DRAW_PARENT) a = 0; else a = totpart; for (pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) { if (a<totpart) { /* handle parent particle */ if (pa->flag & no_draw_flag) continue; /* pa_num = pa->num; */ /* UNUSED */ pa_time = pa->time; size = pa->size; } else { /* handle child particle */ cpa = &psys->child[a - totpart]; /* pa_num = a; */ /* UNUSED */ pa_time = psys->particles[cpa->parent].time; size = psys_get_child_size(psys, cpa, ctime, NULL); } /* some hair paths might be non-existent so they can't be used for duplication */ if (hair && ((a < totpart && psys->pathcache[a]->steps < 0) || (a >= totpart && psys->childcache[a-totpart]->steps < 0))) continue; if (part->ren_as==PART_DRAW_GR) { /* prevent divide by zero below [#28336] */ if (totgroup == 0) continue; /* for groups, pick the object based on settings */ if (part->draw&PART_DRAW_RAND_GR) b= BLI_rand() % totgroup; else b= a % totgroup; ob = oblist[b]; obmat = oblist[b]->obmat; oldobmat = obcopylist[b].obmat; } else { obmat= ob->obmat; oldobmat= obcopy.obmat; } if (hair) { /* hair we handle separate and compute transform based on hair keys */ if (a < totpart) { cache = psys->pathcache[a]; psys_get_dupli_path_transform(&sim, pa, NULL, cache, pamat, &scale); } else { cache = psys->childcache[a-totpart]; psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale); } copy_v3_v3(pamat[3], cache->co); pamat[3][3]= 1.0f; } else { /* first key */ state.time = ctime; if (psys_get_particle_state(&sim, a, &state, 0) == 0) { continue; } else { float tquat[4]; normalize_qt_qt(tquat, state.rot); quat_to_mat4(pamat, tquat); copy_v3_v3(pamat[3], state.co); pamat[3][3]= 1.0f; } } if (part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { for (go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) { copy_m4_m4(tmat, oblist[b]->obmat); /* apply particle scale */ mul_mat3_m4_fl(tmat, size*scale); mul_v3_fl(tmat[3], size*scale); /* group dupli offset, should apply after everything else */ if (!is_zero_v3(part->dup_group->dupli_ofs)) sub_v3_v3v3(tmat[3], tmat[3], part->dup_group->dupli_ofs); /* individual particle transform */ mult_m4_m4m4(tmat, pamat, tmat); if (par_space_mat) mult_m4_m4m4(mat, par_space_mat, tmat); else copy_m4_m4(mat, tmat); dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, obcopylist[b].obmat); if (G.rendering) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { /* to give ipos in object correct offset */ where_is_object_time(scene, ob, ctime-pa_time); copy_v3_v3(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; /* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */ if ((part->draw & PART_DRAW_ROTATE_OB) == 0) { float xvec[3], q[4]; xvec[0] = -1.f; xvec[1] = xvec[2] = 0; vec_to_quat(q, xvec, ob->trackflag, ob->upflag); quat_to_mat4(obmat, q); obmat[3][3]= 1.0f; } /* Normal particles and cached hair live in global space so we need to * remove the real emitter's transformation before 2nd order duplication. */ if (par_space_mat && GS(id->name) != ID_GR) mult_m4_m4m4(mat, psys->imat, pamat); else copy_m4_m4(mat, pamat); mult_m4_m4m4(tmat, mat, obmat); mul_mat3_m4_fl(tmat, size*scale); if (par_space_mat) mult_m4_m4m4(mat, par_space_mat, tmat); else copy_m4_m4(mat, tmat); if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, oldobmat); if (G.rendering) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } /* restore objects since they were changed in where_is_object_time */ if (part->ren_as==PART_DRAW_GR) { for (a=0; a<totgroup; a++) *(oblist[a])= obcopylist[a]; } else *ob= obcopy; } /* clean up */ if (oblist) MEM_freeN(oblist); if (obcopylist) MEM_freeN(obcopylist); if (psys->lattice) { end_latt_deform(psys->lattice); psys->lattice = NULL; } }
void skeleton_animate ( Skeleton_Node* node, double anim_time, mat4 parent_mat, mat4* bone_offset_mats, mat4* bone_animation_mats ) { assert (node); /* the animation of a node after inheriting its parent's animation */ mat4 our_mat = parent_mat; /* the animation for a particular bone at this time */ mat4 local_anim = identity_mat4 (); mat4 node_T = identity_mat4 (); if (node->num_pos_keys > 0) { int prev_key = 0; int next_key = 0; for (int i = 0; i < node->num_pos_keys - 1; i++) { prev_key = i; next_key = i + 1; if (node->pos_key_times[next_key] >= anim_time) { break; } } float total_t = node->pos_key_times[next_key] - node->pos_key_times[prev_key]; float t = (anim_time - node->pos_key_times[prev_key]) / total_t; vec3 vi = node->pos_keys[prev_key]; vec3 vf = node->pos_keys[next_key]; vec3 lerped = vi * (1.0f - t) + vf * t; node_T = translate (identity_mat4 (), lerped); } mat4 node_R = identity_mat4 (); if (node->num_rot_keys > 0) { // find next and previous keys int prev_key = 0; int next_key = 0; for (int i = 0; i < node->num_rot_keys - 1; i++) { prev_key = i; next_key = i + 1; if (node->rot_key_times[next_key] >= anim_time) { break; } } float total_t = node->rot_key_times[next_key] - node->rot_key_times[prev_key]; float t = (anim_time - node->rot_key_times[prev_key]) / total_t; versor qi = node->rot_keys[prev_key]; versor qf = node->rot_keys[next_key]; versor slerped = slerp (qi, qf, t); node_R = quat_to_mat4 (slerped); } local_anim = node_T * node_R; // if node has a weighted bone... int bone_i = node->bone_index; if (bone_i > -1) { // ... then get offset matrices mat4 bone_offset = bone_offset_mats[bone_i]; our_mat = parent_mat * local_anim; bone_animation_mats[bone_i] = parent_mat * local_anim * bone_offset; } for (int i = 0; i < node->num_children; i++) { skeleton_animate ( node->children[i], anim_time, our_mat, bone_offset_mats, bone_animation_mats ); } }
/** * Iterates over ALL objects in the scene and all of its sets, including * making all duplis(not only metas). Copies metas to mainb array. * Computes bounding boxes for building BVH. */ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) { Scene *sce_iter = scene; Base *base; Object *bob; MetaBall *mb; const MetaElem *ml; float obinv[4][4], obmat[4][4]; unsigned int i; int obnr, zero_size = 0; char obname[MAX_ID_NAME]; SceneBaseIter iter; copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from BKE_scene_base_iter_next */ invert_m4_m4(obinv, ob->obmat); BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); /* make main array */ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) { if (bob->type == OB_MBALL) { zero_size = 0; ml = NULL; if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) { mb = ob->data; if (mb->editelems) ml = mb->editelems->first; else ml = mb->elems.first; } else { char name[MAX_ID_NAME]; int nr; BLI_split_name_num(name, &nr, bob->id.name + 2, '.'); if (STREQ(obname, name)) { mb = bob->data; if (mb->editelems) ml = mb->editelems->first; else ml = mb->elems.first; } } /* when metaball object has zero scale, then MetaElem to this MetaBall * will not be put to mainb array */ if (has_zero_axis_m4(bob->obmat)) { zero_size = 1; } else if (bob->parent) { struct Object *pob = bob->parent; while (pob) { if (has_zero_axis_m4(pob->obmat)) { zero_size = 1; break; } pob = pob->parent; } } if (zero_size) { while (ml) { ml = ml->next; } } else { while (ml) { if (!(ml->flag & MB_HIDE)) { float pos[4][4], rot[4][4]; float expx, expy, expz; float tempmin[3], tempmax[3]; MetaElem *new_ml; /* make a copy because of duplicates */ new_ml = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem)); *(new_ml) = *ml; new_ml->bb = BLI_memarena_alloc(process->pgn_elements, sizeof(BoundBox)); new_ml->mat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float)); new_ml->imat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float)); /* too big stiffness seems only ugly due to linear interpolation * no need to have possibility for too big stiffness */ if (ml->s > 10.0f) new_ml->s = 10.0f; else new_ml->s = ml->s; /* if metaball is negative, set stiffness negative */ if (new_ml->flag & MB_NEGATIVE) new_ml->s = -new_ml->s; /* Translation of MetaElem */ unit_m4(pos); pos[3][0] = ml->x; pos[3][1] = ml->y; pos[3][2] = ml->z; /* Rotation of MetaElem is stored in quat */ quat_to_mat4(rot, ml->quat); /* basis object space -> world -> ml object space -> position -> rotation -> ml local space */ mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->obmat, pos, rot); /* ml local space -> basis object space */ invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat); /* rad2 is inverse of squared radius */ new_ml->rad2 = 1 / (ml->rad * ml->rad); /* initial dimensions = radius */ expx = ml->rad; expy = ml->rad; expz = ml->rad; switch (ml->type) { case MB_BALL: break; case MB_CUBE: /* cube is "expanded" by expz, expy and expx */ expz += ml->expz; /* fall through */ case MB_PLANE: /* plane is "expanded" by expy and expx */ expy += ml->expy; /* fall through */ case MB_TUBE: /* tube is "expanded" by expx */ expx += ml->expx; break; case MB_ELIPSOID: /* ellipsoid is "stretched" by exp* */ expx *= ml->expx; expy *= ml->expy; expz *= ml->expz; break; } /* untransformed Bounding Box of MetaElem */ /* TODO, its possible the elem type has been changed and the exp* values can use a fallback */ copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz); /* 0 */ copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz); /* 1 */ copy_v3_fl3(new_ml->bb->vec[2], +expx, +expy, -expz); /* 2 */ copy_v3_fl3(new_ml->bb->vec[3], -expx, +expy, -expz); /* 3 */ copy_v3_fl3(new_ml->bb->vec[4], -expx, -expy, +expz); /* 4 */ copy_v3_fl3(new_ml->bb->vec[5], +expx, -expy, +expz); /* 5 */ copy_v3_fl3(new_ml->bb->vec[6], +expx, +expy, +expz); /* 6 */ copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz); /* 7 */ /* transformation of Metalem bb */ for (i = 0; i < 8; i++) mul_m4_v3((float(*)[4])new_ml->mat, new_ml->bb->vec[i]); /* find max and min of transformed bb */ INIT_MINMAX(tempmin, tempmax); for (i = 0; i < 8; i++) { DO_MINMAX(new_ml->bb->vec[i], tempmin, tempmax); } /* set only point 0 and 6 - AABB of Metaelem */ copy_v3_v3(new_ml->bb->vec[0], tempmin); copy_v3_v3(new_ml->bb->vec[6], tempmax); /* add new_ml to mainb[] */ if (UNLIKELY(process->totelem == process->mem)) { process->mem = process->mem * 2 + 10; process->mainb = MEM_reallocN(process->mainb, sizeof(MetaElem *) * process->mem); } process->mainb[process->totelem++] = new_ml; } ml = ml->next; } } } } /* compute AABB of all Metaelems */ if (process->totelem > 0) { copy_v3_v3(process->allbb.min, process->mainb[0]->bb->vec[0]); copy_v3_v3(process->allbb.max, process->mainb[0]->bb->vec[6]); for (i = 1; i < process->totelem; i++) make_box_union(process->mainb[i]->bb, &process->allbb, &process->allbb); } }
void Camera::recalc_axes() { quat_to_mat4 (R.m, quaternion); fwd = R * FORWARD; rgt = R * RIGHT; up = R * UP; }
int main () { // start GL context with helper libraries assert (glfwInit ()); /* We must specify 3.2 core if on Apple OS X -- other O/S can specify anything here. I defined 'APPLE' in the makefile for OS X */ #ifdef APPLE glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #endif GLFWwindow* window = glfwCreateWindow ( g_viewport_width, g_viewport_height, "GUI Panels", NULL, NULL); glfwSetWindowSizeCallback (window, glfw_window_size_callback); glfwMakeContextCurrent (window); glewExperimental = GL_TRUE; glewInit (); const GLubyte* renderer = glGetString (GL_RENDERER); // get renderer string const GLubyte* version = glGetString (GL_VERSION); // version as a string printf ("Renderer: %s\n", renderer); printf ("OpenGL version supported %s\n", version); // create a 2d panel. from 2 triangles = 6 xy coords. float points[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f }; // for ground plane we can just re-use panel points but y is now z GLuint vp_vbo, vao; glGenBuffers (1, &vp_vbo); glBindBuffer (GL_ARRAY_BUFFER, vp_vbo); glBufferData (GL_ARRAY_BUFFER, sizeof (points), points, GL_STATIC_DRAW); glGenVertexArrays (1, &vao); glBindVertexArray (vao); // note: vertex buffer is already bound glVertexAttribPointer (0, 2, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray (0); // create a 3d camera to move in 3d so that we can tell that the panel is 2d // keep track of some useful vectors that can be used for keyboard movement vec4 fwd (0.0f, 0.0f, -1.0f, 0.0f); vec4 rgt (1.0f, 0.0f, 0.0f, 0.0f); vec4 up (0.0f, 1.0f, 0.0f, 0.0f); vec3 cam_pos (0.0f, 1.0f, 5.0f); mat4 T_inv = translate (identity_mat4 (), cam_pos); // point slightly downwards to see the plane versor quaternion = quat_from_axis_deg (0.0f, 1.0f, 0.0f, 0.0f); mat4 R_inv = quat_to_mat4 (quaternion); // combine the inverse rotation and transformation to make a view matrix V = inverse (R_inv) * inverse (T_inv); // projection matrix P = perspective ( 67.0f, (float)g_viewport_width / (float)g_viewport_height, 0.1f, 100.0f); const float cam_speed = 3.0f; // 1 unit per second const float cam_heading_speed = 50.0f; // 30 degrees per second create_ground_plane_shaders (); create_gui_shaders (); // textures for ground plane and gui GLuint gp_tex, gui_tex; assert (load_texture ("tile2-diamonds256x256.png", &gp_tex)); assert (load_texture ("skulluvmap.png", &gui_tex)); // rendering defaults glDepthFunc (GL_LESS); // set depth function but don't enable yet glEnable (GL_CULL_FACE); // cull face glCullFace (GL_BACK); // cull back face glFrontFace (GL_CCW); // GL_CCW for counter clock-wise // absolute panel dimensions in pixels const float panel_width = 256.0f; const float panel_height = 256.0f; glViewport (0, 0, g_viewport_width, g_viewport_height); // start main rendering loop while (!glfwWindowShouldClose (window)) { // update timers static double previous_seconds = glfwGetTime (); double current_seconds = glfwGetTime (); double elapsed_seconds = current_seconds - previous_seconds; previous_seconds = current_seconds; bool cam_moved = false; vec3 move (0.0, 0.0, 0.0); // wipe the drawing surface clear glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // draw ground plane. note: depth test is enabled here glEnable (GL_DEPTH_TEST); glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, gp_tex); glUseProgram (gp_sp); glBindVertexArray (vao); glDrawArrays (GL_TRIANGLES, 0, 6); // draw GUI panel. note: depth test is disabled here and drawn AFTER scene glDisable (GL_DEPTH_TEST); glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, gui_tex); glUseProgram (gui_sp); // resize panel to size in pixels float x_scale = panel_width / g_viewport_width; float y_scale = panel_height / g_viewport_height; glUniform2f (gui_scale_loc, x_scale, y_scale); glBindVertexArray (vao); glDrawArrays (GL_TRIANGLES, 0, 6); // update other events like input handling glfwPollEvents (); if (GLFW_PRESS == glfwGetKey (window, GLFW_KEY_ESCAPE)) { glfwSetWindowShouldClose (window, 1); } float cam_yaw = 0.0f; // y-rotation in degrees float cam_pitch = 0.0f; float cam_roll = 0.0; if (glfwGetKey (window, GLFW_KEY_A)) { move.v[0] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_D)) { move.v[0] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_Q)) { move.v[1] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_E)) { move.v[1] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_W)) { move.v[2] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_S)) { move.v[2] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (window, GLFW_KEY_LEFT)) { cam_yaw += cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_yaw = quat_from_axis_deg (cam_yaw, up.v[0], up.v[1], up.v[2]); quaternion = q_yaw * quaternion; } if (glfwGetKey (window, GLFW_KEY_RIGHT)) { cam_yaw -= cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_yaw = quat_from_axis_deg (cam_yaw, up.v[0], up.v[1], up.v[2]); quaternion = q_yaw * quaternion; } if (glfwGetKey (window, GLFW_KEY_UP)) { cam_pitch += cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_pitch = quat_from_axis_deg ( cam_pitch, rgt.v[0], rgt.v[1], rgt.v[2]); quaternion = q_pitch * quaternion; } if (glfwGetKey (window, GLFW_KEY_DOWN)) { cam_pitch -= cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_pitch = quat_from_axis_deg ( cam_pitch, rgt.v[0], rgt.v[1], rgt.v[2]); quaternion = q_pitch * quaternion; } if (glfwGetKey (window, GLFW_KEY_Z)) { cam_roll -= cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_roll = quat_from_axis_deg ( cam_roll, fwd.v[0], fwd.v[1], fwd.v[2]); quaternion = q_roll * quaternion; } if (glfwGetKey (window, GLFW_KEY_C)) { cam_roll += cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_roll = quat_from_axis_deg ( cam_roll, fwd.v[0], fwd.v[1], fwd.v[2]); quaternion = q_roll * quaternion; } // update view matrix if (cam_moved) { // re-calculate local axes so can move fwd in dir cam is pointing R_inv = quat_to_mat4 (quaternion); fwd = R_inv * vec4 (0.0, 0.0, -1.0, 0.0); rgt = R_inv * vec4 (1.0, 0.0, 0.0, 0.0); up = R_inv * vec4 (0.0, 1.0, 0.0, 0.0); cam_pos = cam_pos + vec3 (fwd) * -move.v[2]; cam_pos = cam_pos + vec3 (up) * move.v[1]; cam_pos = cam_pos + vec3 (rgt) * move.v[0]; T_inv = translate (identity_mat4 (), cam_pos); V = inverse (R_inv) * inverse (T_inv); glUseProgram (gp_sp); glUniformMatrix4fv (gp_V_loc, 1, GL_FALSE, V.m); } // put the stuff we've been drawing onto the display glfwSwapBuffers (window); } // done glfwTerminate(); return 0; }
/* OB_DUPLIPARTS */ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem *psys) { Scene *scene = ctx->scene; Object *par = ctx->object; bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER; bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; DupliObject *dob; ParticleDupliWeight *dw; ParticleSettings *part; ParticleData *pa; ChildParticle *cpa = NULL; ParticleKey state; ParticleCacheKey *cache; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0; float (*obmat)[4]; int a, b, hair = 0; int totpart, totchild, totgroup = 0 /*, pa_num */; const bool dupli_type_hack = !BKE_scene_use_new_shading_nodes(scene); int no_draw_flag = PARS_UNEXIST; if (psys == NULL) return; part = psys->part; if (part == NULL) return; if (!psys_check_enabled(par, psys)) return; if (!for_render) no_draw_flag |= PARS_NO_DISP; ctime = BKE_scene_frame_get(scene); /* NOTE: in old animsys, used parent object's timeoffset... */ totpart = psys->totpart; totchild = psys->totchild; BLI_srandom((unsigned int)(31415926 + psys->seed)); if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { ParticleSimulationData sim = {NULL}; sim.scene = scene; sim.ob = par; sim.psys = psys; sim.psmd = psys_get_modifier(par, psys); /* make sure emitter imat is in global coordinates instead of render view coordinates */ invert_m4_m4(par->imat, par->obmat); /* first check for loops (particle system object used as dupli object) */ if (part->ren_as == PART_DRAW_OB) { if (ELEM(part->dup_ob, NULL, par)) return; } else { /*PART_DRAW_GR */ if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->gobject)) return; if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) { return; } } /* if we have a hair particle system, use the path cache */ if (part->type == PART_HAIR) { if (psys->flag & PSYS_HAIR_DONE) hair = (totchild == 0 || psys->childcache) && psys->pathcache; if (!hair) return; /* we use cache, update totchild according to cached data */ totchild = psys->totchildcache; totpart = psys->totcached; } psys_check_group_weights(part); psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); /* gather list of objects or single object */ if (part->ren_as == PART_DRAW_GR) { if (ctx->do_update) { BKE_group_handle_recalc_and_update(ctx->eval_ctx, scene, par, part->dup_group); } if (part->draw & PART_DRAW_COUNT_GR) { for (dw = part->dupliweights.first; dw; dw = dw->next) totgroup += dw->count; } else { for (go = part->dup_group->gobject.first; go; go = go->next) totgroup++; } /* we also copy the actual objects to restore afterwards, since * BKE_object_where_is_calc_time will change the object which breaks transform */ oblist = MEM_callocN((size_t)totgroup * sizeof(Object *), "dupgroup object list"); obcopylist = MEM_callocN((size_t)totgroup * sizeof(Object), "dupgroup copy list"); if (part->draw & PART_DRAW_COUNT_GR && totgroup) { dw = part->dupliweights.first; for (a = 0; a < totgroup; dw = dw->next) { for (b = 0; b < dw->count; b++, a++) { oblist[a] = dw->ob; obcopylist[a] = *dw->ob; } } } else { go = part->dup_group->gobject.first; for (a = 0; a < totgroup; a++, go = go->next) { oblist[a] = go->ob; obcopylist[a] = *go->ob; } } } else { ob = part->dup_ob; obcopy = *ob; } if (totchild == 0 || part->draw & PART_DRAW_PARENT) a = 0; else a = totpart; for (pa = psys->particles; a < totpart + totchild; a++, pa++) { if (a < totpart) { /* handle parent particle */ if (pa->flag & no_draw_flag) continue; /* pa_num = pa->num; */ /* UNUSED */ pa_time = pa->time; size = pa->size; } else { /* handle child particle */ cpa = &psys->child[a - totpart]; /* pa_num = a; */ /* UNUSED */ pa_time = psys->particles[cpa->parent].time; size = psys_get_child_size(psys, cpa, ctime, NULL); } /* some hair paths might be non-existent so they can't be used for duplication */ if (hair && psys->pathcache && ((a < totpart && psys->pathcache[a]->segments < 0) || (a >= totpart && psys->childcache[a - totpart]->segments < 0))) { continue; } if (part->ren_as == PART_DRAW_GR) { /* prevent divide by zero below [#28336] */ if (totgroup == 0) continue; /* for groups, pick the object based on settings */ if (part->draw & PART_DRAW_RAND_GR) b = BLI_rand() % totgroup; else b = a % totgroup; ob = oblist[b]; obmat = oblist[b]->obmat; } else { obmat = ob->obmat; } if (hair) { /* hair we handle separate and compute transform based on hair keys */ if (a < totpart) { cache = psys->pathcache[a]; psys_get_dupli_path_transform(&sim, pa, NULL, cache, pamat, &scale); } else { cache = psys->childcache[a - totpart]; psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale); } copy_v3_v3(pamat[3], cache->co); pamat[3][3] = 1.0f; } else { /* first key */ state.time = ctime; if (psys_get_particle_state(&sim, a, &state, 0) == 0) { continue; } else { float tquat[4]; normalize_qt_qt(tquat, state.rot); quat_to_mat4(pamat, tquat); copy_v3_v3(pamat[3], state.co); pamat[3][3] = 1.0f; } } if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { for (go = part->dup_group->gobject.first, b = 0; go; go = go->next, b++) { copy_m4_m4(tmat, oblist[b]->obmat); /* apply particle scale */ mul_mat3_m4_fl(tmat, size * scale); mul_v3_fl(tmat[3], size * scale); /* group dupli offset, should apply after everything else */ if (!is_zero_v3(part->dup_group->dupli_ofs)) sub_v3_v3(tmat[3], part->dup_group->dupli_ofs); /* individual particle transform */ mul_m4_m4m4(mat, pamat, tmat); dob = make_dupli(ctx, go->ob, mat, a, false, false); dob->particle_system = psys; if (use_texcoords) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { /* to give ipos in object correct offset */ BKE_object_where_is_calc_time(scene, ob, ctime - pa_time); copy_v3_v3(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; /* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */ if ((part->draw & PART_DRAW_ROTATE_OB) == 0) { float xvec[3], q[4], size_mat[4][4], original_size[3]; mat4_to_size(original_size, obmat); size_to_mat4(size_mat, original_size); xvec[0] = -1.f; xvec[1] = xvec[2] = 0; vec_to_quat(q, xvec, ob->trackflag, ob->upflag); quat_to_mat4(obmat, q); obmat[3][3] = 1.0f; /* add scaling if requested */ if ((part->draw & PART_DRAW_NO_SCALE_OB) == 0) mul_m4_m4m4(obmat, obmat, size_mat); } else if (part->draw & PART_DRAW_NO_SCALE_OB) { /* remove scaling */ float size_mat[4][4], original_size[3]; mat4_to_size(original_size, obmat); size_to_mat4(size_mat, original_size); invert_m4(size_mat); mul_m4_m4m4(obmat, obmat, size_mat); } mul_m4_m4m4(tmat, pamat, obmat); mul_mat3_m4_fl(tmat, size * scale); copy_m4_m4(mat, tmat); if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); dob = make_dupli(ctx, ob, mat, a, false, false); dob->particle_system = psys; if (use_texcoords) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); /* XXX blender internal needs this to be set to dupligroup to render * groups correctly, but we don't want this hack for cycles */ if (dupli_type_hack && ctx->group) dob->type = OB_DUPLIGROUP; } } /* restore objects since they were changed in BKE_object_where_is_calc_time */ if (part->ren_as == PART_DRAW_GR) { for (a = 0; a < totgroup; a++) *(oblist[a]) = obcopylist[a]; } else *ob = obcopy; } /* clean up */ if (oblist) MEM_freeN(oblist); if (obcopylist) MEM_freeN(obcopylist); if (psys->lattice_deform_data) { end_latt_deform(psys->lattice_deform_data); psys->lattice_deform_data = NULL; } }
int main () { /*--------------------------------START OPENGL--------------------------------*/ assert (restart_gl_log ()); // start GL context and O/S window using the GLFW helper library assert (start_gl ()); // set a function to be called when the mouse is clicked glfwSetMouseButtonCallback (g_window, glfw_mouse_click_callback); /*------------------------------CREATE GEOMETRY-------------------------------*/ GLfloat* vp = NULL; // array of vertex points GLfloat* vn = NULL; // array of vertex normals GLfloat* vt = NULL; // array of texture coordinates int g_point_count = 0; assert (load_obj_file (MESH_FILE, vp, vt, vn, g_point_count)); GLuint vao; glGenVertexArrays (1, &vao); glBindVertexArray (vao); GLuint points_vbo; if (NULL != vp) { glGenBuffers (1, &points_vbo); glBindBuffer (GL_ARRAY_BUFFER, points_vbo); glBufferData ( GL_ARRAY_BUFFER, 3 * g_point_count * sizeof (GLfloat), vp, GL_STATIC_DRAW ); glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray (0); } /*-------------------------------CREATE SHADERS-------------------------------*/ GLuint shader_programme = create_programme_from_files ( VERTEX_SHADER_FILE, FRAGMENT_SHADER_FILE ); int model_mat_location = glGetUniformLocation (shader_programme, "model"); int view_mat_location = glGetUniformLocation (shader_programme, "view"); int proj_mat_location = glGetUniformLocation (shader_programme, "proj"); int blue_location = glGetUniformLocation (shader_programme, "blue"); /*-------------------------------CREATE CAMERA--------------------------------*/ #define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444 // input variables float near = 0.1f; // clipping plane float far = 100.0f; // clipping plane float fovy = 67.0f; // 67 degrees float aspect = (float)g_gl_width / (float)g_gl_height; // aspect ratio proj_mat = perspective (fovy, aspect, near, far); float cam_speed = 3.0f; // 1 unit per second float cam_heading_speed = 50.0f; // 30 degrees per second float cam_heading = 0.0f; // y-rotation in degrees mat4 T = translate ( identity_mat4 (), vec3 (-cam_pos.v[0], -cam_pos.v[1], -cam_pos.v[2]) ); mat4 R = rotate_y_deg (identity_mat4 (), -cam_heading); versor q = quat_from_axis_deg (-cam_heading, 0.0f, 1.0f, 0.0f); view_mat = R * T; // keep track of some useful vectors that can be used for keyboard movement vec4 fwd (0.0f, 0.0f, -1.0f, 0.0f); vec4 rgt (1.0f, 0.0f, 0.0f, 0.0f); vec4 up (0.0f, 1.0f, 0.0f, 0.0f); /*---------------------------SET RENDERING DEFAULTS---------------------------*/ glUseProgram (shader_programme); glUniformMatrix4fv (view_mat_location, 1, GL_FALSE, view_mat.m); glUniformMatrix4fv (proj_mat_location, 1, GL_FALSE, proj_mat.m); // unique model matrix for each sphere mat4 model_mats[NUM_SPHERES]; for (int i = 0; i < NUM_SPHERES; i++) { model_mats[i] = translate (identity_mat4 (), sphere_pos_wor[i]); } glEnable (GL_DEPTH_TEST); // enable depth-testing glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" glEnable (GL_CULL_FACE); // cull face glCullFace (GL_BACK); // cull back face glFrontFace (GL_CCW); // set counter-clock-wise vertex order to mean the front glClearColor (0.2, 0.2, 0.2, 1.0); // grey background to help spot mistakes glViewport (0, 0, g_gl_width, g_gl_height); /*-------------------------------RENDERING LOOP-------------------------------*/ while (!glfwWindowShouldClose (g_window)) { // update timers static double previous_seconds = glfwGetTime (); double current_seconds = glfwGetTime (); double elapsed_seconds = current_seconds - previous_seconds; previous_seconds = current_seconds; _update_fps_counter (g_window); // wipe the drawing surface clear glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram (shader_programme); glBindVertexArray (vao); for (int i = 0; i < NUM_SPHERES; i++) { if (g_selected_sphere == i) { glUniform1f (blue_location, 1.0f); } else { glUniform1f (blue_location, 0.0f); } glUniformMatrix4fv (model_mat_location, 1, GL_FALSE, model_mats[i].m); glDrawArrays (GL_TRIANGLES, 0, g_point_count); } // update other events like input handling glfwPollEvents (); // control keys bool cam_moved = false; vec3 move (0.0, 0.0, 0.0); float cam_yaw = 0.0f; // y-rotation in degrees float cam_pitch = 0.0f; float cam_roll = 0.0; if (glfwGetKey (g_window, GLFW_KEY_A)) { move.v[0] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_D)) { move.v[0] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_Q)) { move.v[1] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_E)) { move.v[1] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_W)) { move.v[2] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_S)) { move.v[2] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_LEFT)) { cam_yaw += cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_yaw = quat_from_axis_deg ( cam_yaw, up.v[0], up.v[1], up.v[2] ); q = q_yaw * q; } if (glfwGetKey (g_window, GLFW_KEY_RIGHT)) { cam_yaw -= cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_yaw = quat_from_axis_deg ( cam_yaw, up.v[0], up.v[1], up.v[2] ); q = q_yaw * q; } if (glfwGetKey (g_window, GLFW_KEY_UP)) { cam_pitch += cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_pitch = quat_from_axis_deg ( cam_pitch, rgt.v[0], rgt.v[1], rgt.v[2] ); q = q_pitch * q; } if (glfwGetKey (g_window, GLFW_KEY_DOWN)) { cam_pitch -= cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_pitch = quat_from_axis_deg ( cam_pitch, rgt.v[0], rgt.v[1], rgt.v[2] ); q = q_pitch * q; } if (glfwGetKey (g_window, GLFW_KEY_Z)) { cam_roll -= cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_roll = quat_from_axis_deg ( cam_roll, fwd.v[0], fwd.v[1], fwd.v[2] ); q = q_roll * q; } if (glfwGetKey (g_window, GLFW_KEY_C)) { cam_roll += cam_heading_speed * elapsed_seconds; cam_moved = true; versor q_roll = quat_from_axis_deg ( cam_roll, fwd.v[0], fwd.v[1], fwd.v[2] ); q = q_roll * q; } // update view matrix if (cam_moved) { // re-calculate local axes so can move fwd in dir cam is pointing R = quat_to_mat4 (q); fwd = R * vec4 (0.0, 0.0, -1.0, 0.0); rgt = R * vec4 (1.0, 0.0, 0.0, 0.0); up = R * vec4 (0.0, 1.0, 0.0, 0.0); cam_pos = cam_pos + vec3 (fwd) * -move.v[2]; cam_pos = cam_pos + vec3 (up) * move.v[1]; cam_pos = cam_pos + vec3 (rgt) * move.v[0]; mat4 T = translate (identity_mat4 (), vec3 (cam_pos)); view_mat = inverse (R) * inverse (T); glUniformMatrix4fv (view_mat_location, 1, GL_FALSE, view_mat.m); } if (GLFW_PRESS == glfwGetKey (g_window, GLFW_KEY_ESCAPE)) { glfwSetWindowShouldClose (g_window, 1); } // put the stuff we've been drawing onto the display glfwSwapBuffers (g_window); } // close GL context and any other GLFW resources glfwTerminate(); return 0; }