usbman3

Members
  • Content count

    26
  • Joined

  • Last visited

Community Reputation

101 Neutral

About usbman3

  • Rank
    Member
  1. I started working on this thing, but lost my motivation. I have bad imagination and I'm out of ideas. [attachment=4910:screenshot.gif] Everything you see is all I have. I'm not sure what the graphics should look like and what should be the game objective etc.. Only one thing is certain: this is going to be a small and simple game (I don't like complicated things). What do you think? Do you want a mini-starcraft? Or shoot 'em up? And do you have any suggestions for the title? Thanks.
  2. Voxels are simple, so I though rendering them would be simple as well. Apparently not. I don't want to spend my life on this, so I forget voxels and start doing something else instead. Thanks for your replies, though.
  3. I have a 3D array of voxels, which represents a landscape (sort of). I wrote a simple function to render these voxels: [code] for each pixel on screen: { calculate the direction and starting position of the ray Vec3 cur_pos = ray_start_pos Voxel voxel = Nothing for( temp=0; temp+=VOXEL_SIZE; temp<RAY_LENGTH ) { voxel = get_voxel( cur_pos ); if ( voxel != Nothing ) break; cur_pos += ray_direction * VOXEL_SIZE } if ( voxel != Nothing ) set_pixel( voxel.r, voxel.g, voxel.b ); else set_pixel( background color ); } [/code] Rendering 80x80x100 (=640k) voxels at resolution 700x444, it takes about 20 seconds to render one frame (on AMD Phenom II X6 @ 3.4 GHz). Although I'm using just one thread for rendering, the performance is absolutely unacceptable! I need at least 25 frames per second. And this algorithm has some other problems than performance as well: [list][*]Aliasing artifacts[*]Some voxels are processed twice[*]Lots of empty voxels are processed even if the ray doesn't hit anything[/list] I have searched the internet but I didn't find any good articles about rendering voxels that don't involve octrees or cuda. So, do you know of any good voxel rendering algorithms?
  4. Quaternions

    I randomly messed with it and finally got it working as it should: [code] static void rotate_bone_2( Bone *bone, float angle ) { float axis[3] = {0.0f}; float rotation[4]; float inverse[4]; float boneRot[4]; // get rotation quaternion axis[the_axis] = 1.0f; axis_to_quat( axis, angle, rotation ); // get original bone rotation memcpy( boneRot, bone->quat, sizeof(float)*4 ); Bone *temp; Bone *bones[80] = {NULL}; int num_bones = 0; int n; // collect the bones in order for( temp=bone; temp; temp=temp->parent ) bones[num_bones++] = temp; // convert from bone space to world space for( n=1; n<num_bones; n++ ) { get_inverse_quat( bones[n]->quat, inverse ); memcpy( inverse, bones[n]->quat, sizeof(float)*4 ); multiply_quat( boneRot, bones[n]->quat ); } // apply rotation multiply_quat( boneRot, rotation ); // convert from world space to bone space for( n=num_bones-1; n>0; n-- ) { get_inverse_quat( bones[n]->quat, inverse ); multiply_quat( boneRot, inverse ); } // normalize normalize_quat( boneRot ); memcpy( bone->quat, boneRot, sizeof(float)*4 ); }[/code] rotate_bone() converts the rotation quaternion to bone space and then multiplies the original rotation with it. rotate_bone_2() converts the original rotation to world space, multiplies by rotation quaternion, and converts back to bone space. But why only rotate_bone_2() works? Aren't they doing the same thing?
  5. Quaternions

    I have been working on a skeletal animation editor. Most of the features are finished. The user can select a bone and rotate it around a global axis (x, y or z), but this doesn't work properly. This function doesn't preserve original rotation if the bone has a parent (i.e. the bone is not the root bone). So if angle == 0 and bone->parent != NULL, the bone gets rotated (it shouldn't rotate then). I don't actually understand quaternions. Can you tell me, what is happening and how I should change the code to make the rotation be always relative? [php] // bone is the selected bone // the_axis is the index of the selected axis (0, 1, or 2) // angle is in radians // quaternion format is [x,y,z,w] static void rotate_bone( Bone *bone, float angle ) { float axis[3] = {0.0f}; float rotation[4]; float temp_quat[4]; // get rotation quaternion axis[the_axis] = 1.0f; axis_to_quat( axis, angle, rotation ); Bone *temp; Bone *bones[80] = {NULL}; int cur_bone = 0; // collect the bones in order // todo: add some bounds checking to prevent overflow (although the test skeleton has just 17 bones) for( temp=bone; temp; temp=temp->parent ) bones[cur_bone++] = temp; // convert rotation quaternion to bone space for( cur_bone--; cur_bone>0; cur_bone-- ) { get_inverse_quat( bones[cur_bone]->quat, temp_quat ); multiply_quat( rotation, temp_quat ); } // apply rotation multiply_quat( bone->quat, rotation ); // normalize normalize_quat( bone->quat ); } [/php] The bone struct: [code] struct Bone; typedef struct Bone { int index; char name[BONE_NAME_LEN]; float quat[4]; float offset[3]; float length; struct Bone *parent; struct Bone *children[MAX_BONE_CHILDREN]; } Bone; [/code] Thanks for your replies (unless its "wib wab woo").
  6. Quote:Original post by Erik Rufelt Try setting the GL_OBJECT_PLANE for GL_R manually, as I believe the defaults are {0, 0, 0, 0} for GL_R. GLfloat plane[4] = {0.0f, 0.0f, 1.0f, 0.0f}; glTexGenfv(GL_R, GL_OBJECT_PLANE, plane); Now texture coordinate generation and glutSolidCube work properly. Thanks. But lighting doesn't work with either methods. Just with the 2D texture. (I have added a normal array to draw_cube()). What might be the problem with lighting? EDIT: Lighting didn't work because I didn't have the glMaterial(...) calls in the new functions which use 3D textures. Just to make it clear, there are no problems anymore (so don't try to help). Thanks for your replies. [Edited by - usbman3 on December 30, 2010 10:23:23 AM]
  7. I wrote my own functions for rendering cubes: #include <GL/gl.h> #include "cube.h" static const GLshort the_coords[] = { -1,-1,-1, // 0 -1,-1,1, // 1 -1,1,-1, // 2 -1,1,1, // 3 1,-1,-1, // 4 1,-1,1, // 5 1,1,-1, // 6 1,1,1, // 7 }; static const GLubyte indexes[] = { // x/y top 1,5,7,3, // x/y bottom 0,2,6,4, // z/x 3,7,6,2, // ------- 1,0,4,5, // z/y 4,6,7,5, // ------- 0,1,3,2 }; void begin_cubes( void ) { glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glVertexPointer( 3, GL_SHORT, 0, the_coords ); glTexCoordPointer( 3, GL_SHORT, 0, the_coords ); } void draw_cube( void ) { glDrawElements( GL_QUADS, 24, GL_UNSIGNED_BYTE, indexes ); } void end_cubes( void ) { glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); } It worked just like glutSolidCube. Then I removed OpenGL texture coordinate generation stuff. Now it works as it should: But I still don't know what was wrong with GL_TEXTURE_GEN_R. I guess it's just the broken ATI drivers, whatever...
  8. Unfortunately none of those debugging tools are available in kubuntu repos (I could install them manually but I'm lazy and I do that only if I can't solve this without them). If I don't initialize the texture pixels at all (they're random!), I still get incorrect texture coordinates, so the problem can not be in the texture generating function.
  9. EDit: Problem has been solved. Don't bother reading this thread. I need to render some textured axis aligned cubes. Currently I'm using a 2D texture. I want to use a 3D texture and let OpenGL automatically generate texture coordinates, to simplify things a bit. I have some code to generate a 2x2x2 checker pattern and then render cubes with it: #include <stdlib.h> #include <stdint.h> #include <string.h> #include <GL/gl.h> #include "image.h" #include "checkers3d.h" GLuint make_3d_checkers( GLubyte color1[3], GLubyte color2[3] ) { GLuint tex; uint8_t pixels[8*3]; /* color1, color2, color2, color1, color2, color1, color1, color2 */ memcpy( pixels, color1, 3 ); memcpy( pixels+3, color2, 3 ); memcpy( pixels+6, color2, 3 ); memcpy( pixels+9, color1, 3 ); memcpy( pixels+12, color2, 3 ); memcpy( pixels+15, color1, 3 ); memcpy( pixels+18, color1, 3 ); memcpy( pixels+21, color2, 3 ); glGenTextures( 1, &tex ); glBindTexture( GL_TEXTURE_3D, tex ); glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT ); // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); // apply color and lighting effects to texture glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); // upload texture glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glTexImage3D( GL_TEXTURE_3D, 0, 3, 2, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); return tex; } static void draw_map_3d( void ) { glEnable( GL_TEXTURE_GEN_S ); glEnable( GL_TEXTURE_GEN_T ); glEnable( GL_TEXTURE_GEN_R ); GLenum mode = GL_OBJECT_LINEAR; glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, mode ); glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, mode ); glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, mode ); glEnable( GL_TEXTURE_3D ); int n; Box *b; static GLuint tex = 0; if ( tex == 0 ) { GLubyte color1[3] = {DARK}; GLubyte colo2[3] = {BRIGHT}; tex = make_3d_checkers( color1, colo2 ); } glBindTexture( GL_TEXTURE_3D, tex ); for( n=0; n<map.num_boxes; n++ ) { b = &map.boxes[n]; glPushMatrix(); glTranslatef( b->centre[0], b->centre[1], b->centre[2] ); glScalef( b->size[0], b->size[1], b->size[2] ); glMatrixMode( GL_TEXTURE ); glLoadIdentity(); glTranslatef( b->centre[0], b->centre[1], b->centre[2] ); glScalef( b->size[0], b->size[1], b->size[2] ); glMatrixMode( GL_MODELVIEW ); glutSolidCube( 2.0f ); glPopMatrix(); } glMatrixMode( GL_TEXTURE ); glLoadIdentity(); glMatrixMode( GL_MODELVIEW ); glDisable( GL_TEXTURE_3D ); glDisable( GL_TEXTURE_GEN_S ); glDisable( GL_TEXTURE_GEN_T ); glDisable( GL_TEXTURE_GEN_R ); } But texture coordinates aren't generated correctly for Z axis <image removed> What am I doing wrong? [Edited by - usbman3 on December 30, 2010 9:44:30 AM]
  10. Edit: Problem solved. Don't bother reading this thread. I have all printable ASCII characters in this picture, excluding empty space: I converted it to raw binary: convert font2.png -size 1128x16 -depth 8 RGBA:font.dat Then I wrote some code to load and display that font: static uint8_t **pixels = NULL; static const uint16_t font_w = 1128; static const uint16_t font_h = 16; static const uint16_t char_w = 12; static int read_pixels( void ) { FILE *fp; int c; size_t ch_size; fp = fopen( "data/font.dat", "r" ); if ( !fp ) return 0; pixels = malloc( sizeof(uint8_t*) * 95 ); ch_size = font_h * char_w * 4; for( c=0; c<95; c++ ) { pixels[c] = malloc( ch_size ); fseek( fp, SEEK_SET, c*ch_size ); fread( pixels[c], ch_size, 1, fp ); } fclose( fp ); return 1; } int load_font( void ) { printf( "Loading font...\n" ); if ( !read_pixels() ) return 0; return 1; } void draw_text( int x, int y, char *str ) { char *c; int index; for( c=str; *c; c++ ) { if ( *c == ' ' ) { x++; continue; } if ( !isprint(*c) ) index = 32; else index = (*c) - 32; if ( index < 0 || index > 127 ) index = 32; glWindowPos2i( x++ * char_w, y ); glDrawPixels( char_w, font_h, GL_RGBA, GL_UNSIGNED_BYTE, pixels[index] ); } } There are 2 problems with draw_text(). It draws the text at wrong coordinates, and the text looks like this: Above should read "Hello world!" (the space shows as green background color because it is not drawn). Do you see the problem in my code? [Edited by - usbman3 on December 12, 2010 10:06:10 AM]
  11. Increasing the minimum octree subcell size increased performance too :) I have made a slightly bigger map, which has 336 boxes. Today I finally got the collision bug fixed. There was a 'return' instead of a 'continue' in a recursive octree searching loop. Then I did a quick benchmark in the new map. Seconds spent for collision testing per one game tick: Brute force: 0.00017 Octree: 0.00004 So octree is about 425% faster than brute-force. The game spends 0.1% of time for collision testing. The rest is mostly rendering. Now I'm happy with this. Time to move onto other things. Thanks for your replies.
  12. I rewrote the entire octree code. Octree is now faster than brute force. And I also improved rendering performance a bit. Boxes: 237 Average FPS with octree: 94.979 Average FPS with brute force: 89.521 Boxes: 7009 Average FPS with octree: 21.401 Average FPS with brute force: 20.772 Boxes: 18948 Average FPS with octree: 9.323 Average FPS with brute force: 8.360 EDIT: Octree seems to make some new collisions bugs. Collisions are not tested when they should be, and player can move trough walls in some rare spots. EDIT: I made player vs. box collision function 10000x slower with SDL_Delay. Brute force: 1 frame per 15 seconds Octree: around 17 FPS It seems to be that AABB vs AABB test is too fast. Traversing octree needs more time than brute force testing all boxes in the map. [Edited by - usbman3 on December 6, 2010 7:51:33 AM]
  13. I finally got it working. The algorithm will keep dividing space into smaller and smaller parts until the parts are small enough or they don't contain any objects (=boxes). But searching the octree sucks too many CPU cycles. Performance is much better with octree disabled. There are usually 0-17 collision tests done with octree enabled, and without octree its 229 (the number of boxes). "Dumb" collision testing outperforms octree even when there are 120000+ boxes! (and btw: building octree takes almost 2 minutes with that box count on my cpu) Pseudocode for my octree search function: struct Octree { int is_leaf; union { struct { float centre[3]; float min[3]; float max[3]; Octree *sub_oc[2][2][2]; } branch; struct { int num_boxes; Box **boxes; } leaf; } data; }; void search_octree_recursive( octree, player_aabb, callback ) { if octree.is_leaf: for each box in octree: if box.has_not_tested: callback( box ) box.has_not_tested = 0 return for each subcell: if player_aabb intersects subcell: search_octree_recursive( octree, player_aabb, callback ) } void search_octree( player_aabb, callback ) { for each box: box.has_not_tested = 1 search_octree_recursive( octree_root ) } Testing if player's AABB intersects the subcells of octree is expensive. How can I get rid of those collision tests? And BTW, the map is 100% static, and the only moving objects are players (and hitscan bullets). I'm not going to need any dynamic data structures.
  14. Hello! There is a Z-axis aligned cylinder (the player), and a map, which is made of AABB's. I have written the collision detection and physics code myself. Currently it just loops through the entire map and tests if the player intersects any AABB. Here's a screenshot (lighting is messed up): Google results for "acceleration structure" shows only raytracing articles :( What's the most efficient and simple data structure to speed up collision detection in this scenario?
  15. Skeletal animation is good but unfortunately matrix & quaternion math is too difficult for me. And quake-style frame-based animation needs too much memory (and looks really jerky). Are there any other options?