diff options
Diffstat (limited to 'source')
58 files changed, 1832 insertions, 728 deletions
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 3ffd8115914..5e025b986c2 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -850,6 +850,7 @@ Object *add_only_object(int type, const char *name) /* ob->pad3 == Contact Processing Threshold */ ob->m_contactProcessingThreshold = 1.0f; ob->obstacleRad = 1.0f; + ob->col_group = ob->col_mask = 1; /* NT fluid sim defaults */ ob->fluidsimSettings = NULL; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9aa87a86b3e..547da946247 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -12894,6 +12894,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } + { + /* Initialize BGE exit key to esc key */ + Scene *scene; + for(scene= main->scene.first; scene; scene= scene->id.next) { + if (!scene->gm.exitkey) + scene->gm.exitkey = 218; //218 is the Blender key code for ESC + } + } + + { + /* Initialize default values for collision masks */ + Object *ob; + for(ob=main->object.first; ob; ob=ob->id.next) + ob->col_group = ob->col_mask = 1; + } } if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 6)) { diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 01afc0e24eb..4d28b86ae25 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -66,5 +66,10 @@ endif() add_definitions(-DGLEW_STATIC) +if(WITH_IMAGE_DDS) + add_definitions(-DWITH_DDS) +endif() + + blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 89976699114..4186466739c 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -119,6 +119,8 @@ void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h, int m void GPU_update_images_framechange(void); int GPU_update_image_time(struct Image *ima, double time); int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, int compare, int mipmap); +void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth, int mipmap, int use_hight_bit_depth, struct Image *ima); +void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, struct Image *ima, struct ImBuf *ibuf); void GPU_free_image(struct Image *ima); void GPU_free_images(void); void GPU_free_images_anim(void); @@ -135,4 +137,3 @@ void GPU_free_unused_buffers(void); #endif #endif - diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 33c5d474932..e2746aef9a8 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -173,6 +173,11 @@ typedef enum GPUDynamicType { GPU_DYNAMIC_SAMPLER_2DBUFFER = 12, GPU_DYNAMIC_SAMPLER_2DIMAGE = 13, GPU_DYNAMIC_SAMPLER_2DSHADOW = 14, + GPU_DYNAMIC_LAMP_DISTANCE = 15, + GPU_DYNAMIC_LAMP_ATT1 = 16, + GPU_DYNAMIC_LAMP_ATT2 = 17, + GPU_DYNAMIC_LAMP_SPOTSIZE = 18, + GPU_DYNAMIC_LAMP_SPOTBLEND = 19, } GPUDynamicType; typedef enum GPUDataType { @@ -230,6 +235,8 @@ void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp); void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[][4]); void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy); +void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2); +void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend); int GPU_lamp_shadow_layer(GPULamp *lamp); #ifdef __cplusplus diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index 11b0ee5f9fa..e6ffc172300 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -16,4 +16,7 @@ incs += ' ' + env['BF_OPENGL_INC'] if env['WITH_BF_SMOKE']: defs.append('WITH_SMOKE') +if env['WITH_BF_DDS']: + defs.append('WITH_DDS') + env.BlenderLib ( 'bf_gpu', sources, Split(incs), defines = defs, libtype=['core','player'], priority=[160,110] ) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index c830971dcbd..b6433e11989 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -413,8 +413,8 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int ImBuf *ibuf = NULL; unsigned int *bind = NULL; int rectw, recth, tpx=0, tpy=0, y; - unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL; - float *ftilerect= NULL, *fscalerect = NULL, *frect = NULL; + unsigned int *tilerect= NULL, *rect= NULL; + float *ftilerect= NULL, *frect = NULL; float *srgb_frect = NULL; short texwindx, texwindy, texwinsx, texwinsy; /* flag to determine whether high resolution format is used */ @@ -597,10 +597,37 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int rect= tilerect; } } +#ifdef WITH_DDS + if (ibuf->ftype & DDS) + GPU_create_gl_tex_compressed(bind, rect, rectw, recth, mipmap, ima, ibuf); + else +#endif + GPU_create_gl_tex(bind, rect, frect, rectw, recth, mipmap, use_high_bit_depth, ima); + + /* clean up */ + if (tilerect) + MEM_freeN(tilerect); + if (ftilerect) + MEM_freeN(ftilerect); + if (srgb_frect) + MEM_freeN(srgb_frect); + return *bind; +} + +void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int rectw, int recth, int mipmap, int use_high_bit_depth, Image *ima) +{ + unsigned int *scalerect = NULL; + float *fscalerect = NULL; + + int tpx = rectw; + int tpy = recth; + /* scale if not a power of two. this is not strictly necessary for newer * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures */ if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) { + int oldw= rectw; + int oldh= recth; rectw= smaller_pow2_limit(rectw); recth= smaller_pow2_limit(recth); @@ -612,9 +639,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int } else { scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); - gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); + gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, pix, rectw, recth, GL_UNSIGNED_BYTE, scalerect); - rect= scalerect; + pix= scalerect; } } @@ -626,7 +653,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if (use_high_bit_depth) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); } @@ -634,7 +661,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if (use_high_bit_depth) gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA16, rectw, recth, GL_RGBA, GL_FLOAT, frect); else - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, pix); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); @@ -645,21 +672,72 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); /* set to modulate with vertex color */ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - /* clean up */ - if (tilerect) - MEM_freeN(tilerect); - if (ftilerect) - MEM_freeN(ftilerect); + if (scalerect) MEM_freeN(scalerect); if (fscalerect) MEM_freeN(fscalerect); - if (srgb_frect) - MEM_freeN(srgb_frect); - return *bind; } +void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, Image *ima, ImBuf *ibuf) +{ +#ifndef WITH_DDS + // Fall back to uncompressed if DDS isn't enabled + GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima); +#else + GLint format=0; + int offset =0, i=0; + int blocksize, width, height; + int size; + GLint err; + + if (ibuf->dds_data.fourcc == FOURCC_DXT1) + format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + else if (ibuf->dds_data.fourcc == FOURCC_DXT3) + format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + else if (ibuf->dds_data.fourcc == FOURCC_DXT5) + format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + else + { + printf("Unable to find a suitable DXT compression, falling back to uncompressed\n"); + GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima); + return; + } + + glGenTextures(1, (GLuint *)bind); + glBindTexture(GL_TEXTURE_2D, *bind); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + + height = ibuf->x; + width = ibuf->y; + blocksize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16; + for (i=0; i<ibuf->dds_data.nummipmaps && (width||height); ++i) + { + if (width == 0) + width = 1; + if (height == 0) + height = 1; + + size = ((width+3)/4)*((height+3)/4)*blocksize; + + glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height, + 0, size, ibuf->dds_data.data + offset); + + err = glGetError(); + + if (err != GL_NO_ERROR) + printf("OpenGL error: %s\nFormat: %x\n", gluErrorString(err), format); + + offset += size; + width >>= 1; + height >>= 1; + } + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#endif +} static void gpu_verify_repeat(Image *ima) { /* set either clamp or repeat in X/Y */ @@ -1897,4 +1975,3 @@ void GPU_state_print(void) gpu_get_print("GL_ZOOM_X", GL_ZOOM_X); gpu_get_print("GL_ZOOM_Y", GL_ZOOM_Y); } - diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index e14e4dce405..63b336963ab 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -117,6 +117,7 @@ struct GPULamp { float dynimat[4][4]; float spotsi, spotbl, k; + float dyndist, dynatt1, dynatt2; float dist, att1, att2; float bias, d, clipend; @@ -401,13 +402,13 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode case LA_FALLOFF_CONSTANT: break; case LA_FALLOFF_INVLINEAR: - GPU_link(mat, "lamp_falloff_invlinear", GPU_uniform(&lamp->dist), *dist, &visifac); + GPU_link(mat, "lamp_falloff_invlinear", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), *dist, &visifac); break; case LA_FALLOFF_INVSQUARE: - GPU_link(mat, "lamp_falloff_invsquare", GPU_uniform(&lamp->dist), *dist, &visifac); + GPU_link(mat, "lamp_falloff_invsquare", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), *dist, &visifac); break; case LA_FALLOFF_SLIDERS: - GPU_link(mat, "lamp_falloff_sliders", GPU_uniform(&lamp->dist), GPU_uniform(&lamp->att1), GPU_uniform(&lamp->att2), *dist, &visifac); + GPU_link(mat, "lamp_falloff_sliders", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_dynamic_uniform(&lamp->att1, GPU_DYNAMIC_LAMP_ATT1, lamp->ob), GPU_dynamic_uniform(&lamp->att2, GPU_DYNAMIC_LAMP_ATT2, lamp->ob), *dist, &visifac); break; case LA_FALLOFF_CURVE: { @@ -415,13 +416,13 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode int size; curvemapping_table_RGBA(lamp->curfalloff, &array, &size); - GPU_link(mat, "lamp_falloff_curve", GPU_uniform(&lamp->dist), GPU_texture(size, array), *dist, &visifac); + GPU_link(mat, "lamp_falloff_curve", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_texture(size, array), *dist, &visifac); } break; } if (lamp->mode & LA_SPHERE) - GPU_link(mat, "lamp_visibility_sphere", GPU_uniform(&lamp->dist), *dist, visifac, &visifac); + GPU_link(mat, "lamp_visibility_sphere", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), *dist, visifac, &visifac); if (lamp->type == LA_SPOT) { if (lamp->mode & LA_SQUARE) { @@ -433,7 +434,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), *lv, &inpr); } - GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac); + GPU_link(mat, "lamp_visibility_spot", GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), inpr, visifac, &visifac); } GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac); @@ -1516,6 +1517,19 @@ void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float ener lamp->col[2]= b* lamp->energy; } +void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2) +{ + lamp->dist = distance; + lamp->att1 = att1; + lamp->att2 = att2; +} + +void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend) +{ + lamp->spotsi= cos(M_PI*spotsize/360.0); + lamp->spotbl= (1.0f - lamp->spotsi)*spotblend; +} + static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) { float temp, angle, pixsize, wsize; diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 076f518585b..c77c48089dd 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -52,6 +52,13 @@ struct ImMetaData; #define IB_MIPMAP_LEVELS 20 #define IB_FILENAME_SIZE 1024 +typedef struct DDSData { + unsigned int fourcc; /* DDS fourcc info */ + unsigned int nummipmaps; /* The number of mipmaps in the dds file */ + unsigned char *data; /* The compressed image data */ + unsigned int size; /* The size of the compressed data */ +} DDSData; + /** * \ingroup imbuf * This is the abstraction of an image. ImBuf is the basic type used for all @@ -126,6 +133,9 @@ typedef struct ImBuf { unsigned char *encodedbuffer; /* Compressed image only used with png currently */ unsigned int encodedsize; /* Size of data written to encodedbuffer */ unsigned int encodedbuffersize; /* Size of encodedbuffer */ + + /* information for compressed textures */ + struct DDSData dds_data; } ImBuf; /* Moved from BKE_bmfont_types.h because it is a userflag bit mask. */ @@ -222,9 +232,31 @@ typedef struct ImBuf { #define IB_PROFILE_SRGB 2 #define IB_PROFILE_CUSTOM 3 + +/* dds */ +#ifdef WITH_DDS +#ifndef MAKEFOURCC +#define MAKEFOURCC(ch0, ch1, ch2, ch3)\ + ((unsigned long)(unsigned char)(ch0) | \ + ((unsigned long)(unsigned char)(ch1) << 8) | \ + ((unsigned long)(unsigned char)(ch2) << 16) | \ + ((unsigned long)(unsigned char)(ch3) << 24)) +#endif //MAKEFOURCC + +/* + * FOURCC codes for DX compressed-texture pixel formats + */ + +#define FOURCC_DDS (MAKEFOURCC('D','D','S',' ')) +#define FOURCC_DXT1 (MAKEFOURCC('D','X','T','1')) +#define FOURCC_DXT2 (MAKEFOURCC('D','X','T','2')) +#define FOURCC_DXT3 (MAKEFOURCC('D','X','T','3')) +#define FOURCC_DXT4 (MAKEFOURCC('D','X','T','4')) +#define FOURCC_DXT5 (MAKEFOURCC('D','X','T','5')) + +#endif // DDS extern const char *imb_ext_image[]; extern const char *imb_ext_image_qt[]; extern const char *imb_ext_movie[]; extern const char *imb_ext_audio[]; - #endif diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 2cfdd7bc324..b9700227328 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -162,6 +162,8 @@ void IMB_freeImBuf(ImBuf *ibuf) IMB_freezbuffloatImBuf(ibuf); freeencodedbufferImBuf(ibuf); IMB_metadata_free(ibuf); + if (ibuf->dds_data.data != NULL) + free(ibuf->dds_data.data); MEM_freeN(ibuf); } } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 3966135ea32..b28451808ce 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -1016,6 +1016,10 @@ uint DirectDrawSurface::mipmapCount() const else return 1; } +uint DirectDrawSurface::fourCC() const +{ + return header.pf.fourcc; +} uint DirectDrawSurface::width() const { @@ -1131,6 +1135,29 @@ void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) } } +// It was easier to copy this function from upstream than to resync. +// This should be removed if a resync ever occurs. +void* DirectDrawSurface::readData(uint &rsize) +{ + uint header_size = 128; // sizeof(DDSHeader); + if (header.hasDX10Header()) + { + header_size += 20; // sizeof(DDSHeader10); + } + + uint size = stream.size - header_size; + rsize = size; + + unsigned char *data = new unsigned char[size]; + + stream.seek(header_size); + mem_read(stream, data, size); + + // Maybe check if size == rsize? assert() isn't in this scope... + + return data; +} + void DirectDrawSurface::readLinearImage(Image * img) { @@ -1523,4 +1550,3 @@ void DirectDrawSurface::printInfo() const printf("User Version: %u\n", header.reserved[8]); } } - diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index 23c8bbf2de3..28ecb948643 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -158,6 +158,7 @@ public: bool hasAlpha() const; uint mipmapCount() const; + uint fourCC() const; uint width() const; uint height() const; uint depth() const; @@ -171,6 +172,7 @@ public: void setUserVersion(int version); void mipmap(Image * img, uint f, uint m); + void* readData(uint &size); // void mipmap(FloatImage * img, uint f, uint m); void printInfo() const; diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 071d94c2076..fba326f7865 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -123,6 +123,8 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags) ibuf->ftype = DDS; ibuf->profile = IB_PROFILE_SRGB; + ibuf->dds_data.fourcc = dds.fourCC(); + ibuf->dds_data.nummipmaps = dds.mipmapCount(); if ((flags & IB_test) == 0) { if (!imb_addrectImBuf(ibuf)) return(ibuf); @@ -136,10 +138,18 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags) cp[0] = pixel.r; /* set R component of col */ cp[1] = pixel.g; /* set G component of col */ cp[2] = pixel.b; /* set B component of col */ - if (bits_per_pixel == 32) + if (dds.hasAlpha()) cp[3] = pixel.a; /* set A component of col */ rect[i] = col; } + + if (ibuf->dds_data.fourcc != FOURCC_DDS) + ibuf->dds_data.data = (unsigned char*)dds.readData(ibuf->dds_data.size); + else { + ibuf->dds_data.data = NULL; + ibuf->dds_data.size = 0; + } + IMB_flipy(ibuf); } diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 05a96ef2f35..3eead8b7b8d 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -234,6 +234,9 @@ typedef struct Object { short recalc; /* dependency flag */ float anisotropicFriction[3]; + /** Collision mask settings */ + unsigned short col_group, col_mask, col_pad[2]; + ListBase constraints; /* object constraints */ ListBase nlastrips DNA_DEPRECATED; // XXX depreceated... old animation system ListBase hooks DNA_DEPRECATED; // XXX depreceated... old animation system @@ -455,6 +458,9 @@ typedef struct DupliObject { /* controller state */ #define OB_MAX_STATES 30 +/* collision masks */ +#define OB_MAX_COL_MASKS 8 + /* ob->gameflag */ #define OB_DYNAMIC 1 #define OB_CHILD 2 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 83688e30643..5239cf2e646 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -624,7 +624,18 @@ typedef struct GameData { short exitkey, pad; short ticrate, maxlogicstep, physubstep, maxphystep; short obstacleSimulation, pad1; + short raster_storage; + short pad3; float levelHeight; + float pad2; + + /* Dynamic Lights */ + short dynpoints; + short dynspots; + short dynsuns; + short dynhemis; + short dynareas; + short light_pad[3]; } GameData; #define STEREO_NOSTEREO 1 @@ -649,6 +660,12 @@ typedef struct GameData { #define OBSTSIMULATION_TOI_rays 1 #define OBSTSIMULATION_TOI_cells 2 +/* Render storage */ +#define RAS_STORE_AUTO 0 +#define RAS_STORE_IMMEDIATE 1 +#define RAS_STORE_VA 2 +#define RAS_STORE_VBO 3 + /* GameData.flag */ #define GAME_RESTRICT_ANIM_UPDATES (1 << 0) #define GAME_ENABLE_ALL_FRAMES (1 << 1) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 140e874eb78..582a396b0b6 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1052,6 +1052,64 @@ static void rna_GameObjectSettings_state_set(PointerRNA *ptr, const int *values) } } +static void rna_GameObjectSettings_col_group_get(PointerRNA *ptr, int *values) +{ + Object *ob= (Object*)ptr->data; + int i; + + memset(values, 0, sizeof(short)*OB_MAX_COL_MASKS); + for(i=0; i<OB_MAX_COL_MASKS; i++) + values[i] = (ob->col_group & (1<<i)); +} + +static void rna_GameObjectSettings_col_group_set(PointerRNA *ptr, const int *values) +{ + Object *ob= (Object*)ptr->data; + int i, tot= 0; + + /* ensure we always have some group selected */ + for(i=0; i<OB_MAX_COL_MASKS; i++) + if(values[i]) + tot++; + + if(tot==0) + return; + + for(i=0; i<OB_MAX_COL_MASKS; i++) { + if(values[i]) ob->col_group |= (1<<i); + else ob->col_group &= ~(1<<i); + } +} + +static void rna_GameObjectSettings_col_mask_get(PointerRNA *ptr, int *values) +{ + Object *ob= (Object*)ptr->data; + int i; + + memset(values, 0, sizeof(short)*OB_MAX_COL_MASKS); + for(i=0; i<OB_MAX_COL_MASKS; i++) + values[i] = (ob->col_mask & (1<<i)); +} + +static void rna_GameObjectSettings_col_mask_set(PointerRNA *ptr, const int *values) +{ + Object *ob= (Object*)ptr->data; + int i, tot= 0; + + /* ensure we always have some mask selected */ + for(i=0; i<OB_MAX_COL_MASKS; i++) + if(values[i]) + tot++; + + if(tot==0) + return; + + for(i=0; i<OB_MAX_COL_MASKS; i++) { + if(values[i]) ob->col_mask |= (1<<i); + else ob->col_mask &= ~(1<<i); + } +} + static void rna_GameObjectSettings_used_state_get(PointerRNA *ptr, int *values) { Object *ob = (Object*)ptr->data; @@ -1412,6 +1470,8 @@ static void rna_def_object_game_settings(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + int default_col_mask[8] = {1,0,0,0, 0,0,0,0}; + static EnumPropertyItem body_type_items[] = { {OB_BODY_TYPE_NO_COLLISION, "NO_COLLISION", 0, "No Collision", "Disable collision for this object"}, {OB_BODY_TYPE_STATIC, "STATIC", 0, "Static", "Stationary object"}, @@ -1516,6 +1576,18 @@ static void rna_def_object_game_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Velocity Max", "Clamp velocity to this maximum speed"); + prop= RNA_def_property(srna, "collision_group", PROP_BOOLEAN, PROP_LAYER_MEMBER); + RNA_def_property_boolean_sdna(prop, NULL, "col_group", 1); + RNA_def_property_array(prop, OB_MAX_COL_MASKS); + RNA_def_property_ui_text(prop, "Collision Group", "The collision group of the object"); + RNA_def_property_boolean_funcs(prop, "rna_GameObjectSettings_col_group_get", "rna_GameObjectSettings_col_group_set"); + + prop= RNA_def_property(srna, "collision_mask", PROP_BOOLEAN, PROP_LAYER_MEMBER); + RNA_def_property_boolean_sdna(prop, NULL, "col_mask", 1); + RNA_def_property_array(prop, OB_MAX_COL_MASKS); + RNA_def_property_ui_text(prop, "Collision Mask", "The groups this object can collide with"); + RNA_def_property_boolean_funcs(prop, "rna_GameObjectSettings_col_mask_get", "rna_GameObjectSettings_col_mask_set"); + /* lock position */ prop = RNA_def_property(srna, "lock_location_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gameflag2", OB_LOCK_RIGID_BODY_X_AXIS); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 359b1e4ee00..b4a70866c44 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2356,6 +2356,13 @@ static void rna_def_scene_game_data(BlenderRNA *brna) {OBSTSIMULATION_TOI_cells, "RVO_CELLS", 0, "RVO (cells)", ""}, {0, NULL, 0, NULL, NULL}}; + static EnumPropertyItem storage_items[] ={ + {RAS_STORE_AUTO, "AUTO", 0, "Auto Select", "Chooses the best supported mode"}, + {RAS_STORE_IMMEDIATE, "IMMEDIATE", 0, "Immediate Mode", "Slowest performance, requires OpenGL (any version)"}, + {RAS_STORE_VA, "VERTEX_ARRAY", 0, "Vertex Arrays", "Moderate performance, requires at least OpenGL 1.1"}, + {RAS_STORE_VBO, "VERTEX_BUFFER_OBJECT", 0, "Vertex Buffer Objects", "Best performance, requires at least OpenGL 1.4"}, + {0, NULL, 0, NULL, NULL}}; + srna = RNA_def_struct(brna, "SceneGameData", NULL); RNA_def_struct_sdna(srna, "GameData"); RNA_def_struct_nested(brna, srna, "Scene"); @@ -2390,6 +2397,11 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, NULL, "rna_GameSettings_exit_key_set", NULL); RNA_def_property_ui_text(prop, "Exit Key", "The key that exits the Game Engine"); RNA_def_property_update(prop, NC_SCENE, NULL); + prop= RNA_def_property(srna, "raster_storage", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "raster_storage"); + RNA_def_property_enum_items(prop, storage_items); + RNA_def_property_ui_text(prop, "Storage", "Sets the storage mode used by the rasterizer"); + RNA_def_property_update(prop, NC_SCENE, NULL); /* Do we need it here ? (since we already have it in World */ prop = RNA_def_property(srna, "frequency", PROP_INT, PROP_NONE); @@ -2408,6 +2420,42 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Desktop", "Uses the current desktop resultion in fullscreen mode"); RNA_def_property_update(prop, NC_SCENE, NULL); + /* Dynamic Lights */ + prop = RNA_def_property(srna, "dynamic_points", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "dynpoints"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_range(prop, 0, 15, 1, 1); + RNA_def_property_ui_text(prop, "Dynamic Point Lights", "Number of point lights available for dynamic use"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop = RNA_def_property(srna, "dynamic_spots", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "dynspots"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_range(prop, 0, 15, 1, 1); + RNA_def_property_ui_text(prop, "Dynamic Spot Lights", "Number of spot lights available for dynamic use"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop = RNA_def_property(srna, "dynamic_suns", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "dynsuns"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_range(prop, 0, 15, 1, 1); + RNA_def_property_ui_text(prop, "Dynamic Sun Lights", "Number of sun lights available for dynamic use"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop = RNA_def_property(srna, "dynamic_hemis", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "dynhemis"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_range(prop, 0, 15, 1, 1); + RNA_def_property_ui_text(prop, "Dynamic Hemi Lights", "Number of hemi lights available for dynamic use"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop = RNA_def_property(srna, "dynamic_areas", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "dynareas"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_range(prop, 0, 15, 1, 1); + RNA_def_property_ui_text(prop, "Dynamic Area Lights", "Number of area lights available for dynamic use"); + RNA_def_property_update(prop, NC_SCENE, NULL); + /* Framing */ prop = RNA_def_property(srna, "frame_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "framing.type"); diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 8b211385928..b12b5d3ff7a 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -57,7 +57,6 @@ #include "RAS_GLExtensionManager.h" #include "RAS_OpenGLRasterizer.h" -#include "RAS_VAOpenGLRasterizer.h" #include "RAS_ListRasterizer.h" #include "NG_LoopBackNetworkDeviceInterface.h" @@ -205,19 +204,16 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c RAS_IRenderTools* rendertools = new KX_BlenderRenderTools(); RAS_IRasterizer* rasterizer = NULL; - if (displaylists) { - if (GLEW_VERSION_1_1 && !novertexarrays) - rasterizer = new RAS_ListRasterizer(canvas, true, true); - else - rasterizer = new RAS_ListRasterizer(canvas); - } - else if (GLEW_VERSION_1_1 && !novertexarrays) - rasterizer = new RAS_VAOpenGLRasterizer(canvas, false); + //Don't use displaylists with VBOs + //If auto starts using VBOs, make sure to check for that here + if (displaylists && startscene->gm.raster_storage != RAS_STORE_VBO) + rasterizer = new RAS_ListRasterizer(canvas, true, startscene->gm.raster_storage); else - rasterizer = new RAS_OpenGLRasterizer(canvas); + rasterizer = new RAS_OpenGLRasterizer(canvas, startscene->gm.raster_storage); // create the inputdevices KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice(); + KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice(); // create a networkdevice diff --git a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h index 18f163d7274..ceadfc846c5 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h @@ -53,10 +53,9 @@ class BL_BlenderInputDevice : public SCA_IInputDevice { public: - BL_BlenderInputDevice() + BL_BlenderInputDevice() { } - virtual ~BL_BlenderInputDevice() { diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 382165065af..2865217c0be 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -777,33 +777,27 @@ bool ConvertMaterial( // No material - old default TexFace properties material->ras_mode |= USE_LIGHT; } - MT_Point2 uv[4]; - MT_Point2 uv2[4]; - const char *uvName = "", *uv2Name = ""; - - uv2[0]= uv2[1]= uv2[2]= uv2[3]= MT_Point2(0.0f, 0.0f); + MT_Point2 uvs[4][MAXTEX]; /* No material, what to do? let's see what is in the UV and set the material accordingly * light and visible is always on */ if ( validface ) { material->tile = tface->tile; - uv[0].setValue(tface->uv[0]); - uv[1].setValue(tface->uv[1]); - uv[2].setValue(tface->uv[2]); + uvs[0][0].setValue(tface->uv[0]); + uvs[1][0].setValue(tface->uv[1]); + uvs[2][0].setValue(tface->uv[2]); if (mface->v4) - uv[3].setValue(tface->uv[3]); - - uvName = tfaceName; + uvs[3][0].setValue(tface->uv[3]); } else { // nothing at all material->alphablend = GEMAT_SOLID; material->tile = 0; - uv[0]= uv[1]= uv[2]= uv[3]= MT_Point2(0.0f, 0.0f); + uvs[0][0]= uvs[1][0]= uvs[2][0]= uvs[3][0]= MT_Point2(0.0f, 0.0f); } if (validmat && validface) { @@ -823,51 +817,43 @@ bool ConvertMaterial( // get uv sets if (validmat) { - bool isFirstSet = true; - - // only two sets implemented, but any of the eight - // sets can make up the two layers for (int vind = 0; vind<material->num_enabled; vind++) { BL_Mapping &map = material->mapping[vind]; - if (map.uvCoName.IsEmpty()) - isFirstSet = false; - else + //If no UVSet is specified, try grabbing one from the UV/Image editor + if (map.uvCoName.IsEmpty() && validface) + { + uvs[0][vind].setValue(tface->uv[0]); + uvs[1][vind].setValue(tface->uv[1]); + uvs[2][vind].setValue(tface->uv[2]); + + if (mface->v4) + uvs[3][vind].setValue(tface->uv[3]); + + continue; + } + + + for (int lay=0; lay<MAX_MTFACE; lay++) { - for (int lay=0; lay<MAX_MTFACE; lay++) - { - MTF_localLayer& layer = layers[lay]; - if (layer.face == 0) break; + MTF_localLayer& layer = layers[lay]; + if (layer.face == 0) break; - if (strcmp(map.uvCoName.ReadPtr(), layer.name)==0) - { - MT_Point2 uvSet[4]; + if (map.uvCoName.IsEmpty() || strcmp(map.uvCoName.ReadPtr(), layer.name)==0) + { + MT_Point2 uvSet[4]; - uvSet[0].setValue(layer.face->uv[0]); - uvSet[1].setValue(layer.face->uv[1]); - uvSet[2].setValue(layer.face->uv[2]); + uvs[0][vind].setValue(layer.face->uv[0]); + uvs[1][vind].setValue(layer.face->uv[1]); + uvs[2][vind].setValue(layer.face->uv[2]); - if (mface->v4) - uvSet[3].setValue(layer.face->uv[3]); - else - uvSet[3].setValue(0.0f, 0.0f); + if (mface->v4) + uvs[3][vind].setValue(layer.face->uv[3]); + else + uvs[3][vind].setValue(0.0f, 0.0f); - if (isFirstSet) - { - uv[0] = uvSet[0]; uv[1] = uvSet[1]; - uv[2] = uvSet[2]; uv[3] = uvSet[3]; - isFirstSet = false; - uvName = layer.name; - } - else if (strcmp(layer.name, uvName) != 0) - { - uv2[0] = uvSet[0]; uv2[1] = uvSet[1]; - uv2[2] = uvSet[2]; uv2[3] = uvSet[3]; - map.mapping |= USECUSTOMUV; - uv2Name = layer.name; - } - } + break; } } } @@ -886,8 +872,7 @@ bool ConvertMaterial( } material->SetConversionRGB(rgb); - material->SetConversionUV(uvName, uv); - material->SetConversionUV2(uv2Name, uv2); + material->SetConversionUV(uvs); if (validmat) material->matname =(mat->id.name); @@ -967,8 +952,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, { Material* ma = 0; bool collider = true; - MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0); - MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0); + MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT]; unsigned int rgb0,rgb1,rgb2,rgb3 = 0; MT_Point3 pt0, pt1, pt2, pt3; @@ -1045,13 +1029,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, rgb0 = rgb[0]; rgb1 = rgb[1]; rgb2 = rgb[2]; rgb3 = rgb[3]; - bl_mat->GetConversionUV(uv); - uv0 = uv[0]; uv1 = uv[1]; - uv2 = uv[2]; uv3 = uv[3]; - - bl_mat->GetConversionUV2(uv); - uv20 = uv[0]; uv21 = uv[1]; - uv22 = uv[2]; uv23 = uv[3]; + bl_mat->GetConversionUV(uvs); /* then the KX_BlenderMaterial */ if (kx_blmat == NULL) @@ -1108,12 +1086,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, /* set UV properties */ if (tface) { - uv0.setValue(tface->uv[0]); - uv1.setValue(tface->uv[1]); - uv2.setValue(tface->uv[2]); + uvs[0][0].setValue(tface->uv[0]); + uvs[1][0].setValue(tface->uv[1]); + uvs[2][0].setValue(tface->uv[2]); if (mface->v4) - uv3.setValue(tface->uv[3]); + uvs[3][0].setValue(tface->uv[3]); tile = tface->tile; } @@ -1232,12 +1210,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, poly->SetTwoside(twoside); //poly->SetEdgeCode(mface->edcode); - meshobj->AddVertex(poly,0,pt0,uv0,uv20,tan0,rgb0,no0,flat,mface->v1); - meshobj->AddVertex(poly,1,pt1,uv1,uv21,tan1,rgb1,no1,flat,mface->v2); - meshobj->AddVertex(poly,2,pt2,uv2,uv22,tan2,rgb2,no2,flat,mface->v3); + meshobj->AddVertex(poly,0,pt0,uvs[0],tan0,rgb0,no0,flat,mface->v1); + meshobj->AddVertex(poly,1,pt1,uvs[1],tan1,rgb1,no1,flat,mface->v2); + meshobj->AddVertex(poly,2,pt2,uvs[2],tan2,rgb2,no2,flat,mface->v3); if (nverts==4) - meshobj->AddVertex(poly,3,pt3,uv3,uv23,tan3,rgb3,no3,flat,mface->v4); + meshobj->AddVertex(poly,3,pt3,uvs[3],tan3,rgb3,no3,flat,mface->v4); } if (tface) @@ -1637,6 +1615,11 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_dyna = (blenderobject->gameflag & OB_DYNAMIC) != 0; objprop.m_softbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0; objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0; + + // Get collision mask information and store it in the upper 8 bits + // The lower 8 bits are reserved for internal blender usage + objprop.m_col_group = blenderobject->col_group << 8; + objprop.m_col_mask = blenderobject->col_mask << 8; ///contact processing threshold is only for rigid bodies and static geometry, not 'dynamic' if (objprop.m_angular_rigidbody || !objprop.m_dyna ) @@ -1890,7 +1873,11 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l lightobj.m_type = RAS_LightObject::LIGHT_SUN; } else if (la->type==LA_SPOT) { lightobj.m_type = RAS_LightObject::LIGHT_SPOT; - } else { + } else if (la->type==LA_HEMI) { + lightobj.m_type = RAS_LightObject::LIGHT_HEMI; + } else if (la->type==LA_AREA) { + lightobj.m_type = RAS_LightObject::LIGHT_AREA; + }else { lightobj.m_type = RAS_LightObject::LIGHT_NORMAL; } @@ -2421,6 +2408,11 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for (SETLOOPER(blenderscene, sce_iter, base)) { Object* blenderobject = base->object; + + // Skip lights from the light pool + if (strcmp(blenderobject->id.name, "__pool__") == 0) + continue; + allblobj.insert(blenderobject); KX_GameObject* gameobj = gameobject_from_blenderobject( diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index df6be142b30..15442622090 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -35,6 +35,7 @@ #endif #include "KX_Scene.h" +#include "KX_Light.h" #include "KX_GameObject.h" #include "KX_BlenderSceneConverter.h" #include "KX_IpoConvert.h" @@ -346,6 +347,15 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, break; } + // Lights added to the scene during the light pool initialization are now skipped when converting objects + if (blenderscene && m_useglslmat) + KX_LightObject::InitBlenderLightPool(blenderscene, + blenderscene->gm.dynpoints, + blenderscene->gm.dynspots, + blenderscene->gm.dynsuns, + blenderscene->gm.dynhemis, + blenderscene->gm.dynareas); + BL_ConvertBlenderObjects(m_maggie, destinationscene, m_ketsjiEngine, @@ -441,6 +451,8 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) meshit++; } } + + KX_LightObject::FreeBlenderLightPool(); } // use blender materials diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index eccb83fe80c..b7b6ff962f4 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -76,7 +76,6 @@ extern "C" #include "SCA_IActuator.h" #include "RAS_MeshObject.h" #include "RAS_OpenGLRasterizer.h" -#include "RAS_VAOpenGLRasterizer.h" #include "RAS_ListRasterizer.h" #include "RAS_GLExtensionManager.h" #include "KX_PythonInit.h" @@ -579,16 +578,12 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) if (!m_rendertools) goto initFailed; - if (useLists) { - if (GLEW_VERSION_1_1) - m_rasterizer = new RAS_ListRasterizer(m_canvas, true); - else - m_rasterizer = new RAS_ListRasterizer(m_canvas); - } - else if (GLEW_VERSION_1_1) - m_rasterizer = new RAS_VAOpenGLRasterizer(m_canvas); + //Don't use displaylists with VBOs + //If auto starts using VBOs, make sure to check for that here + if (useLists && gm->raster_storage != RAS_STORE_VBO) + m_rasterizer = new RAS_ListRasterizer(m_canvas, false, gm->raster_storage); else - m_rasterizer = new RAS_OpenGLRasterizer(m_canvas); + m_rasterizer = new RAS_OpenGLRasterizer(m_canvas, gm->raster_storage); /* Stereo parameters - Eye Separation from the UI - stereomode from the command-line/UI */ m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode); diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 122d692b599..a1f3ea64e1a 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -93,21 +93,15 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) ras->SetTexCoordNum(0); ras->SetAttribNum(attrib_num); - for (i=0; i<attrib_num; i++) + for (i = 0; i < attrib_num; i++) ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, i); for (i = 0; i < attribs.totlayer; i++) { if (attribs.layer[i].glindex > attrib_num) continue; - if (attribs.layer[i].type == CD_MTFACE) { - if (!mat->uvName.IsEmpty() && strcmp(mat->uvName.ReadPtr(), attribs.layer[i].name) == 0) - ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex); - else if (!mat->uv2Name.IsEmpty() && strcmp(mat->uv2Name.ReadPtr(), attribs.layer[i].name) == 0) - ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV2, attribs.layer[i].glindex); - else - ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex); - } + if (attribs.layer[i].type == CD_MTFACE) + ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV, attribs.layer[i].glindex); else if (attribs.layer[i].type == CD_TANGENT) ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, attribs.layer[i].glindex); else if (attribs.layer[i].type == CD_ORCO) diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index 4c7518769e1..716d2ce6076 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -65,14 +65,14 @@ void BL_Material::Initialize() num_users = 1; share = false; - int i; - for (i=0; i<4; i++) + int i,j; + for (i = 0; i < 4; i++) { - uv[i] = MT_Point2(0.f,1.f); - uv2[i] = MT_Point2(0.f, 1.f); + for (j = 0; j < MAXTEX; j++) + uvs[i][j] = MT_Point2(0.0,0.0); } - for (i=0; i<MAXTEX; i++) // :( + for (i = 0; i < MAXTEX; i++) // :( { mapping[i].mapping = 0; mapping[i].offsets[0] = 0.f; @@ -114,37 +114,24 @@ void BL_Material::GetConversionRGB(unsigned int *nrgb) *nrgb = rgb[3]; } -void BL_Material::SetConversionUV(const STR_String& name, MT_Point2 *nuv) +void BL_Material::SetConversionUV(const MT_Point2 nuv[4][MAXTEX]) { - uvName = name; - uv[0] = *nuv++; - uv[1] = *nuv++; - uv[2] = *nuv++; - uv[3] = *nuv; -} - -void BL_Material::GetConversionUV(MT_Point2 *nuv) -{ - *nuv++ = uv[0]; - *nuv++ = uv[1]; - *nuv++ = uv[2]; - *nuv = uv[3]; -} -void BL_Material::SetConversionUV2(const STR_String& name, MT_Point2 *nuv) -{ - uv2Name = name; - uv2[0] = *nuv++; - uv2[1] = *nuv++; - uv2[2] = *nuv++; - uv2[3] = *nuv; + int i, j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < MAXTEX; ++j) + uvs[i][j] = nuv[i][j]; + } } -void BL_Material::GetConversionUV2(MT_Point2 *nuv) +void BL_Material::GetConversionUV(MT_Point2 nuv[4][8]) { - *nuv++ = uv2[0]; - *nuv++ = uv2[1]; - *nuv++ = uv2[2]; - *nuv = uv2[3]; + int i, j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < MAXTEX; ++j) + nuv[i][j] = this->uvs[i][j]; + } } diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index 70fd640a07e..0906b9653b4 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -89,20 +89,13 @@ public: EnvMap* cubemap[MAXTEX]; unsigned int rgb[4]; - MT_Point2 uv[4]; - MT_Point2 uv2[4]; - - STR_String uvName; - STR_String uv2Name; + MT_Point2 uvs[4][MAXTEX]; void SetConversionRGB(unsigned int *rgb); void GetConversionRGB(unsigned int *rgb); - void SetConversionUV(const STR_String& name, MT_Point2 *uv); - void GetConversionUV(MT_Point2 *uv); - - void SetConversionUV2(const STR_String& name, MT_Point2 *uv); - void GetConversionUV2(MT_Point2 *uv); + void SetConversionUV(const MT_Point2 uv[4][MAXTEX]); + void GetConversionUV(MT_Point2 uv[4][MAXTEX]); void SetSharedMaterial(bool v); bool IsShared(); diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index 576da0d3f40..71d07657893 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -144,7 +144,15 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) mNeedsDeleted = 1; glGenTextures(1, (GLuint*)&mTexture); + +#ifdef WITH_DDS + if (ibuf->ftype & DDS) + InitGLCompressedTex(ibuf, mipmap); + else + InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); +#else InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); +#endif // track created units BL_TextureObject obj; @@ -183,6 +191,64 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } +void BL_Texture::InitGLCompressedTex(ImBuf* ibuf, bool mipmap) +{ +#ifndef WITH_DDS + // Fall back to uncompressed if DDS isn't enabled + InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); + return; +#else + GLint format=0; + int offset=0, i=0; + int blocksize, width, height; + int size; + GLint err; + + if (ibuf->dds_data.fourcc == FOURCC_DXT1) + format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + else if (ibuf->dds_data.fourcc == FOURCC_DXT3) + format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + else if (ibuf->dds_data.fourcc == FOURCC_DXT5) + format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + else + { + printf("Unable to find a suitable DXT compression, falling back to uncompressed\n"); + InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); + return; + } + + glBindTexture(GL_TEXTURE_2D, mTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + height = ibuf->x; + width = ibuf->y; + blocksize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16; + for (int i=0; i<ibuf->dds_data.nummipmaps && (width||height); ++i) + { + if (width == 0) + width = 1; + if (height == 0) + height = 1; + + size = ((width+3)/4)*((height+3)/4)*blocksize; + + glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height, + 0, size, ibuf->dds_data.data + offset); + + err = glGetError(); + + if (err != GL_NO_ERROR) + printf("OpenGL error: %s\nFormat: %x\n", gluErrorString(err), format); + + offset += size; + width >>= 1; + height >>= 1; + } + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#endif +} void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) { @@ -681,4 +747,3 @@ void my_free_envmapdata(EnvMap *env) } // extern C - diff --git a/source/gameengine/Ketsji/BL_Texture.h b/source/gameengine/Ketsji/BL_Texture.h index 3c60cad4fbf..e015e8c7137 100644 --- a/source/gameengine/Ketsji/BL_Texture.h +++ b/source/gameengine/Ketsji/BL_Texture.h @@ -35,6 +35,7 @@ private: void InitNonPow2Tex(unsigned int *p,int x,int y,bool mipmap ); void InitGLTex(unsigned int *p,int x,int y,bool mipmap ); + void InitGLCompressedTex(struct ImBuf *p, bool mipmap); public: BL_Texture(); ~BL_Texture( ); diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index c7f54838c10..4b3426e0784 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -221,6 +221,10 @@ set(SRC add_definitions(-DGLEW_STATIC) +if(WITH_IMAGE_DDS) + add_definitions(-DWITH_DDS) +endif() + if(WITH_SDL) list(APPEND INC_SYS ${SDL_INCLUDE_DIR} diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 018a8d44cc1..8cf5b77df1a 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -639,13 +639,6 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const for (int i=0; i<mMaterial->num_enabled; i++) { int mode = mMaterial->mapping[i].mapping; - if (mode &USECUSTOMUV) - { - if (!mMaterial->mapping[i].uvCoName.IsEmpty()) - ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV2, i); - continue; - } - if ( mode &(USEREFL|USEOBJ)) ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_GEN, i); else if (mode &USEORCO) @@ -653,7 +646,7 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const else if (mode &USENORM) ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_NORM, i); else if (mode &USEUV) - ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV1, i); + ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV, i); else if (mode &USETANG) ras->SetTexCoord(RAS_IRasterizer::RAS_TEXTANGENT, i); else diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index f1f58d7da9a..d1ca1629dad 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -80,6 +80,11 @@ struct KX_ObjectProperties ///////////////////////// + short m_col_group; + short m_col_mask; + + ///////////////////////// + int m_gamesoftFlag; float m_soft_linStiff; /* linear stiffness 0..1 */ float m_soft_angStiff; /* angular stiffness 0..1 */ diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index e0e8e2d9b3f..148c9224457 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -400,12 +400,12 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, //////////////////// ci.m_collisionFilterGroup = (isbulletsensor) ? short(CcdConstructionInfo::SensorFilter) : - (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : short(CcdConstructionInfo::StaticFilter); + ci.m_collisionFilterGroup = objprop->m_col_group; ci.m_collisionFilterMask = (isbulletsensor) ? short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter) : - (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter); + ci.m_collisionFilterMask = objprop->m_col_mask; ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody; ci.m_contactProcessingThreshold = objprop->m_contactProcessingThreshold;//todo: expose this in advanced settings, just like margin, default to 10000 or so diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index c5145ef2171..101ce0cdced 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -2972,7 +2972,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, m_testPropName = propName; else m_testPropName.SetLength(0); - KX_RayCast::Callback<KX_GameObject> callback(this,spc); + KX_RayCast::Callback<KX_GameObject> callback(this,spc, NULL, false, true); KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); if (m_pHitObject) diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 7e9d95b37a2..314727c62ab 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -46,6 +46,32 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "GPU_material.h" + +#include "MEM_guardedalloc.h" + +extern "C" +{ +#include "BKE_object.h" +#include "BKE_scene.h" +#include "BKE_library.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BLI_listbase.h" +} + +typedef struct PoolLight { + Object* blenderlight; + bool lock; +} PoolLight; + +static Scene* m_blenderlight_scene = NULL; +static int m_blenderlight_count = 0; + +static std::vector<PoolLight*> m_blenderlight_points = vector<PoolLight*>(); +static std::vector<PoolLight*> m_blenderlight_spots = vector<PoolLight*>(); +static std::vector<PoolLight*> m_blenderlight_suns = vector<PoolLight*>(); +static std::vector<PoolLight*> m_blenderlight_hemis = vector<PoolLight*>(); +static std::vector<PoolLight*> m_blenderlight_areas = vector<PoolLight*>(); KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, class RAS_IRenderTools* rendertools, @@ -59,13 +85,16 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, m_lightobj.m_light = this; m_rendertools->AddLight(&m_lightobj); m_glsl = glsl; + m_poollight = NULL; m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene(); + m_dynamic = false; }; KX_LightObject::~KX_LightObject() { GPULamp *lamp; + Object* obj; if ((lamp = GetGPULamp())) { float obmat[4][4] = {{0}}; @@ -73,6 +102,9 @@ KX_LightObject::~KX_LightObject() } m_rendertools->RemoveLight(&m_lightobj); + + if (m_dynamic && m_poollight) + checkin_blenderlight(); } @@ -86,9 +118,17 @@ CValue* KX_LightObject::GetReplica() replica->m_lightobj.m_light = replica; m_rendertools->AddLight(&replica->m_lightobj); + replica->MakeDynamic(); + return replica; } +void KX_LightObject::MakeDynamic() +{ + m_dynamic = true; + checkout_blenderlight(); +} + bool KX_LightObject::ApplyLight(KX_Scene *kxscene, int oblayer, int slot) { KX_Scene* lightscene = (KX_Scene*)m_lightobj.m_scene; @@ -181,8 +221,11 @@ bool KX_LightObject::ApplyLight(KX_Scene *kxscene, int oblayer, int slot) GPULamp *KX_LightObject::GetGPULamp() { - if (m_glsl) - return GPU_lamp_from_blender(m_blenderscene, GetBlenderObject(), GetBlenderGroupObject()); + if (m_glsl && GetBlenderObject()) + { + Scene *scene = (m_dynamic) ? m_blenderlight_scene : m_blenderscene; + return GPU_lamp_from_blender(scene, GetBlenderObject(), GetBlenderGroupObject()); + } else return NULL; } @@ -192,6 +235,12 @@ void KX_LightObject::Update() GPULamp *lamp; if ((lamp = GetGPULamp()) != NULL && GetSGNode()) { + // If the light is inactive, we can reuse it's blender light for active lights + if (m_lightobj.m_layer != m_blenderscene->layact) { + forfeit_blenderlight(); + return; + } + float obmat[4][4]; // lights don't get their openGL matrix updated, do it now if (GetSGNode()->IsDirty()) @@ -205,6 +254,8 @@ void KX_LightObject::Update() GPU_lamp_update(lamp, m_lightobj.m_layer, 0, obmat); GPU_lamp_update_colors(lamp, m_lightobj.m_red, m_lightobj.m_green, m_lightobj.m_blue, m_lightobj.m_energy); + GPU_lamp_update_distance(lamp, m_lightobj.m_distance, m_lightobj.m_att1, m_lightobj.m_att2); + GPU_lamp_update_spot(lamp, m_lightobj.m_spotsize, m_lightobj.m_spotblend); } } @@ -267,6 +318,149 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) GPU_lamp_shadow_buffer_unbind(lamp); } +void init_subpool(Scene *scene, std::vector<PoolLight*> *subpool, int count, short type) +{ + Lamp *la; + subpool->resize(count); + for (int i = 0; i < count; ++i) + { + subpool->at(i) = new PoolLight(); + subpool->at(i)->blenderlight = add_object(m_blenderlight_scene, OB_LAMP); + + //Give the lights a unique name so the converter can avoid them + strcpy(subpool->at(i)->blenderlight->id.name, "__pool__"); + + la = (Lamp*)subpool->at(i)->blenderlight->data; + la->type = type; + la->energy = 0; + } +} + +void KX_LightObject::InitBlenderLightPool(Scene *scene, int point_count, int spot_count, int sun_count, int hemi_count, int area_count) +{ + //If the light pool is already built, there is no need to rebuild it, + //we don't want libload trying to reinitialize the light pool + if (m_blenderlight_count != 0) + return; + + m_blenderlight_scene = scene; + m_blenderlight_count = point_count + spot_count + sun_count + hemi_count + area_count; + + //Don't bother finishing setup if there are no lights in the pools + //Also if no Dynamic lights are allocated, sometimes libload will get passed the count + //check and screw things up + if (m_blenderlight_count == 0) + return; + + init_subpool(scene, &m_blenderlight_points, point_count, LA_LOCAL); + init_subpool(scene, &m_blenderlight_spots, spot_count, LA_SPOT); + init_subpool(scene, &m_blenderlight_suns, sun_count, LA_SUN); + init_subpool(scene, &m_blenderlight_hemis, hemi_count, LA_HEMI); + init_subpool(scene, &m_blenderlight_areas, area_count, LA_AREA); + + GPU_materials_free(); +} + +std::vector<PoolLight*>* get_subpool(short type) +{ + if (type == RAS_LightObject::LIGHT_NORMAL) + return &m_blenderlight_points; + if (type == RAS_LightObject::LIGHT_SPOT) + return &m_blenderlight_spots; + if (type == RAS_LightObject::LIGHT_SUN) + return &m_blenderlight_suns; + if (type == RAS_LightObject::LIGHT_HEMI) + return &m_blenderlight_hemis; + if (type == RAS_LightObject::LIGHT_AREA) + return &m_blenderlight_areas; +} + +void KX_LightObject::checkout_blenderlight() +{ + std::vector<PoolLight*> *subpool = get_subpool(m_lightobj.m_type); + + if (subpool->size() == 0) + { + SetBlenderObject(NULL); + return; //Sorry, out of lights :( + } + + PoolLight* light = subpool->back(); + subpool->pop_back(); + m_poollight = light; + SetBlenderObject(light->blenderlight); +} + +void KX_LightObject::checkin_blenderlight() +{ + PoolLight* light = m_poollight; + std::vector<PoolLight*> *subpool = get_subpool(m_lightobj.m_type); + subpool->push_back(light); + m_poollight = NULL; +} + +void KX_LightObject::forfeit_blenderlight() +{ + std::vector<PoolLight*> *subpool = get_subpool(m_lightobj.m_type); + + Object *obj = GetBlenderObject(); + PoolLight* light = new PoolLight(); + light->blenderlight = obj; + light->lock = true; + + SetBlenderObject(NULL); + + subpool->push_back(light); + m_blenderlight_count++; +} + +void KX_LightObject::FreeBlenderLightPool() +{ + Base *base; + std::vector<PoolLight*> *subpool; + PoolLight *light; + unsigned int i = 0; + int total = m_blenderlight_points.size() + m_blenderlight_spots.size() + m_blenderlight_suns.size() + m_blenderlight_hemis.size() + m_blenderlight_areas.size(); + if (total != m_blenderlight_count) + { + printf("Light pool still has lights checked out. Or extra lights have been checked in\n"); + m_blenderlight_count = total; + } + + for (int i = 0; i < m_blenderlight_count; ++i) + { + if (m_blenderlight_points.size() > 0) + subpool = &m_blenderlight_points; + else if (m_blenderlight_spots.size() > 0) + subpool = &m_blenderlight_spots; + else if (m_blenderlight_suns.size() > 0) + subpool = &m_blenderlight_suns; + else if (m_blenderlight_hemis.size() > 0) + subpool = &m_blenderlight_hemis; + else if (m_blenderlight_areas.size() > 0) + subpool = &m_blenderlight_areas; + + light = subpool->back(); + if (light->lock) + { + subpool->pop_back(); + continue; + } + + base = object_in_scene(light->blenderlight, m_blenderlight_scene); + BLI_remlink(&m_blenderlight_scene->base, base); + GPU_lamp_free(base->object); + free_libblock_us(&G.main->object, base->object); + if (m_blenderlight_scene->basact == base) m_blenderlight_scene->basact = NULL; + MEM_freeN(base); + subpool->pop_back(); + } + + m_blenderlight_count = 0; + + GPU_materials_free(); +} + #ifdef WITH_PYTHON /* ------------------------------------------------------------------------- */ /* Python Integration Hooks */ diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index c2815e7afaa..0f749e5478b 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -34,9 +34,11 @@ #include "RAS_LightObject.h" #include "KX_GameObject.h" +#include "DNA_lamp_types.h" struct GPULamp; struct Scene; +struct PoolLight; class KX_Camera; class RAS_IRasterizer; class RAS_IRenderTools; @@ -47,15 +49,22 @@ class KX_LightObject : public KX_GameObject Py_Header protected: RAS_LightObject m_lightobj; + PoolLight* m_poollight; class RAS_IRenderTools* m_rendertools; //needed for registering and replication of lightobj bool m_glsl; Scene* m_blenderscene; + bool m_dynamic; + void checkout_blenderlight(); + void checkin_blenderlight(); + void forfeit_blenderlight(); + public: KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl); virtual ~KX_LightObject(); virtual CValue* GetReplica(); RAS_LightObject* GetLightData() { return &m_lightobj;} + void MakeDynamic(); /* OpenGL Light */ bool ApplyLight(KX_Scene *kxscene, int oblayer, int slot); @@ -67,6 +76,10 @@ public: void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans); void UnbindShadowBuffer(class RAS_IRasterizer *ras); void Update(); + + /* Light Pool */ + static void InitBlenderLightPool(Scene *scene, int point_count, int spot_count, int sun_count, int hemi_count, int area_count); + static void FreeBlenderLightPool(); void UpdateScene(class KX_Scene *kxscene) {m_lightobj.m_scene = (void*)kxscene;} diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 503c16fae9c..73c518013f8 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1821,9 +1821,12 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene } #endif // USE_BULLET } - /* If the object is a light, update it's scene */ + /* If the object is a light, update it's scene and make it dynamic*/ if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) + { ((KX_LightObject*)gameobj)->UpdateScene(to); + ((KX_LightObject*)gameobj)->MakeDynamic(); + } /* Add the object to the scene's logic manager */ to->GetLogicManager()->RegisterGameObjectName(gameobj->GetName(), gameobj); diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 1739f26ab6f..c6d5c6801e2 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -146,25 +146,25 @@ PyObject* KX_VertexProxy::pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *a PyObject* KX_VertexProxy::pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v); - return PyFloat_FromDouble(self->m_vertex->getUV1()[0]); + return PyFloat_FromDouble(self->m_vertex->getUV(0)[0]); } PyObject* KX_VertexProxy::pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v); - return PyFloat_FromDouble(self->m_vertex->getUV1()[1]); + return PyFloat_FromDouble(self->m_vertex->getUV(0)[1]); } PyObject* KX_VertexProxy::pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v); - return PyFloat_FromDouble(self->m_vertex->getUV2()[0]); + return PyFloat_FromDouble(self->m_vertex->getUV(1)[0]); } PyObject* KX_VertexProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v); - return PyFloat_FromDouble(self->m_vertex->getUV2()[1]); + return PyFloat_FromDouble(self->m_vertex->getUV(1)[1]); } PyObject* KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -176,7 +176,7 @@ PyObject* KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF PyObject* KX_VertexProxy::pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v); - return PyObjectFrom(MT_Point2(self->m_vertex->getUV1())); + return PyObjectFrom(MT_Point2(self->m_vertex->getUV(0))); } PyObject* KX_VertexProxy::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -245,9 +245,9 @@ int KX_VertexProxy::pyattr_set_u(void *self_v, const struct KX_PYATTRIBUTE_DEF * if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); - MT_Point2 uv = self->m_vertex->getUV1(); + MT_Point2 uv = self->m_vertex->getUV(0); uv[0] = val; - self->m_vertex->SetUV(uv); + self->m_vertex->SetUV(0, uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -260,9 +260,9 @@ int KX_VertexProxy::pyattr_set_v(void *self_v, const struct KX_PYATTRIBUTE_DEF * if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); - MT_Point2 uv = self->m_vertex->getUV1(); + MT_Point2 uv = self->m_vertex->getUV(0); uv[1] = val; - self->m_vertex->SetUV(uv); + self->m_vertex->SetUV(0, uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -275,9 +275,9 @@ int KX_VertexProxy::pyattr_set_u2(void *self_v, const struct KX_PYATTRIBUTE_DEF if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); - MT_Point2 uv = self->m_vertex->getUV2(); + MT_Point2 uv = self->m_vertex->getUV(1); uv[0] = val; - self->m_vertex->SetUV2(uv); + self->m_vertex->SetUV(1, uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -290,9 +290,9 @@ int KX_VertexProxy::pyattr_set_v2(void *self_v, const struct KX_PYATTRIBUTE_DEF if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); - MT_Point2 uv = self->m_vertex->getUV2(); + MT_Point2 uv = self->m_vertex->getUV(1); uv[1] = val; - self->m_vertex->SetUV2(uv); + self->m_vertex->SetUV(1, uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -391,7 +391,7 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF MT_Point2 vec; if (PyVecTo(value, vec)) { - self->m_vertex->SetUV(vec); + self->m_vertex->SetUV(0, vec); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -523,7 +523,7 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject* value) PyObject* KX_VertexProxy::PyGetUV() { - return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); + return PyObjectFrom(MT_Vector2(m_vertex->getUV(0))); } PyObject* KX_VertexProxy::PySetUV(PyObject* value) @@ -532,31 +532,23 @@ PyObject* KX_VertexProxy::PySetUV(PyObject* value) if (!PyVecTo(value, vec)) return NULL; - m_vertex->SetUV(vec); + m_vertex->SetUV(0, vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } PyObject* KX_VertexProxy::PyGetUV2() { - return PyObjectFrom(MT_Vector2(m_vertex->getUV2())); + return PyObjectFrom(MT_Vector2(m_vertex->getUV(1))); } -PyObject* KX_VertexProxy::PySetUV2(PyObject* args) +PyObject* KX_VertexProxy::PySetUV2(PyObject* value) { MT_Point2 vec; - unsigned int unit= RAS_TexVert::SECOND_UV; - - PyObject* list= NULL; - if (!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit)) - return NULL; - - if (!PyVecTo(list, vec)) + if (!PyVecTo(value, vec)) return NULL; - m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); - m_vertex->SetUnit(unit); - m_vertex->SetUV2(vec); + m_vertex->SetUV(1, vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 2228b6511ce..b456d45c733 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -221,7 +221,8 @@ struct CcdConstructionInfo KinematicFilter = 4, DebrisFilter = 8, SensorFilter = 16, - AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorFilter, + UserFilter = 1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12 | 1<<13 | 1<<14 | 1<<15, + AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorFilter | UserFilter, }; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index ba0d3f18b1d..b65d35cbbf0 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -1095,6 +1095,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac // don't collision with sensor object rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter; + rayCallback.m_collisionFilterGroup = CcdConstructionInfo::AllFilter; //, ,filterCallback.m_faceNormal); m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback); diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 592ddbe07d3..2af0b60d037 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -52,6 +52,7 @@ using namespace std; class RAS_ICanvas; class RAS_IPolyMaterial; +class RAS_MeshSlot; typedef vector<unsigned short> KX_IndexArray; typedef vector<RAS_TexVert> KX_VertexArray; @@ -129,7 +130,7 @@ public: RAS_TEXCO_GEN, //< GPU will generate texture coordinates RAS_TEXCO_ORCO, //< Vertex coordinates (object space) RAS_TEXCO_GLOB, //< Vertex coordinates (world space) - RAS_TEXCO_UV1, //< UV coordinates + RAS_TEXCO_UV, //< UV coordinates RAS_TEXCO_OBJECT, //< Use another object's position as coordinates RAS_TEXCO_LAVECTOR, //< Light vector as coordinates RAS_TEXCO_VIEW, //< View vector as coordinates @@ -137,7 +138,6 @@ public: RAS_TEXCO_WINDOW, //< Window coordinates RAS_TEXCO_NORM, //< Normal coordinates RAS_TEXTANGENT, //< - RAS_TEXCO_UV2, //< RAS_TEXCO_VCOL, //< Vertex Color RAS_TEXCO_DISABLE //< Disable this texture unit (cached) }; diff --git a/source/gameengine/Rasterizer/RAS_LightObject.h b/source/gameengine/Rasterizer/RAS_LightObject.h index c378a9ea0c2..96bb1a3e314 100644 --- a/source/gameengine/Rasterizer/RAS_LightObject.h +++ b/source/gameengine/Rasterizer/RAS_LightObject.h @@ -39,7 +39,9 @@ struct RAS_LightObject enum LightType{ LIGHT_SPOT, LIGHT_SUN, - LIGHT_NORMAL + LIGHT_NORMAL, + LIGHT_HEMI, + LIGHT_AREA }; bool m_modified; int m_layer; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index a18adfd8986..22572dd8958 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -47,6 +47,7 @@ #include "RAS_MeshObject.h" #include "RAS_Deformer.h" // __NLA + /* mesh slot */ RAS_MeshSlot::RAS_MeshSlot() : SG_QList() @@ -605,7 +606,8 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa if (ms.m_pDeformer) { - ms.m_pDeformer->Apply(m_material); + if (ms.m_pDeformer->Apply(m_material)); + ms.m_mesh->SetMeshModified(true); // KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_) } @@ -648,9 +650,8 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa else rasty->IndexPrimitives(ms); - if (rasty->QueryLists()) - if (ms.m_DisplayList) - ms.m_mesh->SetMeshModified(false); + + ms.m_mesh->SetMeshModified(false); rendertools->PopMatrix(); } diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 7da0be3a506..ea8cf9e498c 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -324,15 +324,14 @@ void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i, const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, + const MT_Point2 uvs[RAS_TexVert::MAX_UNIT], const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, bool flat, int origindex) { - RAS_TexVert texvert(xyz, uv, uv2, tangent, rgba, normal, flat, origindex); + RAS_TexVert texvert(xyz, uvs, tangent, rgba, normal, flat, origindex); RAS_MeshMaterial *mmat; RAS_DisplayArray *darray; RAS_MeshSlot *slot; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index b3e84c4656b..396ed293925 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -116,8 +116,7 @@ public: virtual RAS_Polygon* AddPolygon(RAS_MaterialBucket *bucket, int numverts); virtual void AddVertex(RAS_Polygon *poly, int i, const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, + const MT_Point2 uvs[RAS_TexVert::MAX_UNIT], const MT_Vector4& tangent, const unsigned int rgbacolor, const MT_Vector3& normal, diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt index 189c4f78f77..9e4dc1f749f 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt @@ -46,12 +46,17 @@ set(SRC RAS_GLExtensionManager.cpp RAS_ListRasterizer.cpp RAS_OpenGLRasterizer.cpp - RAS_VAOpenGLRasterizer.cpp + RAS_StorageIM.cpp + RAS_StorageVA.cpp + RAS_StorageVBO.cpp RAS_GLExtensionManager.h + RAS_IStorage.h RAS_ListRasterizer.h RAS_OpenGLRasterizer.h - RAS_VAOpenGLRasterizer.h + RAS_StorageIM.h + RAS_StorageVA.h + RAS_StorageVBO.h ) add_definitions(-DGLEW_STATIC) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h new file mode 100644 index 00000000000..f5c16bc8cd8 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h @@ -0,0 +1,62 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_STORAGE +#define __KX_STORAGE + +#include "RAS_MaterialBucket.h" + +enum RAS_STORAGE_TYPE { + RAS_AUTO_STORAGE, + RAS_IMMEDIATE, + RAS_VA, + RAS_VBO +}; + +class RAS_IStorage +{ + +public: + virtual ~RAS_IStorage() {}; + + virtual bool Init()=0; + virtual void Exit()=0; + + virtual void IndexPrimitives(RAS_MeshSlot& ms)=0; + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms)=0; + + virtual void SetDrawingMode(int drawingmode)=0; + + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_IStorage"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //__KX_STORAGE diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index 1f411a09586..f6246458878 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -106,9 +106,8 @@ bool RAS_ListSlot::End() -RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays, bool lock) -: RAS_VAOpenGLRasterizer(canvas, lock), - mUseVertexArrays(useVertexArrays), +RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock, int storage) +: RAS_OpenGLRasterizer(canvas, storage), mATI(false) { if (!strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc.")) @@ -238,11 +237,8 @@ void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms) return; } } - // derived mesh cannot use vertex array - if (mUseVertexArrays && !ms.m_pDerivedMesh) - RAS_VAOpenGLRasterizer::IndexPrimitives(ms); - else - RAS_OpenGLRasterizer::IndexPrimitives(ms); + + RAS_OpenGLRasterizer::IndexPrimitives(ms); if (ms.m_bDisplayList) { localSlot->EndList(); @@ -267,13 +263,7 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) } } - // workaround: note how we do not use vertex arrays for making display - // lists, since glVertexAttribPointerARB doesn't seem to work correct - // in display lists on ATI? either a bug in the driver or in Blender .. - if (mUseVertexArrays && !mATI && !ms.m_pDerivedMesh) - RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms); - else - RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms); + RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms); if (ms.m_bDisplayList) { localSlot->EndList(); @@ -283,29 +273,17 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) bool RAS_ListRasterizer::Init(void) { - if (mUseVertexArrays) { - return RAS_VAOpenGLRasterizer::Init(); - } else { - return RAS_OpenGLRasterizer::Init(); - } + return RAS_OpenGLRasterizer::Init(); } void RAS_ListRasterizer::SetDrawingMode(int drawingmode) { - if (mUseVertexArrays) { - RAS_VAOpenGLRasterizer::SetDrawingMode(drawingmode); - } else { - RAS_OpenGLRasterizer::SetDrawingMode(drawingmode); - } + RAS_OpenGLRasterizer::SetDrawingMode(drawingmode); } void RAS_ListRasterizer::Exit() { - if (mUseVertexArrays) { - RAS_VAOpenGLRasterizer::Exit(); - } else { - RAS_OpenGLRasterizer::Exit(); - } + RAS_OpenGLRasterizer::Exit(); } // eof diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index 0b36bbf3876..03371896549 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -7,7 +7,7 @@ #define __RAS_LISTRASTERIZER_H__ #include "RAS_MaterialBucket.h" -#include "RAS_VAOpenGLRasterizer.h" +#include "RAS_OpenGLRasterizer.h" #include <vector> #include <map> @@ -49,7 +49,7 @@ typedef std::map<RAS_DisplayArrayList, RAS_ListSlot*> RAS_ArrayLists; typedef std::vector<RAS_ListSlot*> RAS_ListSlots; // indexed by material slot number typedef std::map<DerivedMesh*, RAS_ListSlots*> RAS_DerivedMeshLists; -class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer +class RAS_ListRasterizer : public RAS_OpenGLRasterizer { bool mUseVertexArrays; bool mATI; @@ -61,7 +61,7 @@ class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer public: void RemoveListSlot(RAS_ListSlot* list); - RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays=false, bool lock=false); + RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock=false, int storage=RAS_AUTO_STORAGE); virtual ~RAS_ListRasterizer(); virtual void IndexPrimitives(class RAS_MeshSlot& ms); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 7db433b5b4f..7c0956839a7 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -43,6 +43,10 @@ #include "MT_CmMatrix4x4.h" #include "RAS_IRenderTools.h" // rendering text +#include "RAS_StorageIM.h" +#include "RAS_StorageVA.h" +#include "RAS_StorageVBO.h" + #include "GPU_draw.h" #include "GPU_material.h" #include "GPU_extensions.h" @@ -71,7 +75,7 @@ static GLuint right_eye_vinterlace_mask[32]; */ static GLuint hinterlace_mask[33]; -RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) +RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage) :RAS_IRasterizer(canvas), m_2DCanvas(canvas), m_fogenabled(false), @@ -90,7 +94,8 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_attrib_num(0), //m_last_alphablend(GPU_BLEND_SOLID), m_last_frontface(true), - m_materialCachingInfo(0) + m_materialCachingInfo(0), + m_storage_type(storage) { m_viewmatrix.setIdentity(); m_viewinvmatrix.setIdentity(); @@ -104,6 +109,24 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) hinterlace_mask[32] = 0; m_prevafvalue = GPU_get_anisotropic(); + + if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE && GLEW_ARB_vertex_buffer_object*/) + { + m_storage = new RAS_StorageVBO(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_storage_type = RAS_VBO; + } + else if (m_storage_type == RAS_VA || m_storage_type == RAS_AUTO_STORAGE && GLEW_VERSION_1_1) + { + m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_storage_type = RAS_VA; + } + else + { + m_storage = m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_storage_type = RAS_IMMEDIATE; + } } @@ -112,10 +135,12 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer() { // Restore the previous AF value GPU_set_anisotropic(m_prevafvalue); + delete m_storage; } bool RAS_OpenGLRasterizer::Init() { + bool storage_init; GPU_state_init(); @@ -143,7 +168,9 @@ bool RAS_OpenGLRasterizer::Init() glShadeModel(GL_SMOOTH); - return true; + storage_init = m_storage->Init(); + + return true && storage_init; } @@ -264,6 +291,8 @@ bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat) void RAS_OpenGLRasterizer::Exit() { + m_storage->Exit(); + glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glClearDepth(1.0); @@ -286,7 +315,7 @@ void RAS_OpenGLRasterizer::Exit() bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) { m_time = time; - m_drawingmode = drawingmode; + SetDrawingMode(drawingmode); // Blender camera routine destroys the settings if (m_drawingmode < KX_SOLID) @@ -325,6 +354,8 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode) if (m_drawingmode == KX_WIREFRAME) glDisable(GL_CULL_FACE); + + m_storage->SetDrawingMode(drawingmode); } int RAS_OpenGLRasterizer::GetDrawingMode() @@ -664,7 +695,7 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms, glattrib = -1; if (GLEW_ARB_vertex_program) for (unit=0; unit<m_attrib_num; unit++) - if (m_attrib[unit] == RAS_TEXCO_UV1) + if (m_attrib[unit] == RAS_TEXCO_UV) glattrib = unit; rendertools->RenderText(polymat->GetDrawingMode(), polymat, @@ -706,256 +737,20 @@ void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit) m_attrib[unit] = coords; } -void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv) -{ - int unit; - - if (GLEW_ARB_multitexture) { - for (unit=0; unit<m_texco_num; unit++) { - if (tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) { - glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2()); - continue; - } - switch(m_texco[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ()); - break; - case RAS_TEXCO_UV1: - glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1()); - break; - case RAS_TEXCO_NORM: - glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal()); - break; - case RAS_TEXTANGENT: - glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent()); - break; - case RAS_TEXCO_UV2: - glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2()); - break; - default: - break; - } - } - } - - if (GLEW_ARB_vertex_program) { - for (unit=0; unit<m_attrib_num; unit++) { - switch(m_attrib[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - glVertexAttrib3fvARB(unit, tv.getXYZ()); - break; - case RAS_TEXCO_UV1: - glVertexAttrib2fvARB(unit, tv.getUV1()); - break; - case RAS_TEXCO_NORM: - glVertexAttrib3fvARB(unit, tv.getNormal()); - break; - case RAS_TEXTANGENT: - glVertexAttrib4fvARB(unit, tv.getTangent()); - break; - case RAS_TEXCO_UV2: - glVertexAttrib2fvARB(unit, tv.getUV2()); - break; - case RAS_TEXCO_VCOL: - glVertexAttrib4ubvARB(unit, tv.getRGBA()); - break; - default: - break; - } - } - } - -} - void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) { - IndexPrimitivesInternal(ms, false); + if (ms.m_pDerivedMesh) + m_failsafe_storage->IndexPrimitives(ms); + else + m_storage->IndexPrimitives(ms); } void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) { - IndexPrimitivesInternal(ms, true); -} - -static bool current_wireframe; -static RAS_MaterialBucket *current_bucket; -static RAS_IPolyMaterial *current_polymat; -static RAS_MeshSlot *current_ms; -static RAS_MeshObject *current_mesh; -static int current_blmat_nr; -static GPUVertexAttribs current_gpu_attribs; -static Image *current_image; -static int CheckMaterialDM(int matnr, void *attribs) -{ - // only draw the current material - if (matnr != current_blmat_nr) - return 0; - GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs; - if (gattribs) - memcpy(gattribs, ¤t_gpu_attribs, sizeof(GPUVertexAttribs)); - return 1; -} - -/* -static int CheckTexfaceDM(void *mcol, int index) -{ - - // index is the original face index, retrieve the polygon - RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ? - current_mesh->GetPolygon(index) : NULL; - if (polygon && polygon->GetMaterial() == current_bucket) { - // must handle color. - if (current_wireframe) - return 2; - if (current_ms->m_bObjectColor) { - MT_Vector4& rgba = current_ms->m_RGBAcolor; - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - // don't use mcol - return 2; - } - if (!mcol) { - // we have to set the color from the material - unsigned char rgba[4]; - current_polymat->GetMaterialRGBAColor(rgba); - glColor4ubv((const GLubyte *)rgba); - return 2; - } - return 1; - } - return 0; -} -*/ - -static DMDrawOption CheckTexDM(MTFace *tface, int has_mcol, int matnr) -{ - - // index is the original face index, retrieve the polygon - if (matnr == current_blmat_nr && - (tface == NULL || tface->tpage == current_image)) { - // must handle color. - if (current_wireframe) - return DM_DRAW_OPTION_NO_MCOL; - if (current_ms->m_bObjectColor) { - MT_Vector4& rgba = current_ms->m_RGBAcolor; - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - // don't use mcol - return DM_DRAW_OPTION_NO_MCOL; - } - if (!has_mcol) { - // we have to set the color from the material - unsigned char rgba[4]; - current_polymat->GetMaterialRGBAColor(rgba); - glColor4ubv((const GLubyte *)rgba); - return DM_DRAW_OPTION_NO_MCOL; - } - return DM_DRAW_OPTION_NORMAL; - } - return DM_DRAW_OPTION_SKIP; -} - -void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) -{ - bool obcolor = ms.m_bObjectColor; - bool wireframe = m_drawingmode <= KX_WIREFRAME; - MT_Vector4& rgba = ms.m_RGBAcolor; - RAS_MeshSlot::iterator it; - - if (ms.m_pDerivedMesh) { - // mesh data is in derived mesh, - current_bucket = ms.m_bucket; - current_polymat = current_bucket->GetPolyMaterial(); - current_ms = &ms; - current_mesh = ms.m_mesh; - current_wireframe = wireframe; - // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */ - - // handle two-side - if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL) - this->SetCullFace(true); - else - this->SetCullFace(false); - - if (current_polymat->GetFlag() & RAS_BLENDERGLSL) { - // GetMaterialIndex return the original mface material index, - // increment by 1 to match what derived mesh is doing - current_blmat_nr = current_polymat->GetMaterialIndex()+1; - // For GLSL we need to retrieve the GPU material attribute - Material* blmat = current_polymat->GetBlenderMaterial(); - Scene* blscene = current_polymat->GetBlenderScene(); - if (!wireframe && blscene && blmat) - GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), ¤t_gpu_attribs); - else - memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs)); - // DM draw can mess up blending mode, restore at the end - int current_blend_mode = GPU_get_material_alpha_blend(); - ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM); - GPU_set_material_alpha_blend(current_blend_mode); - } else { - //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol); - current_blmat_nr = current_polymat->GetMaterialIndex(); - current_image = current_polymat->GetBlenderImage(); - ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL); - } - return; - } - // iterate over display arrays, each containing an index + vertex array - for (ms.begin(it); !ms.end(it); ms.next(it)) { - RAS_TexVert *vertex; - size_t i, j, numvert; - - numvert = it.array->m_type; - - if (it.array->m_type == RAS_DisplayArray::LINE) { - // line drawing - glBegin(GL_LINES); - - for (i=0; i<it.totindex; i+=2) - { - vertex = &it.vertex[it.index[i]]; - glVertex3fv(vertex->getXYZ()); - - vertex = &it.vertex[it.index[i+1]]; - glVertex3fv(vertex->getXYZ()); - } - - glEnd(); - } - else { - // triangle and quad drawing - if (it.array->m_type == RAS_DisplayArray::TRIANGLE) - glBegin(GL_TRIANGLES); - else - glBegin(GL_QUADS); - - for (i=0; i<it.totindex; i+=numvert) - { - if (obcolor) - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - - for (j=0; j<numvert; j++) { - vertex = &it.vertex[it.index[i+j]]; - - if (!wireframe) { - if (!obcolor) - glColor4ubv((const GLubyte *)(vertex->getRGBA())); - - glNormal3fv(vertex->getNormal()); - - if (multi) - TexCoord(*vertex); - else - glTexCoord2fv(vertex->getUV1()); - } - - glVertex3fv(vertex->getXYZ()); - } - } - - glEnd(); - } - } + if (ms.m_pDerivedMesh) + m_failsafe_storage->IndexPrimitivesMulti(ms); + else + m_storage->IndexPrimitivesMulti(ms); } void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 3b4a6c4900c..bd85367fae8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -41,6 +41,7 @@ using namespace std; #include "RAS_IRasterizer.h" +#include "RAS_IStorage.h" #include "RAS_MaterialBucket.h" #include "RAS_ICanvas.h" @@ -83,7 +84,6 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer float m_ambr; float m_ambg; float m_ambb; - double m_time; MT_Matrix4x4 m_viewmatrix; MT_Matrix4x4 m_viewinvmatrix; @@ -115,9 +115,15 @@ protected: /** Stores the caching information for the last material activated. */ RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo; + /** Making use of a Strategy desing pattern for storage behavior. + Examples of concrete strategies: Vertex Arrays, VBOs, Immediate Mode*/ + int m_storage_type; + RAS_IStorage* m_storage; + RAS_IStorage* m_failsafe_storage; //So derived mesh can use immediate mode + public: double GetTime(); - RAS_OpenGLRasterizer(RAS_ICanvas* canv); + RAS_OpenGLRasterizer(RAS_ICanvas* canv, int storage=RAS_AUTO_STORAGE); virtual ~RAS_OpenGLRasterizer(); /*enum DrawType @@ -166,8 +172,6 @@ public: class RAS_IPolyMaterial* polymat, class RAS_IRenderTools* rendertools); - void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi); - virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat); virtual void SetProjectionMatrix(const MT_Matrix4x4 & mat); virtual void SetViewMatrix( diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp new file mode 100644 index 00000000000..dcb10c0dd93 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp @@ -0,0 +1,307 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "RAS_StorageIM.h" + +#include "GL/glew.h" +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + +#include "DNA_meshdata_types.h" + +#include "BKE_DerivedMesh.h" + +RAS_StorageIM::RAS_StorageIM(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib) : + m_texco_num(texco_num), + m_texco(texco), + m_attrib_num(attrib_num), + m_attrib(attrib) +{ +} +RAS_StorageIM::~RAS_StorageIM() +{ +} + +bool RAS_StorageIM::Init() +{ + return true; +} +void RAS_StorageIM::Exit() +{ +} + +void RAS_StorageIM::IndexPrimitives(RAS_MeshSlot& ms) +{ + IndexPrimitivesInternal(ms, false); +} + +void RAS_StorageIM::IndexPrimitivesMulti(class RAS_MeshSlot& ms) +{ + IndexPrimitivesInternal(ms, true); +} + +void RAS_StorageIM::TexCoord(const RAS_TexVert &tv) +{ + int unit; + + if (GLEW_ARB_multitexture) { + for (unit = 0; unit < *m_texco_num; unit++) { + switch(m_texco[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, tv.getXYZ()); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glMultiTexCoord2fvARB(GL_TEXTURE0_ARB + unit, tv.getUV(unit)); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, tv.getNormal()); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glMultiTexCoord4fvARB(GL_TEXTURE0_ARB + unit, tv.getTangent()); + break; + default: + break; + } + } + } + + if (GLEW_ARB_vertex_program) { + int uv = 0; + for (unit = 0; unit < *m_attrib_num; unit++) { + switch(m_attrib[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glVertexAttrib3fvARB(unit, tv.getXYZ()); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glVertexAttrib2fvARB(unit, tv.getUV(uv++)); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glVertexAttrib3fvARB(unit, tv.getNormal()); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glVertexAttrib4fvARB(unit, tv.getTangent()); + break; + case RAS_IRasterizer::RAS_TEXCO_VCOL: + glVertexAttrib4ubvARB(unit, tv.getRGBA()); + break; + default: + break; + } + } + } + +} + +void RAS_StorageIM::SetCullFace(bool enable) +{ + if (enable) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); +} + +static bool current_wireframe; +static RAS_MaterialBucket *current_bucket; +static RAS_IPolyMaterial *current_polymat; +static RAS_MeshSlot *current_ms; +static RAS_MeshObject *current_mesh; +static int current_blmat_nr; +static GPUVertexAttribs current_gpu_attribs; +static Image *current_image; +static int CheckMaterialDM(int matnr, void *attribs) +{ + // only draw the current material + if (matnr != current_blmat_nr) + return 0; + GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs; + if (gattribs) + memcpy(gattribs, ¤t_gpu_attribs, sizeof(GPUVertexAttribs)); + return 1; +} + +/* +static int CheckTexfaceDM(void *mcol, int index) +{ + + // index is the original face index, retrieve the polygon + RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ? + current_mesh->GetPolygon(index) : NULL; + if (polygon && polygon->GetMaterial() == current_bucket) { + // must handle color. + if (current_wireframe) + return 2; + if (current_ms->m_bObjectColor) { + MT_Vector4& rgba = current_ms->m_RGBAcolor; + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + // don't use mcol + return 2; + } + if (!mcol) { + // we have to set the color from the material + unsigned char rgba[4]; + current_polymat->GetMaterialRGBAColor(rgba); + glColor4ubv((const GLubyte *)rgba); + return 2; + } + return 1; + } + return 0; +} +*/ + +static DMDrawOption CheckTexDM(MTFace *tface, int has_mcol, int matnr) +{ + + // index is the original face index, retrieve the polygon + if (matnr == current_blmat_nr && + (tface == NULL || tface->tpage == current_image)) { + // must handle color. + if (current_wireframe) + return DM_DRAW_OPTION_NO_MCOL; + if (current_ms->m_bObjectColor) { + MT_Vector4& rgba = current_ms->m_RGBAcolor; + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + // don't use mcol + return DM_DRAW_OPTION_NO_MCOL; + } + if (!has_mcol) { + // we have to set the color from the material + unsigned char rgba[4]; + current_polymat->GetMaterialRGBAColor(rgba); + glColor4ubv((const GLubyte *)rgba); + return DM_DRAW_OPTION_NO_MCOL; + } + return DM_DRAW_OPTION_NORMAL; + } + return DM_DRAW_OPTION_SKIP; +} + +void RAS_StorageIM::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) +{ + bool obcolor = ms.m_bObjectColor; + bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME; + MT_Vector4& rgba = ms.m_RGBAcolor; + RAS_MeshSlot::iterator it; + + if (ms.m_pDerivedMesh) { + // mesh data is in derived mesh, + current_bucket = ms.m_bucket; + current_polymat = current_bucket->GetPolyMaterial(); + current_ms = &ms; + current_mesh = ms.m_mesh; + current_wireframe = wireframe; + // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */ + + // handle two-side + if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL) + this->SetCullFace(true); + else + this->SetCullFace(false); + + if (current_polymat->GetFlag() & RAS_BLENDERGLSL) { + // GetMaterialIndex return the original mface material index, + // increment by 1 to match what derived mesh is doing + current_blmat_nr = current_polymat->GetMaterialIndex()+1; + // For GLSL we need to retrieve the GPU material attribute + Material* blmat = current_polymat->GetBlenderMaterial(); + Scene* blscene = current_polymat->GetBlenderScene(); + if (!wireframe && blscene && blmat) + GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), ¤t_gpu_attribs); + else + memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs)); + // DM draw can mess up blending mode, restore at the end + int current_blend_mode = GPU_get_material_alpha_blend(); + ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM); + GPU_set_material_alpha_blend(current_blend_mode); + } else { + //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol); + current_blmat_nr = current_polymat->GetMaterialIndex(); + current_image = current_polymat->GetBlenderImage(); + ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL); + } + return; + } + // iterate over display arrays, each containing an index + vertex array + for (ms.begin(it); !ms.end(it); ms.next(it)) { + RAS_TexVert *vertex; + size_t i, j, numvert; + + numvert = it.array->m_type; + + if (it.array->m_type == RAS_DisplayArray::LINE) { + // line drawing + glBegin(GL_LINES); + + for (i = 0; i < it.totindex; i += 2) + { + vertex = &it.vertex[it.index[i]]; + glVertex3fv(vertex->getXYZ()); + + vertex = &it.vertex[it.index[i+1]]; + glVertex3fv(vertex->getXYZ()); + } + + glEnd(); + } + else { + // triangle and quad drawing + if (it.array->m_type == RAS_DisplayArray::TRIANGLE) + glBegin(GL_TRIANGLES); + else + glBegin(GL_QUADS); + + for (i = 0; i < it.totindex; i += numvert) + { + if (obcolor) + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + + for (j = 0; j < numvert; j++) { + vertex = &it.vertex[it.index[i+j]]; + + if (!wireframe) { + if (!obcolor) + glColor4ubv((const GLubyte *)(vertex->getRGBA())); + + glNormal3fv(vertex->getNormal()); + + if (multi) + TexCoord(*vertex); + else + glTexCoord2fv(vertex->getUV(0)); + } + + glVertex3fv(vertex->getXYZ()); + } + } + + glEnd(); + } + } +} diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h new file mode 100644 index 00000000000..de4ff30d394 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h @@ -0,0 +1,68 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_IMMEDIATEMODESTORAGE +#define __KX_IMMEDIATEMODESTORAGE + +#include "RAS_IStorage.h" +#include "RAS_IRasterizer.h" + +class RAS_StorageIM : public RAS_IStorage +{ +public: + RAS_StorageIM(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib); + virtual ~RAS_StorageIM(); + + virtual bool Init(); + virtual void Exit(); + + virtual void IndexPrimitives(RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); + + virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;}; + +protected: + int m_drawingmode; + int* m_texco_num; + int* m_attrib_num; + RAS_IRasterizer::TexCoGen* m_texco; + RAS_IRasterizer::TexCoGen* m_attrib; + + void TexCoord(const RAS_TexVert &tv); + void SetCullFace(bool enable); + + void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi); + + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageIM"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //__KX_IMMEDIATEMODESTORAGE diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp index ff24bd639ba..d61e657d7ad 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp @@ -25,97 +25,51 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp - * \ingroup bgerastogl - */ - -#include "RAS_VAOpenGLRasterizer.h" -#include <stdlib.h> +#include "RAS_StorageVA.h" #include "GL/glew.h" -#include "GPU_extensions.h" - -#include "STR_String.h" -#include "RAS_TexVert.h" -#include "MT_CmMatrix4x4.h" -#include "RAS_IRenderTools.h" // rendering text - -RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock) -: RAS_OpenGLRasterizer(canvas), - m_Lock(lock && GLEW_EXT_compiled_vertex_array), + +RAS_StorageVA::RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib) : + m_texco_num(texco_num), + m_texco(texco), + m_attrib_num(attrib_num), + m_attrib(attrib), m_last_texco_num(0), m_last_attrib_num(0) { } -RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer() +RAS_StorageVA::~RAS_StorageVA() { } -bool RAS_VAOpenGLRasterizer::Init(void) +bool RAS_StorageVA::Init() { - - bool result = RAS_OpenGLRasterizer::Init(); - - if (result) - { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } - - return result; -} + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); -void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode) -{ - m_drawingmode = drawingmode; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - switch (m_drawingmode) - { - case KX_BOUNDINGBOX: - case KX_WIREFRAME: - //glDisableClientState(GL_COLOR_ARRAY); - //glDisable(GL_CULL_FACE); - break; - case KX_SOLID: - //glDisableClientState(GL_COLOR_ARRAY); - break; - case KX_TEXTURED: - case KX_SHADED: - case KX_SHADOW: - //glEnableClientState(GL_COLOR_ARRAY); - default: - break; - } + return true; } -void RAS_VAOpenGLRasterizer::Exit() +void RAS_StorageVA::Exit() { glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - - RAS_OpenGLRasterizer::Exit(); } -void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) +void RAS_StorageVA::IndexPrimitives(RAS_MeshSlot& ms) { static const GLsizei stride = sizeof(RAS_TexVert); - bool wireframe = m_drawingmode <= KX_WIREFRAME; + bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME; RAS_MeshSlot::iterator it; GLenum drawmode; - if (ms.m_pDerivedMesh) { - // cannot be handled here, pass to RAS_OpenGLRasterizer - RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, false); - return; - } - if (!wireframe) glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -151,7 +105,7 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); if (!wireframe) { - glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1()); + glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV(0)); if (glIsEnabled(GL_COLOR_ARRAY)) glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); } @@ -166,19 +120,13 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) } } -void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) +void RAS_StorageVA::IndexPrimitivesMulti(class RAS_MeshSlot& ms) { static const GLsizei stride = sizeof(RAS_TexVert); - bool wireframe = m_drawingmode <= KX_WIREFRAME; + bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME; RAS_MeshSlot::iterator it; GLenum drawmode; - if (ms.m_pDerivedMesh) { - // cannot be handled here, pass to RAS_OpenGLRasterizer - RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, true); - return; - } - if (!wireframe) EnableTextures(true); @@ -229,7 +177,7 @@ void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) } } -void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) +void RAS_StorageVA::TexCoordPtr(const RAS_TexVert *tv) { /* note: this function must closely match EnableTextures to enable/disable * the right arrays, otherwise coordinate and attribute pointers from other @@ -238,34 +186,26 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) if (GLEW_ARB_multitexture) { - for (unit=0; unit<m_texco_num; unit++) + for (unit = 0; unit < *m_texco_num; unit++) { glClientActiveTextureARB(GL_TEXTURE0_ARB+unit); - if (tv->getFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2()); - continue; - } - switch(m_texco[unit]) + switch (m_texco[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ()); - break; - case RAS_TEXCO_UV1: - glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1()); - break; - case RAS_TEXCO_NORM: - glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal()); - break; - case RAS_TEXTANGENT: - glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent()); - break; - case RAS_TEXCO_UV2: - glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV2()); - break; - default: - break; + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ()); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV(unit)); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal()); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent()); + break; + default: + break; } } @@ -273,51 +213,49 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) } if (GLEW_ARB_vertex_program) { - for (unit=0; unit<m_attrib_num; unit++) { - switch(m_attrib[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ()); - break; - case RAS_TEXCO_UV1: - glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1()); - break; - case RAS_TEXCO_NORM: - glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal()); - break; - case RAS_TEXTANGENT: - glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent()); - break; - case RAS_TEXCO_UV2: - glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2()); - break; - case RAS_TEXCO_VCOL: - glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA()); - break; - default: - break; + int uv = 0; + for (unit = 0; unit < *m_attrib_num; unit++) { + switch (m_attrib[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ()); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV(uv++)); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal()); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent()); + break; + case RAS_IRasterizer::RAS_TEXCO_VCOL: + glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA()); + break; + default: + break; } } } } -void RAS_VAOpenGLRasterizer::EnableTextures(bool enable) +void RAS_StorageVA::EnableTextures(bool enable) { - TexCoGen *texco, *attrib; + RAS_IRasterizer::TexCoGen *texco, *attrib; int unit, texco_num, attrib_num; /* we cache last texcoords and attribs to ensure we disable the ones that * were actually last set */ if (enable) { texco = m_texco; - texco_num = m_texco_num; + texco_num = *m_texco_num; attrib = m_attrib; - attrib_num = m_attrib_num; + attrib_num = *m_attrib_num; - memcpy(m_last_texco, m_texco, sizeof(TexCoGen)*m_texco_num); - m_last_texco_num = m_texco_num; - memcpy(m_last_attrib, m_attrib, sizeof(TexCoGen)*m_attrib_num); - m_last_attrib_num = m_attrib_num; + memcpy(m_last_texco, m_texco, sizeof(RAS_IRasterizer::TexCoGen)*(*m_texco_num)); + m_last_texco_num = *m_texco_num; + memcpy(m_last_attrib, m_attrib, sizeof(RAS_IRasterizer::TexCoGen)*(*m_attrib_num)); + m_last_attrib_num = *m_attrib_num; } else { texco = m_last_texco; @@ -327,23 +265,22 @@ void RAS_VAOpenGLRasterizer::EnableTextures(bool enable) } if (GLEW_ARB_multitexture) { - for (unit=0; unit<texco_num; unit++) { - glClientActiveTextureARB(GL_TEXTURE0_ARB+unit); + for (unit = 0; unit < texco_num; unit++) { + glClientActiveTextureARB(GL_TEXTURE0_ARB + unit); - switch(texco[unit]) + switch (texco[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - case RAS_TEXCO_UV1: - case RAS_TEXCO_NORM: - case RAS_TEXTANGENT: - case RAS_TEXCO_UV2: - if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY); - else glDisableClientState(GL_TEXTURE_COORD_ARRAY); - break; - default: - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - break; + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + case RAS_IRasterizer::RAS_TEXCO_UV: + case RAS_IRasterizer::RAS_TEXCO_NORM: + case RAS_IRasterizer::RAS_TEXTANGENT: + if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY); + else glDisableClientState(GL_TEXTURE_COORD_ARRAY); + break; + default: + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + break; } } @@ -357,21 +294,20 @@ void RAS_VAOpenGLRasterizer::EnableTextures(bool enable) } if (GLEW_ARB_vertex_program) { - for (unit=0; unit<attrib_num; unit++) { - switch(attrib[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - case RAS_TEXCO_UV1: - case RAS_TEXCO_NORM: - case RAS_TEXTANGENT: - case RAS_TEXCO_UV2: - case RAS_TEXCO_VCOL: - if (enable) glEnableVertexAttribArrayARB(unit); - else glDisableVertexAttribArrayARB(unit); - break; - default: - glDisableVertexAttribArrayARB(unit); - break; + for (unit = 0; unit < attrib_num; unit++) { + switch (attrib[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + case RAS_IRasterizer::RAS_TEXCO_UV: + case RAS_IRasterizer::RAS_TEXCO_NORM: + case RAS_IRasterizer::RAS_TEXTANGENT: + case RAS_IRasterizer::RAS_TEXCO_VCOL: + if (enable) glEnableVertexAttribArrayARB(unit); + else glDisableVertexAttribArrayARB(unit); + break; + default: + glDisableVertexAttribArrayARB(unit); + break; } } } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h index d96f390ad74..da7766ec5ca 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h @@ -25,49 +25,53 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file RAS_VAOpenGLRasterizer.h - * \ingroup bgerastogl - */ +#ifndef __KX_VERTEXARRAYSTORAGE +#define __KX_VERTEXARRAYSTORAGE -#ifndef __RAS_VAOPENGLRASTERIZER_H__ -#define __RAS_VAOPENGLRASTERIZER_H__ +#include "RAS_IStorage.h" +#include "RAS_IRasterizer.h" #include "RAS_OpenGLRasterizer.h" -class RAS_VAOpenGLRasterizer : public RAS_OpenGLRasterizer +class RAS_StorageVA : public RAS_IStorage { - void TexCoordPtr(const RAS_TexVert *tv); - bool m_Lock; - - TexCoGen m_last_texco[RAS_MAX_TEXCO]; - TexCoGen m_last_attrib[RAS_MAX_ATTRIB]; - int m_last_texco_num; - int m_last_attrib_num; public: - RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock=false); - virtual ~RAS_VAOpenGLRasterizer(); + RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib); + virtual ~RAS_StorageVA(); virtual bool Init(); virtual void Exit(); - virtual void SetDrawingMode(int drawingmode); - - virtual void IndexPrimitives(class RAS_MeshSlot& ms); + virtual void IndexPrimitives(RAS_MeshSlot& ms); virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); -private: + virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;}; + +protected: + int m_drawingmode; + + int* m_texco_num; + int* m_attrib_num; + + int m_last_texco_num; + int m_last_attrib_num; + + RAS_IRasterizer::TexCoGen* m_texco; + RAS_IRasterizer::TexCoGen* m_attrib; + + RAS_IRasterizer::TexCoGen m_last_texco[RAS_MAX_TEXCO]; + RAS_IRasterizer::TexCoGen m_last_attrib[RAS_MAX_ATTRIB]; + virtual void EnableTextures(bool enable); - //virtual bool QueryArrays(){return true;} - //virtual bool QueryLists(){return m_Lock;} + virtual void TexCoordPtr(const RAS_TexVert *tv); #ifdef WITH_CXX_GUARDEDALLOC public: - void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_VAOpenGLRasterizer"); } + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageVA"); } void operator delete( void *mem ) { MEM_freeN(mem); } #endif }; -#endif //__RAS_VAOPENGLRASTERIZER_H__ - +#endif //__KX_VERTEXARRAYSTORAGE diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp new file mode 100644 index 00000000000..e38dc367eff --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp @@ -0,0 +1,272 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "RAS_StorageVBO.h" +#include "RAS_MeshObject.h" + +#include "GL/glew.h" + +VBO::VBO(RAS_DisplayArray *data, unsigned int indices) +{ + this->data = data; + this->size = data->m_vertex.size(); + this->indices = indices; + this->stride = 28*sizeof(GLfloat); + + // Determine drawmode + if (data->m_type == data->QUAD) + this->mode = GL_QUADS; + else if (data->m_type == data->TRIANGLE) + this->mode = GL_TRIANGLES; + else + this->mode = GL_LINE; + + // Generate Buffers + glGenBuffersARB(1, &this->ibo); + glGenBuffersARB(1, &this->vbo_id); + + // Allocate some space to gather data into before uploading to GPU + this->vbo = new GLfloat[this->stride*this->size]; + + // Fill the buffers with initial data + UpdateIndices(); + UpdateData(); + + // Establish offsets + this->vertex_offset = 0; + this->normal_offset = (void*)(3*sizeof(GLfloat)); + this->tangent_offset = (void*)(6*sizeof(GLfloat)); + this->color_offset = (void*)(10*sizeof(GLfloat)); + this->uv_offset = (void*)(11*sizeof(GLfloat)); + this->dummy_offset = (void*)(27*sizeof(GLfloat)); +} + +VBO::~VBO() +{ + glDeleteBuffersARB(1, &this->ibo); + glDeleteBuffersARB(1, &this->vbo_id); + + delete this->vbo; +} + +void VBO::UpdateData() +{ + unsigned int i, j, k; + + glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id); + + // Lets the video card know we are done with the old VBO + glBufferDataARB(GL_ARRAY_BUFFER_ARB, 0, NULL, GL_DYNAMIC_DRAW_ARB); + + // Gather data + for (i = 0, j = 0; i < data->m_vertex.size(); i++, j += this->stride/sizeof(GLfloat)) + { + memcpy(&this->vbo[j], data->m_vertex[i].getXYZ(), sizeof(float)*3); + memcpy(&this->vbo[j+3], data->m_vertex[i].getNormal(), sizeof(float)*3); + memcpy(&this->vbo[j+6], data->m_vertex[i].getTangent(), sizeof(float)*4); + memcpy(&this->vbo[j+10], data->m_vertex[i].getRGBA(), sizeof(char)*4); + + for (k = 0; k < RAS_TexVert::MAX_UNIT; k++) + memcpy(&this->vbo[j+11+(k*2)], data->m_vertex[i].getUV(k), sizeof(float)*2); + } + + // Upload Data to GPU + glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->size*this->stride, this->vbo, GL_DYNAMIC_DRAW_ARB); +} + +void VBO::UpdateIndices() +{ + int space = data->m_index.size() * sizeof(GLushort); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo); + + // Lets the video card know we are done with the old VBO + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, NULL, GL_DYNAMIC_DRAW_ARB); + + // Upload Data to VBO + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, space, &data->m_index[0], GL_DYNAMIC_DRAW_ARB); +} + +void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, bool multi) +{ + int unit; + + // Bind buffers + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id); + + // Vertexes + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, this->stride, this->vertex_offset); + + // Normals + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, this->stride, this->normal_offset); + + // Colors + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, this->stride, this->color_offset); + + if (multi) + { + for (unit = 0; unit < texco_num; ++unit) + { + glClientActiveTexture(GL_TEXTURE0_ARB + unit); + switch (texco[unit]) + { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(3, GL_FLOAT, this->stride, this->vertex_offset); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, this->stride, (void*)((intptr_t)this->uv_offset+(sizeof(GLfloat)*2*unit))); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(3, GL_FLOAT, this->stride, this->normal_offset); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(4, GL_FLOAT, this->stride, this->tangent_offset); + break; + default: + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(1, GL_SHORT, this->stride, this->dummy_offset); + break; + } + } + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + else //TexFace + { + glClientActiveTextureARB(GL_TEXTURE0_ARB); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, this->stride, this->uv_offset); + } + + if (GLEW_ARB_vertex_program) + { + int uv = 0; + for (unit = 0; unit < attrib_num; ++unit) + { + switch (attrib[unit]) + { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, this->stride, this->vertex_offset); + glEnableVertexAttribArrayARB(unit); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, this->stride, (void*)((intptr_t)this->uv_offset+uv)); + uv += sizeof(GLfloat)*2; + glEnableVertexAttribArrayARB(unit); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, stride, this->normal_offset); + glEnableVertexAttribArrayARB(unit); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, this->stride, this->tangent_offset); + glEnableVertexAttribArrayARB(unit); + break; + default: + break; + } + } + } + + glDrawElements(this->mode, this->indices, GL_UNSIGNED_SHORT, 0); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + if (GLEW_ARB_vertex_program) + { + for (int i = 0; i < attrib_num; ++i) + glDisableVertexAttribArrayARB(i); + } + + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } + +RAS_StorageVBO::RAS_StorageVBO(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib): + m_texco_num(texco_num), + m_texco(texco), + m_attrib_num(attrib_num), + m_attrib(attrib) +{ +} + +RAS_StorageVBO::~RAS_StorageVBO() +{ +} + +bool RAS_StorageVBO::Init() +{ + return true; +} + +void RAS_StorageVBO::Exit() +{ + m_vbo_lookup.clear(); +} + +void RAS_StorageVBO::IndexPrimitives(RAS_MeshSlot& ms) +{ + IndexPrimitivesInternal(ms, false); +} + +void RAS_StorageVBO::IndexPrimitivesMulti(RAS_MeshSlot& ms) +{ + IndexPrimitivesInternal(ms, true); +} + +void RAS_StorageVBO::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) +{ + RAS_MeshSlot::iterator it; + VBO *vbo; + + for (ms.begin(it); !ms.end(it); ms.next(it)) + { + vbo = m_vbo_lookup[it.array]; + + if (vbo == 0) + m_vbo_lookup[it.array] = vbo = new VBO(it.array, it.totindex); + + // Update the vbo + if (ms.m_mesh->MeshModified()) + { + vbo->UpdateData(); + } + + vbo->Draw(*m_texco_num, m_texco, *m_attrib_num, m_attrib, multi); + } +} diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h new file mode 100644 index 00000000000..12c97816e4f --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h @@ -0,0 +1,102 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_VERTEXBUFFEROBJECTSTORAGE +#define __KX_VERTEXBUFFEROBJECTSTORAGE + +#include <map> +#include "GL/glew.h" + +#include "RAS_IStorage.h" +#include "RAS_IRasterizer.h" + +#include "RAS_OpenGLRasterizer.h" + +class VBO +{ +public: + VBO(RAS_DisplayArray *data, unsigned int indices); + ~VBO(); + + void Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, bool multi); + + void UpdateData(); + void UpdateIndices(); +private: + RAS_DisplayArray* data; + GLuint size; + GLuint stride; + GLuint indices; + GLenum mode; + GLuint ibo; + GLuint vbo_id; + GLfloat* vbo; + + void* vertex_offset; + void* normal_offset; + void* color_offset; + void* tangent_offset; + void* uv_offset; + void* dummy_offset; +}; + +class RAS_StorageVBO : public RAS_IStorage +{ + +public: + RAS_StorageVBO(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib); + virtual ~RAS_StorageVBO(); + + virtual bool Init(); + virtual void Exit(); + + virtual void IndexPrimitives(RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(RAS_MeshSlot& ms); + + virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;}; + +protected: + int m_drawingmode; + + int* m_texco_num; + int* m_attrib_num; + + RAS_IRasterizer::TexCoGen* m_texco; + RAS_IRasterizer::TexCoGen* m_attrib; + + std::map<RAS_DisplayArray*, class VBO*> m_vbo_lookup; + + virtual void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi); + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageVA"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //__KX_VERTEXBUFFEROBJECTSTORAGE diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index f74aa24232b..a848bce410a 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -34,8 +34,7 @@ #include "MT_Matrix4x4.h" RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, + const MT_Point2 uvs[MAX_UNIT], const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, @@ -43,8 +42,6 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, const unsigned int origindex) { xyz.getValue(m_localxyz); - uv.getValue(m_uv1); - uv2.getValue(m_uv2); SetRGBA(rgba); SetNormal(normal); tangent.getValue(m_tangent); @@ -52,6 +49,11 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, m_origindex = origindex; m_unit = 2; m_softBodyIndex = -1; + + for (int i = 0; i < MAX_UNIT; ++i) + { + uvs[i].getValue(m_uvs[i]); + } } const MT_Point3& RAS_TexVert::xyz() @@ -80,14 +82,9 @@ void RAS_TexVert::SetXYZ(const float *xyz) m_localxyz[0]= xyz[0]; m_localxyz[1]= xyz[1]; m_localxyz[2]= xyz[2]; } -void RAS_TexVert::SetUV(const MT_Point2& uv) +void RAS_TexVert::SetUV(int index, const MT_Point2& uv) { - uv.getValue(m_uv1); -} - -void RAS_TexVert::SetUV2(const MT_Point2& uv) -{ - uv.getValue(m_uv2); + uv.getValue(m_uvs[index]); } @@ -121,14 +118,17 @@ void RAS_TexVert::SetTangent(const MT_Vector3& tangent) // compare two vertices, and return TRUE if both are almost identical (they can be shared) bool RAS_TexVert::closeTo(const RAS_TexVert* other) { + bool uv_match = true; + for (int i=0; i<MAX_UNIT; i++) + uv_match = uv_match && MT_fuzzyEqual(MT_Vector2(m_uvs[i]), MT_Vector2(other->m_uvs[i])); + return ( /* m_flag == other->m_flag && */ /* at the moment the face only stores the smooth/flat setting so don't bother comparing it */ m_rgba == other->m_rgba && MT_fuzzyEqual(MT_Vector3(m_normal), MT_Vector3(other->m_normal)) && MT_fuzzyEqual(MT_Vector3(m_tangent), MT_Vector3(other->m_tangent)) && - MT_fuzzyEqual(MT_Vector2(m_uv1), MT_Vector2(other->m_uv1)) && - MT_fuzzyEqual(MT_Vector2(m_uv2), MT_Vector2(other->m_uv2)) /* && + uv_match /* && MT_fuzzyEqual(MT_Vector3(m_localxyz), MT_Vector3(other->m_localxyz))*/); /* don't bother comparing m_localxyz since we know there from the same vert */ } diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index f76c6a66c86..68074adfede 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -48,23 +48,21 @@ class RAS_TexVert { float m_localxyz[3]; // 3*4 = 12 - float m_uv1[2]; // 2*4 = 8 - float m_uv2[2]; // 2*4 = 8 + float m_uvs[8][2]; // 8*2*4=64 //8 = MAX_UNIT unsigned int m_rgba; // 4 - float m_tangent[4]; // 4*4 = 16 - float m_normal[3]; // 3*4 = 12 + float m_tangent[4]; // 4*4 = 16 + float m_normal[3]; // 3*4 = 12 short m_flag; // 2 short m_softBodyIndex; //2 unsigned int m_unit; // 4 unsigned int m_origindex; // 4 //--------- - // 56+6+8+2=72 - // 32 bytes total size, fits nice = 56 = not fit nice. + // 120 + // 32 bytes total size, fits nice = 120 = not fit nice. public: enum { FLAT = 1, - SECOND_UV = 2, MAX_UNIT = 8 }; @@ -74,8 +72,7 @@ public: RAS_TexVert()// :m_xyz(0,0,0),m_uv(0,0),m_rgba(0) {} RAS_TexVert(const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, + const MT_Point2 uvs[MAX_UNIT], const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, @@ -83,12 +80,8 @@ public: const unsigned int origindex); ~RAS_TexVert() {}; - const float* getUV1 () const { - return m_uv1; - }; - - const float* getUV2 () const { - return m_uv2; + const float* getUV (int unit) const { + return m_uvs[unit]; }; const float* getXYZ() const { @@ -123,8 +116,7 @@ public: void SetXYZ(const MT_Point3& xyz); void SetXYZ(const float *xyz); - void SetUV(const MT_Point2& uv); - void SetUV2(const MT_Point2& uv); + void SetUV(int index, const MT_Point2& uv); void SetRGBA(const unsigned int rgba); void SetNormal(const MT_Vector3& normal); diff --git a/source/gameengine/Rasterizer/RAS_texmatrix.cpp b/source/gameengine/Rasterizer/RAS_texmatrix.cpp index 4399265c380..5309dc7feae 100644 --- a/source/gameengine/Rasterizer/RAS_texmatrix.cpp +++ b/source/gameengine/Rasterizer/RAS_texmatrix.cpp @@ -52,9 +52,9 @@ void RAS_CalcTexMatrix(RAS_TexVert p[3],MT_Point3& origin,MT_Vector3& udir,MT_Ve MT_Scalar d = -p[0].xyz().dot(normal); - MT_Matrix3x3 mat3( p[0].getUV1()[0],p[0].getUV1()[1], 1, - p[1].getUV1()[0],p[1].getUV1()[1], 1, - p[2].getUV1()[0],p[2].getUV1()[1], 1); + MT_Matrix3x3 mat3( p[0].getUV(0)[0],p[0].getUV(0)[1], 1, + p[1].getUV(0)[0],p[1].getUV(0)[1], 1, + p[2].getUV(0)[0],p[2].getUV(0)[1], 1); MT_Matrix3x3 mat3inv = mat3.inverse(); |