Changeset b73cb3b in opengl-game


Ignore:
Timestamp:
Mar 29, 2018, 5:09:16 AM (7 years ago)
Author:
Dmitry Portnoy <dmp1488@…>
Branches:
feature/imgui-sdl, master, points-test
Children:
fc424f6
Parents:
e82692b
Message:

Fix all issues with object click detection, and add the shader files to the NewOpenGLGame project.

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • NewOpenGLGame.vcxproj

    re82692b rb73cb3b  
    136136    <Text Include="gl.log" />
    137137  </ItemGroup>
     138  <ItemGroup>
     139    <None Include="color.frag" />
     140    <None Include="color.vert" />
     141    <None Include="texture.frag" />
     142    <None Include="texture.vert" />
     143  </ItemGroup>
    138144  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
    139145  <ImportGroup Label="ExtensionTargets">
  • new-game.cpp

    re82692b rb73cb3b  
    3030#define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444
    3131
     32/*
     33 * If I use one array to store the points for all the object faces in the scene, I'll probably remove the ObjectFace object,
     34 * and store the start and end indices of a given object's point coordinates in that array in the SceneObject.
     35 *
     36 * Should probably do something similar with colors and texture coordinates, once I figure out the best way to store tex coords
     37 * for all objects in one array.
     38 */
     39
     40
     41// might also want to store the shader to be used for the object
    3242struct SceneObject {
    3343   mat4 model_mat;
     
    6272
    6373void printVector(string label, vec3 v);
     74void print4DVector(string label, vec4 v);
    6475
    6576float NEAR_CLIP = 0.1f;
     
    7182
    7283void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
    73    /*
    74    double mouse_x, mouse_y;
    75    glfwGetCursorPos(window, &mouse_x, &mouse_y);
    76 
    77    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
    78       cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
    79 
    80       float x = (2.0f*mouse_x) / width - 1.0f;
    81       float y = 1.0f - (2.0f*mouse_y) / height;
    82       cout << "x: " << x << ", y: " << y << endl;
    83 
    84       // Since the projection matrix gets applied before the view matrix,
    85       // treat the initial camera position (aka origin of the ray) as (0, 0, 0)
    86 
    87       // When getting the ray direction, you can use near and fov to get the
    88       // coordinates
    89 
    90       vec4 ray_clip = vec4(x, y, -1.0f, 1.0f); // this should have a z equal to the near clipping plane
    91       vec4 ray_eye = inverse(proj_mat) * ray_clip;
    92       ray_eye = vec4(ray_eye.xy(), -1.0f, 0.0f);
    93       vec3 ray_world = normalize((inverse(view_mat) * ray_eye).xyz());
    94 
    95       / * LATEST NOTES:
    96        *
    97        * Normalizing the world ray caused issues, although it should make sense with the projection
    98        * matrix, since the z coordinate has meaning there.
    99        *
    100        * Now, I need to figure out the correct intersection test in 2D space
    101        * Also, need to check that the global triangle points are correct
    102        * /
    103 
    104       // since ray_world is the end result we want anyway, we probably don't need to add cam_pos to
    105       // it, only to subtract it later
    106 
    107       vec3 click_point = cam_pos + ray_world;
    108 
    109       / * Now, we need to generate the constants for the equations describing
    110        * a 3D line:
    111        *   (x - x0) / a = (y - y0) / b = (z - z0) / c
    112        *
    113        * The line goes through the camera position, so
    114        * cam_pos = <x0, y0, z0>
    115        * /
    116 
    117       // upper right corner is 1, 1 in opengl
    118 
    119       cout << "Converted -> (" << ray_world.x << "," << ray_world.y << "," << ray_world.z << ")" << endl << endl;;
    120       cout << "Camera -> (" << cam_pos.x << "," << cam_pos.y << "," << cam_pos.z << ")" << endl;
    121       cout << "Click point -> (" << click_point.x << "," << click_point.y << "," << click_point.z << ")" << endl;
    122 
    123       float a = 1.0f;
    124       float b = a * (click_point.y - cam_pos.y) / (click_point.x - cam_pos.x);
    125       float c = a * (click_point.z - cam_pos.z) / (click_point.x - cam_pos.x);
    126 
    127       cout << "(x - " << cam_pos.x << ") / " << a << " = ";
    128       cout << "(y - " << cam_pos.y << ") / " << b << " = ";
    129       cout << "(z - " << cam_pos.z << ") / " << c << endl;;
    130 
    131       / * Now, we need to generate the constants for the equations describing
    132        * a 3D plane:
    133        * dx + ey +fz +g = 0
    134        * /
    135 
    136       vec3 fp1 = triangle_face[0];
    137       vec3 fp2 = triangle_face[1];
    138       vec3 fp3 = triangle_face[2];
    139 
    140       cout << "Points on the plane" << endl;
    141       cout << "(" << fp1.x << ", " << fp1.y << ", " << fp1.z << ")" << endl;
    142       cout << "(" << fp2.x << ", " << fp2.y << ", " << fp2.z << ")" << endl;
    143       cout << "(" << fp3.x << ", " << fp3.y << ", " << fp3.z << ")" << endl;
    144 
    145       float pa = (fp2.y-fp1.y)*(fp3.z-fp1.z) - (fp3.y-fp1.y)*(fp2.z-fp1.z);
    146       float pb = (fp2.z-fp1.z)*(fp3.x-fp1.x) - (fp3.z-fp1.z)*(fp2.x-fp1.x);
    147       float pc = (fp2.x-fp1.x)*(fp3.y-fp1.y) - (fp3.x-fp1.x)*(fp2.y-fp1.y);
    148       float pd = -(pa*fp1.x+pb*fp1.y+pc*fp1.z);
    149 
    150       cout << pa << "x+" << pb << "y+" << pc << "z+" << pd << "=0" << endl;
    151 
    152       // get intersection
    153 
    154       // the intersection this computes is incorrect
    155       // it doesn't match the equation of the plane
    156       vec3 i;
    157       i.z = -cam_pos.z - pc*pd/(pa*a+pb*b);
    158       i.x = cam_pos.x + a * (i.z-cam_pos.z) / c;
    159       i.y = cam_pos.y + b * (i.z-cam_pos.z) / c;
    160 
    161       cout << "The holy grail?" << endl;
    162       cout << "(" << i.x << "," << i.y << "," << i.z << ")" << endl;
    163 
    164       clicked = insideTriangle(i, triangle_face);
    165       cout << (clicked ? "true" : "false")  << endl;
    166    }
    167    */
    168 }
    169 
    170 /* REFACTORING PLAN:
    171  *
    172  * Have an array of object structs
    173  * Each object struct has:
    174  *    -a model matrix
    175  *    -a selected boolean
    176  * Eventually, maybe also want to store a reference to the correct shader
    177  * or whatever other info I need to properly render it
    178  *
    179  * Have an array of face structs
    180  * Each face struct has
    181  *    -an object index indicating which object it is a part of
    182  *    -an array of three points
    183  *
    184  * The mouse button callback will:
    185  *    -iterate through the faces array
    186  *    -For each face, it will call faceClicked() with the following params:
    187  *       -Probably a world ray created from the mouse click coordinates
    188  *       -An array of 3 points representing the face
    189  *       -The object struct represnting the object the face is a part of
    190  *
    191  *       -Really, all I need to pass in are the world ray and an ObjectFace reference
    192  *       -The world ray will first need to be multiplied by the view and projection matrices before being passed in
    193  */
    194 
    195 void mouse_button_callback_new(GLFWwindow* window, int button, int action, int mods) {
    19684   double mouse_x, mouse_y;
    19785   glfwGetCursorPos(window, &mouse_x, &mouse_y);
     
    20694      cout << "x: " << x << ", y: " << y << endl;
    20795
    208       // Since the projection matrix gets applied before the view matrix,
    209       // treat the initial camera position (aka origin of the ray) as (0, 0, 0)
    210 
    211       // When getting the ray direction, you can use near and fov to get the
    212       // coordinates
    213 
    214       // vec4 ray_clip = vec4(x, y, -1.0f, 1.0f); // this should have a z equal to the near clipping plane
    215       // vec4 ray_eye = inverse(proj_mat) * ray_clip;
    216       // ray_eye = vec4(ray_eye.xy(), -1.0f, 0.0f);
    217       // vec3 ray_world = normalize((inverse(view_mat) * ray_eye).xyz());
    218 
    219       vec4 ray_clip = vec4(x, y, NEAR_CLIP, 1.0f); // this should have a z equal to the near clipping plane
    220       vec4 ray_eye = ray_clip; // Need to apply the projection matrix here
     96      vec4 ray_clip = vec4(x, y, -1.0f, 1.0f);
     97      vec4 ray_eye = inverse(proj_mat) * ray_clip;
     98      ray_eye = vec4(ray_eye.xy(), -1.0f, 1.0f);
    22199      vec4 ray_world = inverse(view_mat) * ray_eye;
    222100
    223       /* LATEST NOTES:
    224        *
    225        * Normalizing the world ray caused issues, although it should make sense with the projection
    226        * matrix, since the z coordinate has meaning there.
    227        * Plus, we really want to normalize it only once we recompute it below as the difference of two points,
    228        * although doing so shouldn't effect the results. Check the book to see if there is a good reason for doing so.
    229        */
    230 
    231       printVector("Initial world ray:", ray_world.xyz());
    232 
    233       vec4 cam_pos_origin = vec4(x, y, 0.0f, 1.0f);
    234       vec4 cam_pos_temp = inverse(view_mat) * cam_pos_origin;
    235 
    236       cout << "Ray clip -> (" << ray_clip.x << "," << ray_clip.y << "," << ray_clip.z << ")" << endl << endl;;
    237       cout << "Ray world -> (" << ray_world.x << "," << ray_world.y << "," << ray_world.z << ")" << endl << endl;;
    238       cout << "Camera -> (" << cam_pos_temp.x << "," << cam_pos_temp.y << "," << cam_pos_temp.z << ")" << endl;
     101      vec4 cam_pos_temp = vec4(cam_pos, 1.0f);
    239102
    240103      vec4 click_point;
    241       vec3 closest_point;
     104      vec3 closest_point = vec3(0.0f, 0.0f, -FAR_CLIP); // Any valid point will be closer than the far clipping plane, so initial value to that
    242105      int closest_face_id = -1;
    243106
    244       // Need to account for faces that are behind one another
    245       // Using an iterator for the loop makes it difficult to get a reference to each face (for the faceClicked function)
    246107      for (int i = 0; i<faces.size(); i++) {
    247108         if (faceClicked(&faces[i], ray_world, cam_pos_temp, click_point)) {
    248109            click_point = view_mat * click_point;
    249110
    250             // Check against clipping planes once I start applying the projection matrix
    251             // if (NEAR_CLIP <= click_point.z && click_point.z < FAR_CLIP && ...) {
    252             if (-1.0f <= click_point.z && click_point.z < 1.0f && click_point.z < closest_point.z) {
     111            if (-NEAR_CLIP >= click_point.z && click_point.z > -FAR_CLIP && click_point.z > closest_point.z) {
    253112               closest_point = click_point.xyz();
    254113               closest_face_id = i;
     
    262121         clickedObject = &objects[faces[closest_face_id].object_id];
    263122         cout << "Clicked object: " << faces[closest_face_id].object_id << endl;
    264          printVector("Click point", closest_point);
    265123      }
    266124   }
     
    309167   }
    310168
    311    bool squareSelected = false;
    312 
    313    glfwSetMouseButtonCallback(window, mouse_button_callback_new);
     169   glfwSetMouseButtonCallback(window, mouse_button_callback);
    314170
    315171   glfwMakeContextCurrent(window);
     
    317173   glewInit();
    318174
    319    // Check if we might ever need this. If not, remove it.
     175   // Check the extended initialization section of the book to learn how to use this
     176   // Maybe move this and other OpenGL setup/settings code into a separate function
    320177   // glViewport(0, 0, width*2, height*2);
    321178
     
    383240
    384241   GLfloat points2[] = {
    385       0.5f,  0.5f,  0.0f,
     242       0.5f,  0.5f,  0.0f,
    386243      -0.5f,  0.5f,  0.0f,
    387244      -0.5f, -0.5f,  0.0f,
    388       0.5f,  0.5f,  0.0f,
     245       0.5f,  0.5f,  0.0f,
    389246      -0.5f, -0.5f,  0.0f,
    390       0.5f, -0.5f,  0.0f,
     247       0.5f, -0.5f,  0.0f,
    391248   };
    392249
     
    412269   int numPoints2 = (sizeof(points2) / sizeof(float)) / 3;
    413270
    414    // initialize global variables for click intersection tests
    415 
    416271   mat4 T_model, R_model;
    417272
     
    419274   objects.push_back(SceneObject());
    420275
    421    /*
    422    mat4 R_model = rotate(mat4(), 4.0f, vec3(0.0f, 1.0f, 0.0f));
    423    */
    424    T_model = translate(mat4(), vec3(0.0f, 0.0f, 0.0f));
     276   T_model = translate(mat4(), vec3(0.25f, 0.0f, 0.0f));
    425277   R_model = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
    426278   objects[0].model_mat = T_model*R_model;
     
    437289   objects.push_back(SceneObject());
    438290
    439    // mat4 T_model2 = translate(mat4(), vec3(-1.0f, 0.0f, 0.0f));
    440    T_model = translate(mat4(), vec3(-0.5f, 0.0f, 0.1f));
    441    R_model = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
     291   T_model = translate(mat4(), vec3(-0.5f, 0.0f, -1.00f));
     292   R_model = rotate(mat4(), 0.5f, vec3(0.0f, 1.0f, 0.0f));
    442293   objects[1].model_mat = T_model*R_model;
    443294
     
    516367   float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
    517368
    518    //cam_pos = vec3(0.0f, 0.0f, 2.0f);
    519    cam_pos = vec3(0.0f, 0.0f, 0.3f);
     369   // glm::lookAt can create the view matrix
     370   // glm::perspective can create the projection matrix
     371
     372   cam_pos = vec3(0.0f, 0.0f, 2.0f);
    520373   float cam_yaw = 0.0f * 2.0f * 3.14159f / 360.0f;
    521374
    522375   mat4 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
    523376   mat4 R = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
    524    /*
    525    mat4 T = translate(mat4(), vec3(0.0f, 0.0f, 0.0f));
    526    mat4 R = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
    527    */
    528377   view_mat = R*T;
    529378
     
    537386   float Pz = -(2.0f * FAR_CLIP * NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
    538387
    539    /*
    540388   float proj_arr[] = {
    541389     Sx, 0.0f, 0.0f, 0.0f,
     
    544392     0.0f, 0.0f, Pz, 0.0f,
    545393   };
    546    */
    547    float proj_arr[] = {
    548      1.0f, 0.0f, 0.0f, 0.0f,
    549      0.0f, 1.0f, 0.0f, 0.0f,
    550      0.0f, 0.0f, 1.0f, 0.0f,
    551      0.0f, 0.0f, 0.0f, 1.0f,
    552    };
    553394   proj_mat = make_mat4(proj_arr);
    554395
     
    605446      glUseProgram(shader_program);
    606447
     448      // Since every object will have a different model matrix, maybe it shouldn't be a uniform
     449
    607450      // this is temporary.
    608451      // It's needed to offset the code for the recoloring of the square working during click detection
     
    614457
    615458      if (clickedObject == &objects[1]) {
    616          squareSelected = !squareSelected;
    617459         selectedObject = &objects[1];
    618460      }
     
    743585
    744586bool faceClicked(ObjectFace* face, vec4 world_ray, vec4 cam, vec4& click_point) {
    745    cout << "Points on the plane" << endl;
    746    printVector("fp1", face->points[0]);
    747    printVector("fp2", face->points[1]);
    748    printVector("fp3", face->points[2]);
    749 
    750587   // LINE EQUATION:            P = O + Dt
    751    // O = cam_pos
     588   // O = cam
    752589   // D = ray_world
    753590
    754    // PLANE EQUATION:   P dot n + d = 0  (n is the normal vector and d is the offset from the origin)
     591   // PLANE EQUATION:   P dot n + d = 0
     592   // n is the normal vector
     593   // d is the offset from the origin
    755594
    756595   // Take the cross-product of two vectors on the plane to get the normal
     
    759598
    760599   vec3 normal = vec3(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
    761    printVector("v1", v1);
    762    printVector("v2", v2);
    763    printVector("Cross", normal);
     600
     601   print4DVector("Full world ray", world_ray);
    764602
    765603   SceneObject* obj = &objects[face->object_id];
    766604   vec3 local_ray = (inverse(obj->model_mat) * world_ray).xyz();
    767605   vec3 local_cam = (inverse(obj->model_mat) * cam).xyz();
     606
    768607   local_ray = local_ray - local_cam;
    769 
    770    cout << "Test theory: " << glm::dot(local_cam, normal) << endl;
    771    cout << "Test 2: " << glm::dot(local_ray, normal) << endl;
    772608
    773609   float d = -glm::dot(face->points[0], normal);
     
    804640   cout << label << " -> (" << v.x << "," << v.y << "," << v.z << ")" << endl;
    805641}
     642
     643void print4DVector(string label, vec4 v) {
     644   cout << label << " -> (" << v.x << "," << v.y << "," << v.z << "," << v.w << ")" << endl;
     645}
Note: See TracChangeset for help on using the changeset viewer.