From 1eac9d1f82dc92722ecaeb9fbe9cbbfa7726651c Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sat, 11 Dec 2010 10:14:22 +0000 Subject: Fin de création de l'architecture pour les dirty rectangle. La méthode findAndSortZOrder pourra faire un bête scan des objets ou utiliser un R-Tree pour gagner en perfs. Il faut déplacer les dernières fonctions ajoutées dans netlem.c vers graphic.c et implémenter ce qui ne l'est pas. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2010-netlemmings/trunk@189 077b3477-7977-48bd-8428-443f22f7bfda --- src/graphic.c | 42 ++++++++--------- src/include/data_localgame.h | 22 +++++++-- src/netlem.c | 89 +++++++++++++++++++++++++++++------- src/test/testfunc_004_buildterrain.c | 4 +- 4 files changed, 113 insertions(+), 44 deletions(-) diff --git a/src/graphic.c b/src/graphic.c index b9990f6..b596be8 100644 --- a/src/graphic.c +++ b/src/graphic.c @@ -76,31 +76,31 @@ int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, gameGraphics_t *gGraph) { Uint32 dstPixel, dstStencil; SDL_Surface *tile; - gGraph->terrain=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); - if (gGraph->terrain==NULL) { + gGraph->surfaces.terrain=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); + if (gGraph->surfaces.terrain==NULL) { logs(LOG_ERROR, "paintTerrain(), SDL_CreateRGBSurface() returns NULL"); return 1; } - gGraph->stencil=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); - if (gGraph->stencil==NULL) { + gGraph->surfaces.stencil=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); + if (gGraph->surfaces.stencil==NULL) { logs(LOG_ERROR, "paintTerrain(), SDL_CreateRGBSurface() returns NULL"); return 2; } - res=SDL_FillRect(gGraph->terrain, &(gGraph->terrain->clip_rect), gIni->style.bgColor); + res=SDL_FillRect(gGraph->surfaces.terrain, &(gGraph->surfaces.terrain->clip_rect), gIni->style.bgColor); if (res!=0) { logs(LOG_WARN, "paintTerrain(), SDL_FillRect() failed"); return 3; } - res=SDL_FillRect(gGraph->stencil, &(gGraph->stencil->clip_rect), ccc_nothing); + res=SDL_FillRect(gGraph->surfaces.stencil, &(gGraph->surfaces.stencil->clip_rect), ccc_nothing); if (res!=0) { logs(LOG_WARN, "paintTerrain(), SDL_FillRect() failed"); return 4; } - SDL_LockSurface(gGraph->terrain); - SDL_LockSurface(gGraph->stencil); + SDL_LockSurface(gGraph->surfaces.terrain); + SDL_LockSurface(gGraph->surfaces.stencil); for(i=0 ; i < gIni->level.terrainCount ; i++) { //FIXME : check sanity for id value tile=gRess->style.tiles[gIni->level.terrains[i].id]; @@ -131,9 +131,9 @@ int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, gameGraphics_t *gGraph) { // For each tile pixel, without going outside of the terrain ymin=(gIni->level.terrains[i].ypos>=0)?0:-gIni->level.terrains[i].ypos; - ymax=min(tile->clip_rect.h, gGraph->terrain->clip_rect.h - gIni->level.terrains[i].ypos); + ymax=min(tile->clip_rect.h, gGraph->surfaces.terrain->clip_rect.h - gIni->level.terrains[i].ypos); xmin=(gIni->level.terrains[i].xpos>=0)?0:-gIni->level.terrains[i].xpos; - xmax=min(tile->clip_rect.w, gGraph->terrain->clip_rect.w - gIni->level.terrains[i].xpos); + xmax=min(tile->clip_rect.w, gGraph->surfaces.terrain->clip_rect.w - gIni->level.terrains[i].xpos); SDL_LockSurface(tile); for (y=ymin; ystencil, xdst, ydst) == ccc_terrain ) ) { + getPixel(gGraph->surfaces.stencil, xdst, ydst) == ccc_terrain ) ) { // If we have REMOVE modifier, dstPixel will be rolled back to bgColor, else, it will be identical to the source pixel. We have to update stencil consistenly. if ( (modifier & 2) == 2 ) { dstPixel=gIni->style.bgColor; @@ -163,22 +163,22 @@ int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, gameGraphics_t *gGraph) { } //FIXME : optimiser le nombre d'appels ici ! - putPixel(gGraph->terrain, xdst, ydst, dstPixel); - putPixel(gGraph->terrain, xdst+1, ydst, dstPixel); - putPixel(gGraph->terrain, xdst, ydst+1, dstPixel); - putPixel(gGraph->terrain, xdst+1, ydst+1, dstPixel); - putPixel(gGraph->stencil, xdst, ydst, dstStencil); - putPixel(gGraph->stencil, xdst+1, ydst, dstStencil); - putPixel(gGraph->stencil, xdst, ydst+1, dstStencil); - putPixel(gGraph->stencil, xdst+1, ydst+1, dstStencil); + putPixel(gGraph->surfaces.terrain, xdst, ydst, dstPixel); + putPixel(gGraph->surfaces.terrain, xdst+1, ydst, dstPixel); + putPixel(gGraph->surfaces.terrain, xdst, ydst+1, dstPixel); + putPixel(gGraph->surfaces.terrain, xdst+1, ydst+1, dstPixel); + putPixel(gGraph->surfaces.stencil, xdst, ydst, dstStencil); + putPixel(gGraph->surfaces.stencil, xdst+1, ydst, dstStencil); + putPixel(gGraph->surfaces.stencil, xdst, ydst+1, dstStencil); + putPixel(gGraph->surfaces.stencil, xdst+1, ydst+1, dstStencil); } } } } SDL_UnlockSurface(tile); } - SDL_UnlockSurface(gGraph->stencil); - SDL_UnlockSurface(gGraph->terrain); + SDL_UnlockSurface(gGraph->surfaces.stencil); + SDL_UnlockSurface(gGraph->surfaces.terrain); return 0; } diff --git a/src/include/data_localgame.h b/src/include/data_localgame.h index 9153d6e..01f5008 100644 --- a/src/include/data_localgame.h +++ b/src/include/data_localgame.h @@ -5,15 +5,27 @@ typedef struct { SDL_Rect screen; - } gameConfig_t; typedef struct { - SDL_Surface *screen, *terrain, *stencil; - SDL_Rect viewport; // Viewport top-left corner coords in screen - int dirtRectsCount; // Dirt rectangle to refresh for current tick - SDL_Rect *dirtRects; + int zOrder, surfId, animFrames, currentAnimFrame; + SDL_Rect *objectsBBox; +} gameGraphObjState_t; + +typedef struct { + SDL_Surface *screen, *terrain, *stencil, **objectsSurf; + gameGraphObjState_t *objectsStat; +} gameGraphSurfaces_t; + +typedef struct { + SDL_Surface *screen; + SDL_Rect viewport; // Viewport top-left corner coords in screen + + gameGraphSurfaces_t surfaces; + + int dirtRectsCount; + SDL_Rect *dirtRects; // Dirt rectangles to refresh for current tick } gameGraphics_t; typedef struct { diff --git a/src/netlem.c b/src/netlem.c index 8e43d13..9628050 100644 --- a/src/netlem.c +++ b/src/netlem.c @@ -51,6 +51,10 @@ void processLocalEvents(SDL_Rect *viewport, SDL_Rect *screen, SDL_Rect *terrain) int act(tick_t *tick, int loadProgress, TCPsocket sockClient, int *dirtRectsCount, SDL_Rect **dirtRects); int updateGraphics(gameGraphics_t *gGraph); +int repaint(gameGraphSurfaces_t *srcSurfs, SDL_Rect *srcRect, SDL_Surface *dstSurf, SDL_Rect dstRect); +int findAndZSortObjects(gameGraphObjState_t *objectsStat, SDL_Rect *offsetRect, gameGraphObjState_t **objectsFound); +int paintObject(gameGraphObjState_t *obj, SDL_Rect *srcRect, SDL_Surface *dstSurf); + int main(int argc, char **argv) { @@ -161,7 +165,7 @@ int main(int argc, char **argv) { // Process local player keyboard and mouse events // (note: remote events are processed by network read thread) - processLocalEvents(&(gGraph.viewport), &(gGraph.screen->clip_rect), &(gGraph.terrain->clip_rect)); + processLocalEvents(&(gGraph.viewport), &(gGraph.screen->clip_rect), &(gGraph.surfaces.terrain->clip_rect)); endMainLoop=act(&tick, loadProgress, client.sockClient, &(gGraph.dirtRectsCount), &(gGraph.dirtRects)); @@ -247,14 +251,14 @@ int init(gameConfig_t *conf, gameGraphics_t *gGraph) { SDL_ShowCursor(0); // Memory allocation and initialization for all display layers - gGraph->terrain = createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); - if( gGraph->terrain == NULL ) { + gGraph->surfaces.terrain = createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); + if( gGraph->surfaces.terrain == NULL ) { logs2(LOG_ERROR, "init(), SDL_createSurface()", SDL_GetError()); return 3; } - gGraph->stencil = createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); - if( gGraph->stencil == NULL ) { + gGraph->surfaces.stencil = createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); + if( gGraph->surfaces.stencil == NULL ) { logs2(LOG_ERROR, "init(), SDL_createSurface()", SDL_GetError()); return 3; } @@ -546,25 +550,21 @@ int updateGraphics(gameGraphics_t *gGraph) { memcpy(gGraph->dirtRects, &(gGraph->screen->clip_rect), sizeof(SDL_Rect)); gGraph->dirtRectsCount=1; } - // We use a dirt rectangle method for performance + // We use a dirt rectangle method for performance for(i=0; idirtRectsCount; i++) { - //FIXME : faire une vrai procedure qui va chercher les objets sur une zone donnée, qui paint tout dans l'ordre srcRect.x=gGraph->dirtRects[i].x+lastViewport.x; srcRect.y=gGraph->dirtRects[i].y+lastViewport.y; srcRect.w=gGraph->dirtRects[i].w; srcRect.h=gGraph->dirtRects[i].h; - res=SDL_BlitSurface(gGraph->terrain, &srcRect, gGraph->screen, gGraph->dirtRects+i); - if ( res!=0 ) { - logs2(LOG_DEBUG, "updateGraphics(), SDL_BlitSurface()", SDL_GetError()); - return res; - } + res=repaint(&gGraph->surfaces, &srcRect, gGraph->screen, gGraph->dirtRects[i]); + if ( res != 0 ) { + logs(LOG_WARN, "updateGraphics(), repain() failed"); + } SDL_UpdateRect(gGraph->screen, - gGraph->dirtRects[i].x, - gGraph->dirtRects[i].y, - gGraph->dirtRects[i].w, - gGraph->dirtRects[i].h); + gGraph->dirtRects[i].x, gGraph->dirtRects[i].y, + gGraph->dirtRects[i].w, gGraph->dirtRects[i].h); } gGraph->dirtRectsCount=0; free(gGraph->dirtRects); @@ -575,3 +575,60 @@ int updateGraphics(gameGraphics_t *gGraph) { return 0; } + +int repaint(gameGraphSurfaces_t *srcSurfs, SDL_Rect *srcRect, SDL_Surface *dstSurf, SDL_Rect dstRect) { + int objToRepaintCount, i, res; + gameGraphObjState_t *objToRepaint; + SDL_Surface *tmpSurf; + + tmpSurf=createSurface(srcRect->w, srcRect->h); + if (tmpSurf==NULL) { + logs(LOG_ERROR, "repain(), createSurface() has failed"); + return 1; + } + objToRepaintCount=findAndZSortObjects(srcSurfs->objectsStat, srcRect, &objToRepaint); + + for(i=0;i0) break; + res=paintObject(objToRepaint+i, srcRect, tmpSurf); + if ( res!=0 ) { + logs(LOG_DEBUG, "repaint(), paintObject() failed"); + return res; + } + } + + res=SDL_BlitSurface(srcSurfs->terrain, srcRect, tmpSurf, NULL); + if ( res!=0 ) { + logs2(LOG_DEBUG, "repaint(), SDL_BlitSurface()", SDL_GetError()); + return res; + } + + for(;i