Jump to content
  • Advertisement

AndyEsser

Member
  • Content Count

    797
  • Joined

  • Last visited

Everything posted by AndyEsser

  1. Hi all,   Trying to implement SAT in my code to detect collisions (binary yes/no is fine for the moment - no requirement to get the actual contact point). However I'm having an issue that the objects seem to intersect a small amount before the collision is detected.   Below is my code, and attached is a screenshot and I would very much appreciate it if someone could point me in the right direction. I must be doing something silly somewhere as it seems so close.   I'm implementing SAT as described here: http://www.dyn4j.org/2010/01/sat/   I'm aware that the code is quite messy and obviously not optimised (that's for a later stage  ) const std::vector<Vector>& vertices1 = entity1RigidBody->GetCollisionVertices(); const std::vector<Vector>& faces1 = entity1RigidBody->GetCollisionFaces(); const std::vector<Vector>& normals1 = entity1RigidBody->GetCollisionFaceNormals(); const std::vector<Vector>& vertices2 = entity2RigidBody->GetCollisionVertices(); const std::vector<Vector>& faces2 = entity2RigidBody->GetCollisionFaces(); const std::vector<Vector>& normals2 = entity2RigidBody->GetCollisionFaceNormals(); glm::mat4 entity1TransformMatrix = entity1Transform->GetTransform().GetMatrix(); glm::mat4 entity2TransformMatrix = entity2Transform->GetTransform().GetMatrix(); if(vertices1.size() == 0 || faces1.size() == 0 || normals1.size() == 0) { return false; } if(vertices2.size() == 0 || faces2.size() == 0 || normals2.size() == 0) { return false; } std::vector<Vector> axes; for(unsigned int i = 0; i < normals1.size(); i++) { glm::vec4 vector(normals1[i].x, normals1[i].y, normals1[i].z, 0.0f); vector = vector * entity1TransformMatrix; // Transform the vertices Vector axis(vector.x, vector.y, vector.z); axes.push_back(axis); } for(unsigned int i = 0; i < normals2.size(); i++) { glm::vec4 vector(normals2[i].x, normals2[i].y, normals2[i].z, 0.0f); vector = vector * entity2TransformMatrix; // Transform the vertices Vector axis(vector.x, vector.y, vector.z); axes.push_back(axis); } // We have all the axes from the Normals (this should probably only be computed once...) // For each axis, lets get a projection from each vertex onto each axis (!!!!) for(unsigned int a = 0; a < axes.size(); a++) { double min1 = 0; double max1 = 0; double min2 = 0; double max2 = 0; Vector axis = axes[a]; for(unsigned int face = 0; face < faces1.size(); face++) { Vector faceIndices = faces1[face]; Vector faceVertices[3]; faceVertices[0] = vertices1[faceIndices.x]; faceVertices[1] = vertices1[faceIndices.y]; faceVertices[2] = vertices1[faceIndices.z]; for(unsigned int vert = 0; vert < 3; vert++) { Vector vertex = faceVertices[vert]; glm::vec4 v(vertex.x, vertex.y, vertex.z, 0.0f); glm::vec4 transformedV = (v * entity1TransformMatrix); // Transform the vertices vertex.x = transformedV.x; vertex.y = transformedV.y; vertex.z = transformedV.z; double p = Vector::Dot(axis, vertex); if(p < min1) { min1 = p; } else if (p > max1) { max1 = 0; } } } for(unsigned int face = 0; face < faces2.size(); face++) { Vector faceIndices = faces2[face]; Vector faceVertices[3]; faceVertices[0] = vertices2[faceIndices.x]; faceVertices[1] = vertices2[faceIndices.y]; faceVertices[2] = vertices2[faceIndices.z]; for(unsigned int vert = 0; vert < 3; vert++) { Vector vertex = faceVertices[vert]; glm::vec4 v(vertex.x, vertex.y, vertex.z, 0.0f); glm::vec4 transformedV = (v * entity2TransformMatrix); // Transform the vertices vertex.x = transformedV.x; vertex.y = transformedV.y; vertex.z = transformedV.z; double p = Vector::Dot(axis, vertex); if(p < min2) { min2 = p; } else if (p > max1) { max2 = 0; } } } // Check if they overlap if(min1 < min2 && max1 < min2) { // No Overlap return false; } if(min1 > max2 && max1 > max2) { // No Overlap return false; } } // We've reached this far - there must be a collision return true;
  2. AndyEsser

    Problem Implementing Separating Axis Theorem

    Hurrah! Changing the vertex vec4 to have a 1.0f at the end has made it all magically work (at least at first inspection - need to run a full set of tests on it).   With regards to the 3x3 rotation matrix, the matrix kept in the Transform is for the entity and used in rendering so I need a full Translation * Rotation * Scale matrix. However, it might be one of the optimizations I look at doing.   Thanks very much all!
  3. AndyEsser

    Problem Implementing Separating Axis Theorem

      Well derp... I'll try modifying that and seeing what happens! Thanks
  4. AndyEsser

    Problem Implementing Separating Axis Theorem

    Thanks for your response, that equality test was modified from your example - although I appear to have gotten the true/false part the wrong way around so shall modify it accordingly.   I actually went through this morning and wrote a very simple test to ensure my understanding of the maths involved was correct. It appears to be all correct (currently not doing the Edge test - will implement that once I know the face tests are working). This seems to behave has expected - however it is obviously vastly simplified (only has 2 defined axes to test (ones that I can verify on paper) and the vertex co-ordinates are in world space, not local space so that I didn't need to include a transformation matrix. bool simpleSatTest() { std::vector<Vector> axes; // Object 1 Vertices std::vector<Vector> object1vertices; std::vector<Vector> object1faces; object1vertices.push_back(Vector(3.0f, 1.0f, 0.0f)); object1vertices.push_back(Vector(4.0f, 1.0f, 0.0f)); object1vertices.push_back(Vector(3.5f, 1.0f, 0.0f)); object1faces.push_back(Vector(0.0f, 1.0f, 2.0f)); // Object 2 Vertices std::vector<Vector> object2vertices; std::vector<Vector> object2faces; object2vertices.push_back(Vector(3.0f, 1.0f, 0.0f)); object2vertices.push_back(Vector(4.0f, 1.0f, 0.0f)); object2vertices.push_back(Vector(3.0f, 2.0f, 0.0f)); object2vertices.push_back(Vector(4.0f, 2.0f, 0.0f)); object2faces.push_back(Vector(0.0f, 1.0f, 2.0f)); object2faces.push_back(Vector(2.0f, 3.0f, 0.0f)); // Axes to test axes.push_back(Vector(1.0f, 0.0f, 0.0f)); // X-Axis axes.push_back(Vector(0.0f, 1.0f, 0.0f)); // Y-Axis for(unsigned int a = 0; a < axes.size(); ++a) { float Obj1Min = 10000.0f; float Obj1Max = -10000.0f; float Obj2Min = 10000.0f; float Obj2Max = -10000.0f; Vector axis = axes[a]; for(unsigned int f = 0; f < object1faces.size(); ++f) { Vector face = object1faces[f]; int index[3]; index[0] = face.x; index[1] = face.y; index[2] = face.z; for(unsigned int v = 0; v < 3; ++v) { Vector vertex = object1vertices[index[v]]; float result = dot(vertex, axis); if(result < Obj1Min) { Obj1Min = result; } else if (result > Obj1Max) { Obj1Max = result; } } } for(unsigned int f = 0; f < object2faces.size(); ++f) { Vector face = object2faces[f]; int index[3]; index[0] = face.x; index[1] = face.y; index[2] = face.z; for(unsigned int v = 0; v < 3; ++v) { Vector vertex = object2vertices[index[v]]; float result = dot(vertex, axis); if(result < Obj2Min) { Obj2Min = result; } else if (result > Obj2Max) { Obj2Max = result; } } } if(Obj1Max < Obj2Min || Obj2Max < Obj1Min) { std::cout << "Non-Collision Hyperplane found" << std::endl; } else { std::cout << "Collision Hyperplane found" << std::endl; } } std::cout << "Test complete" << std::endl; return true; } I am generating axes from both objects normals - as per here:  for(unsigned int i = 0; i < normals1.size(); i++) { glm::vec4 normal(normals1[i].x, normals1[i].y, normals1[i].z, 0.0f); normal = entity1TransformMatrix * normal; // Transform the vertices normal = glm::normalize(normal); Vector axis(normal.x, normal.y, normal.z); axes.push_back(axis); } for(unsigned int i = 0; i < normals2.size(); i++) { glm::vec4 normal(normals2[i].x, normals2[i].y, normals2[i].z, 0.0f); normal = entity2TransformMatrix * normal; // Transform the vertices normal = glm::normalize(normal); Vector axis(normal.x, normal.y, normal.z); axes.push_back(axis); }
  5. AndyEsser

    Problem Implementing Separating Axis Theorem

      Thanks for these - I've updated my code to use very large numbers for initialising min/max accordingly. With regards to your 2nd point - this was a coding error - I've since fixed that now.       Thanks for that code, I've refactored some of mine from being a horrible huge method just to try and make it a bit more readable like yours.   However, it turns out the problem was completely different to what I thought. I had originally had another test that preceeded the SAT test that basically just checked whether two spheres (1 for each rigidbody) were intersecting before then trying to do the more accurate test - this was working as expected - but then the result of the SAT test was always claiming a collision).   So I've removed my sphere test for the moment, and refactored a bit of my code to make it more readable and unfortunately it's still going wrong. It's reporting a collision constantly. Looking deeper, it seems that the Projection for both meshes on each axis is always identical - which is obviously incorrect. So I need to dig around a bit deeper - I suspect I'm misunderstanding how to project the vertices onto the plane defined by the axes.   I've included my modified code for completeness sake, but I'll keep researching and checking my code - right now nothing is popping out at me. const bool System::DoesCollide(Lucidity::Scene::Entity& entity1, Lucidity::Scene::Entity& entity2) const { Lucidity::Scene::TransformComponent* entity1Transform = entity1.GetComponent<Lucidity::Scene::TransformComponent>(); Lucidity::Scene::TransformComponent* entity2Transform = entity2.GetComponent<Lucidity::Scene::TransformComponent>(); Lucidity::Physics::RigidBody* entity1RigidBody = entity1.GetComponent<Lucidity::Physics::RigidBody>(); Lucidity::Physics::RigidBody* entity2RigidBody = entity2.GetComponent<Lucidity::Physics::RigidBody>(); if(!entity1Transform || !entity1RigidBody) { // Entity 1 has no Transform OR has no RigidBody return false; } if(!entity2Transform || !entity2RigidBody) { // Entity 2 has no Transform OR has no RigidBody return false; } Vector entity1Origin(entity1Transform->GetTransform().GetPositionX(), entity1Transform->GetTransform().GetPositionY(), entity1Transform->GetTransform().GetPositionZ()); Vector entity2Origin(entity2Transform->GetTransform().GetPositionX(), entity2Transform->GetTransform().GetPositionY(), entity2Transform->GetTransform().GetPositionZ()); Vector vectorBetween = entity1Origin - entity2Origin; float vectorDistance = vectorBetween.Length(); float superDistance = entity1RigidBody->GetSuperRadius() + entity2RigidBody->GetSuperRadius(); if(true) { //if(vectorDistance < superDistance) { const std::vector<Vector>& vertices1 = entity1RigidBody->GetCollisionVertices(); const std::vector<Vector>& faces1 = entity1RigidBody->GetCollisionFaces(); const std::vector<Vector>& normals1 = entity1RigidBody->GetCollisionFaceNormals(); const std::vector<Vector>& vertices2 = entity2RigidBody->GetCollisionVertices(); const std::vector<Vector>& faces2 = entity2RigidBody->GetCollisionFaces(); const std::vector<Vector>& normals2 = entity2RigidBody->GetCollisionFaceNormals(); glm::mat4 entity1TransformMatrix = entity1Transform->GetTransform().GetMatrix(); glm::mat4 entity2TransformMatrix = entity2Transform->GetTransform().GetMatrix(); if(vertices1.size() == 0 || faces1.size() == 0 || normals1.size() == 0) { return false; } if(vertices2.size() == 0 || faces2.size() == 0 || normals2.size() == 0) { return false; } std::vector<Vector> axes; for(unsigned int i = 0; i < normals1.size(); i++) { glm::vec4 normal(normals1[i].x, normals1[i].y, normals1[i].z, 0.0f); normal = entity1TransformMatrix * normal; // Transform the vertices normal = glm::normalize(normal); Vector axis(normal.x, normal.y, normal.z); axes.push_back(axis); } for(unsigned int i = 0; i < normals2.size(); i++) { glm::vec4 normal(normals2[i].x, normals2[i].y, normals2[i].z, 0.0f); normal = entity2TransformMatrix * normal; // Transform the vertices normal = glm::normalize(normal); Vector axis(normal.x, normal.y, normal.z); axes.push_back(axis); } // We have all the axes from the Normals (this should probably only be computed once...) // For each axis, lets get a projection from each vertex onto each axis (!!!!) std::vector<Vector>::iterator it = axes.begin(); std::vector<Vector>::iterator itEnd = axes.end(); for(it; it != itEnd; it++) { Vector axis = *it; // TODO: Currently these projections don't seem to be correct Projection projection1 = projectOntoAxis(entity1TransformMatrix, axis, faces1, vertices1); Projection projection2 = projectOntoAxis(entity2TransformMatrix, axis, faces2, vertices2); // Check if they overlap if(projection1.max < projection2.min || projection2.max < projection1.min) { return false; } } // We've reached this far - there must be a collision return true; } return false; }; const Projection System::projectOntoAxis(const glm::mat4& transform, const Vector& axis, const std::vector<Vector>& faces, const std::vector<Vector>& vertices) const { Projection projection; projection.min = 1000.0f; projection.max = -1000.0f; glm::vec4 glmAxis = glm::vec4(axis.x, axis.y, axis.z, 0.0f); for(unsigned int face = 0; face < faces.size(); face++) { Vector faceIndices = faces[face]; Vector faceVertices[3]; faceVertices[0] = vertices[faceIndices.x]; faceVertices[1] = vertices[faceIndices.y]; faceVertices[2] = vertices[faceIndices.z]; for(unsigned int vert = 0; vert < 3; ++vert) { Vector vertex = faceVertices[vert]; glm::vec4 v(vertex.x, vertex.y, vertex.z, 0.0f); v = (transform * v); // Transform the vertices float p = glm::dot(v, glmAxis); if(p < projection.min) { projection.min = p; } else if (p > projection.max) { projection.max = p; } //std::cout << "Vertex [ " << vertex.x << ", " << vertex.y << ", " << vertex.z << " ] - " << projection.min << "/" << projection.max << std::endl; } } return projection; };
  6. AndyEsser

    MMOs and modern scaling techniques

      +1 simply for this comment
  7. I'm in the process of porting my engine across to Linux support.    I can successfully create a window, and set up an OpenGL context however, the contents of the window are whatever was displayed behind it at the time of creation. NOTE: This is not a transparent window, if I drag the window around it still contains an 'image' of whatever was behind it at the time of creation. (See attached image).   Now I'm not sure where the issue could be, however I'm not looking for a solution to a specific issue in my code, mainly just any insight from other Linux/GLX developers who may have seen a similar issue and might know where I should start looking?   Cheers!
  8. glGetError() returns no errors anywhere in my application.    Immediately after glXCreateContext() I then call glXMakeCurrent() and calling glGetIntegerv() with GL_MAJOR_VERSION and GL_MINOR_VERSION returns 4 and 2 (4.2) respectively which indicates the GL context has been created successfully.   I tried having a glXMakeCurrent() call immediately before I try my glClear/glXSwapBuffers() but to effect.   Further info I should have mentioned before, this is a multithreaded application, however all X11/GLX/OpenGL calls are only made by a single thread. I have also tried calling XInitThreads() from the main application thread, and from the Rendering thread with no luck either.
  9. I stripped all the code in my update function right down to just be:   glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glXSwapBuffers(dpy, win);   With no joy. My first thought was that it was garbage, but with just those calls I'd expect to the see the glClearColor().
  10. Hello,   I'm currently implementing a shader for doing some Directional Lights. I'm following the tutorial at Lighthouse 3d (http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/directional-lights-per-pixel/)   The issue I'm having is in the following few lines: vec3 h = normalize(l_dir + e); float intSpec = max(dot(h, n), 0.0); float specularPower = pow(intSpec, shininess); If I leave the "float specularPower" line in - then the shader no longer 'works'.... I say 'works' in quotations, because I get no output or errors from the Shader Log, however, now the uniform locations for my all return -1 and I can't set my texture locations, etc.   If I remove it, the rest of the shader works as expected (but producing incorrect results as a result of missing the Specular Power).   What's even more curious, is that if I have the nVidia Nsight Debugger attached, then I get output on screen and it appears to 'work', but if I just use VS2012 in Debug mode I get nothing displayed on screen, and the following error message: First-chance exception at 0x000000005EB066E6 (nvoglv64.dll) in application.exe: 0xC0000005: Access violation reading location 0x0000000000000008. First-chance exception at 0x000000005EB066E6 (nvoglv64.dll) in application.exe: 0xC0000005: Access violation reading location 0x0000000000000008. This behaviour has been witnessed on both a GTX 480 and a GTX 560 - on a PC running Windows 8 64-bit.   Any suggestions as to what I might be doing wrong are very welcome.   Cheers.  
  11. AndyEsser

    GLSL Issue when using pow()

    Hi Tanzanite,   I'll try and strip the shader down to the bare minimum reproducable code and paste it this evening.   With regards to the stack trace, I can't access it. The output above is pumped into the console log in VS, and the actual exception seems to be swallowed by the nvoglv64.dll so I can't actually see where it's being triggered.   I'll go through and check that all memory is correctly initialised as well and see if I can get some more information about the exception.   Many thanks
  12. AndyEsser

    GLSL Issue when using pow()

    I haven't checked glGetProgramInfoLog() - I'll do that this evening. glGetError() returns no errors.   With regards to the -1, I know that typically means the value has been optimised out, but since I'm not even using the value return from pow() in my test code, I don't see how it could be affecting any of the other uniforms which work normally with that line commented out.    I'm not using uniform blocks, just standard glUniform*() functions.   I don't have access to the shader code at the moment, I'll try and get a copy onto Pastebin this evening and post the link.
  13. Just my two cents here.   I've found in my experience (nVidia GTX 480/560 cards - can't remember Driver Version off heart) but I had to rebind the Index buffer before each Draw Call... I also had to call glEnableVertexAttribArray() for each Vertex Attrib Array before each Draw Call.
  14. Hi all,   Trying to get my code to use an OpenGL 3.x Core Context.    Previously my code has been working fine on Windows using just a 1.2 Context, but now that I've prototyped out the design I need to get a more recent context to do some of the more exciting things.   The issue I'm having is that my CreateWindow() call is return a null HWND, and GetLastError() is returning 0 - which is less than helpful!   Bit of background info. This code is called in a child thread of the main application thread (I've tried calling it in the main thread, with the same results) and there is already a Window that has been successfully created (but not created a GL Context yet).   Any thoughts what I might be doing wrong? WNDCLASS wndClass; HINSTANCE hInstance = 0; ZeroMemory(&wndClass, sizeof(WNDCLASS)); wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hInstance = hInstance; wndClass.lpfnWndProc = WndProc; wndClass.lpszClassName = TEXT("Dummy Window"); wndClass.lpszMenuName = 0; wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; DWORD err = GetLastError(); RegisterClass(&wndClass); err = GetLastError(); HWND hWnd = CreateWindow(TEXT("Dummy Window"), "Dummy Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); err = GetLastError(); if (hWnd == NULL) { return false; } return true;
  15. Right, fixed this - I was being stupid.   In the WndProc method I was passing to Register class I was just returning 0 (as the method wouldn't be used). Changing that to    static LRESULT CALLBACK WndProc(HWND hwnd, cxuint message, WPARAM wparam, LPARAM lparam) { return DefWindowProc(hwnd, message, wparam, lparam); }   Worked perfectly...
  16. Hi everyone,   I'm working on a new project, and could really use your input. I've set up a short 10 question survey, that should only take a few minutes of your time to answer and the responses will really help us tailor the project we're working on to be as good as it can be.   http://www.surveymonkey.com/s/9DSTCL9   If you could also pass the link around to as many gaming type people you know, the more responses we have the more accurate our data will be, and the better the project will be.   Also, apologies in advance for a couple spelling mistakes, and the overlapping age sections, feel free to just skip that question if you want. (I'm going to blame lack of coffee this morning).   Thanks!  
  17. AndyEsser

    So I've learned C...

    I am primarily a C/C++ programmer. However, in April I started a new job as a Java backend server developer. I had never touched Java before I got asked to come in for the interview. I spent a week using it before my interview, and I passed. Once you have the programming mindset, and have 'learnt' one language, it's very easy to learn another, it's simply a case of syntax. I agree with those suggesting learning an API. I think my most valuable skill is my knowledge of OpenGL, having been using it for about 10 years.
  18. I'm afraid I'm going to have to bow out - just too much to do with packing ready to move I'm afraid.
  19. I took part last year and really enjoyed myself. I'd be up for it again, but I move house on the 28th so will be spending most of the weekend packing. However if I can find the time and the theme is a good one I'd give it a try
  20. Does anyone know anyone that works at the Modern Art Oxford?
  21. I asked two friends if they wanted to hang out this evening. Both of their responses were "Let me check with the missus and get back to you"
  22. So I got called to fix a problem. I was told "The printer has an error message on it" - Surely this isn't difficult! http://t.co/NlSbklai
  23. Pain. Ow. Pain. Ow. Pain. Ow. Pain. Ow. Pain. Ow. Pain. Ow. Pain. Ow. Pain. Ow. Pain. Ow.
  24. /me has been reading too much imgur today...
  25. We've just finished recording our 2nd episode of "The Indie Game Show" - we've got a Wordpress site up and running http://t.co/cdVkLL5S
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!