• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

AndyEsser

GDNet+ Basic
  • Content count

    797
  • Joined

  • Last visited

Community Reputation

394 Neutral

About AndyEsser

  • Rank
    GDNet+

Personal Information

  • Location
    Cambridge, United Kingdom
  1. 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!
  2.   Well derp... I'll try modifying that and seeing what happens! Thanks
  3. 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); }
  4.   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; };
  5. 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;
  6.   +1 simply for this comment
  7. 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.
  8. 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().
  9. 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!
  10. 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
  11. 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.
  12. 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.  
  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. 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...
  15. 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;