
Announcements

November GameDev Challenge: Pong! 11/01/17


Content count
797 
Joined

Last visited
Community Reputation
394 NeutralAbout AndyEsser

Rank
GDNet+

Problem Implementing Separating Axis Theorem
AndyEsser replied to AndyEsser's topic in Math and Physics
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! 
Problem Implementing Separating Axis Theorem
AndyEsser replied to AndyEsser's topic in Math and Physics
Well derp... I'll try modifying that and seeing what happens! Thanks 
Problem Implementing Separating Axis Theorem
AndyEsser replied to AndyEsser's topic in Math and Physics
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 coordinates 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)); // XAxis axes.push_back(Vector(0.0f, 1.0f, 0.0f)); // YAxis 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 << "NonCollision 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); } 
Problem Implementing Separating Axis Theorem
AndyEsser replied to AndyEsser's topic in Math and Physics
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; }; 
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;

MMOs and modern scaling techniques
AndyEsser replied to Kylotan's topic in Networking and Multiplayer
+1 simply for this comment 
OpenGL Issue with GLX/X11 on Ubuntu not showing correct Window Contents
AndyEsser replied to AndyEsser's topic in Graphics and GPU Programming
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. 
OpenGL Issue with GLX/X11 on Ubuntu not showing correct Window Contents
AndyEsser replied to AndyEsser's topic in Graphics and GPU Programming
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(). 
OpenGL Issue with GLX/X11 on Ubuntu not showing correct Window Contents
AndyEsser posted a topic in Graphics and GPU Programming
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! 
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

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.

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/glslcoretutorial/directionallightsperpixel/) 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: Firstchance exception at 0x000000005EB066E6 (nvoglv64.dll) in application.exe: 0xC0000005: Access violation reading location 0x0000000000000008. Firstchance 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 64bit. Any suggestions as to what I might be doing wrong are very welcome. Cheers.

OpenGL What's up with my VAO/VBO Loading/Rendering code?
AndyEsser replied to mynameisnafe's topic in Graphics and GPU Programming
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. 
OpenGL Error creating dummy window for OpenGL 3.x Content
AndyEsser replied to AndyEsser's topic in Graphics and GPU Programming
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... 
OpenGL Error creating dummy window for OpenGL 3.x Content
AndyEsser posted a topic in Graphics and GPU Programming
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;