BGE: Some as of yet unmerged work I did in the Swiss branch. These changes include:

* Cleaning up the conversion code to avoid a per-face material conversion. Materials are now stored in buckets and only converted if a new material is found. This replaces some of Campbell's earlier work on the subject. His work wasn't as thorough, but it was much safer for a release.
  * Shaders are only compiled for LibLoaded materials once. Before they could be compiled twice, which could really slow things down.
  * Refactoring the rasterizer code to use a strategy design pattern to handle different geometry rendering methods such as immediate mode, vertex arrays and vertex buffer objects. VBOs are added, but they will be disabled in a following commit since they are still slower than vertex arrays with display lists. However, VBOs are still useful for mobile, so it's good to keep them around.
  * Better multi-uv support. The BGE should now be able to handle more than two UV layers, which should help it better match the viewport.
This commit is contained in:
Mitchell Stokes 2012-12-18 20:56:25 +00:00
parent 6b2af22d37
commit ef0473994b
46 changed files with 1867 additions and 1296 deletions

@ -402,14 +402,18 @@ class RENDER_PT_game_system(RenderButtonsPanel, Panel):
layout = self.layout
gs = context.scene.game_settings
col = layout.column()
row = col.row()
col = row.column()
col.prop(gs, "use_frame_rate")
col.prop(gs, "restrict_animation_updates")
col = row.column()
col.prop(gs, "use_display_lists")
col.active = gs.raster_storage != 'VERTEX_BUFFER_OBJECT'
row = layout.row()
row.prop(gs, "use_frame_rate")
row.prop(gs, "restrict_animation_updates")
row = layout.row()
row.prop(gs, "use_display_lists")
row.prop(gs, "raster_storage")
row = layout.row()
row.label("Exit Key")
row.prop(gs, "exit_key", text="", event=True)

@ -636,7 +636,8 @@ typedef struct GameData {
short physicsEngine;
short exitkey, pad;
short ticrate, maxlogicstep, physubstep, maxphystep;
short obstacleSimulation, pad1;
short obstacleSimulation;
short raster_storage;
float levelHeight;
float deactivationtime, lineardeactthreshold, angulardeactthreshold, pad2;
} GameData;
@ -663,6 +664,12 @@ typedef struct GameData {
#define OBSTSIMULATION_TOI_rays 1
#define OBSTSIMULATION_TOI_cells 2
/* Raster 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)

@ -2444,6 +2444,13 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
{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");
@ -2479,6 +2486,12 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
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);
RNA_def_property_int_sdna(prop, NULL, "freqplay");

@ -58,7 +58,6 @@
#include "RAS_GLExtensionManager.h"
#include "RAS_OpenGLRasterizer.h"
#include "RAS_VAOpenGLRasterizer.h"
#include "RAS_ListRasterizer.h"
#include "NG_LoopBackNetworkDeviceInterface.h"
@ -287,16 +286,12 @@ 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();

@ -423,55 +423,61 @@ static void SetDefaultLightMode(Scene* scene)
// --
static void GetRGB(
const bool use_mcol,
MFace *mface,
MCol *mmcol,
Material *mat,
unsigned int &c0,
unsigned int &c1,
unsigned int &c2,
unsigned int &c3)
static void GetRGB(short type,
MFace* mface,
MCol* mmcol,
Material *mat,
unsigned int c[4])
{
unsigned int color = 0xFFFFFFFFL;
if (use_mcol) {
// vertex colors
if (mmcol) {
c0 = KX_Mcol2uint_new(mmcol[0]);
c1 = KX_Mcol2uint_new(mmcol[1]);
c2 = KX_Mcol2uint_new(mmcol[2]);
switch (type) {
case 0: // vertex colors
{
if (mmcol) {
c[0] = KX_Mcol2uint_new(mmcol[0]);
c[1] = KX_Mcol2uint_new(mmcol[1]);
c[2] = KX_Mcol2uint_new(mmcol[2]);
if (mface->v4)
c[3] = KX_Mcol2uint_new(mmcol[3]);
}
else { // backup white
c[0] = KX_rgbaint2uint_new(color);
c[1] = KX_rgbaint2uint_new(color);
c[2] = KX_rgbaint2uint_new(color);
if (mface->v4)
c[3] = KX_rgbaint2uint_new( color );
}
} break;
case 1: // material rgba
{
if (mat) {
union {
unsigned char cp[4];
unsigned int integer;
} col_converter;
col_converter.cp[3] = (unsigned char) (mat->r * 255.0f);
col_converter.cp[2] = (unsigned char) (mat->g * 255.0f);
col_converter.cp[1] = (unsigned char) (mat->b * 255.0f);
col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f);
color = col_converter.integer;
}
c[0] = KX_rgbaint2uint_new(color);
c[1] = KX_rgbaint2uint_new(color);
c[2] = KX_rgbaint2uint_new(color);
if (mface->v4)
c3 = KX_Mcol2uint_new(mmcol[3]);
}
else { // backup white
c0 = KX_rgbaint2uint_new(color);
c1 = KX_rgbaint2uint_new(color);
c2 = KX_rgbaint2uint_new(color);
c[3] = KX_rgbaint2uint_new(color);
} break;
default: // white
{
c[0] = KX_rgbaint2uint_new(color);
c[1] = KX_rgbaint2uint_new(color);
c[2] = KX_rgbaint2uint_new(color);
if (mface->v4)
c3 = KX_rgbaint2uint_new( color );
}
}
else {
// material rgba
if (mat) {
union {
unsigned char cp[4];
unsigned int integer;
} col_converter;
col_converter.cp[3] = (unsigned char) (mat->r * 255.0f);
col_converter.cp[2] = (unsigned char) (mat->g * 255.0f);
col_converter.cp[1] = (unsigned char) (mat->b * 255.0f);
col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f);
color = col_converter.integer;
}
// backup white is fallback
c0 = KX_rgbaint2uint_new(color);
c1 = KX_rgbaint2uint_new(color);
c2 = KX_rgbaint2uint_new(color);
if (mface->v4)
c3 = KX_rgbaint2uint_new(color);
c[3] = KX_rgbaint2uint_new(color);
} break;
}
}
@ -480,42 +486,67 @@ typedef struct MTF_localLayer {
const char *name;
} MTF_localLayer;
static void tface_to_uv_bge(const MFace *mface, const MTFace *tface, MT_Point2 uv[4])
static void GetUVs(BL_Material *material, MTF_localLayer *layers, MFace *mface, MTFace *tface, MT_Point2 uvs[4][MAXTEX])
{
uv[0].setValue(tface->uv[0]);
uv[1].setValue(tface->uv[1]);
uv[2].setValue(tface->uv[2]);
if (mface->v4) {
uv[3].setValue(tface->uv[3]);
int unit = 0;
if (tface)
{
uvs[0][0].setValue(tface->uv[0]);
uvs[1][0].setValue(tface->uv[1]);
uvs[2][0].setValue(tface->uv[2]);
if (mface->v4)
uvs[3][0].setValue(tface->uv[3]);
}
}
else
{
uvs[0][0] = uvs[1][0] = uvs[2][0] = uvs[3][0] = MT_Point2(0.f, 0.f);
}
for (int vind = 0; vind<MAXTEX; vind++)
{
BL_Mapping &map = material->mapping[vind];
static void GetUV(
MFace *mface,
MTFace *tface,
MTF_localLayer *layers,
const int layer_uv[2],
MT_Point2 uv[4],
MT_Point2 uv2[4])
{
bool validface = (tface != NULL);
if (!(map.mapping & USEUV)) continue;
uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f);
//If no UVSet is specified, try grabbing one from the UV/Image editor
if (map.uvCoName.IsEmpty() && tface)
{
uvs[0][unit].setValue(tface->uv[0]);
uvs[1][unit].setValue(tface->uv[1]);
uvs[2][unit].setValue(tface->uv[2]);
/* 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 (layer_uv[0] != -1) {
tface_to_uv_bge(mface, layers[layer_uv[0]].face, uv);
if (layer_uv[1] != -1) {
tface_to_uv_bge(mface, layers[layer_uv[1]].face, uv2);
if (mface->v4)
uvs[3][unit].setValue(tface->uv[3]);
++unit;
continue;
}
for (int lay=0; lay<MAX_MTFACE; lay++)
{
MTF_localLayer& layer = layers[lay];
if (layer.face == 0) break;
if (map.uvCoName.IsEmpty() || strcmp(map.uvCoName.ReadPtr(), layer.name)==0)
{
MT_Point2 uvSet[4];
uvs[0][unit].setValue(layer.face->uv[0]);
uvs[1][unit].setValue(layer.face->uv[1]);
uvs[2][unit].setValue(layer.face->uv[2]);
if (mface->v4)
uvs[3][unit].setValue(layer.face->uv[3]);
else
uvs[3][unit].setValue(0.0f, 0.0f);
++unit;
break;
}
}
}
else if (validface) {
tface_to_uv_bge(mface, tface, uv);
}
else {
// nothing at all
uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f);
}
}
@ -526,25 +557,29 @@ static bool ConvertMaterial(
MTFace* tface,
const char *tfaceName,
MFace* mface,
MCol* mmcol, /* only for text, use first mcol, weak */
MTF_localLayer *layers,
int layer_uv[2],
const bool glslmat)
MCol* mmcol,
bool glslmat)
{
material->Initialize();
int numchan = -1, texalpha = 0;
int texalpha = 0;
bool validmat = (mat!=0);
bool validface = (tface!=0);
short type = 0;
if ( validmat )
type = 1; // material color
material->IdMode = DEFAULT_BLENDER;
material->glslmat = (validmat)? glslmat: false;
material->materialindex = mface->mat_nr;
/* default value for being unset */
layer_uv[0] = layer_uv[1] = -1;
// --------------------------------
if (validmat) {
// use vertex colors by explicitly setting
if (mat->mode &MA_VERTEXCOLP || glslmat)
type = 0;
// use lighting?
material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT;
material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED;
@ -552,7 +587,6 @@ static bool ConvertMaterial(
// cast shadows?
material->ras_mode |= ( mat->mode & MA_SHADBUF )?CAST_SHADOW:0;
MTex *mttmp = 0;
numchan = getNumTexChannels(mat);
int valid_index = 0;
/* In Multitexture use the face texture if and only if
@ -561,12 +595,9 @@ static bool ConvertMaterial(
bool facetex = false;
if (validface && mat->mode &MA_FACETEXTURE)
facetex = true;
numchan = numchan>MAXTEX?MAXTEX:numchan;
if (facetex && numchan == 0) numchan = 1;
// foreach MTex
for (int i=0; i<numchan; i++) {
for (int i=0; i<MAXTEX; i++) {
// use face tex
if (i==0 && facetex ) {
@ -798,14 +829,11 @@ static bool ConvertMaterial(
material->ras_mode |= USE_LIGHT;
}
const char *uvName = "", *uv2Name = "";
/* 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;
uvName = tfaceName;
}
}
else {
// nothing at all
material->alphablend = GEMAT_SOLID;
@ -826,46 +854,20 @@ static bool ConvertMaterial(
material->ras_mode |= (mat && (mat->game.alpha_blend & GEMAT_ALPHA_SORT))? ZSORT: 0;
}
// get uv sets
if (validmat) {
bool isFirstSet = true;
// XXX The RGB values here were meant to be temporary storage for the conversion process,
// but fonts now make use of them too, so we leave them in for now.
unsigned int rgb[4];
GetRGB(type,mface,mmcol,mat,rgb);
// 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 {
for (int lay=0; lay<MAX_MTFACE; lay++) {
MTF_localLayer& layer = layers[lay];
if (layer.face == 0) break;
if (strcmp(map.uvCoName.ReadPtr(), layer.name)==0) {
if (isFirstSet) {
layer_uv[0] = lay;
isFirstSet = false;
uvName = layer.name;
}
else if (strcmp(layer.name, uvName) != 0) {
layer_uv[1] = lay;
map.mapping |= USECUSTOMUV;
uv2Name = layer.name;
}
}
}
}
}
// swap the material color, so MCol on bitmap font works
if (validmat && type==1 && (mat->game.flag & GEMAT_TEXT))
{
rgb[0] = KX_rgbaint2uint_new(rgb[0]);
rgb[1] = KX_rgbaint2uint_new(rgb[1]);
rgb[2] = KX_rgbaint2uint_new(rgb[2]);
rgb[3] = KX_rgbaint2uint_new(rgb[3]);
}
if (validmat && mmcol) { /* color is only for text */
material->m_mcol = *(unsigned int *)mmcol;
}
material->SetUVLayerName(uvName);
material->SetUVLayerName2(uv2Name);
if (validmat)
material->matname =(mat->id.name);
@ -879,8 +881,189 @@ static bool ConvertMaterial(
return true;
}
RAS_MaterialBucket* material_from_mesh(Material *ma, MFace *mface, MTFace *tface, MCol *mcol, MTF_localLayer *layers, int lightlayer, unsigned int *rgb, MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT], const char *tfaceName, KX_Scene* scene, KX_BlenderSceneConverter *converter)
{
RAS_IPolyMaterial* polymat = converter->FindCachedPolyMaterial(ma);
BL_Material* bl_mat = converter->FindCachedBlenderMaterial(ma);
KX_BlenderMaterial* kx_blmat = NULL;
KX_PolygonMaterial* kx_polymat = NULL;
if (converter->GetMaterials()) {
/* do Blender Multitexture and Blender GLSL materials */
/* first is the BL_Material */
if (!bl_mat)
{
bl_mat = new BL_Material();
ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol,
converter->GetGLSLMaterials());
converter->CacheBlenderMaterial(ma, bl_mat);
}
short type = (ma) ? ((ma->mode & MA_VERTEXCOLP || bl_mat->glslmat) ? 0 : 1) : 0;
GetRGB(type,mface,mcol,ma,rgb);
GetUVs(bl_mat, layers, mface, tface, uvs);
/* then the KX_BlenderMaterial */
if (polymat == NULL)
{
kx_blmat = new KX_BlenderMaterial();
kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL), lightlayer);
polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat);
converter->CachePolyMaterial(ma, polymat);
}
}
else {
/* do Texture Face materials */
Image* bima = (tface)? (Image*)tface->tpage: NULL;
STR_String imastr = (tface)? (bima? (bima)->id.name : "" ) : "";
char alpha_blend=0;
short tile=0;
int tilexrep=4,tileyrep = 4;
/* set material properties - old TexFace */
if (ma) {
alpha_blend = ma->game.alpha_blend;
/* Commented out for now. If we ever get rid of
* "Texture Face/Singletexture" we can then think about it */
/* Texture Face mode ignores texture but requires "Face Textures to be True "*/
#if 0
if ((ma->mode &MA_FACETEXTURE)==0 && (ma->game.flag &GEMAT_TEXT)==0) {
bima = NULL;
imastr = "";
alpha_blend = GEMAT_SOLID;
}
else {
alpha_blend = ma->game.alpha_blend;
}
#endif
}
/* check for tface tex to fallback on */
else {
if (bima) {
/* see if depth of the image is 32 */
if (BKE_image_has_alpha(bima))
alpha_blend = GEMAT_ALPHA;
else
alpha_blend = GEMAT_SOLID;
}
else {
alpha_blend = GEMAT_SOLID;
}
}
if (bima) {
tilexrep = bima->xrep;
tileyrep = bima->yrep;
}
/* set UV properties */
if (tface) {
uvs[0][0].setValue(tface->uv[0]);
uvs[1][0].setValue(tface->uv[1]);
uvs[2][0].setValue(tface->uv[2]);
if (mface->v4)
uvs[3][0].setValue(tface->uv[3]);
tile = tface->tile;
}
else {
/* no texfaces */
tile = 0;
}
/* get vertex colors */
if (mcol) {
/* we have vertex colors */
rgb[0] = KX_Mcol2uint_new(mcol[0]);
rgb[1] = KX_Mcol2uint_new(mcol[1]);
rgb[2] = KX_Mcol2uint_new(mcol[2]);
if (mface->v4)
rgb[3] = KX_Mcol2uint_new(mcol[3]);
}
else {
/* no vertex colors, take from material, otherwise white */
unsigned int color = 0xFFFFFFFFL;
if (ma)
{
union
{
unsigned char cp[4];
unsigned int integer;
} col_converter;
col_converter.cp[3] = (unsigned char) (ma->r*255.0);
col_converter.cp[2] = (unsigned char) (ma->g*255.0);
col_converter.cp[1] = (unsigned char) (ma->b*255.0);
col_converter.cp[0] = (unsigned char) (ma->alpha*255.0);
color = col_converter.integer;
}
rgb[0] = KX_rgbaint2uint_new(color);
rgb[1] = KX_rgbaint2uint_new(color);
rgb[2] = KX_rgbaint2uint_new(color);
if (mface->v4)
rgb[3] = KX_rgbaint2uint_new(color);
}
// only zsort alpha + add
bool alpha = ELEM3(alpha_blend, GEMAT_ALPHA, GEMAT_ADD, GEMAT_ALPHA_SORT);
bool zsort = (alpha_blend == GEMAT_ALPHA_SORT);
bool light = (ma)?(ma->mode & MA_SHLESS)==0:default_light_mode;
// don't need zort anymore, deal as if it it's alpha blend
if (alpha_blend == GEMAT_ALPHA_SORT) alpha_blend = GEMAT_ALPHA;
if (polymat == NULL)
{
kx_polymat = new KX_PolygonMaterial();
kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr,
tile, tilexrep, tileyrep,
alpha_blend, alpha, zsort, light, lightlayer, tface, (unsigned int*)mcol);
polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat);
if (ma) {
polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec;
polymat->m_shininess = (float)ma->har/4.0f; // 0 < ma->har <= 512
polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref);
}
else {
polymat->m_specular.setValue(0.0f,0.0f,0.0f);
polymat->m_shininess = 35.0;
}
converter->CachePolyMaterial(ma, polymat);
}
}
// see if a bucket was reused or a new one was created
// this way only one KX_BlenderMaterial object has to exist per bucket
bool bucketCreated;
RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated);
if (bucketCreated) {
// this is needed to free up memory afterwards
converter->RegisterPolyMaterial(polymat);
if (converter->GetMaterials())
converter->RegisterBlenderMaterial(bl_mat);
}
return bucket;
}
/* blenderobj can be NULL, make sure its checked for */
RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, KX_BlenderSceneConverter *converter)
RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, KX_BlenderSceneConverter *converter, bool libloading)
{
RAS_MeshObject *meshobj;
int lightlayer = blenderobj ? blenderobj->lay:(1<<20)-1; // all layers if no object.
@ -910,7 +1093,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
// Extract avaiable layers
MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE];
int layer_uv[2]; /* store uv1, uv2 layers */
for (int lay=0; lay<MAX_MTFACE; lay++) {
layers[lay].face = 0;
layers[lay].name = "";
@ -933,31 +1115,23 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
meshobj->SetName(mesh->id.name + 2);
meshobj->m_sharedvertex_map.resize(totvert);
RAS_IPolyMaterial* polymat = NULL;
STR_String imastr;
// These pointers will hold persistent material structure during the conversion
// to avoid countless allocation/deallocation of memory.
BL_Material* bl_mat = NULL;
KX_BlenderMaterial* kx_blmat = NULL;
KX_PolygonMaterial* kx_polymat = NULL;
Material* ma = 0;
bool collider = true;
MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT];
unsigned int rgb[4] = {0};
MT_Point3 pt[4];
MT_Vector3 no[4];
MT_Vector4 tan[4];
for (int f=0;f<totface;f++,mface++)
{
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);
unsigned int rgb0,rgb1,rgb2,rgb3 = 0;
MT_Point3 pt0, pt1, pt2, pt3;
MT_Vector3 no0(0,0,0), no1(0,0,0), no2(0,0,0), no3(0,0,0);
MT_Vector4 tan0(0,0,0,0), tan1(0,0,0,0), tan2(0,0,0,0), tan3(0,0,0,0);
/* get coordinates, normals and tangents */
pt0.setValue(mvert[mface->v1].co);
pt1.setValue(mvert[mface->v2].co);
pt2.setValue(mvert[mface->v3].co);
if (mface->v4) pt3.setValue(mvert[mface->v4].co);
pt[0].setValue(mvert[mface->v1].co);
pt[1].setValue(mvert[mface->v2].co);
pt[2].setValue(mvert[mface->v3].co);
if (mface->v4) pt[3].setValue(mvert[mface->v4].co);
if (mface->flag & ME_SMOOTH) {
float n0[3], n1[3], n2[3], n3[3];
@ -965,13 +1139,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
normal_short_to_float_v3(n0, mvert[mface->v1].no);
normal_short_to_float_v3(n1, mvert[mface->v2].no);
normal_short_to_float_v3(n2, mvert[mface->v3].no);
no0 = n0;
no1 = n1;
no2 = n2;
no[0] = n0;
no[1] = n1;
no[2] = n2;
if (mface->v4) {
normal_short_to_float_v3(n3, mvert[mface->v4].no);
no3 = n3;
no[3] = n3;
}
}
else {
@ -982,16 +1156,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
else
normal_tri_v3(fno,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
no0 = no1 = no2 = no3 = MT_Vector3(fno);
no[0] = no[1] = no[2] = no[3] = MT_Vector3(fno);
}
if (tangent) {
tan0 = tangent[f*4 + 0];
tan1 = tangent[f*4 + 1];
tan2 = tangent[f*4 + 2];
tan[0] = tangent[f*4 + 0];
tan[1] = tangent[f*4 + 1];
tan[2] = tangent[f*4 + 2];
if (mface->v4)
tan3 = tangent[f*4 + 3];
tan[3] = tangent[f*4 + 3];
}
if (blenderobj)
ma = give_current_material(blenderobj, mface->mat_nr+1);
@ -1007,171 +1181,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
bool visible = true;
bool twoside = false;
if (converter->GetMaterials()) {
const bool is_bl_mat_new = (bl_mat == NULL);
//const bool is_kx_blmat_new = (kx_blmat == NULL);
const bool glslmat = converter->GetGLSLMaterials();
const bool use_mcol = ma ? (ma->mode & MA_VERTEXCOLP || glslmat) : true;
/* do Blender Multitexture and Blender GLSL materials */
MT_Point2 uv_1[4];
MT_Point2 uv_2[4];
/* first is the BL_Material */
if (!bl_mat) {
bl_mat = new BL_Material();
}
/* only */
if (is_bl_mat_new || (bl_mat->material != ma)) {
ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol,
layers, layer_uv, glslmat);
}
/* vertex colors and uv's from the faces */
GetRGB(use_mcol, mface, mcol, ma, rgb0, rgb1, rgb2, rgb3);
GetUV(mface, tface, layers, layer_uv, uv_1, uv_2);
uv0 = uv_1[0]; uv1 = uv_1[1];
uv2 = uv_1[2]; uv3 = uv_1[3];
uv20 = uv_2[0]; uv21 = uv_2[1];
uv22 = uv_2[2]; uv23 = uv_2[3];
/* then the KX_BlenderMaterial */
if (kx_blmat == NULL)
kx_blmat = new KX_BlenderMaterial();
//if (is_kx_blmat_new || !kx_blmat->IsMaterial(bl_mat)) {
kx_blmat->Initialize(scene, bl_mat, (ma ? &ma->game : NULL));
//}
polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat);
}
else {
/* do Texture Face materials */
Image* bima = (tface)? (Image*)tface->tpage: NULL;
imastr = (tface)? (bima? (bima)->id.name : "" ) : "";
char alpha_blend=0;
short tile=0;
int tilexrep=4,tileyrep = 4;
/* set material properties - old TexFace */
if (ma) {
alpha_blend = ma->game.alpha_blend;
/* Commented out for now. If we ever get rid of
* "Texture Face/Singletexture" we can then think about it */
/* Texture Face mode ignores texture but requires "Face Textures to be True "*/
#if 0
if ((ma->mode &MA_FACETEXTURE)==0 && (ma->game.flag &GEMAT_TEXT)==0) {
bima = NULL;
imastr = "";
alpha_blend = GEMAT_SOLID;
}
else {
alpha_blend = ma->game.alpha_blend;
}
#endif
}
/* check for tface tex to fallback on */
else {
if (bima) {
/* see if depth of the image is 32 */
if (BKE_image_has_alpha(bima))
alpha_blend = GEMAT_ALPHA;
else
alpha_blend = GEMAT_SOLID;
}
else {
alpha_blend = GEMAT_SOLID;
}
}
if (bima) {
tilexrep = bima->xrep;
tileyrep = bima->yrep;
}
/* set UV properties */
if (tface) {
uv0.setValue(tface->uv[0]);
uv1.setValue(tface->uv[1]);
uv2.setValue(tface->uv[2]);
if (mface->v4)
uv3.setValue(tface->uv[3]);
tile = tface->tile;
}
else {
/* no texfaces */
tile = 0;
}
/* get vertex colors */
if (mcol) {
/* we have vertex colors */
rgb0 = KX_Mcol2uint_new(mcol[0]);
rgb1 = KX_Mcol2uint_new(mcol[1]);
rgb2 = KX_Mcol2uint_new(mcol[2]);
if (mface->v4)
rgb3 = KX_Mcol2uint_new(mcol[3]);
}
else {
/* no vertex colors, take from material, otherwise white */
unsigned int color = 0xFFFFFFFFL;
if (ma)
{
union
{
unsigned char cp[4];
unsigned int integer;
} col_converter;
col_converter.cp[3] = (unsigned char) (ma->r * 255.0f);
col_converter.cp[2] = (unsigned char) (ma->g * 255.0f);
col_converter.cp[1] = (unsigned char) (ma->b * 255.0f);
col_converter.cp[0] = (unsigned char) (ma->alpha * 255.0f);
color = col_converter.integer;
}
rgb0 = KX_rgbaint2uint_new(color);
rgb1 = KX_rgbaint2uint_new(color);
rgb2 = KX_rgbaint2uint_new(color);
if (mface->v4)
rgb3 = KX_rgbaint2uint_new(color);
}
// only zsort alpha + add
bool alpha = ELEM3(alpha_blend, GEMAT_ALPHA, GEMAT_ADD, GEMAT_ALPHA_SORT);
bool zsort = (alpha_blend == GEMAT_ALPHA_SORT);
bool light = (ma)?(ma->mode & MA_SHLESS)==0:default_light_mode;
// don't need zort anymore, deal as if it it's alpha blend
if (alpha_blend == GEMAT_ALPHA_SORT) alpha_blend = GEMAT_ALPHA;
if (kx_polymat == NULL)
kx_polymat = new KX_PolygonMaterial();
kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr,
tile, tilexrep, tileyrep,
alpha_blend, alpha, zsort, light, lightlayer, tface, (unsigned int*)mcol);
polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat);
if (ma) {
polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec;
polymat->m_shininess = (float)ma->har/4.0f; // 0 < ma->har <= 512
polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref);
}
else {
polymat->m_specular.setValue(0.0f,0.0f,0.0f);
polymat->m_shininess = 35.0;
}
}
RAS_MaterialBucket* bucket = material_from_mesh(ma, mface, tface, mcol, layers, lightlayer, rgb, uvs, tfaceName, scene, converter);
// set render flags
if (ma)
@ -1188,30 +1198,9 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
/* mark face as flat, so vertices are split */
bool flat = (mface->flag & ME_SMOOTH) == 0;
// see if a bucket was reused or a new one was created
// this way only one KX_BlenderMaterial object has to exist per bucket
bool bucketCreated;
RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated);
if (bucketCreated) {
// this is needed to free up memory afterwards
converter->RegisterPolyMaterial(polymat);
if (converter->GetMaterials()) {
converter->RegisterBlenderMaterial(bl_mat);
// the poly material has been stored in the bucket, next time we must create a new one
bl_mat = NULL;
kx_blmat = NULL;
} else {
// the poly material has been stored in the bucket, next time we must create a new one
kx_polymat = NULL;
}
} else {
// from now on, use the polygon material from the material bucket
polymat = bucket->GetPolyMaterial();
// keep the material pointers, they will be reused for next face
}
int nverts = (mface->v4)? 4: 3;
RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts);
poly->SetVisible(visible);
@ -1219,12 +1208,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,pt[0],uvs[0],tan[0],rgb[0],no[0],flat,mface->v1);
meshobj->AddVertex(poly,1,pt[1],uvs[1],tan[1],rgb[1],no[1],flat,mface->v2);
meshobj->AddVertex(poly,2,pt[2],uvs[2],tan[2],rgb[2],no[2],flat,mface->v3);
if (nverts==4)
meshobj->AddVertex(poly,3,pt3,uv3,uv23,tan3,rgb3,no3,flat,mface->v4);
meshobj->AddVertex(poly,3,pt[3],uvs[3],tan[3],rgb[3],no[3],flat,mface->v4);
}
if (tface)
@ -1246,22 +1235,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
meshobj->EndConversion();
// pre calculate texture generation
for (list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial();
mit != meshobj->GetLastMaterial(); ++ mit) {
mit->m_bucket->GetPolyMaterial()->OnConstruction(lightlayer);
// However, we want to delay this if we're libloading so we can make sure we have the right scene.
if (!libloading) {
for (list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial();
mit != meshobj->GetLastMaterial(); ++ mit) {
mit->m_bucket->GetPolyMaterial()->OnConstruction();
}
}
if (layers)
delete []layers;
dm->release(dm);
// cleanup material
if (bl_mat)
delete bl_mat;
if (kx_blmat)
delete kx_blmat;
if (kx_polymat)
delete kx_polymat;
converter->RegisterGameMesh(meshobj, mesh);
return meshobj;
}
@ -1921,7 +1907,8 @@ static KX_GameObject *gameobject_from_blenderobject(
Object *ob,
KX_Scene *kxscene,
RAS_IRenderTools *rendertools,
KX_BlenderSceneConverter *converter)
KX_BlenderSceneConverter *converter,
bool libloading)
{
KX_GameObject *gameobj = NULL;
Scene *blenderscene = kxscene->GetBlenderScene();
@ -1958,7 +1945,7 @@ static KX_GameObject *gameobject_from_blenderobject(
Mesh* mesh = static_cast<Mesh*>(ob->data);
float center[3], extents[3];
float radius = my_boundbox_mesh((Mesh*) ob->data, center, extents);
RAS_MeshObject* meshobj = BL_ConvertMesh(mesh,ob,kxscene,converter);
RAS_MeshObject* meshobj = BL_ConvertMesh(mesh,ob,kxscene,converter, libloading);
// needed for python scripting
kxscene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
@ -2332,7 +2319,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
RAS_IRenderTools* rendertools,
RAS_ICanvas* canvas,
KX_BlenderSceneConverter* converter,
bool alwaysUseExpandFraming
bool alwaysUseExpandFraming,
bool libloading
)
{
@ -2442,7 +2430,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
base->object,
kxscene,
rendertools,
converter);
converter,
libloading);
bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0;
bool addobj=true;
@ -2501,7 +2490,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
blenderobject,
kxscene,
rendertools,
converter);
converter,
libloading);
// this code is copied from above except that
// object from groups are never in active layer

@ -38,7 +38,7 @@
#include "KX_PhysicsEngineEnums.h"
#include "SCA_IInputDevice.h"
class RAS_MeshObject* BL_ConvertMesh(struct Mesh* mesh,struct Object* lightobj,class KX_Scene* scene, class KX_BlenderSceneConverter *converter);
class RAS_MeshObject* BL_ConvertMesh(struct Mesh* mesh,struct Object* lightobj,class KX_Scene* scene, class KX_BlenderSceneConverter *converter, bool libloading);
void BL_ConvertBlenderObjects(struct Main* maggie,
class KX_Scene* kxscene,
@ -47,7 +47,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
class RAS_IRenderTools* rendertools,
class RAS_ICanvas* canvas,
class KX_BlenderSceneConverter* sceneconverter,
bool alwaysUseExpandFraming
bool alwaysUseExpandFraming,
bool libloading=false
);
SCA_IInputDevice::KX_EnumInputs ConvertKeyCode(int key_code);

@ -151,6 +151,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
while (itp != m_polymaterials.end()) {
m_polymat_cache.erase((*itp).second->GetBlenderMaterial());
delete (*itp).second;
itp++;
}
@ -158,6 +159,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
// delete after RAS_IPolyMaterial
vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin();
while (itmat != m_materials.end()) {
m_mat_cache.erase((*itmat).second->material);
delete (*itmat).second;
itmat++;
}
@ -286,7 +288,8 @@ struct BlenderDebugDraw : public btIDebugDraw
void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
class RAS_IRenderTools* rendertools,
class RAS_ICanvas* canvas)
class RAS_ICanvas* canvas,
bool libloading)
{
//find out which physics engine
Scene *blenderscene = destinationscene->GetBlenderScene();
@ -355,7 +358,8 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
rendertools,
canvas,
this,
m_alwaysUseExpandFraming
m_alwaysUseExpandFraming,
libloading
);
//These lookup are not needed during game
@ -406,6 +410,7 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
size = m_polymaterials.size();
for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
if ((*polymit).first == scene) {
m_polymat_cache.erase((*polymit).second->GetBlenderMaterial());
delete (*polymit).second;
*polymit = m_polymaterials.back();
m_polymaterials.pop_back();
@ -420,6 +425,7 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
size = m_materials.size();
for (i=0, matit=m_materials.begin(); i<size; ) {
if ((*matit).first == scene) {
m_mat_cache.erase((*matit).second->material);
delete (*matit).second;
*matit = m_materials.back();
m_materials.pop_back();
@ -470,6 +476,12 @@ bool KX_BlenderSceneConverter::GetGLSLMaterials()
void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
{
// First make sure we don't register the material twice
vector<pair<KX_Scene*,BL_Material*> >::iterator it;
for (it = m_materials.begin(); it != m_materials.end(); ++it)
if (it->second == mat)
return;
m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat));
}
@ -540,19 +552,37 @@ RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
} else {
return NULL;
}
}
}
void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat)
{
// First make sure we don't register the material twice
vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator it;
for (it = m_polymaterials.begin(); it != m_polymaterials.end(); ++it)
if (it->second == polymat)
return;
m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat));
}
void KX_BlenderSceneConverter::CachePolyMaterial(struct Material *mat, RAS_IPolyMaterial *polymat)
{
m_polymat_cache[mat] = polymat;
}
RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(struct Material *mat)
{
return m_polymat_cache[mat];
}
void KX_BlenderSceneConverter::CacheBlenderMaterial(struct Material *mat, BL_Material *blmat)
{
m_mat_cache[mat] = blmat;
}
BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(struct Material *mat)
{
return m_mat_cache[mat];
}
void KX_BlenderSceneConverter::RegisterInterpolatorList(
BL_InterpolatorList *actList,
@ -1016,7 +1046,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) {
if (options & LIB_LOAD_VERBOSE)
printf("MeshName: %s\n", mesh->name+2);
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this);
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders
scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
}
}
@ -1038,7 +1068,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
printf("SceneName: %s\n", scene->name+2);
/* merge into the base scene */
KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene);
KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene, true);
scene_merge->MergeScene(other);
// RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene
@ -1302,7 +1332,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
}
if (IS_TAGGED(bmat)) {
m_polymat_cache.erase((*polymit).second->GetBlenderMaterial());
delete (*polymit).second;
*polymit = m_polymaterials.back();
m_polymaterials.pop_back();
@ -1320,6 +1350,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
for (i=0, matit=m_materials.begin(); i<size; ) {
BL_Material *mat= (*matit).second;
if (IS_TAGGED(mat->material)) {
m_mat_cache.erase((*matit).second->material);
delete (*matit).second;
*matit = m_materials.back();
m_materials.pop_back();
@ -1469,7 +1500,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene,
}
}
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this);
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this, false);
kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */
return meshobj;

@ -39,6 +39,8 @@
#include "KX_ISceneConverter.h"
#include "KX_IpoConvert.h"
#include <map>
using namespace std;
class KX_WorldInfo;
@ -58,6 +60,11 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter
vector<pair<KX_Scene*,RAS_IPolyMaterial*> > m_polymaterials;
vector<pair<KX_Scene*,RAS_MeshObject*> > m_meshobjects;
vector<pair<KX_Scene*,BL_Material *> > m_materials;
// Cached material conversions
map<struct Material*, BL_Material*> m_mat_cache;
map<struct Material*, RAS_IPolyMaterial*> m_polymat_cache;
// Should also have a list of collision shapes.
// For the time being this is held in KX_Scene::m_shapes
@ -93,7 +100,8 @@ public:
virtual void ConvertScene(
class KX_Scene* destinationscene,
class RAS_IRenderTools* rendertools,
class RAS_ICanvas* canvas
class RAS_ICanvas* canvas,
bool libloading=false
);
virtual void RemoveScene(class KX_Scene *scene);
@ -110,8 +118,12 @@ public:
RAS_MeshObject *FindGameMesh(struct Mesh *for_blendermesh/*, unsigned int onlayer*/);
void RegisterPolyMaterial(RAS_IPolyMaterial *polymat);
void CachePolyMaterial(struct Material *mat, RAS_IPolyMaterial *polymat);
RAS_IPolyMaterial *FindCachedPolyMaterial(struct Material *mat);
void RegisterBlenderMaterial(BL_Material *mat);
void CacheBlenderMaterial(struct Material *mat, BL_Material *blmat);
BL_Material *FindCachedBlenderMaterial(struct Material *mat);
void RegisterInterpolatorList(BL_InterpolatorList *actList, struct bAction *for_act);
BL_InterpolatorList *FindInterpolatorList(struct bAction *for_act);

@ -523,7 +523,8 @@ void BL_ConvertActuators(const char* maggiename,
editobact->me,
blenderobject,
scene,
converter
converter,
false
);
KX_SCA_ReplaceMeshActuator* tmpreplaceact = new KX_SCA_ReplaceMeshActuator(

@ -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"
@ -582,16 +581,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);

@ -95,21 +95,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)

@ -20,15 +20,6 @@ MTex* getImageFromMaterial(Material *mat, int index)
return m?m:0;
}
int getNumTexChannels( Material *mat )
{
int count = -1;
if (!mat) return -1;
for (count =0; (count < 10) && mat->mtex[count] != 0; count++) {}
return count;
}
BL_Material::BL_Material()
{
Initialize();
@ -36,7 +27,10 @@ BL_Material::BL_Material()
void BL_Material::Initialize()
{
m_mcol = 0xFFFFFFFFL;
rgb[0] = 0;
rgb[1] = 0;
rgb[2] = 0;
rgb[3] = 0;
IdMode = 0;
ras_mode = 0;
glslmat = 0;
@ -64,7 +58,7 @@ void BL_Material::Initialize()
int i;
for (i=0; i<MAXTEX; i++) // :(
for (i = 0; i < MAXTEX; i++) // :(
{
mapping[i].mapping = 0;
mapping[i].offsets[0] = 0.f;
@ -90,15 +84,6 @@ void BL_Material::Initialize()
}
}
void BL_Material::SetUVLayerName(const STR_String& name)
{
uvName = name;
}
void BL_Material::SetUVLayerName2(const STR_String& name)
{
uv2Name = name;
}
void BL_Material::SetSharedMaterial(bool v)
{
if ((v && num_users == -1) || num_users > 1 )

@ -87,13 +87,8 @@ public:
MTFace tface; /* copy of the derived meshes tface */
Image* img[MAXTEX];
EnvMap* cubemap[MAXTEX];
unsigned int m_mcol; /* for text color (only) */
STR_String uvName;
STR_String uv2Name;
void SetUVLayerName(const STR_String &name);
void SetUVLayerName2(const STR_String &name);
unsigned int rgb[4];
void SetSharedMaterial(bool v);
bool IsShared();
@ -180,7 +175,6 @@ enum BL_MappingProj
// ------------------------------------
//extern void initBL_Material(BL_Material* mat);
extern MTex* getImageFromMaterial(Material *mat, int index);
extern int getNumTexChannels( Material *mat );
// ------------------------------------
#endif

@ -60,6 +60,7 @@ public:
typedef std::map<char*, BL_TextureObject> BL_TextureMap;
static BL_TextureMap g_textureManager;
static GLint g_max_units = -1;
BL_Texture::BL_Texture()
@ -379,14 +380,17 @@ unsigned int BL_Texture::GetTextureType() const
int BL_Texture::GetMaxUnits()
{
GLint unit=0;
if (GLEW_ARB_multitexture) {
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit);
return (MAXTEX>=unit?unit:MAXTEX);
if (g_max_units < 0) {
GLint unit;
if (GLEW_ARB_multitexture) {
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit);
g_max_units = (MAXTEX>=unit)?unit:MAXTEX;
} else {
g_max_units = 0;
}
}
return 0;
return g_max_units;
}
void BL_Texture::ActivateFirst()

@ -60,7 +60,8 @@ KX_BlenderMaterial::KX_BlenderMaterial()
void KX_BlenderMaterial::Initialize(
KX_Scene *scene,
BL_Material *data,
GameSettings *game)
GameSettings *game,
int lightlayer)
{
RAS_IPolyMaterial::Initialize(
data->texname[0],
@ -84,6 +85,7 @@ void KX_BlenderMaterial::Initialize(
mModified = 0;
mConstructed = false;
mPass = 0;
mLightLayer = lightlayer;
// --------------------------------
// RAS_IPolyMaterial variables...
m_flag |= RAS_BLENDERMAT;
@ -92,16 +94,11 @@ void KX_BlenderMaterial::Initialize(
m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0;
m_flag |= ((mMaterial->ras_mode & CAST_SHADOW)!=0)? RAS_CASTSHADOW: 0;
// figure max
int enabled = mMaterial->num_enabled;
int max = BL_Texture::GetMaxUnits();
mMaterial->num_enabled = enabled>=max?max:enabled;
// test the sum of the various modes for equality
// so we can ether accept or reject this material
// as being equal, this is rather important to
// prevent material bleeding
for (int i=0; i<mMaterial->num_enabled; i++) {
for (int i=0; i<BL_Texture::GetMaxUnits(); i++) {
m_multimode += (mMaterial->flag[i] + mMaterial->blend_mode[i]);
}
m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(USE_LIGHT));
@ -124,7 +121,7 @@ MTFace* KX_BlenderMaterial::GetMTFace(void) const
unsigned int* KX_BlenderMaterial::GetMCol(void) const
{
// fonts on polys
return &mMaterial->m_mcol;
return mMaterial->rgb;
}
void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
@ -138,11 +135,6 @@ void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
}
bool KX_BlenderMaterial::IsMaterial(const BL_Material *bl_mat) const
{
return (mMaterial == bl_mat);
}
Material *KX_BlenderMaterial::GetBlenderMaterial() const
{
return mMaterial->material;
@ -163,7 +155,7 @@ void KX_BlenderMaterial::InitTextures()
{
// for each unique material...
int i;
for (i=0; i<mMaterial->num_enabled; i++) {
for (i=0; i<BL_Texture::GetMaxUnits(); i++) {
if ( mMaterial->mapping[i].mapping & USEENV ) {
if (!GLEW_ARB_texture_cube_map) {
spit("CubeMap textures not supported");
@ -185,14 +177,14 @@ void KX_BlenderMaterial::InitTextures()
}
}
void KX_BlenderMaterial::OnConstruction(int layer)
void KX_BlenderMaterial::OnConstruction()
{
if (mConstructed)
// when material are reused between objects
return;
if (mMaterial->glslmat)
SetBlenderGLSLShader(layer);
SetBlenderGLSLShader();
InitTextures();
@ -239,7 +231,8 @@ void KX_BlenderMaterial::OnExit()
}
BL_Texture::ActivateFirst();
for (int i=0; i<mMaterial->num_enabled; i++) {
for (int i=0; i<BL_Texture::GetMaxUnits(); i++) {
if (!mTextures[i].Ok()) continue;
BL_Texture::ActivateUnit(i);
mTextures[i].DeleteTex();
mTextures[i].DisableUnit();
@ -278,7 +271,7 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
mShader->ApplyShader();
// for each enabled unit
for (i=0; i<mMaterial->num_enabled; i++) {
for (i=0; i<BL_Texture::GetMaxUnits(); i++) {
if (!mTextures[i].Ok()) continue;
mTextures[i].ActivateTexture();
mTextures[0].SetMapping(mMaterial->mapping[i].mapping);
@ -354,7 +347,7 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras)
}
int mode = 0,i=0;
for (i=0; (i<mMaterial->num_enabled && i<MAXTEX); i++) {
for (i=0; i<BL_Texture::GetMaxUnits(); i++) {
if ( !mTextures[i].Ok() ) continue;
mTextures[i].ActivateTexture();
@ -647,16 +640,9 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
ras->SetTexCoordNum(mMaterial->num_enabled);
for (int i=0; i<mMaterial->num_enabled; i++) {
for (int i=0; i<BL_Texture::GetMaxUnits(); 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)
@ -664,7 +650,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
@ -790,10 +776,19 @@ void KX_BlenderMaterial::UpdateIPO(
mMaterial->ref = (float)(ref);
}
void KX_BlenderMaterial::SetBlenderGLSLShader(int layer)
void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val)
{
mScene= static_cast<KX_Scene *>(val);
if (mBlenderShader)
mBlenderShader->SetScene(mScene);
OnConstruction();
}
void KX_BlenderMaterial::SetBlenderGLSLShader()
{
if (!mBlenderShader)
mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, layer);
mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, mLightLayer);
if (!mBlenderShader->Ok()) {
delete mBlenderShader;

@ -39,7 +39,8 @@ public:
void Initialize(
class KX_Scene* scene,
BL_Material* mat,
GameSettings* game
GameSettings* game,
int lightlayer
);
virtual ~KX_BlenderMaterial();
@ -76,8 +77,6 @@ public:
TCachingInfo& cachingInfo
)const;
/* mMaterial is private, but need this for conversion */
bool IsMaterial(const BL_Material *bl_mat) const;
Material* GetBlenderMaterial() const;
MTFace* GetMTFace(void) const;
unsigned int* GetMCol(void) const;
@ -97,14 +96,7 @@ public:
MT_Scalar ref, MT_Scalar emit, MT_Scalar alpha
);
virtual void Replace_IScene(SCA_IScene *val)
{
mScene= static_cast<KX_Scene *>(val);
if (mBlenderShader)
{
mBlenderShader->SetScene(mScene);
}
};
virtual void Replace_IScene(SCA_IScene *val);
#ifdef WITH_PYTHON
// --------------------------------
@ -125,7 +117,7 @@ public:
// --------------------------------
// pre calculate to avoid pops/lag at startup
virtual void OnConstruction(int layer);
virtual void OnConstruction();
static void EndFrame();
@ -139,10 +131,11 @@ private:
unsigned int mBlendFunc[2];
bool mModified;
bool mConstructed; // if false, don't clean on exit
int mLightLayer;
void InitTextures();
void SetBlenderGLSLShader(int layer);
void SetBlenderGLSLShader();
void ActivatGLMaterials( RAS_IRasterizer* rasty )const;
void ActivateTexGen( RAS_IRasterizer *ras ) const;

@ -57,7 +57,8 @@ public:
virtual void ConvertScene(
class KX_Scene* destinationscene,
class RAS_IRenderTools* rendertools,
class RAS_ICanvas* canvas)=0;
class RAS_ICanvas* canvas,
bool libloading=false)=0;
virtual void RemoveScene(class KX_Scene *scene)=0;

@ -1686,7 +1686,7 @@ void KX_KetsjiEngine::RemoveScheduledScenes()
}
}
KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene)
KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene, bool libloading)
{
KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
m_mousedevice,
@ -1697,7 +1697,8 @@ KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene)
m_sceneconverter->ConvertScene(tmpscene,
m_rendertools,
m_canvas);
m_canvas,
libloading);
return tmpscene;
}

@ -413,7 +413,7 @@ public:
void GetOverrideFrameColor(float& r, float& g, float& b) const;
KX_Scene* CreateScene(const STR_String& scenename);
KX_Scene* CreateScene(Scene *scene);
KX_Scene* CreateScene(Scene *scene, bool libloading=false);
GlobalSettings* GetGlobalSettings(void);
void SetGlobalSettings(GlobalSettings* gs);

@ -338,20 +338,20 @@ PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds)
for (i = it.startvertex; i < it.endvertex; i++) {
RAS_TexVert *vert = &it.vertex[i];
if (uvindex_from != -1) {
if (uvindex_from == 0) vert->SetUV2(vert->getUV1());
else vert->SetUV1(vert->getUV2());
if (uvindex_from == 0) vert->SetUV(1, vert->getUV(0));
else vert->SetUV(0, vert->getUV(1));
}
switch (uvindex) {
case 0:
vert->TransformUV1(transform);
vert->TransformUV(0, transform);
break;
case 1:
vert->TransformUV2(transform);
vert->TransformUV(1, transform);
break;
case -1:
vert->TransformUV1(transform);
vert->TransformUV2(transform);
vert->TransformUV(0, transform);
vert->TransformUV(1, transform);
break;
}
}

@ -109,7 +109,7 @@ void KX_PolygonMaterial::Initialize(
m_mcol = *mcol;
}
else {
m_mcol = 0;
memset(&m_mcol, 0, sizeof(m_mcol));
}
m_material = ma;

@ -60,7 +60,7 @@ class KX_PolygonMaterial : public PyObjectPlus, public RAS_IPolyMaterial
private:
/** Blender texture face structure. */
mutable MTFace m_tface;
mutable unsigned int m_mcol; /* for text color (only) */
mutable unsigned int m_mcol;
Material* m_material;
#ifdef WITH_PYTHON

@ -94,6 +94,7 @@ PyAttributeDef KX_VertexProxy::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("XYZ", KX_VertexProxy, pyattr_get_XYZ, pyattr_set_XYZ),
KX_PYATTRIBUTE_RW_FUNCTION("UV", KX_VertexProxy, pyattr_get_UV, pyattr_set_UV),
KX_PYATTRIBUTE_RW_FUNCTION("uvs", KX_VertexProxy, pyattr_get_uvs, pyattr_set_uvs),
KX_PYATTRIBUTE_RW_FUNCTION("color", KX_VertexProxy, pyattr_get_color, pyattr_set_color),
KX_PYATTRIBUTE_RW_FUNCTION("normal", KX_VertexProxy, pyattr_get_normal, pyattr_set_normal),
@ -146,25 +147,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 +177,20 @@ 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_uvs(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
PyObject* uvlist = PyList_New(RAS_TexVert::MAX_UNIT);
for (int i=0; i<RAS_TexVert::MAX_UNIT; ++i)
{
PyList_SET_ITEM(uvlist, i, PyObjectFrom(MT_Point2(self->m_vertex->getUV(i))));
}
return uvlist;
}
PyObject *KX_VertexProxy::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@ -245,9 +259,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->SetUV1(uv);
self->m_vertex->SetUV(0, uv);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@ -260,9 +274,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->SetUV1(uv);
self->m_vertex->SetUV(0, uv);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@ -275,9 +289,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 +304,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;
}
@ -390,7 +404,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->SetUV1(vec);
self->m_vertex->SetUV(0, vec);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@ -398,6 +412,32 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF
return PY_SET_ATTR_FAIL;
}
int KX_VertexProxy::pyattr_set_uvs(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
if (PySequence_Check(value))
{
MT_Point2 vec;
for (int i=0; i<PySequence_Size(value) && i<RAS_TexVert::MAX_UNIT; ++i)
{
if (PyVecTo(PySequence_GetItem(value, i), vec))
{
self->m_vertex->SetUV(i, vec);
self->m_mesh->SetMeshModified(true);
}
else
{
PyErr_SetString(PyExc_AttributeError, STR_String().Format("list[%d] was not a vector", i).ReadPtr());
return PY_SET_ATTR_FAIL;
}
}
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
return PY_SET_ATTR_FAIL;
}
int KX_VertexProxy::pyattr_set_color(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v);
@ -522,7 +562,7 @@ PyObject *KX_VertexProxy::PySetRGBA(PyObject *value)
PyObject *KX_VertexProxy::PyGetUV1()
{
return PyObjectFrom(MT_Vector2(m_vertex->getUV1()));
return PyObjectFrom(MT_Vector2(m_vertex->getUV(0)));
}
PyObject *KX_VertexProxy::PySetUV1(PyObject *value)
@ -531,31 +571,23 @@ PyObject *KX_VertexProxy::PySetUV1(PyObject *value)
if (!PyVecTo(value, vec))
return NULL;
m_vertex->SetUV1(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)
{
MT_Point2 vec;
unsigned int unit= RAS_TexVert::SECOND_UV;
PyObject *list = NULL;
if (!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit))
if (!PyVecTo(args, vec))
return NULL;
if (!PyVecTo(list, 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;
}

@ -74,6 +74,7 @@ public:
static PyObject *pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_uvs(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_x(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_y(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_z(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
@ -89,6 +90,7 @@ public:
static int pyattr_set_UV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_color(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_normal(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_uvs(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ);
KX_PYMETHOD_O(KX_VertexProxy,SetXYZ);

@ -232,6 +232,24 @@ void RAS_BucketManager::Renderbuckets(
RenderSolidBuckets(cameratrans, rasty, rendertools);
RenderAlphaBuckets(cameratrans, rasty, rendertools);
/* All meshes should be up to date now */
/* Don't do this while processing buckets because some meshes are split between buckets */
BucketList::iterator bit;
list<RAS_MeshSlot>::iterator mit;
for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
RAS_MaterialBucket* bucket = *bit;
for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
mit->m_mesh->SetMeshModified(false);
}
}
for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) {
RAS_MaterialBucket* bucket = *bit;
for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
mit->m_mesh->SetMeshModified(false);
}
}
rendertools->SetClientObject(rasty, NULL);
}

@ -184,7 +184,7 @@ public:
/*
* PreCalculate texture gen
*/
virtual void OnConstruction(int layer) {}
virtual void OnConstruction() {}
#ifdef WITH_CXX_GUARDEDALLOC

@ -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)
};

@ -605,7 +605,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,10 +649,6 @@ 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);
rendertools->PopMatrix();
}

@ -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;

@ -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,

@ -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)

@ -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

@ -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

@ -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);

@ -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"
@ -74,7 +78,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),
@ -93,7 +97,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();
@ -107,6 +112,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;
}
}
@ -115,10 +138,16 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
{
// Restore the previous AF value
GPU_set_anisotropic(m_prevafvalue);
if (m_failsafe_storage && m_failsafe_storage != m_storage)
delete m_failsafe_storage;
if (m_storage)
delete m_storage;
}
bool RAS_OpenGLRasterizer::Init()
{
bool storage_init;
GPU_state_init();
@ -146,7 +175,9 @@ bool RAS_OpenGLRasterizer::Init()
glShadeModel(GL_SMOOTH);
return true;
storage_init = m_storage->Init();
return true && storage_init;
}
@ -267,6 +298,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);
@ -289,7 +322,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)
@ -328,6 +361,8 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
if (m_drawingmode == KX_WIREFRAME)
glDisable(GL_CULL_FACE);
m_storage->SetDrawingMode(drawingmode);
}
int RAS_OpenGLRasterizer::GetDrawingMode()
@ -666,7 +701,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,
@ -708,257 +743,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, &current_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), &current_gpu_attribs);
else
memset(&current_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)

@ -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(

@ -0,0 +1,310 @@
/*
* ***** 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"
extern "C"{
#include "BLI_utildefines.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, &current_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), &current_gpu_attribs);
else
memset(&current_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();
}
}
}

@ -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

@ -0,0 +1,320 @@
/*
* ***** 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_StorageVA.h"
#include "GL/glew.h"
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_StorageVA::~RAS_StorageVA()
{
}
bool RAS_StorageVA::Init()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return true;
}
void RAS_StorageVA::Exit()
{
}
void RAS_StorageVA::IndexPrimitives(RAS_MeshSlot& ms)
{
static const GLsizei stride = sizeof(RAS_TexVert);
bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME;
RAS_MeshSlot::iterator it;
GLenum drawmode;
if (!wireframe)
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
// use glDrawElements to draw each vertexarray
for (ms.begin(it); !ms.end(it); ms.next(it)) {
if (it.totindex == 0)
continue;
// drawing mode
if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
drawmode = GL_TRIANGLES;
else if (it.array->m_type == RAS_DisplayArray::QUAD)
drawmode = GL_QUADS;
else
drawmode = GL_LINES;
// colors
if (drawmode != GL_LINES && !wireframe) {
if (ms.m_bObjectColor) {
const MT_Vector4& rgba = ms.m_RGBAcolor;
glDisableClientState(GL_COLOR_ARRAY);
glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
}
else {
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glEnableClientState(GL_COLOR_ARRAY);
}
}
else
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
if (!wireframe) {
glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV(0));
if (glIsEnabled(GL_COLOR_ARRAY))
glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
}
// here the actual drawing takes places
glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
if (!wireframe) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
}
void RAS_StorageVA::IndexPrimitivesMulti(class RAS_MeshSlot& ms)
{
static const GLsizei stride = sizeof(RAS_TexVert);
bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME, use_color_array;
RAS_MeshSlot::iterator it;
GLenum drawmode;
if (!wireframe)
EnableTextures(true);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
// use glDrawElements to draw each vertexarray
for (ms.begin(it); !ms.end(it); ms.next(it)) {
if (it.totindex == 0)
continue;
// drawing mode
if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
drawmode = GL_TRIANGLES;
else if (it.array->m_type == RAS_DisplayArray::QUAD)
drawmode = GL_QUADS;
else
drawmode = GL_LINES;
// colors
if (drawmode != GL_LINES && !wireframe) {
if (ms.m_bObjectColor) {
const MT_Vector4& rgba = ms.m_RGBAcolor;
glDisableClientState(GL_COLOR_ARRAY);
glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
use_color_array = false;
}
else {
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glEnableClientState(GL_COLOR_ARRAY);
use_color_array = true;
}
}
else
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
if (!wireframe) {
TexCoordPtr(it.vertex);
if (use_color_array)
glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
}
// here the actual drawing takes places
glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
if (!wireframe) {
glDisableClientState(GL_COLOR_ARRAY);
EnableTextures(false);
}
}
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
* materials can still be used and cause crashes */
int unit;
if (GLEW_ARB_multitexture)
{
for (unit = 0; unit < *m_texco_num; unit++)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
switch (m_texco[unit]) {
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;
}
}
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
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:
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_StorageVA::EnableTextures(bool enable)
{
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;
attrib = m_attrib;
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;
texco_num = m_last_texco_num;
attrib = m_last_attrib;
attrib_num = m_last_attrib_num;
}
if (GLEW_ARB_multitexture) {
for (unit = 0; unit < texco_num; unit++) {
glClientActiveTextureARB(GL_TEXTURE0_ARB + unit);
switch (texco[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:
if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
break;
default:
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
break;
}
}
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
else {
if (texco_num) {
if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
if (GLEW_ARB_vertex_program) {
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;
}
}
}
if (!enable) {
m_last_texco_num = 0;
m_last_attrib_num = 0;
}
}

@ -25,46 +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; */ /* UNUSED */
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
MEM_CXX_CLASS_ALLOC_FUNCS("GE:RAS_VAOpenGLRasterizer")
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 /* __RAS_VAOPENGLRASTERIZER_H__ */
#endif //__KX_VERTEXARRAYSTORAGE

@ -0,0 +1,259 @@
/*
* ***** 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 = 32*sizeof(GLfloat); // ATI cards really like 32byte aligned VBOs, so we add a little padding
// 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);
// 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));
}
VBO::~VBO()
{
glDeleteBuffersARB(1, &this->ibo);
glDeleteBuffersARB(1, &this->vbo_id);
}
void VBO::UpdateData()
{
unsigned int i, j, k;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id);
glBufferData(GL_ARRAY_BUFFER, this->stride*this->size, NULL, GL_STATIC_DRAW);
// Map the buffer
GLfloat *vbo_map = (GLfloat*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
// Gather data
for (i = 0, j = 0; i < data->m_vertex.size(); i++, j += this->stride/sizeof(GLfloat))
{
memcpy(&vbo_map[j], data->m_vertex[i].getXYZ(), sizeof(float)*3);
memcpy(&vbo_map[j+3], data->m_vertex[i].getNormal(), sizeof(float)*3);
memcpy(&vbo_map[j+6], data->m_vertex[i].getTangent(), sizeof(float)*4);
memcpy(&vbo_map[j+10], data->m_vertex[i].getRGBA(), sizeof(char)*4);
for (k = 0; k < RAS_TexVert::MAX_UNIT; k++)
memcpy(&vbo_map[j+11+(k*2)], data->m_vertex[i].getUV(k), sizeof(float)*2);
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
}
void VBO::UpdateIndices()
{
int space = data->m_index.size() * sizeof(GLushort);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo);
// Upload Data to VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, space, &data->m_index[0], GL_STATIC_DRAW);
}
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:
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);
}
}

@ -0,0 +1,100 @@
/*
* ***** 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;
void* vertex_offset;
void* normal_offset;
void* color_offset;
void* tangent_offset;
void* uv_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

@ -1,382 +0,0 @@
/*
* ***** 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 *****
*/
/** \file gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
* \ingroup bgerastogl
*/
#include "RAS_VAOpenGLRasterizer.h"
#include <stdlib.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), */ /* UNUSED */
m_last_texco_num(0),
m_last_attrib_num(0)
{
}
RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
{
}
bool RAS_VAOpenGLRasterizer::Init(void)
{
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;
}
void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
{
m_drawingmode = drawingmode;
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;
}
}
void RAS_VAOpenGLRasterizer::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)
{
static const GLsizei stride = sizeof(RAS_TexVert);
bool wireframe = m_drawingmode <= 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);
// use glDrawElements to draw each vertexarray
for (ms.begin(it); !ms.end(it); ms.next(it)) {
if (it.totindex == 0)
continue;
// drawing mode
if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
drawmode = GL_TRIANGLES;
else if (it.array->m_type == RAS_DisplayArray::QUAD)
drawmode = GL_QUADS;
else
drawmode = GL_LINES;
// colors
if (drawmode != GL_LINES && !wireframe) {
if (ms.m_bObjectColor) {
const MT_Vector4& rgba = ms.m_RGBAcolor;
glDisableClientState(GL_COLOR_ARRAY);
glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
}
else {
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glEnableClientState(GL_COLOR_ARRAY);
}
}
else
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
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());
if (glIsEnabled(GL_COLOR_ARRAY))
glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
}
// here the actual drawing takes places
glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
}
if (!wireframe) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
}
void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
{
static const GLsizei stride = sizeof(RAS_TexVert);
bool wireframe = m_drawingmode <= 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);
// use glDrawElements to draw each vertexarray
for (ms.begin(it); !ms.end(it); ms.next(it)) {
if (it.totindex == 0)
continue;
// drawing mode
if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
drawmode = GL_TRIANGLES;
else if (it.array->m_type == RAS_DisplayArray::QUAD)
drawmode = GL_QUADS;
else
drawmode = GL_LINES;
// colors
if (drawmode != GL_LINES && !wireframe) {
if (ms.m_bObjectColor) {
const MT_Vector4& rgba = ms.m_RGBAcolor;
glDisableClientState(GL_COLOR_ARRAY);
glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
}
else {
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glEnableClientState(GL_COLOR_ARRAY);
}
}
else
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
if (!wireframe) {
TexCoordPtr(it.vertex);
if (glIsEnabled(GL_COLOR_ARRAY))
glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
}
// here the actual drawing takes places
glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
}
if (!wireframe) {
glDisableClientState(GL_COLOR_ARRAY);
EnableTextures(false);
}
}
void RAS_VAOpenGLRasterizer::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
* materials can still be used and cause crashes */
int unit;
if (GLEW_ARB_multitexture)
{
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]) {
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;
}
}
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
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;
}
}
}
}
void RAS_VAOpenGLRasterizer::EnableTextures(bool enable)
{
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;
attrib = m_attrib;
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;
}
else {
texco = m_last_texco;
texco_num = m_last_texco_num;
attrib = m_last_attrib;
attrib_num = m_last_attrib_num;
}
if (GLEW_ARB_multitexture) {
for (unit=0; unit<texco_num; unit++) {
glClientActiveTextureARB(GL_TEXTURE0_ARB+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;
}
}
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
else {
if (texco_num) {
if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
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;
}
}
}
if (!enable) {
m_last_texco_num = 0;
m_last_attrib_num = 0;
}
}

@ -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,26 +82,15 @@ void RAS_TexVert::SetXYZ(const float xyz[3])
m_localxyz[0] = xyz[0]; m_localxyz[1] = xyz[1]; m_localxyz[2] = xyz[2];
}
void RAS_TexVert::SetUV1(const MT_Point2& uv)
void RAS_TexVert::SetUV(int index, const MT_Point2& uv)
{
uv.getValue(m_uv1);
uv.getValue(m_uvs[index]);
}
void RAS_TexVert::SetUV1(const float uv[3])
void RAS_TexVert::SetUV(int index, const float uv[2])
{
m_uv1[0] = uv[0];
m_uv1[1] = uv[1];
}
void RAS_TexVert::SetUV2(const MT_Point2& uv)
{
uv.getValue(m_uv2);
}
void RAS_TexVert::SetUV2(const float uv[3])
{
m_uv2[0] = uv[0];
m_uv2[1] = uv[1];
m_uvs[index][0] = uv[0];
m_uvs[index][1] = uv[1];
}
void RAS_TexVert::SetRGBA(const unsigned int rgba)
@ -132,14 +123,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 */
}
@ -162,12 +156,7 @@ void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat)
SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue());
}
void RAS_TexVert::TransformUV1(const MT_Matrix4x4& mat)
void RAS_TexVert::TransformUV(int index, const MT_Matrix4x4& mat)
{
SetUV1((mat * MT_Vector4(m_uv1[0], m_uv1[1], 0.0, 1.0)).getValue());
}
void RAS_TexVert::TransformUV2(const MT_Matrix4x4& mat)
{
SetUV2((mat * MT_Vector4(m_uv2[0], m_uv2[1], 0.0, 1.0)).getValue());
SetUV(index, (mat * MT_Vector4(m_uvs[index][0], m_uvs[index][1], 0.0, 1.0)).getValue());
}

@ -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,10 +116,8 @@ public:
void SetXYZ(const MT_Point3& xyz);
void SetXYZ(const float xyz[3]);
void SetUV1(const MT_Point2& uv);
void SetUV2(const MT_Point2& uv);
void SetUV1(const float uv[2]);
void SetUV2(const float uv[2]);
void SetUV(int index, const MT_Point2& uv);
void SetUV(int index, const float uv[2]);
void SetRGBA(const unsigned int rgba);
void SetNormal(const MT_Vector3& normal);
@ -139,8 +130,7 @@ public:
void Transform(const class MT_Matrix4x4& mat,
const class MT_Matrix4x4& nmat);
void TransformUV1(const MT_Matrix4x4& mat);
void TransformUV2(const MT_Matrix4x4& mat);
void TransformUV(int index, const MT_Matrix4x4& mat);
// compare two vertices, to test if they can be shared, used for
// splitting up based on uv's, colors, etc

@ -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();