   a few questions concerning my first 2d game engine
  Hi,I'm currently coding my first 2d game engine using SDL for windowing/input, OpenGL for rendering, and OpenAL for audio.  I'm coding it alongside a game of course, and that game is a port of Arkanoid.  I figured this would be a good project that I'd actually likely be able to finish. I've got 2 questions mainly:1. I've recently come across a bug I can't seem to overcome.  I've searched for someone having a similar issue and found nothing.  It's been an obstacle for over a week now, so I've decided to reach out for help.I have a Texture class, a Quad class, and a Sprite class.  The Sprite class has an instance of a Quad class as a member variable.  And the Quad has an instance of the texture class as a member variable.  I'm currently not utilizing the sprite class yes, I'm just working with the quad class directly for putting a textured quad on the display.  The issue lies in me instantiating the Quad class, then accessing the Texture class within to load a png file as a texture. So something like:Quad myQuad;myQuad.getTexture().loadImage("texture.png");Now when I step through the code using the debugger, it goes into the texture class, uses the loadImage function, creates a texture and returns a GLuint (for the texture ID) which ends up being 1.  This is as expected.Now if I draw the quad:myQuad.Draw();And step through THAT function, where it of course enables texturing for opengl etc, then binds the texture using:glBindTexture(GL_TEXTURE_2D,m_texture.getTextureID());m_texture is the instance of the texture class, and getTextureID() returns the GLuint that was created from the loadImage function.  The problem is the texture doesn't display, I just get a white quad.  Stepping through shows me that it's returning 0 for the textureID (even tho it should be set to 1).  If I simply change the call to:glBindTexture(GL_TEXTURE_2D,1); then of course it works.  It's baffling me as I can literally have one line after the other like:myQuad.getTexture().loadImage("texture.png");myQuad.getTexture().getTextureID();Step throught the code in the first line and it indeed generates the texture and gives it an ID of 1...  then step through the code in the second line, and it returns a 0.  I think it's something REALLY stupid and small that I'm missing, but have just been looking at the code so long it's not showing itself to me.2. Is there a better way for me to do this?  Is there a major flaw in my architecture?  Instead of a texture class should I have a texture_cache class or texture_manager class of some sort that holds all of my textures and the quads/sprites draw from it?  The only downfall that I KNOW of in my approach is that it's wasteful on memory because each sprite has it's own texture, so even sprites using identical textures would be using extra memory due to it's own copy of the texture.  But is there any other issues with this?Texture class loadTexture() function in the texture class setting the texture_id member variableGLuint Texture::loadTexture(const char* file)    {  SDL_Surface* surface = IMG_Load(file);  GLuint texture;  glPixelStorei(GL_UNPACK_ALIGNMENT,4);  glGenTextures(1, &texture);  glBindTexture(GL_TEXTURE_2D, texture);  SDL_PixelFormat *format = surface->format;  if (format->Amask)  {gluBuild2DMipmaps(GL_TEXTURE_2D, 4,   surface->w, surface->h, GL_RGBA,GL_UNSIGNED_BYTE, surface->pixels);  }  else  {gluBuild2DMipmaps(GL_TEXTURE_2D, 3,   surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);  }  SDL_FreeSurface(surface);  m_texture_id = texture; // <----- m_texture_id being set  return texture;    }Texture class getTextureID() function:GLuint getTextureID()   {return m_texture_id;}Quad class draw() functionvoid Quad::draw(){   glLoadIdentity();   // textured quad specific code   if (m_isTextured)   {  glEnable(GL_TEXTURE_2D);  // this line always returning a 0 for getTextureID()!!!!!!  glBindTexture(GL_TEXTURE_2D,m_texture.getTextureID());   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);  glEnableClientState(GL_TEXTURE_COORD_ARRAY);    glTexCoordPointer(2, GL_FLOAT, 0, &m_texture.getTexCoords()[0]);   };   glEnableClientState(GL_VERTEX_ARRAY); // We want a vertex array   glVertexPointer(2, GL_FLOAT, 0, &m_vertices[0]);   // All values are grouped to three Floats, we start at the beginning of the array (offset=0) and want to use m_vertices as VertexArray   // draw the quad   glTranslated(this->m_position.x, this->m_position.y, 0);   glRotatef(this->m_rotation.x,1.0,0.0,0.0);   glRotatef(this->m_rotation.y,0.0,1.0,0.0);   glRotatef(this->m_rotation.z,0.0,0.0,1.0);   glColor3f(this->m_color.x, this->m_color.y, this->m_color.z);   glDrawArrays(GL_QUADS, 0, 4);   glRotatef(this->m_rotation.z,0.0,0.0,-1.0);   glRotatef(this->m_rotation.y,0.0,-1.0,0.0);   glRotatef(this->m_rotation.x,-1.0,0.0,0.0);   glTranslated(-this->m_position.x, -this->m_position.y, 0);   // disable using the vertex and texture array   glDisableClientState(GL_VERTEX_ARRAY);   if (m_isTextured)   {  glDisableClientState(GL_TEXTURE_COORD_ARRAY);  glDisable( GL_TEXTURE_2D );   };}Again, my idea is to create a texture manager instead of each Quad having a copy of a texture class...  but is there any reason the way I'm doing it isn't working?  If you guys need any more of the code I'll gladly post, I just thought I'd post the pertinent parts...Thanks for any help, I REALLY appreciate it.  I HATE not being able to figure stuff out.   
  If it's ok with you, could you please post all the code for the Quad class? Each Quad has its own Texture instance, right? and you're calling loadTexture() on each instance, right?   ;  Yes each quad has it's own texture instance.I'll post as much code as you want, because it will be opensource anyhow.#ifndef NEXYZ_QUAD_H_INCLUDED#define NEXYZ_QUAD_H_INCLUDED#include <vector>#include "NeXYZ_Vector.h"#include "NeXYZ_Texture.h"namespace NeXYZ{    class Quad    {   private:  NeXYZ::Vector3 m_position;  // position in x,y,z space  NeXYZ::Vector2 m_size; // size w, h  NeXYZ::Vector3 m_rotation;  // rotation around x,y,z axis  NeXYZ::Vector3 m_color;// floating point r,g,b color  NeXYZ::Texture m_texture;   // texture class  std::vector<NeXYZ::Vector2> m_vertices;// quad's vertex buffer  bool m_isTextured;  // is this a textured quad?   public:  Quad();~Quad();void init(float positionX, float positionY, float positionZ, float sizeW, float sizeH, float rotationX, float rotationY, float rotationZ, float colorR, float colorG, float colorB  );  // accessors  NeXYZ::Vector3 getPosition()    {return m_position;}  float getPositionX()  {return m_position.x;}  float getPositionY()  {return m_position.x;}  float getPositionZ()  {return m_position.x;}  NeXYZ::Vector2 getSize()   {return m_size;}  float getSizeW() {return m_size.x;}  float getSizeH() {return m_size.y;}  NeXYZ::Vector3 getRotation()    {return m_rotation;}  float getRotationX()  {return m_rotation.x;}  float getRotationY()  {return m_rotation.y;}  float getRotationZ()  {return m_rotation.z;}  NeXYZ::Vector3 getColor()  {return m_color;}  float getColorR(){return m_color.x;}  float getColorG(){return m_color.y;}  float getColorB(){return m_color.z;}  NeXYZ::Texture getTexture(){return m_texture;}  // mutators  void setPosition(NeXYZ::Vector3 position)   {m_position = position;}  void setPositionX(float positionX){m_position.x = positionX;}  void setPositionY(float positionY){m_position.y = positionY;}  void setPositionZ(float positionZ){m_position.z = positionZ;}  void setSize(NeXYZ::Vector2 size) {m_size = size;}  void setSizeW(float sizeW)   {m_size.x = sizeW;}  void setSizeH(float sizeH)   {m_size.y = sizeH;}  void setRotation(NeXYZ::Vector3 rotation)   {m_rotation = rotation;}  void setRotationX(float rotationX){m_rotation.x = rotationX;}  void setRotationY(float rotationY){m_rotation.y = rotationY;}  void setRotationZ(float rotationZ){m_rotation.z = rotationZ;}  void setColor(NeXYZ::Vector3 color)    {m_color = color;}  void setColorR(float colorR) {m_color.x = colorR;}  void setColorG(float colorG) {m_color.y = colorG;}  void setColorB(float colorB) {m_color.z = colorB;}  void setTexture(NeXYZ::Texture texture){m_texture = texture;}  void setIsTextured(bool isTextured)    {m_isTextured = isTextured;}  // methods  void draw();    };};#endif // NEXYZ_QUAD_H_INCLUDED#include "NeXYZ_Quad.h"namespace NeXYZ{    Quad::Quad():    m_position(0,0,0),    m_size(0,0),    m_rotation(0,0,0),    m_color(0,0,0)    {}Quad::~Quad(){}void Quad::init(float posX=0, float posY=0, float posZ=0, float sizeW=0,float sizeH=0, float rotX=0, float rotY=0, float rotZ=0,float colorR=0, float colorG=0, float colorB=0){    m_position.x = posX;    m_position.y = posY;    m_position.z = posZ;   m_size.x = sizeW;   m_size.y = sizeH;   m_rotation.x = rotX;   m_rotation.y = rotY;   m_rotation.z = rotZ;   m_color.x = colorR;   m_color.y = colorG;   m_color.z = colorB;   // quad vertices   m_vertices.push_back(Vector2( -(m_size.x/2), (m_size.y/2)));  // Top Left   m_vertices.push_back(Vector2( (m_size.x/2), (m_size.y/2)));   // Top Right   m_vertices.push_back(Vector2( (m_size.x/2),-(m_size.y/2)));   // Bottom Right   m_vertices.push_back(Vector2( -(m_size.x/2),-(m_size.y/2)));  // Bottom Left}void Quad::draw(){   glLoadIdentity();   // textured quad specific code   if (m_isTextured)   {  glEnable(GL_TEXTURE_2D);  GLuint test = m_texture.getTextureID();  glBindTexture(GL_TEXTURE_2D,m_texture.getTextureID());  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);  glEnableClientState(GL_TEXTURE_COORD_ARRAY);    // and a texture array    glTexCoordPointer(2, GL_FLOAT, 0, &m_texture.getTexCoords()[0]);   };   glEnableClientState(GL_VERTEX_ARRAY); // We want a vertex array   glVertexPointer(2, GL_FLOAT, 0, &m_vertices[0]);   // All values are grouped to three Floats, we start at the beginning of the array (offset=0) and want to use m_vertices as VertexArray   // draw the quad   glTranslated(this->m_position.x, this->m_position.y, 0);   glRotatef(this->m_rotation.x,1.0,0.0,0.0);   glRotatef(this->m_rotation.y,0.0,1.0,0.0);   glRotatef(this->m_rotation.z,0.0,0.0,1.0);   glColor3f(this->m_color.x, this->m_color.y, this->m_color.z);   glDrawArrays(GL_QUADS, 0, 4);   glRotatef(this->m_rotation.z,0.0,0.0,-1.0);   glRotatef(this->m_rotation.y,0.0,-1.0,0.0);   glRotatef(this->m_rotation.x,-1.0,0.0,0.0);   glTranslated(-this->m_position.x, -this->m_position.y, 0);   // disable using the vertex and texture array   glDisableClientState(GL_VERTEX_ARRAY);   if (m_isTextured)   {  glDisableClientState(GL_TEXTURE_COORD_ARRAY);  glDisable( GL_TEXTURE_2D );   };    }};;  It looks like you're returning the texture object by value, which means that when you write:myQuad.getTexture().loadImage("texture.png");You're returning a copy, loading the texture, and then (presumably) throwing it away.To fix this, try returning it by reference instead (this may not be the best option design-wise, but it should work).Also, could you break the longer lines when posting your code? (As is, with smaller screen resolutions, you have to scroll back and forth to read them.)   ;  Sure thing, sorry about the long lines.So you mean return a reference to the texture class as opposed to the texture class itself?Or do you mean the texture ID? Thanks for taking a look at this by the way.  I'm eager to move forward on this.   ;Quote:So you mean return a reference to the texture class as opposed to the texture class itself?Yeah (well, a reference to the texture object, but I know what you mean).This is C++, right? Keep in mind that C++ has different reference/value semantics than languages such as C#, etc. When you write:Texture GetTexture() { return my_texture; }A copy of my_texture is returned, not a reference to it. The copy is not connected to the original in any way, so any changes you make to the copy will not affect the original. I'm pretty sure this is why your code isn't behaving as you expect.However, if you write:Texture& GetTexture() { return my_texture; }A reference (both in the general sense, and in the C++ sense) is returned, which you can then use to modify the object to which it refers.   ;  OMG.  Fantastic.  Thank you SO MUCH.  Fixed with a SINGLE AMPERSAND!Ugh, I feel a bit dumb.  It's been a long time since I coded and I just started getting into it again.  This will help immensely thanks again.  Now, for the second part of my question...I don't seem to see anyone else anywhere doing this the way I am.  i.e. each quad having it's own texture object. Seems everyone has a global texture_cache or manager of some sort and the quads draw their texture data from it instead.  I understand the memory savings this provides, but is that the only difference to how I'm doing it now?Reason being is I'd rather have each object keep track of it's own textures, because eventually an object will have many textures associated with it for animation...  I see how this could be done with a manager and indexing I guess.  Any thoughts?THANK YOU SO MUCH AGAIN! <3   ;  Edit: looks like you got it as I typed this.What jyk is saying is this:You have declared getTexture as follows:NeXYZ::Texture getTexture(){return m_texture;}This means that getTexture will copy m_texture and return that, since the Texture is returned by value.  And as such, when you call loadImage, it is using this copy to load it, never touching the quad's instance of texture.If, instead, you declared the function as follows:NeXYZ::Texture& getTexture(){return m_texture;}Then it would return a reference to the class' actual texture object.  In doing so, when you called loadImage, it would now actually use the quad's instance of texture and everything should work as expected.   ;Quote:Seems everyone has a global texture_cache or manager of some sort and the quads draw their texture data from it instead.  I understand the memory savings this provides, but is that the only difference to how I'm doing it now?Reason being is I'd rather have each object keep track of it's own textures, because eventually an object will have many textures associated with it for animation...  I see how this could be done with a manager and indexing I guess.The typical solution is to use a cache of some sort, as you said. Potential advantages of this approach include:1. More efficient use of system and/or video memory.2. Less texture thrashing.3. Centralized management of resources (all in one place, so easier to deal with).4. Faster loading/reloading (one load per texture rather than one per sprite/quad).If it's a simple game with only a few different sprites, it probably won't matter either way, but for anything non-trivial I'd recommend switching to a cache-based system. A typical approach is to have a single object or module that manages the textures (although some don't like the word 'manage' ;), and passes out references/handles to them on request. As for what to use for 'handles', a reference-counted smart pointer such as boost/tr1::shared_ptr is often a good choice.   ;Quote:Reason being is I'd rather have each object keep track of it's own textures, because eventually an object will have many textures associated with it for animation...  I see how this could be done with a manager and indexing I guess.I wouldn't handle animations in such a low-level way: you'll want to wrap up that functionality in a separate class. Let's say, an AnimationData class that stores a list of texture references and associated frame durations (and perhaps rectangles - so you can display only part of a texture, which allows you to use spritesheets). As with textures, animation data can be cached as well. Quads do need to keep track of what frame they're currently displaying and how much time they have left before switching to the next frame, but multiple quads can reference the same AnimationData objects - and multiple AnimationData objects can reference the same Textures.   