Jump to content

  • Log In with Google      Sign In   
  • Create Account


bensmith87

Member Since 02 Jul 2008
Offline Last Active Jul 14 2012 11:04 PM
-----

Topics I've Started

Mouse picking with GLSL

08 February 2011 - 07:29 PM

Hi,
Using an OpenGL 3.1 core profile I've been trying to get mouse picking to work.

I want to be able to render each object with a simple GLSL shader that outputs a color corresponding to the ID of the object, more precisely I wanted the red component to be an unsigned char that has the ID of the player that the object belongs to, the green to contain the type of object (character, building, map resource, etc...) and the blue component to contain the ID of the object.

I have created a FBO with a texture for the color attachment the size of the screen and GL_RGB8 for the internal format and GL_UNSIGNED_BYTE for the type...
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

I bind this FBO, render the scene with the picking shader, and then get the pixel from the texture at the mouse location.

So, my questions are...
  • Will this work?
  • How do I make the outFragColor in the shader the exact char values I want?

Thanks for any help.

Qt Simple Tree Model Question

25 July 2009 - 11:04 AM

Hi, I'm working on my own scene editor for my game engine using Qt. I have implemented a tree view with a custom model to represent my scene graph, and it works great, I'm able to add and delete nodes. However, the root node is not visible, which is a problem, as I cant select it, therefore I cant add nodes under it. I followed through this example, but I didn't understand exactly what I was doing :( So, I have tried changing things all over the place, but every time it ends in a seg fault, If anyone knows what needs modifying to show the root item it would be greatly appreciated. Thanks in advance. Also, what is the best Qt book? Edit: made the link a clicky, made subject solved [Edited by - ApochPiQ on July 29, 2009 6:32:42 PM]

[SOLVED] QGLWidget and glew

20 July 2009 - 11:01 PM

Hi, I'm in the process of making an editor for an engine I'm working on. Just a learning experience really. Anyway, my call to glewInit() fails. Here is the relevant code...
class Renderer : public QGLWidget
{
public:
    Renderer();
    
    void addMeshNode(MeshNode *aMeshNode);
    
    void setCamera(Camera *aCamera);

    void initializeGL();
    void resizeGL(int aWidth, int aHeight);
    void paintGL();

private:
    std::vector<MeshNode *> fMeshNodes;
    Camera *fCamera;
    int fWidth;
    int fHeight;
};



void Renderer::initializeGL()
{
    std::cout << this << " Renderer::initializeGL()\n";

    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        std::cout << "error: glewInit() failed\n";
    }

    glShadeModel(GL_SMOOTH);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}



I thought the only way it would fail, was if the OpenGL context hadn't been created yet, but I'm calling it after my QGLWidget has been created. Any help would be appreciated, I couldn't get glee to work either. I'm on Linux, using the latest QT Creator. Thanks in advance [Edited by - bensmith87 on July 21, 2009 5:36:50 PM]

GUI Design Questions

15 March 2009 - 02:26 PM

Hi all, I'm writing a GUI, I have a couple of reasons to do so, to improve my OO skills, and so that I can use it in future projects. Here is what I have written so far. It should compile under Linux if linked with the libs SDL, SDL_ttf and SDL_gfx. So I guess it might compile under winblows also. main.cpp, sample GUI setup ...
#include "video.h"
#include "gui.h"

#include <iostream>


using namespace std;


int handleEvents(GUIManager *gui)
{
  SDL_Event event;

  while(SDL_PollEvent(&event))
  {
		switch(event.type)
    {
			case SDL_KEYDOWN:
        if(event.key.keysym.sym == SDLK_ESCAPE)
          return 0;
				break;

      case SDL_MOUSEBUTTONDOWN:
          gui->onClick(event.button.x, event.button.y);
        break;

			case SDL_QUIT:
				return 0;
				break;
		}
	}
  return 1;
}


class QuitButton : public Button
{
  public:
    bool mQuit;
    QuitButton(string text, int positionX, int positionY, int width, int height) :
      Button(text, positionX, positionY, width, height)
    {
      mQuit = false;
    }

    void onClickVirtual()
    {
      mQuit = true;
    }
};


class MyButton : public Button
{
  public:
    MyButton(string text, int positionX, int positionY, int width, int height) :
      Button(text, positionX, positionY, width, height) { }

    void onClickVirtual()
    {
      cout << "myButton has been clicked\n";
    }
};


class MyCheckBox : public CheckBox
{
  public:
    MyCheckBox(string text, int positionX, int positionY, int width, int height) :
      CheckBox(text, positionX, positionY, width, height) { }

    void onClickVirtual()
    {
      cout << "myCheckBox has been toggled\n";
    }
};


int main()
{
  Video video;
  video.setup(640, 480, 32, 0);

  GUIManager gui;

  Control::loadFont();

  Frame baseFrame(10, 10, 620, 460);

  gui.setRootControl(&baseFrame);

  Frame frame1(10, 10, 200, 200);
  Frame frame2(10, 220, 200, 200);
  Surface surface(220, 10, 390, 440);
  QuitButton quitButton("Quit", 10, 430, 60, 20);

  baseFrame.addChildControl(&frame1);
  baseFrame.addChildControl(&frame2);
  baseFrame.addChildControl(&surface);
  baseFrame.addChildControl(&quitButton);

  MyButton myButton("myButton", 10, 10, 60, 20);
  MyCheckBox myCheckBox("myCheckBox", 10, 30, 80, 20);
  Label myLabel("myLabel", 10, 50);

  frame1.addChildControl(&myButton);
  frame1.addChildControl(&myCheckBox);
  frame1.addChildControl(&myLabel);

  while(handleEvents(&gui) && !quitButton.mQuit)
  {
    video.clear();

    gui.render();

    video.flip();
  }

  return 0;
}

gui.h ...
#ifndef GUI_H_
#define GUI_H_

#include "video.h"

#include <vector>
#include <iostream>


class Control
{
  friend class CompositeControl;
  friend class GUIManager;

  private:

  protected:
    int mPositionRelativeX, mPositionRelativeY;
    int mPositionAbsoluteX, mPositionAbsoluteY;

    static TTF_Font *mFont;
    static int mFontSize;

    static int mNormalFillColor;
    static int mNormalBorderColor;
    static int mFocusFillColor;
    static int mFocusBorderColor;
    static int mTextColor;

  public:
    Control();
    
    virtual void render() = 0;
    virtual void onClick(int clickX, int clickY) = 0;

    static void loadFont();
};


class CompositeControl : public Control
{
  private:

  protected:
    std::vector<Control *> mChildControls;

  public:
    void renderChildren();
    void onClickChildren(int clickX, int clickY);
    void addChildControl(Control *childControl); 
};


class Frame : public CompositeControl
{
  private:
    int mWidth, mHeight;

  protected:

  public:
    Frame(int positionX, int positionY, int width, int height);
    void render();
    void onClick(int clickX, int clickY);
};


class Surface : public Control
{
  private:
    int mWidth, mHeight;
    SDL_Surface *mSurface;
    SDL_Rect mRect;

  protected:

  public:
    Surface(int positionX, int positionY, int width, int height);
    ~Surface();
    void render();
    void onClick(int clickX, int clickY) { clickX = 0; clickY = 0; };
};


class Button : public Control
{
  private:
    int mWidth, mHeight;
    std::string mText;

  protected:

  public:
    Button(std::string text, int positionX, int positionY, int width, int height);
    void render();
    void onClick(int clickX, int clickY);
    virtual void onClickVirtual() = 0;
};


class CheckBox : public Control
{
  private:
    int mWidth, mHeight;
    std::string mText;
    bool mValue;

  public:
    CheckBox(std::string text, int positionX, int positionY, int width, int height);
    void render();
    void onClick(int clickX, int clickY);
    virtual void onClickVirtual() = 0;
};


class Label : public Control
{
  private:
    std::string mText;

  public:
    Label(std::string text, int positionX, int positionY);
    void render();
    void onClick(int clickX, int clickY) { clickX = 0; clickY = 0; };
};


class GUIManager
{
  private:
    Control *mRootControl;

  protected:

  public:
    void setRootControl(Control *rootControl);
    void onClick(int clickX, int clickY);
    void render();
};


#endif

gui.cpp ...
#include "gui.h"

#include <functional>
#include <algorithm>
#include <iostream>

using namespace std;


TTF_Font *Control::mFont = 0;
int Control::mFontSize = 12;

int Control::mNormalFillColor = 0x307080ff;
int Control::mNormalBorderColor = 0x5090a0ff;
int Control::mFocusFillColor = 0x004050ff;
int Control::mFocusBorderColor = 0x002030ff;
int Control::mTextColor = 0xffffffff;


Control::Control()
{
  mPositionRelativeX = 0;
  mPositionRelativeY = 0;
  mPositionAbsoluteX = 0;
  mPositionAbsoluteY = 0;
}


void Control::loadFont()
{
  mFont = TTF_OpenFont("data/arial.ttf", 12);
}


void CompositeControl::renderChildren()
{
  for(vector<Control *>::const_iterator it = mChildControls.begin(); it != mChildControls.end(); ++it)
    (*it)->render();
}


void CompositeControl::onClickChildren(int clickX, int clickY)
{
  for(vector<Control *>::const_iterator it = mChildControls.begin(); it != mChildControls.end(); ++it)
    (*it)->onClick(clickX, clickY);
}


void CompositeControl::addChildControl(Control *childControl)
{
  childControl->mPositionAbsoluteX = mPositionAbsoluteX + childControl->mPositionRelativeX;
  childControl->mPositionAbsoluteY = mPositionAbsoluteY + childControl->mPositionRelativeY;

  mChildControls.push_back(childControl);
}


Frame::Frame(int positionX, int positionY, int width, int height)
{
  mPositionRelativeX = positionX;
  mPositionRelativeY = positionY;
  mWidth = width;
  mHeight = height;
}


void Frame::render()
{
  rectangleColor(SDL_GetVideoSurface(),
    mPositionAbsoluteX, mPositionAbsoluteY,
    mPositionAbsoluteX + mWidth, mPositionAbsoluteY + mHeight, mNormalBorderColor);

  renderChildren();
}


void Frame::onClick(int clickX, int clickY)
{
  if(clickX > mPositionAbsoluteX &&
     clickX < mPositionAbsoluteX + mWidth &&
     clickY > mPositionAbsoluteY &&
     clickY < mPositionAbsoluteY + mHeight)
  {
    onClickChildren(clickX, clickY);
  }  
}


Surface::Surface(int positionX, int positionY, int width, int height)
{
  mPositionRelativeX = positionX;
  mPositionRelativeY = positionY;
  mWidth = width;
  mHeight = height;
  mSurface = 0;
}


Surface::~Surface()
{
  if(mSurface)
    SDL_FreeSurface(mSurface);
}


void Surface::render()
{
  mRect.x = mPositionAbsoluteX;
  mRect.y = mPositionAbsoluteY;
  mRect.w = mWidth;
  mRect.h = mHeight;

  SDL_BlitSurface(mSurface, 0, SDL_GetVideoSurface(), &mRect);

  rectangleColor(SDL_GetVideoSurface(),
    mPositionAbsoluteX, mPositionAbsoluteY,
    mPositionAbsoluteX + mWidth, mPositionAbsoluteY + mHeight, mNormalBorderColor);
}


Button::Button(string text, int positionX, int positionY, int width, int height)
{
  mText = text;
  mPositionRelativeX = positionX;
  mPositionRelativeY = positionY;
  mWidth = width;
  mHeight = height;
}


void Button::render()
{
  boxColor(SDL_GetVideoSurface(),
    mPositionAbsoluteX, mPositionAbsoluteY,
    mPositionAbsoluteX + mWidth, mPositionAbsoluteY + mHeight, mNormalFillColor);

  rectangleColor(SDL_GetVideoSurface(),
    mPositionAbsoluteX, mPositionAbsoluteY,
    mPositionAbsoluteX + mWidth, mPositionAbsoluteY + mHeight, mNormalBorderColor);

  int offset = (mHeight - mFontSize) / 2;

  renderText(mText, mPositionAbsoluteX + offset, mPositionAbsoluteY + offset, mFont); 
}


void Button::onClick(int clickX, int clickY)
{
  if(clickX > mPositionAbsoluteX &&
     clickX < mPositionAbsoluteX + mWidth &&
     clickY > mPositionAbsoluteY &&
     clickY < mPositionAbsoluteY + mHeight)
  {
    onClickVirtual();
  }  
}


CheckBox::CheckBox(string text, int positionX, int positionY, int width, int height)
{
  mText = text;
  mPositionRelativeX = positionX;
  mPositionRelativeY = positionY;
  mWidth = width;
  mHeight = height;
  mValue = false;
}


void CheckBox::render()
{
  int boxSize = 8;
  int offsetBox = (mHeight - boxSize) / 2;
  int offsetText = (mHeight - mFontSize) / 2;

  rectangleColor(SDL_GetVideoSurface(),
    mPositionAbsoluteX, mPositionAbsoluteY + offsetBox,
    mPositionAbsoluteX + boxSize, mPositionAbsoluteY + offsetBox + boxSize, mNormalBorderColor);

  if(mValue)
  {
    boxColor(SDL_GetVideoSurface(),
      mPositionAbsoluteX + 2, mPositionAbsoluteY + offsetBox + 2,
      mPositionAbsoluteX + boxSize - 2, mPositionAbsoluteY + offsetBox + boxSize - 2, mNormalFillColor);
  }

  renderText(mText, mPositionAbsoluteX + offsetBox + boxSize, mPositionAbsoluteY + offsetText, mFont); 
}


void CheckBox::onClick(int clickX, int clickY)
{
  if(clickX > mPositionAbsoluteX &&
     clickX < mPositionAbsoluteX + mWidth &&
     clickY > mPositionAbsoluteY &&
     clickY < mPositionAbsoluteY + mHeight)
  {
    mValue = !mValue;
    onClickVirtual();
  }  
}


Label::Label(string text, int positionX, int positionY)
{
  mText = text;
  mPositionRelativeX = positionX;
  mPositionRelativeY = positionY;
}


void Label::render()
{
  renderText(mText, mPositionAbsoluteX, mPositionAbsoluteY, mFont); 
}


void GUIManager::setRootControl(Control *rootControl)
{
  mRootControl = rootControl;
  mRootControl->mPositionAbsoluteX = mRootControl->mPositionRelativeX;
  mRootControl->mPositionAbsoluteY = mRootControl->mPositionRelativeY;
}


void GUIManager::onClick(int clickX, int clickY)
{
  mRootControl->onClick(clickX, clickY);
}


void GUIManager::render()
{
  mRootControl->render();
}

The inspiration for the design come from this quote on an old thread in these forums. sb01234
Quote:
Some thoughts on overall structure of the management system: Form a tree of controls, using the composite pattern. Panels etc can have children but buttons etc can't. Store a (smart) pointer to the root control in a Manager class. The Manager class should have members onClick, onKeyPress etc (choosing which messages to use requires some careful design), which by performing collision detection etc. forward the messages to the appropriate control by traversing the tree. The manager class will need some book-keeping data such as pointers (for example, boost::weak_ptr or your own equivalent) to currently selected control etc in order to be able to know where to forward keypress calls to. All controls should also have methods onClick, onKeyPress etc. Don't fall into the trap of letting the Manager and Controls inherit from the same base class because they have somewhat similar event methods! They are NOT exactly the same and it is likely you will want to change the set of available messages and their signature in the manager and controls independently of one another. The onClick etc of your controls are part of the internal message representation of your GUI system. The onClick etc of your manager class are typically just raw forwarding of windows events to your manager system. The final aspect is how to deal with messages from controls. A common method is to let the user inherit from a button and overriding the onClick method to get a button with a particular behavior. The template method pattern can be useful here: there are always some things a button needs to do when clicked (such as changing appearance), so don't just make one onClick method. Instead, make two! One which is never overridden and called internally by the manager, and another, which is automatically called by the internally used method, and it is this one that the user overrides. Hope this helps!
My questions are... 1. What do you think of the design thus far? 2. Does each button really need a derived class of its own? 3. How do I handle text input using SDL keyboard events? Should the control have its own event handler, or should all key press's be passed to the control? 4. Is it possible to use OpenGL to render to and SDL_Surface? 5. Any other advice? Thanks in advance.

Physics on Tree Model

23 September 2008 - 11:21 AM

Hi, I've written a short program that simulates a tree growing, it is based on one of Hugo Elias's tutorials (they are all amazing). http://freespace.virgin.net/hugo.elias/models/m_p_tree.htm I'm using a "tree" data structure to store all the branches (duh), and I'm using a polar coordinate system. What I want to do is add soft body physics to it, but am not sure how to do that. I want them to be droopy, blow in the wind etc... I'm using a lot of glMatrixPush and Pop functions, and when the depth of the branches gets too great funky stuff begins to happen, is there a solution to this.
typedef struct sBranch
{
    float angleX;   // this is how much the branch angles away from the previous branch
    float angleY;   // and this angle rotates the previous angle, it is between 0 and 360

    float length;   // the length of the branch at the current time
    float radius;   // the radius of the branch at the current time

    float lengthSprout; // the lenght of the branch when it initially splits into 2
    float growSpeed;    // the speed of growth of both the length and radius
    
    struct sBranch *left, *right;   // pointers to sibling branchs
} tBranch;
tBranch *newBranch(float angleX, float angleY, float length, float radius, float lengthSprout, float growSpeed)
{
    tBranch *branch;

    branch = malloc(sizeof(tBranch));
    if(!branch)
        return NULL;

    branch->angleX = angleX;
    branch->angleY = angleY;
    
    branch->length = length;
    branch->radius = radius;

    branch->lengthSprout = lengthSprout;
    branch->growSpeed = growSpeed;

    branch->left = NULL;
    branch->right = NULL;

    return branch;
}
void growBranch(tBranch *branch, float dt)
{
    float angleXleft, angleYleft;
    float angleXright, angleYright;
    float growLeft, growRight;
    float lengthSproutLeft, lengthSproutRight;
    float radiusLeft, radiusRight;

    if(branch == NULL) return;

    branch->length += branch->growSpeed * dt;
    branch->radius += branch->growSpeed * 0.1f * dt;

    if(branch->length > branch->lengthSprout)
    {
        if(!branch->left)                    // if has no children yet, generate 2 new branchs
        {
            angleXleft = ((double)rand() / (double)(RAND_MAX)) * 90.0f;
            angleYleft = ((double)rand() / (double)(RAND_MAX)) * 360.0f;
            angleXright = angleXleft - 90;
            angleYright = angleYleft - 180;

            growLeft = cos(angleXleft / 57.2f) * branch->growSpeed;
            growRight = cos(angleXright / 57.2f) * branch->growSpeed;
            
            lengthSproutLeft = ((double)rand() / (double)(RAND_MAX)) * 0.1f;
            lengthSproutRight = ((double)rand() / (double)(RAND_MAX)) * 0.1f;
            
            radiusLeft = growLeft * branch->radius;
            radiusRight = growRight * branch->radius;
            
            branch->left = newBranch(angleXleft, angleYleft, 0.0f, radiusLeft, lengthSproutLeft, growLeft);
            branch->right = newBranch(angleXright, angleYright, 0.0f, radiusRight, lengthSproutRight, growRight);
        }
    }

    growBranch(branch->left, dt);
    growBranch(branch->right, dt);
}
void renderBranch(tBranch *branch, GLUquadricObj *quad)
{
    if(branch == NULL)
        return;

    glPushMatrix();
    glRotatef(branch->angleX, 1.0f, 0.0f, 0.0f);
    glRotatef(branch->angleY, 0.0f, 1.0f, 0.0f);

    glPushMatrix();
    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);        // required to orientate the cylinder along the y-axis
    gluCylinder(quad, branch->radius, branch->radius, branch->length, 8, 1);
    glPopMatrix();

    glTranslatef(0.0f, branch->length, 0.0f);   // translate to the end of the branch, so the next ones start in the correct place */

    renderBranch(branch->left, quad);
    renderBranch(branch->right, quad);
    glPopMatrix();
}
So, there is some of the source, I thought it be very cool, use it if you want, and if you have any tips/ideas on how it could be improved, much appreciated.

PARTNERS