Jump to content

  • Log In with Google      Sign In   
  • Create Account


blueshogun96

Member Since 09 Jun 2005
Offline Last Active Today, 03:59 AM

#5124755 Vertex normal calculation for triangle strips?

Posted by blueshogun96 on 18 January 2014 - 08:09 PM

I understand that calculating a normal is a rather simple concept, but for some reason, I can't wrap my head around generating normals for a triangle strip.  What I have is a heightmap and I need normals for lighting.  The whole thing is rendered using triangle strips.

 

Just in case you need a visual, take a look at this code I used to generate vertices and texture coordinates.

void heightmap_t::build_vertices()
{
    float X, Y;
    float x, y, z;
    bool switch_sides = No;
    
    /* Sanity check */
    if( !m_height_data )
        return;
    
    /* 
     * First Pass: determine total number of vertices needed
     */
    m_vertex_count = 0;
    
    for ( X = 0; X <= m_width; X += m_polygon_scale )
    {
        /* Are we switching sides? */
        if( switch_sides )
        {
            for( Y = m_height; Y >= 0; Y -= m_polygon_scale )
            {
                m_vertex_count += 2;
            }
        }
        else
        {
            for( Y = 0; Y <= m_height; Y += m_polygon_scale )
            {
                m_vertex_count += 2;
            }
        }
        
        /* Switch the direction the columb renders to allow fluid tri-strips */
        switch_sides = !switch_sides;
    }
    
    /*
     * Second Pass: Allocate and generate vertices
     */
    
    switch_sides = No;
    m_vertices = new float[m_vertex_count*3];
    m_texcoords = new float[m_vertex_count*2];
    int v = 0;
    
    for ( X = 0; X <= m_width; X += m_polygon_scale )
    {
        /* Are we switching sides? */
        if( switch_sides )
        {
            /* Columns */
            for( Y = m_height; Y >= 0; Y -= m_polygon_scale )
            {
                /* Bottom left vertex */
                x = X;
                y = get_height( X, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
                
                /* Bottom right vertex */
                x = X + m_polygon_scale;
                y = get_height( X + m_polygon_scale, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
            }
        }
        else
        {
            for( Y = 0; Y <= m_height; Y += m_polygon_scale )
            {
                /* Bottom right vertex */
                x = X + m_polygon_scale;
                y = get_height( X + m_polygon_scale, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
                
                /* Bottom left vertex */
                x = X;
                y = get_height( X, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
            }
        }
        
        /* Switch the direction the columb renders to allow fluid tri-strips */
        switch_sides = !switch_sides;
    }
    
    /* Use the vertex data to generate a VBO */
    glGenBuffers( 3, m_vbo );
    glBindBuffer( GL_ARRAY_BUFFER, m_vbo[0] );
    glBufferData( GL_ARRAY_BUFFER, m_vertex_count*3*sizeof(float), m_vertices, GL_STATIC_DRAW );
    glBindBuffer( GL_ARRAY_BUFFER, m_vbo[1] );
    glBufferData( GL_ARRAY_BUFFER, m_vertex_count*2*sizeof(float), m_texcoords, GL_STATIC_DRAW );
}

This is based off of an old tutorial from gametutorials.com.  A bit of a shame that they didn't calculate normals in the heightmap tutorial...

 

My initial idea was to take each triangle individually, and calculate face normals first.  Then I get confused after the 2nd part.  Do I like go each vertex and  match up vertices with matching coordinates, add the normals and re-normalize?  That's the part I'm having trouble wrapping my head around.  My brain is a bit fried at the moment, and I'm in a 24-hour coding competition right now.  Any ideas?  Thanks.

 

Shogun.




#5124576 What to learn to be able to create a 3rd person camera and terrain.

Posted by blueshogun96 on 17 January 2014 - 08:04 PM

There are multiple ways to do this.  I personally prefer the cheap and easy way of doing it.  Take a look at this tutorial written by swiftless: http://www.swiftless.com/tutorials/opengl/camera3.html

 

It uses legacy OpenGL (i.e. glTranslatef and glRotatef), but if you already have your own matrix rotation functions, you can easily replace the legacy/deprecated stuff.  

 

If you prefer a quaternion based camera, take a look at this tutorial by dhpoware: http://www.dhpoware.com/demos/glThirdPersonCamera1.html  (IIRC, it's quaternion based, at least the D3D version is).

 

Hope that helps.

 

Shogun.




#5114795 Colission Avoidance using c++ and opengl

Posted by blueshogun96 on 05 December 2013 - 11:35 PM

Okay, I know it's already been said, but OpenGL is a 2D/3D rendering library, not a game engine, so it's not going to do collision detection for you.  Also, you can't rely on someone else to walk you through everything, while expecting someone else to figure out complex problems for you.

 

Now that I have the obvious out of the way (before someone else can say it again), I'll give you a method of how I personally would approach this, but the implementation is totally up to you.

 

First of all, you may want to consider a few variables here:

 

- How close do I need to be for the object to begin avoiding?

- What direction do I want it to move to avoid me?

- Do I want the avoiding object to dodge me every time, or simply attempt to dodge me if possible?

 

After you have this thought out, you can begin.  I'm going to assume you have an understanding of basic trigonometry.  If you don't, then you're clearly getting a bit ahead of yourself.

 

Now, first you want to at the very least have some code to compute a bounding circle.  Use the distance formula to check whether the user is currently within that "threat range".  If it is, then ideally, you should take the velocity as well as the angle at which the object is being approached.  You should be able to form the angles of direction/avoidance by calculating the angle that the user is approaching the object, and do the same using the velocity to adjust the angle.  With the resulting angle of both, you move the object in that direction at a velocity that you decide, and you should have a desirable result, if not, a result worth tweaking.

 

I've never done this before, but I've done similar things.  It's only hard if you aren't fluent in 2D math.  Of course, no one can simply just write your implementation for you, you have to rely on your own strength if you're going to survive.  Hope this helps.

 

Shogun.




#5051744 Texture filtering on normal and specular maps

Posted by blueshogun96 on 10 April 2013 - 01:36 AM

For starters, it looks like you are just simply using bilinear filtering for those texture maps.  Before you can use anisotropic filtering, you got to have trilinear filtering enabled (which is mipmapping).  Are you creating mipmaps for your normal and specular maps?  Do that first, then use anisotropic filtering.  Antialiasing isn't going to help with this.

 

I wrote an example on how to use anisotropic filtering, but that HDD crapped out and I might have lost it for good =(

 

Shogun.




#5048093 c# opentk - converting screen coords to world coords

Posted by blueshogun96 on 29 March 2013 - 01:32 PM

Glad you got it fixed.  Sorry I couldn't have been more helpful.

 

Just curious, how "not very accurate is it"?  Are you accounting for the window's height and the title bar?

 

Shogun.




#5047318 c# opentk - converting screen coords to world coords

Posted by blueshogun96 on 27 March 2013 - 12:16 PM

Okay then, my next guess would be to change this (but after reverting the previous changes I suggested).

 

vec.Y = (2.0f * mouse.Y / (float)viewport.Height - 1);

 

Try removing the '-' and see if that works.

 

Also, sorry I didn't better explain what I was doing with the matrix suggestion.  13 is the column based matrix's location of the Y translation coordinate.  

 

| 1 0 0 X |
| 0 1 0 -Y |
| 0 0 1 Z |
| 0 0 0 1 |

 

I simply suggested you invert it.  I also had to do this to get my vertex projection code to work properly.

 

Hopefully, my suggestion helps a bit better this time.  Sorry for any confusion.

 

Shogun.

 

EDIT: This may or may not matter for you, but I had to invert the incoming Y coordinate and the Y component of the translation vector in my modelview matrix in order to fix the problem.




#5047281 c# opentk - converting screen coords to world coords

Posted by blueshogun96 on 27 March 2013 - 10:45 AM

Try inverting your Y coordinate before using it.

 

I had this same problem when using my own customized routine to project vertices.  It wasn't until I set the Y coordinate to -Y that it finally worked right.  Tbh, I've never actually had to unproject a vertex as of yet, but I'm quite sure that it's similar to projecting a vertex in OpenGL w/ RH matrices.  So, given that, I'm not 100% sure how you should do it in your code, but I suggest trying this:

 

mouse.Y = -( viewport[3] - y );

 

or this:

 

mouse.Y = viewport[3] + y;

 

I assume the first one would do the trick.

 

Also, I'm assuming this might not apply to you, but I had to invert one component of my modelview matrix as well in order for it to work.

 

modelview[13] = -modelview[13];

 

So, like I said, I'm familiar with your problem, just not 100% sure what order the steps need to be taken to fix it.  I gave it my best shot, so let us know if this works.  smile.png

 

Shogun.




#5045515 Class instances gone wrong!

Posted by blueshogun96 on 21 March 2013 - 11:26 PM

^lol, no worries.  I started C++ before .net and ended up picking up many bad programming practices.  Back then, I was very smug and thought I knew everything (mostly because I stayed in a small town in the midwest where there was no one to challenge what little skill I had, or call me out on my BS).  Even then, I had no excuse.  That what you guys are for. wink.png

 

What if I used the stack instead?

Nope. First, you can't delete things on the stack. And second, even if you manually called the destructor, it's still undefined behavior. If you use the non-trivial destructor in any way before returning from the constructor, it's undefined behavior.

Well, I'd never call delete on a stack object. >.<

 

I was thinking of changing it to this so the constructor returns and the lifecycle begins:

 

int main(...)
{
    game_app_t* app = new game_app_t();
    app->kick_off(); /* Start the main loop */

    return 0;
}

 

Shogun.




#5045118 Class instances gone wrong!

Posted by blueshogun96 on 20 March 2013 - 09:09 PM

Dear C++ newbies, experts and all of you people in between,

 

Today, I ended up doing something really stupid, and I don't want any of you doing what I did today.  If breakpoints and debugging features are part of your IDE, please, for the love of God, please use them!  sad.png

 

While working on a new game concept I thought of a couple of days ago, I stopped and thought to myself "I'm going to use C++ this time and not use pure C to avoid the mistake of letting my cross platform code base getting messy again now that I'm more comfortable with the various mobile and desktop APIs and what not".  So I start writing my basic application classes with portability in mind.  For reasons I don't feel like getting into, I made my decision to use OpenGL via GLUT on MacOSX.  I know, I know, I've never recommended GLUT in the past, but this time, I felt like using it since the game only uses either a mouse or a touch screen anyway (except for the old fashioned exit procedure; the escape key).

 

I don't know about you, but I have a tendancy to think about how I want my app to execute!  I liking having my main() function contain as little code as possible.  With that in mind, I ended up writing my main.cpp file to look like this:

 

game_app_t* app = NULL;

void exit_func()
{
    if( app )
        delete app;
}

//-----------------------------------------------------------------------------
// Name: main
// Desc: Program entry point.
//-----------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
    atexit( exit_func );
    app = new game_app_t;

    return 0;
}

 

Okay, hold on, I promise you the problem with this code is NOT that obvious!  You're probably thinking "Yeah, no s@#% sherlock! You didn't call delete or your game loop function!"  Actually, I did.  The class constructor calls the initialization function where glutMainLoop is called upon success.  Instinctively, I check my code to verify that everything is uninitialized properly, even more than I check for successful initialization.  So I put a breakpoint inside of exit_func to verify that it's being called (well, I knew the function works, but I habitually check anyway).  Just in case you're wondering, the code for my class (the initialization stuff) looked like this:

 


#include "game.h"
#include <assert.h>


/* Useful macros */
#define safe_delete(x) if(x) { delete x; x = NULL; }
#define fail_safe(x) if(!x) return;

/* Global class instance */
game_app_t* This = NULL;


/* Default constructor/deconstructor */
game_app_t::game_app_t()
{
    this->init();
}

game_app_t::~game_app_t()
{
    this->uninit();
}

/* Initialization and uninitialization */
bool game_app_t::init()
{
    /* Set global class instance */
    This = this;
    
    /* Initialize OpenGL */
    m_ogldrv = new ogldrv_t();
    assert( m_ogldrv != NULL );
    
    if( !m_ogldrv->init( 0, NULL, 640, 480, GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH, "Loop-til" ) )
        return false;
    
    /* Set default callbacks */
    glutDisplayFunc( this->display_func );
    glutIdleFunc( this->idle_func );
    glutKeyboardFunc( this->keyboard_func );
    glutReshapeFunc( this->reshape_func );
    glutMouseFunc( this->mouse_click_func );
    glutPassiveMotionFunc( this->mouse_move_func );
    
    /* Start the main loop */
    glutMainLoop();
    
    return true;
}

void game_app_t::uninit()
{
    safe_delete( m_ogldrv );
}

/* Event callback functions */
void game_app_t::display_func()
{
    fail_safe(This->m_ogldrv);
    
    /* Clear the rendering buffers */
    This->m_ogldrv->clear_buffers();
    
    /* Swap the double buffer */
    This->m_ogldrv->swap_buffers();
}

void game_app_t::idle_func()
{
    glutPostRedisplay();
}

/* Blah blah blah */

 

 

And yes, the event callback functions were declared as static, so I needed an extra copy of my this pointer.  Since there only needs to be one instance of this class, it doesn't really matter, IMHO.

 

This is where I found my REAL problem: app is still NULL!  I was kinda dumbfounded when I realized that the class instance didn't get uninitialized (hence my deconstructor was never called).  I spent a few minutes going over the code to see why this wasn't working.  The last thing I wanted was to be leaking memory every launch.  After a few more moments of scratching my head, I realized that the problem was that it the call to "new" doesn't return anyway.  So the logical thing to do was to use the copy of my this pointer and delete that explicitly instead.  After that thought, I added another function:

 

void game_app_t::exit_func()
{
    safe_delete(This);
}


/* Added after setting all the other callbacks */
atexit( this->exit_func );

 

So, I added a breakpoint, ran my app in debug mode, and this time, my class instance not only gets deleted properly, but now my deconstructor gets called, and calls the uninit function.  Bam, problem solved!  Now my main function looks like this:

int main( int argc, char* argv[] )
{
    new game_app_t;

    return 0;
} 

 

So short, so sweet.  Isn't C++ great once you use it properly?

 

So, the moral of the story is- "Don't be as stupid as Shogun?"  Yeah, that too, but please, use your breakpoints and always, ALWAYS, cover your digital butt!  I've seen a handful of rookie game programmers who have never learned to use breakpoints (I was one of those).  What I did was dumb.  I made this mistake for you, please don't do it for yourself. ph34r.png

 

Shogun.

 

 




#5043762 a way to port a code?

Posted by blueshogun96 on 16 March 2013 - 02:43 PM

Portability is something to consider BEFORE you begin coding a project.  It's best to plan out a wrapper class or function(s) to suit functionality for both APIs.  Create something fairly high level so that changing it would be simple enough to do with minimal hassle.

 

I do agree with Joyal to a certain degree, but I'd propose a slightly different approach.  If you're using Windows, I recommend instead of compiling Direct3D and OpenGL code in the same binary, create seperate .dll files that you load manually to support whatever API the user needs or requires.  This is what the Unreal Engine does (or did, at least).  In a .dll, you can explicitly export classes, functions and variables and load them manually using ::LoadLibrary and GetProcAddress.  It's also convenient if you plan on supporting multiple versions of Direct3D, because it helps prevent naming collisions and what not.  I just see it as less hassle to do it this way, unless you're under another platform besides windows that uses only one API like OpenGL, or a custom API for consoles.

 

Just make sure you think things through before taking action.  It will save you much trouble in the long run.

 

Shogun.




#5042987 Gain experience by learning(studying) or by doing?

Posted by blueshogun96 on 14 March 2013 - 01:57 AM

My opinion, until you actually apply what you have studied, how do you really know if you've learned anything? smile.png

 

As you study, continuously try to put that new found knowledge into practice somehow.  If you are reading a book or tutorial, feel free to deviate a bit by tinkering with the code to see what changes can do what.  You'll never know when you find an interesting way of doing things.

 

One thing I like to do is read the MSDN documentation on certain functions (assuming you're on Windows).  This way, not only do you understand how the functions work and what different paremters you can use, but at the bottom of the page, Microsoft usually lists some closely related and similar functions.  I've learned much by doing this.  You can do this for Win32 APIs and DirectX.  Win32 is alot of fun once you really get into it (especially multithreading; I enjoy the potential challenge and nightmare of multithreaded code).

 

My final bit of advice is the same advice I give everybody.  Don't rush yourself or bite off more than you can chew.  Study at your own pace, a pace that works best for you!

 

Shogun.




#5042944 programming game levels

Posted by blueshogun96 on 13 March 2013 - 08:33 PM

I don't know what type of 2D game you're creating, but for level design, I'd recommend creating a level editor, if you haven't already.  First you need a clear definition and a list of what your game's levels will contain, then create your tool to save level data defining where walls, doors, enemy respawn points, whatever, into a scripting file like .xml or a custom format.  Using your own level editor would make your life much easier.  This way, you can put the relevant data in the right places upon load time. smile.png

 

Shogun




#5042938 Cuda / OpenCL vs Rendered Textures

Posted by blueshogun96 on 13 March 2013 - 07:53 PM

If you want a basic rundown of how CUDA compares to OpenCL and vice versa, read this: http://streamcomputing.eu/blog/2010-04-22/difference-between-cuda-and-opencl/

 

I myself am just getting started learning CUDA.  Currently, I'm reading the book known as "CUDA C by Example".  Like MJP already stated, it's very much like C and I haven't used OpenCL yet either.

 

I'd say they are both a bit overkill for a simple particle engine (unless you're massively drawing and updating millions of particles like rain or snow).  I've seen raytracing done using shaders many times before, so it depends on what scale you're doing it on, I guess.  Like I said, I'm still learning this myself. ^^

 

Shogun.




#5042545 [Solved] Difference between GL_ARRAY_BUFFER and GL_ARRAY_BUFFER_ARB?

Posted by blueshogun96 on 12 March 2013 - 07:28 PM

I wondered this for a time, but I think that it doesn't really matter which one you use.  Tbh, I even put it to the test with OpenGL and OpenGL ES.  Each and every time, the same result... it worked! happy.png

 

Now, when you have two or more different extensions (i.e. GL_NV_texture_rectangle vs GL_ARB_texture_rectangle vs GL_EXT_texture_rectangle), then chances are you have a vendor specific extension, where using the ARB version is optimal.




#5042544 Chess and OpenGL

Posted by blueshogun96 on 12 March 2013 - 07:23 PM

Question, how new are you to OpenGL?  I have the feeling you're getting a bit ahead of yourself; trying to take on a project that may be a bit too large for your current skill level.  Sorry if I'm wrong, but that's sorta the vibe I'm getting.

 

If you already have your chess pieces exported from 3dsmax, what you need to do is export them to a 3d file format that's easy to read/parse.  3DS, MD2, LWO, OBJ, etc. are good formats to start off with.  If you have never written a 3D mesh file loader, then you need to start there.  After you've chosen your file format, you need to read in the vertex data and then you translate the meshes to their respective positions.  If you know the size of your chess board, then putting the chess peices in their respective squares just requires you to translate them by multiplying the square size by the number of squares from the origin.

 

Back to the 3D loader part, if you cannot write your own 3D loader, then give Assimp a try: http://assimp.sourceforge.net/

 

If you want some sample code that specifically deals with a chess game with OpenGL, check out the SGI page here and click the chess example: http://www.sgi.com/products/software/opengl/examples/more_samples/

 

There's another one out there, but I can't remember where it is.  I'll have to find it again because it actually plays through an entire game of chess while moving the pieces on it's own.

 

Shogun.






PARTNERS