/** * @brief Print line info * @param _line Line to print */ void print_line(Line const &_line) { DebugLogPrint("LINE:\n"); DebugLogPrint("POSITION:\n"); print_vector(_line.position); DebugLogPrint("LENGTH: %f\n", _line.length); }
/** * @brief Load an image by file name. * @param aName Name of the file. */ void PCShaderSurface::LoadImage(HashString const &aName) { /* If the file was already loaded, let's avoid assigning a new id. */ TextureData const& textureData = GetManager()->GetTextureData(aName); if(textureData.mTextureID != (unsigned)-1) { mTextureID = textureData.mTextureID; SetTextureSize(Vector3(textureData.mWidth, textureData.mHeight, 0)); } // else we load the image from file else if((mSurface = IMG_Load(Common::RelativePath("Art", aName).c_str()))) { if ((mSurface->w & (mSurface->w - 1)) != 0 ) { DebugLogPrint("warning: width of image: %s is not a power of 2\n", aName.ToCharArray()); } if ((mSurface->h & (mSurface->h - 1)) != 0 ) { DebugLogPrint("warning: height of image: %s is not a power of 2\n", aName.ToCharArray()); } SetTextureSize(Vector3(mSurface->w, mSurface->h, 0)); mNumberOfColors = mSurface->format->BytesPerPixel; if (mNumberOfColors == 4) { if (mSurface->format->Rmask == 0x000000ff) mTextureFormat = GL_RGBA; else #ifndef _WIN32 mTextureFormat = GL_BGRA; #else mTextureFormat = GL_RGBA; #endif } else if (mNumberOfColors == 3) { if (mSurface->format->Rmask == 0x000000ff) mTextureFormat = GL_RGB; else #ifndef _WIN32 mTextureFormat = GL_BGR; #else mTextureFormat = GL_RGB; #endif } else { DebugLogPrint("warning: image %s is not truecolor... this will probably break\n", aName.ToCharArray()); DebugLogPrint("warning: bytes per pixel for image %s: %d\n", aName.ToCharArray(), mNumberOfColors); } AddTexturePairing(aName); } else { DebugLogPrint("warning: file: %s not found or incompatible format, check this out\n", aName.ToCharArray()); } }
/** * @brief Loads a text surface in font. * @param aFont Font to use. * @param aText Text to render. * @param aForegroundColor Color of the text. * @param aBackgroundColor Color of the background. * @param aSize Size of font. * @param aMaxWidth Max width of a single line (in pixels). * @return */ Vector3 PCShaderSurface::LoadText(HashString const &aFont, HashString const &aText, Vector4 const &aForegroundColor, Vector4 const &aBackgroundColor, int aSize, int aMaxWidth) { // Endianness is important here Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif HashString const textureDataHash = aFont + aText + Common::IntToString(aSize); TextureData const& data = GetManager()->GetTextureData(textureDataHash); if(data.mTextureID != (unsigned)-1) { Vector3 size = Vector3(data.mWidth, data.mHeight, 0); mTextureID = data.mTextureID; SetTextureSize(size); return size; } else { if(!TTF_WasInit()) TTF_Init(); mFont = TTF_OpenFont(Common::RelativePath("Fonts", aFont).c_str(), aSize); if(!mFont) { mFont = NULL; DebugLogPrint("warning: file not found or incompatible format, check this out\n"); DebugLogPrint("%s", TTF_GetError()); return Vector3(0, 0, 0); } // Create text texture SDL_Color fgColor = {(Uint8)aForegroundColor.x, (Uint8)aForegroundColor.y, (Uint8)aForegroundColor.z, (Uint8)aForegroundColor.w}; //SDL_Color bgColor = {(Uint8)aBackgroundColor.x, (Uint8)aBackgroundColor.y, (Uint8)aBackgroundColor.z, (Uint8)aBackgroundColor.w}; SDL_Surface *msg = TTF_RenderText_Blended_Wrapped(mFont, aText.ToCharArray(), fgColor, aMaxWidth); if(!msg) { DebugLogPrint("TTF_RenderText failed: %s", TTF_GetError()); assert(msg); } mTextureFormat = GL_RGBA; mSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, msg->w, msg->h, 32, rmask, gmask, bmask, amask); SetTextureSize(Vector3(mSurface->w, mSurface->h, 0)); SDL_BlitSurface(msg, NULL, mSurface, NULL); AddTexturePairing(textureDataHash); return Vector3(mSurface->w, mSurface->h, 0); } }
// Helpful print functions void print_matrix(Matrix33 const &_matrix) { DebugLogPrint("MATRIX:\n"); for (int i = 0; i < 3; ++i) { DebugLogPrint("ROW%d:", i); for (int j = 0; j < 3; ++j) { DebugLogPrint(" %f ", _matrix.values[i][j]); } DebugLogPrint("\n"); } DebugLogPrint("DETERMINANT: %f\n", _matrix.Determinant()); }
/** * @brief Add object to objects vector. * @param aObj The object to add * @param aStatic Is this a static environment object, as in, not designed to be updated? */ void ObjectManager::AddObject(GameObject *aObj, bool aStatic) { if(aObj == nullptr) { DebugLogPrint("Not sure why, but a null object was created. (ObjectManager AddObject)"); } // Check to see if object is in our list ObjectIT objectsEnd = mObjects.end(); for(ObjectIT it = mObjects.begin(); it != objectsEnd; ++it) { if(*it == aObj) { return; } } ObjectIT staticObjectsEnd = mStaticObjects.end(); for(ObjectIT it = mStaticObjects.begin(); it != staticObjectsEnd; ++it) { if(*it == aObj) { return; } } if(!aStatic) mObjects.push_back(aObj); else mStaticObjects.push_back(aObj); }
/** * @brief Print circle info * @param _circle Circle to print */ void print_circle(Circle const &_circle) { DebugLogPrint("\n"); DebugLogPrint("-------------------------\n"); DebugLogPrint("RESULTS:\n"); DebugLogPrint("-------------------------\n"); DebugLogPrint("CIRCLE:\n"); DebugLogPrint("POSITION:\n"); print_vector(_circle.position); DebugLogPrint("UP:\n"); print_vector(_circle.up); DebugLogPrint("RIGHT:\n"); print_vector(_circle.right); DebugLogPrint("RADIUS: %f\n", _circle.radius); }
/** * @brief Get data of shader based on file name. * @param aFilename Name of shader file. * @return Data of shader file. Will assert if file not found. */ ShaderData const& GraphicsManager::GetShaderData(HashString const &aFilename) const { std::map<HashString, ShaderData>::const_iterator pos = mShaders.find(aFilename); if(pos == mShaders.end()) { DebugLogPrint("No shader with name %s found\n", aFilename.ToCharArray()); assert(!"No shader found."); } return pos->second; }
/** * @brief Interact with another game object * @param aObject Object to interact with */ void GameObject::Interact(GameObject *aObject) { DebugLogPrint("%s collided into %s\n", mName.ToCharArray(), aObject->GetName().ToCharArray()); }
/** * @brief Load shaders. * @param aVertexShaderFilename Name of vertex shader. * @param aFragmentShaderFilename Name of fragment shader. */ void PCShaderSurface::LoadShaders(HashString const &aVertexShaderFilename, HashString const &aFragmentShaderFilename) { mVertexShaderFileName = aVertexShaderFilename; mFragmentShaderFileName = aFragmentShaderFilename; HashString shaderKey = aVertexShaderFilename + aFragmentShaderFilename; if(GetManager()->ShaderDataExists(shaderKey)) { mProgramID = GetManager()->GetShaderData(shaderKey).mProgramID; return; } std::ifstream vertexFile(Common::RelativePath("Shaders", aVertexShaderFilename.ToCharArray()).c_str()); std::ifstream fragmentFile(Common::RelativePath("Shaders", aFragmentShaderFilename.ToCharArray()).c_str()); if(vertexFile.is_open() && fragmentFile.is_open()) { GLenum program = glCreateProgram(); GLenum vertexShader = glCreateShader(GL_VERTEX_SHADER); GLenum fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); GLint didCompile = 0; GLint isLinked = 0; HashString vertexFileContents = std::string((std::istreambuf_iterator<char>(vertexFile)), std::istreambuf_iterator<char>()); const char* vertexContents = vertexFileContents.ToCharArray(); // Compile glShaderSource(vertexShader, 1, &vertexContents, NULL); glCompileShader(vertexShader); glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &didCompile); if(didCompile == GL_FALSE) { DebugLogPrint("VERTEX SHADER %s READ:\n%s\n", aVertexShaderFilename.ToCharArray(), vertexContents); GLint maxLength = 0; glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength); //The maxLength includes the NULL character std::vector<char> infoLog(maxLength); glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]); DebugLogPrint("GLERROR %s: %s\n", aVertexShaderFilename.ToCharArray(), &infoLog[0]); //We don't need the shader anymore. glDeleteShader(vertexShader); } HashString fragmentFileContents = std::string((std::istreambuf_iterator<char>(fragmentFile)), std::istreambuf_iterator<char>()); const char* fragmentContents = fragmentFileContents.ToCharArray(); glShaderSource(fragmentShader, 1, &fragmentContents, NULL); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &didCompile); if(didCompile == GL_FALSE) { DebugLogPrint("FRAGMENT SHADER %s READ:\n%s\n", aFragmentShaderFilename.ToCharArray(), fragmentContents); GLint maxLength = 0; glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength); //The maxLength includes the NULL character std::vector<char> infoLog(maxLength); glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]); DebugLogPrint("GLERROR %s: %s\n", aFragmentShaderFilename.ToCharArray(), &infoLog[0]); //We don't need the shader anymore. glDeleteShader(fragmentShader); } // Linking glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &isLinked); if(isLinked == GL_FALSE) { GLint maxLength = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); //The maxLength includes the NULL character std::vector<GLchar> infoLog(maxLength); glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]); //We don't need the program anymore. glDeleteProgram(program); //Don't leak shaders either. glDeleteShader(vertexShader); glDeleteShader(fragmentShader); DebugLogPrint("GL LINK ERROR: %s\n", &infoLog[0]); } GetManager()->AddShaderPairing(shaderKey, ShaderData(program, vertexShader, fragmentShader, vertexContents, fragmentContents)); mProgramID = program; } else { DebugLogPrint("No shader with name %s or %s found\n", aVertexShaderFilename.ToCharArray(), aFragmentShaderFilename.ToCharArray()); assert(!"Shader file not found."); } }
/** * @brief Get all possible collisions with another line * @param aCompare Line to check * @param aOutput Output circle * @return If circle is found or not */ bool Line::GetCollisions(Line const &aCompare, Circle &aOutput) { Vector3 d = aCompare.position - position; float dist = d.length(); float longer = length >= aCompare.length ? length : aCompare.length; float shorter = length >= aCompare.length ? aCompare.length : length; print_line(*this); print_line(aCompare); // If they're in the exact same location that would be a problem if (position == aCompare.position) { // IS THIS THE SAME EXACT SPHERE?! if (length == aCompare.length) { aOutput.position = position; aOutput.radius = length; aOutput.up = Vector3(0, 1, 0); aOutput.right = Vector3(0, 0, 1); DebugLogPrint("Same exact sphere, gonna return false\n\n"); } else { DebugLogPrint("One sphere is inside of another, WAT\n"); DebugLogPrint("Therefore, cannot touch, gonna return false\n\n"); } print_circle(aOutput); DebugLogPrint("\n\n"); return false; } // > is an early out if (dist < length + aCompare.length && dist != longer - shorter) { // THE IDEA: Find one point, rotate about arbitrary axis between spheres // Reduce the problem to solving a circle Vector3 axis = d.normalize(); float xylength = sqrt(axis.x * axis.x + axis.y * axis.y); float xyzlength = axis.length(); // Don't want to divide by zero float templength = xylength > 0.0f ? xylength : 1.0f; // Our matrices // First, go to xz plane float xzvalues[3][3] = { { axis.x / templength, axis.y / templength, 0 }, { -axis.y / templength, axis.x / templength, 0 }, { 0, 0, 1 } }; // Then, only to z axis float zvalues[3][3] = { { axis.z / xyzlength, 0, -xylength / xyzlength }, { 0, 1, 0 }, { xylength / xyzlength, 0, axis.z / xyzlength } }; // Create identity matrix if we're already on the z plane if (xylength <= 0.0f) { xzvalues[0][0] = 1.0f; xzvalues[1][1] = 1.0f; xzvalues[1][0] = 0.0f; xzvalues[0][1] = 0.0f; } // Create our matrices and invert them Matrix33 xztrans(xzvalues); Matrix33 ztrans(zvalues); Matrix33 toZAxis = ztrans * xztrans; Matrix33 toZAxisInverse = toZAxis.Invert(); Vector3 comparePos = toZAxis * d; dist = comparePos.length(); // Circle collision function float z = ((dist * dist) - (aCompare.length * aCompare.length) + (length * length)) / (2.0f * dist); float y = sqrt((length * length) - (z * z)); // Create our circle aOutput.position = Vector3(0, 0, z); aOutput.up = Vector3(0, 1, 0); aOutput.right = Vector3(0, 0, 1); aOutput.radius = y; aOutput.position = toZAxisInverse * aOutput.position; aOutput.position += position; aOutput.up = toZAxisInverse * aOutput.up; aOutput.right = toZAxisInverse * aOutput.right; } else if (dist == length + aCompare.length) { // They barely touch, from the outside Vector3 largerPos = length >= aCompare.length ? position : aCompare.position; Vector3 smallerPos = length >= aCompare.length ? aCompare.position : position; float smallerLen = length >= aCompare.length ? aCompare.length : length; d = smallerPos - largerPos; DebugLogPrint("The radii barely touch, will still return true, but radius is zero\n"); aOutput.position = smallerPos - (d.normalize() * smallerLen); aOutput.radius = 0; aOutput.up = Vector3(0, 1, 0); aOutput.right = Vector3(0, 0, 1); } else if (dist == longer - shorter) { // They barely touch, from the inside Vector3 largerPos = length >= aCompare.length ? position : aCompare.position; Vector3 smallerPos = length >= aCompare.length ? aCompare.position : position; float smallerLen = length >= aCompare.length ? aCompare.length : length; d = smallerPos - largerPos; DebugLogPrint("The radii barely touch, will still return true, but radius is zero\n"); aOutput.position = smallerPos + (d.normalize() * smallerLen); aOutput.radius = 0; aOutput.up = Vector3(0, 1, 0); aOutput.right = Vector3(0, 0, 1); } else { DebugLogPrint("These LineSegments can never touch. Returning false.\n\n"); return false; } print_circle(aOutput); DebugLogPrint("\n\n"); return true; }
void print_vector(Vector3 const &_point) { DebugLogPrint("VECTOR:\n"); DebugLogPrint("X: %f, Y: %f, Z: %f\n", _point.x, _point.y, _point.z); }