Allow objects to use a mesh instead of pixel-based graphics

stable-5.2
Armin Burgmeier 2009-07-11 01:10:18 +02:00
parent a3f1ccf66e
commit 01f2da1366
14 changed files with 307 additions and 27 deletions

View File

@ -85,6 +85,8 @@
#define C4CFN_IconPNG "Icon.png" #define C4CFN_IconPNG "Icon.png"
#define C4CFN_ScenarioObjects "Objects.txt" #define C4CFN_ScenarioObjects "Objects.txt"
#define C4CFN_ScenarioDesc "Desc%s.rtf" #define C4CFN_ScenarioDesc "Desc%s.rtf"
#define C4CFN_DefMaterials "*.material"
#define C4CFN_DefMesh "Graphics.mesh.xml"
#define C4CFN_DefGraphics "Graphics.bmp" #define C4CFN_DefGraphics "Graphics.bmp"
#define C4CFN_DefGraphicsPNG "Graphics.png" #define C4CFN_DefGraphicsPNG "Graphics.png"
#define C4CFN_ClrByOwnerPNG "Overlay.png" #define C4CFN_ClrByOwnerPNG "Overlay.png"

View File

@ -44,16 +44,30 @@ class C4DefGraphics
C4DefGraphics *GetLast(); // get last graphics in list C4DefGraphics *GetLast(); // get last graphics in list
public: public:
C4Surface *Bitmap, *BitmapClr; enum GraphicsType {
TYPE_Bitmap,
TYPE_Mesh
};
GraphicsType Type;
union {
struct {
C4Surface *Bitmap, *BitmapClr;
};
StdMesh *Mesh;
};
bool fColorBitmapAutoCreated; // if set, the color-by-owner-bitmap has been created automatically by all blue shades of the bitmap bool fColorBitmapAutoCreated; // if set, the color-by-owner-bitmap has been created automatically by all blue shades of the bitmap
inline C4Surface *GetBitmap(DWORD dwClr=0) { if (BitmapClr) { BitmapClr->SetClr(dwClr); return BitmapClr; } else return Bitmap; } inline C4Surface *GetBitmap(DWORD dwClr=0) { if(Type != TYPE_Bitmap) return NULL; if (BitmapClr) { BitmapClr->SetClr(dwClr); return BitmapClr; } else return Bitmap; }
C4DefGraphics(C4Def *pOwnDef=NULL); // ctor C4DefGraphics(C4Def *pOwnDef=NULL); // ctor
virtual ~C4DefGraphics() { Clear(); }; // dtor virtual ~C4DefGraphics() { Clear(); }; // dtor
bool LoadBitmap(C4Group &hGroup, const char *szFilename, const char *szFilenamePNG, const char *szOverlayPNG, bool fColorByOwner); // load specified graphics from group bool LoadBitmap(C4Group &hGroup, const char *szFilename, const char *szFilenamePNG, const char *szOverlayPNG, bool fColorByOwner); // load specified graphics from group
bool LoadBitmaps(C4Group &hGroup, bool fColorByOwner); // load graphics from group bool LoadMesh(C4Group &hGroup, StdMeshSkeletonLoader& loader);
bool Load(C4Group &hGroup, bool fColorByOwner); // load graphics from group
bool ColorizeByMaterial(int32_t iMat, C4MaterialMap &rMats, BYTE bGBM); // colorize all graphics by material bool ColorizeByMaterial(int32_t iMat, C4MaterialMap &rMats, BYTE bGBM); // colorize all graphics by material
C4DefGraphics *Get(const char *szGrpName); // get graphics by name C4DefGraphics *Get(const char *szGrpName); // get graphics by name
void Clear(); // clear fields; delete additional graphics void Clear(); // clear fields; delete additional graphics

View File

@ -24,7 +24,7 @@
#ifndef INC_C4Game #ifndef INC_C4Game
#define INC_C4Game #define INC_C4Game
#include <StdMeshMaterial.h>
#include <C4GameParameters.h> #include <C4GameParameters.h>
#include <C4PlayerInfo.h> #include <C4PlayerInfo.h>
#include <C4RoundResults.h> #include <C4RoundResults.h>
@ -82,7 +82,7 @@ class C4Game
C4PathFinder PathFinder; C4PathFinder PathFinder;
C4TransferZones TransferZones; C4TransferZones TransferZones;
C4Group ScenarioFile; C4Group ScenarioFile;
C4GroupSet GroupSet; C4GroupSet GroupSet;
C4Group *pParentGroup; C4Group *pParentGroup;
C4Extra Extra; C4Extra Extra;
@ -94,6 +94,7 @@ class C4Game
#endif #endif
C4Scoreboard Scoreboard; C4Scoreboard Scoreboard;
C4VideoPlayer VideoPlayer; C4VideoPlayer VideoPlayer;
StdMeshMatManager MaterialManager;
class C4Network2Stats *pNetworkStatistics; // may be NULL if no statistics are recorded class C4Network2Stats *pNetworkStatistics; // may be NULL if no statistics are recorded
class C4KeyboardInput &KeyboardInput; class C4KeyboardInput &KeyboardInput;
class C4FileMonitor *pFileMonitor; class C4FileMonitor *pFileMonitor;

View File

@ -178,6 +178,7 @@ class C4Object
C4NotifyingObjectList Contents; C4NotifyingObjectList Contents;
C4MaterialList *MaterialContents; // SyncClearance-NoSave // C4MaterialList *MaterialContents; // SyncClearance-NoSave //
C4DefGraphics *pGraphics; // currently set object graphics C4DefGraphics *pGraphics; // currently set object graphics
StdMeshInstance* pMeshInstance; // Instance for mesh-type objects
C4Effect *pEffects; // linked list of effects C4Effect *pEffects; // linked list of effects
C4ParticleList FrontParticles, BackParticles; // lists of object local particles C4ParticleList FrontParticles, BackParticles; // lists of object local particles
@ -260,6 +261,7 @@ class C4Object
void DrawTopFace(C4TargetFacet &cgo, int32_t iByPlayer = -1, DrawMode eDrawMode=ODM_Normal); void DrawTopFace(C4TargetFacet &cgo, int32_t iByPlayer = -1, DrawMode eDrawMode=ODM_Normal);
void DrawActionFace(C4TargetFacet &cgo, float offX, float offY); void DrawActionFace(C4TargetFacet &cgo, float offX, float offY);
void DrawFace(C4TargetFacet &cgo, float offX, float offY, int32_t iPhaseX=0, int32_t iPhaseY=0); void DrawFace(C4TargetFacet &cgo, float offX, float offY, int32_t iPhaseX=0, int32_t iPhaseY=0);
void DrawFaceImpl(C4TargetFacet &cgo, bool action, float fx, float fy, float fwdt, float fhgt, float tx, float ty, float twdt, float thgt, C4DrawTransform* transform);
void Execute(); void Execute();
void ClearPointers(C4Object *ptr); void ClearPointers(C4Object *ptr);
BOOL ExecMovement(); BOOL ExecMovement();

View File

@ -605,7 +605,7 @@ BOOL C4Def::Load(C4Group &hGroup,
// Read surface bitmap // Read surface bitmap
if (dwLoadWhat & C4D_Load_Bitmap) if (dwLoadWhat & C4D_Load_Bitmap)
if (!Graphics.LoadBitmaps(hGroup, !!ColorByOwner)) if (!Graphics.Load(hGroup, !!ColorByOwner))
{ {
DebugLogF(" Error loading graphics of %s (%s)", hGroup.GetFullName().getData(), C4IdText(id)); DebugLogF(" Error loading graphics of %s (%s)", hGroup.GetFullName().getData(), C4IdText(id));
return FALSE; return FALSE;
@ -866,14 +866,30 @@ void C4Def::Draw(C4Facet &cgo, BOOL fSelected, DWORD iColor, C4Object *pObj, int
// if assigned: use object specific rect and graphics // if assigned: use object specific rect and graphics
if (pObj) if(pObj->PictureRect.Wdt) fctPicRect = pObj->PictureRect; if (pObj) if(pObj->PictureRect.Wdt) fctPicRect = pObj->PictureRect;
fctPicture.Set((pObj ? *pObj->GetGraphics() : Graphics).GetBitmap(iColor),fctPicRect.x,fctPicRect.y,fctPicRect.Wdt,fctPicRect.Hgt);
if (fSelected) if (fSelected)
Application.DDraw->DrawBox(cgo.Surface,cgo.X,cgo.Y,cgo.X+cgo.Wdt-1,cgo.Y+cgo.Hgt-1,CRed); Application.DDraw->DrawBox(cgo.Surface,cgo.X,cgo.Y,cgo.X+cgo.Wdt-1,cgo.Y+cgo.Hgt-1,CRed);
C4DefGraphics* graphics = pObj ? pObj->GetGraphics() : &Graphics;
// specific object color? // specific object color?
if (pObj) pObj->PrepareDrawing(); if (pObj) pObj->PrepareDrawing();
fctPicture.Draw(cgo,TRUE,iPhaseX,iPhaseY,TRUE);
switch(graphics->Type)
{
case C4DefGraphics::TYPE_Bitmap:
fctPicture.Set((pObj ? *pObj->GetGraphics() : Graphics).GetBitmap(iColor),fctPicRect.x,fctPicRect.y,fctPicRect.Wdt,fctPicRect.Hgt);
fctPicture.Draw(cgo,TRUE,iPhaseX,iPhaseY,TRUE);
break;
case C4DefGraphics::TYPE_Mesh:
{
// TODO: Allow rendering of a mesh directly, without instance
StdMeshInstance dummy(*graphics->Mesh);
// TODO: Keep aspect ratio of mesh dimensions
lpDDraw->RenderMesh(dummy, cgo.Surface, cgo.X, cgo.Y, cgo.Wdt, cgo.Hgt);
}
break;
}
if (pObj) pObj->FinishedDrawing(); if (pObj) pObj->FinishedDrawing();
// draw overlays // draw overlays

View File

@ -42,6 +42,35 @@
#include <C4GameObjects.h> #include <C4GameObjects.h>
#endif #endif
// Helper class to load additional ressources required for meshes from
// a C4Group.
class AdditionalRessourcesLoader:
public StdMeshMaterialTextureLoader, public StdMeshSkeletonLoader
{
public:
AdditionalRessourcesLoader(C4Group& hGroup): Group(hGroup) {}
virtual bool LoadTexture(const char* filename, CPNGFile& dest)
{
char* buf;
size_t size;
if(!Group.LoadEntry(filename, &buf, &size, 1)) return false;
bool ret = dest.Load(reinterpret_cast<BYTE*>(buf), size);
delete[] buf;
return ret;
}
virtual StdStrBuf LoadSkeleton(const char* filename)
{
StdStrBuf ret;
if(!Group.LoadEntryString(filename, ret)) return StdStrBuf();
return ret;
}
private:
C4Group& Group;
};
//-------------------------------- C4DefGraphics ----------------------------------------------- //-------------------------------- C4DefGraphics -----------------------------------------------
C4DefGraphics::C4DefGraphics(C4Def *pOwnDef) C4DefGraphics::C4DefGraphics(C4Def *pOwnDef)
@ -49,6 +78,7 @@ C4DefGraphics::C4DefGraphics(C4Def *pOwnDef)
// store def // store def
pDef = pOwnDef; pDef = pOwnDef;
// zero fields // zero fields
Type = TYPE_Bitmap;
Bitmap = BitmapClr = NULL; Bitmap = BitmapClr = NULL;
pNext = NULL; pNext = NULL;
fColorBitmapAutoCreated = false; fColorBitmapAutoCreated = false;
@ -64,8 +94,17 @@ C4DefGraphics *C4DefGraphics::GetLast()
void C4DefGraphics::Clear() void C4DefGraphics::Clear()
{ {
// zero own fields // zero own fields
if (BitmapClr) { delete BitmapClr; BitmapClr=NULL; } switch (Type)
if (Bitmap) { delete Bitmap; Bitmap=NULL; } {
case TYPE_Bitmap:
if (BitmapClr) { delete BitmapClr; BitmapClr=NULL; }
if (Bitmap) { delete Bitmap; Bitmap=NULL; }
break;
case TYPE_Mesh:
if (Mesh) { delete Mesh; Mesh = NULL; }
break;
}
// delete additonal graphics // delete additonal graphics
C4AdditionalDefGraphics *pGrp2N = pNext, *pGrp2; C4AdditionalDefGraphics *pGrp2N = pNext, *pGrp2;
while (pGrp2=pGrp2N) { pGrp2N = pGrp2->pNext; pGrp2->pNext = NULL; delete pGrp2; } while (pGrp2=pGrp2N) { pGrp2N = pGrp2->pNext; pGrp2->pNext = NULL; delete pGrp2; }
@ -116,17 +155,74 @@ bool C4DefGraphics::LoadBitmap(C4Group &hGroup, const char *szFilename, const ch
if (!BitmapClr->CreateColorByOwner(Bitmap)) return false; if (!BitmapClr->CreateColorByOwner(Bitmap)) return false;
fColorBitmapAutoCreated = true; fColorBitmapAutoCreated = true;
} }
Type = TYPE_Bitmap;
// success // success
return true; return true;
} }
bool C4DefGraphics::LoadBitmaps(C4Group &hGroup, bool fColorByOwner) bool C4DefGraphics::LoadMesh(C4Group &hGroup, StdMeshSkeletonLoader& loader)
{
char* buf;
size_t size;
if(!hGroup.LoadEntry(C4CFN_DefMesh, &buf, &size, 1)) return false;
Mesh = new StdMesh;
bool result;
try
{ {
Mesh->InitXML(C4CFN_DefMesh, buf, loader, Game.MaterialManager);
result = true;
}
catch(const StdMeshError& ex)
{
DebugLogF("Failed to load mesh: %s\n", ex.what());
result = false;
}
delete[] buf;
if(!result)
{
delete Mesh;
Mesh = NULL;
return false;
}
Type = TYPE_Mesh;
return true;
}
bool C4DefGraphics::Load(C4Group &hGroup, bool fColorByOwner)
{
char Filename[_MAX_PATH+1]; *Filename=0;
AdditionalRessourcesLoader loader(hGroup);
// Load all materials for this definition:
hGroup.ResetSearch();
while (hGroup.FindNextEntry(C4CFN_DefMaterials, Filename, NULL, NULL, !!*Filename))
{
StdStrBuf material;
if(hGroup.LoadEntryString(Filename, material))
{
try
{
Game.MaterialManager.Parse(material.getData(), Filename, loader);
}
catch(const StdMeshMaterialError& ex)
{
DebugLogF("Failed to read material script: %s\n", ex.what());
}
}
}
// Try from Mesh first
if (LoadMesh(hGroup, loader)) return true;
// load basic graphics // load basic graphics
if (!LoadBitmap(hGroup, C4CFN_DefGraphics, C4CFN_DefGraphicsPNG, C4CFN_ClrByOwnerPNG, fColorByOwner)) return false; if (!LoadBitmap(hGroup, C4CFN_DefGraphics, C4CFN_DefGraphicsPNG, C4CFN_ClrByOwnerPNG, fColorByOwner)) return false;
// load additional graphics // load additional graphics
// first, search all png-graphics in NewGfx // first, search all png-graphics in NewGfx
char Filename[_MAX_PATH+1]; *Filename=0;
C4DefGraphics *pLastGraphics = this; C4DefGraphics *pLastGraphics = this;
int32_t iWildcardPos; int32_t iWildcardPos;
iWildcardPos = SCharPos('*', C4CFN_DefGraphicsExPNG); iWildcardPos = SCharPos('*', C4CFN_DefGraphicsExPNG);
@ -229,6 +325,8 @@ bool C4DefGraphics::LoadBitmaps(C4Group &hGroup, bool fColorByOwner)
bool C4DefGraphics::ColorizeByMaterial(int32_t iMat, C4MaterialMap &rMats, BYTE bGBM) bool C4DefGraphics::ColorizeByMaterial(int32_t iMat, C4MaterialMap &rMats, BYTE bGBM)
{ {
if(Type != TYPE_Bitmap) return false;
SURFACE sfcBitmap = GetBitmap(); // first bitmap only SURFACE sfcBitmap = GetBitmap(); // first bitmap only
if (sfcBitmap) if (sfcBitmap)
{ {
@ -265,6 +363,7 @@ C4PortraitGraphics *C4PortraitGraphics::Get(const char *szGrpName)
bool C4DefGraphics::CopyGraphicsFrom(C4DefGraphics &rSource) bool C4DefGraphics::CopyGraphicsFrom(C4DefGraphics &rSource)
{ {
if (Type != TYPE_Bitmap) return false; // TODO!
// clear previous // clear previous
if (BitmapClr) { delete BitmapClr; BitmapClr=NULL; } if (BitmapClr) { delete BitmapClr; BitmapClr=NULL; }
if (Bitmap) { delete Bitmap; Bitmap=NULL; } if (Bitmap) { delete Bitmap; Bitmap=NULL; }
@ -291,6 +390,7 @@ bool C4DefGraphics::CopyGraphicsFrom(C4DefGraphics &rSource)
void C4DefGraphics::DrawClr(C4Facet &cgo, BOOL fAspect, DWORD dwClr) void C4DefGraphics::DrawClr(C4Facet &cgo, BOOL fAspect, DWORD dwClr)
{ {
if(Type != TYPE_Bitmap) return; // TODO
// create facet and draw it // create facet and draw it
C4Surface *pSfc = BitmapClr ? BitmapClr : Bitmap; if (!pSfc) return; C4Surface *pSfc = BitmapClr ? BitmapClr : Bitmap; if (!pSfc) return;
C4Facet fct(pSfc, 0,0,pSfc->Wdt, pSfc->Hgt); C4Facet fct(pSfc, 0,0,pSfc->Wdt, pSfc->Hgt);
@ -507,7 +607,7 @@ bool C4Portrait::Link(C4DefGraphics *pGfxPortrait)
bool C4Portrait::SavePNG(C4Group &rGroup, const char *szFilename, const char *szOverlayFN) bool C4Portrait::SavePNG(C4Group &rGroup, const char *szFilename, const char *szOverlayFN)
{ {
// safety // safety
if (!pGfxPortrait || !szFilename || !pGfxPortrait->Bitmap) return false; if (!pGfxPortrait || !szFilename || pGfxPortrait->Type != C4DefGraphics::TYPE_Bitmap || !pGfxPortrait->Bitmap) return false;
// save files // save files
if (pGfxPortrait->fColorBitmapAutoCreated) if (pGfxPortrait->fColorBitmapAutoCreated)
{ {
@ -616,6 +716,7 @@ void C4GraphicsOverlay::UpdateFacet()
if (eMode == MODE_Object) return; if (eMode == MODE_Object) return;
// otherwise, source graphics must be specified // otherwise, source graphics must be specified
if (!pSourceGfx) return; if (!pSourceGfx) return;
if (pSourceGfx->Type != C4DefGraphics::TYPE_Bitmap) return;
C4Def *pDef = pSourceGfx->pDef; C4Def *pDef = pSourceGfx->pDef;
assert(pDef); assert(pDef);
fZoomToShape = false; fZoomToShape = false;

View File

@ -594,6 +594,7 @@ void C4Game::Clear()
KeyboardInput.Clear(); KeyboardInput.Clear();
SetMusicLevel(100); SetMusicLevel(100);
PlayList.Clear(); PlayList.Clear();
MaterialManager.Clear();
// global fullscreen class is not cleared, because it holds the carrier window // global fullscreen class is not cleared, because it holds the carrier window
// but the menu must be cleared (maybe move Fullscreen.Menu somewhere else?) // but the menu must be cleared (maybe move Fullscreen.Menu somewhere else?)

View File

@ -157,6 +157,7 @@ void C4Object::Default()
pLayer=NULL; pLayer=NULL;
pSolidMaskData=NULL; pSolidMaskData=NULL;
pGraphics=NULL; pGraphics=NULL;
pMeshInstance=NULL;
pDrawTransform=NULL; pDrawTransform=NULL;
pEffects=NULL; pEffects=NULL;
FirstRef=NULL; FirstRef=NULL;
@ -186,6 +187,10 @@ BOOL C4Object::Init(C4Def *pDef, C4Object *pCreator,
// graphics // graphics
pGraphics = &Def->Graphics; pGraphics = &Def->Graphics;
if(pGraphics->Type == C4DefGraphics::TYPE_Mesh)
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
else
pMeshInstance = NULL;
BlitMode = Def->BlitMode; BlitMode = Def->BlitMode;
// Position // Position
@ -418,6 +423,13 @@ void C4Object::UpdateGraphics(bool fGraphicsChanged, bool fTemp)
// ensure SolidMask-rect lies within new graphics-rect // ensure SolidMask-rect lies within new graphics-rect
CheckSolidMaskRect(); CheckSolidMaskRect();
} }
delete pMeshInstance;
if(pGraphics->Type == C4DefGraphics::TYPE_Mesh)
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
else
pMeshInstance = NULL;
// update face - this also puts any SolidMask // update face - this also puts any SolidMask
UpdateFace(false); UpdateFace(false);
} }
@ -459,6 +471,25 @@ void C4Object::UpdateFlipDir()
} }
} }
void C4Object::DrawFaceImpl(C4TargetFacet &cgo, bool action, float fx, float fy, float fwdt, float fhgt, float tx, float ty, float twdt, float thgt, C4DrawTransform* transform)
{
CSurface* sfc;
switch(GetGraphics()->Type)
{
case C4DefGraphics::TYPE_Bitmap:
sfc = action ? Action.Facet.Surface : GetGraphics()->GetBitmap(Color);
lpDDraw->Blit(sfc,
fx, fy, fwdt, fhgt,
cgo.Surface, tx, ty, twdt, thgt,
TRUE, transform);
break;
case C4DefGraphics::TYPE_Mesh:
lpDDraw->RenderMesh(*pMeshInstance, cgo.Surface, tx, ty, twdt, thgt);
break;
}
}
void C4Object::DrawFace(C4TargetFacet &cgo, float offX, float offY, int32_t iPhaseX, int32_t iPhaseY) void C4Object::DrawFace(C4TargetFacet &cgo, float offX, float offY, int32_t iPhaseX, int32_t iPhaseY)
{ {
const float swdt = float(Def->Shape.Wdt); const float swdt = float(Def->Shape.Wdt);
@ -488,10 +519,11 @@ void C4Object::DrawFace(C4TargetFacet &cgo, float offX, float offY, int32_t iPha
// Straight // Straight
if ((!Def->Rotateable || (r==0)) && !pDrawTransform) if ((!Def->Rotateable || (r==0)) && !pDrawTransform)
{ {
lpDDraw->Blit(GetGraphics()->GetBitmap(Color), DrawFaceImpl(cgo, false, fx, fy, fwdt, fhgt, tx, ty, twdt, thgt, NULL);
/* lpDDraw->Blit(GetGraphics()->GetBitmap(Color),
fx, fy, fwdt, fhgt, fx, fy, fwdt, fhgt,
cgo.Surface, tx, ty, twdt, thgt, cgo.Surface, tx, ty, twdt, thgt,
TRUE, NULL); TRUE, NULL);*/
} }
// Rotated or transformed // Rotated or transformed
else else
@ -506,10 +538,11 @@ void C4Object::DrawFace(C4TargetFacet &cgo, float offX, float offY, int32_t iPha
{ {
rot.SetRotate(r * 100, offX, offY); rot.SetRotate(r * 100, offX, offY);
} }
lpDDraw->Blit(GetGraphics()->GetBitmap(Color), DrawFaceImpl(cgo, false, fx, fy, fwdt, fhgt, tx, ty, twdt, thgt, &rot);
/* lpDDraw->Blit(GetGraphics()->GetBitmap(Color),
fx, fy, fwdt, fhgt, fx, fy, fwdt, fhgt,
cgo.Surface, tx, ty, twdt, thgt, cgo.Surface, tx, ty, twdt, thgt,
TRUE, &rot); TRUE, &rot);*/
} }
} }
@ -554,10 +587,11 @@ void C4Object::DrawActionFace(C4TargetFacet &cgo, float offX, float offY)
// Straight // Straight
if ((!Def->Rotateable || (r==0)) && !pDrawTransform) if ((!Def->Rotateable || (r==0)) && !pDrawTransform)
{ {
lpDDraw->Blit(Action.Facet.Surface, DrawFaceImpl(cgo, true, fx, fy, fwdt, fhgt, tx, ty, twdt, thgt, NULL);
/*lpDDraw->Blit(Action.Facet.Surface,
fx, fy, fwdt, fhgt, fx, fy, fwdt, fhgt,
cgo.Surface, tx, ty, twdt, thgt, cgo.Surface, tx, ty, twdt, thgt,
TRUE, NULL); TRUE, NULL);*/
} }
// Rotated or transformed // Rotated or transformed
else else
@ -574,10 +608,11 @@ void C4Object::DrawActionFace(C4TargetFacet &cgo, float offX, float offY)
{ {
rot.SetRotate(r * 100, offX, offY); rot.SetRotate(r * 100, offX, offY);
} }
lpDDraw->Blit(Action.Facet.Surface, DrawFaceImpl(cgo, true, fx, fy, fwdt, fhgt, tx, ty, twdt, thgt, &rot);
/* lpDDraw->Blit(Action.Facet.Surface,
fx, fy, fwdt, fhgt, fx, fy, fwdt, fhgt,
cgo.Surface, tx, ty, twdt, thgt, cgo.Surface, tx, ty, twdt, thgt,
TRUE, &rot); TRUE, &rot);*/
} }
} }
@ -2264,7 +2299,8 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode)
{ if (FrontParticles && !Contained) FrontParticles.Draw(cgo,this); return; } { if (FrontParticles && !Contained) FrontParticles.Draw(cgo,this); return; }
// ensure correct color is set // ensure correct color is set
if (GetGraphics()->BitmapClr) GetGraphics()->BitmapClr->SetClr(Color); if (GetGraphics()->Type == C4DefGraphics::TYPE_Bitmap)
if (GetGraphics()->BitmapClr) GetGraphics()->BitmapClr->SetClr(Color);
// Debug Display ////////////////////////////////////////////////////////////////////// // Debug Display //////////////////////////////////////////////////////////////////////
if (::GraphicsSystem.ShowCommand && !eDrawMode) if (::GraphicsSystem.ShowCommand && !eDrawMode)
@ -2416,7 +2452,7 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode)
(fixtof(Action.Target->fix_y) + Action.Target->Shape.GetY()) - (fixtof(fix_y) + Shape.GetY() + Action.FacetY), (fixtof(Action.Target->fix_y) + Action.Target->Shape.GetY()) - (fixtof(fix_y) + Shape.GetY() + Action.FacetY),
TRUE); TRUE);
} }
else if (Action.Facet.Surface) else if (Action.Facet.Surface || GetGraphics()->Type != C4DefGraphics::TYPE_Bitmap)
DrawActionFace(cgo, offX, offY); DrawActionFace(cgo, offX, offY);
} }
@ -3185,7 +3221,7 @@ void C4Object::Clear()
if (pEffects) { delete pEffects; pEffects=NULL; } if (pEffects) { delete pEffects; pEffects=NULL; }
if (FrontParticles) FrontParticles.Clear(); if (FrontParticles) FrontParticles.Clear();
if (BackParticles) BackParticles.Clear(); if (BackParticles) BackParticles.Clear();
if (pSolidMaskData) { delete pSolidMaskData; pSolidMaskData=NULL; } if (pSolidMaskData) { delete pSolidMaskData; pSolidMaskData=NULL; }
if (Menu) delete Menu; Menu=NULL; if (Menu) delete Menu; Menu=NULL;
if (MaterialContents) delete MaterialContents; MaterialContents=NULL; if (MaterialContents) delete MaterialContents; MaterialContents=NULL;
// clear commands! // clear commands!
@ -3196,7 +3232,8 @@ void C4Object::Clear()
} }
if (pDrawTransform) { delete pDrawTransform; pDrawTransform=NULL; } if (pDrawTransform) { delete pDrawTransform; pDrawTransform=NULL; }
if (pGfxOverlay) { delete pGfxOverlay; pGfxOverlay=NULL; } if (pGfxOverlay) { delete pGfxOverlay; pGfxOverlay=NULL; }
while (FirstRef) FirstRef->Set(0); if (pMeshInstance) { delete pMeshInstance; pMeshInstance = NULL; }
while (FirstRef) FirstRef->Set(0);
} }
BOOL C4Object::ContainedControl(BYTE byCom) BOOL C4Object::ContainedControl(BYTE byCom)
@ -3756,6 +3793,9 @@ void C4Object::SetSolidMask(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt,
bool C4Object::CheckSolidMaskRect() bool C4Object::CheckSolidMaskRect()
{ {
// SolidMasks are only supported for bitmap graphics
if(GetGraphics()->Type != C4DefGraphics::TYPE_Bitmap) return false;
// check NewGfx only, because invalid SolidMask-rects are OK in OldGfx // check NewGfx only, because invalid SolidMask-rects are OK in OldGfx
// the bounds-check is done in CStdDDraw::GetPixel() // the bounds-check is done in CStdDDraw::GetPixel()
CSurface *sfcGraphics = GetGraphics()->GetBitmap(); CSurface *sfcGraphics = GetGraphics()->GetBitmap();

View File

@ -27,6 +27,7 @@
#include <StdSurface8.h> #include <StdSurface8.h>
#include <StdFont.h> #include <StdFont.h>
#include <StdBuf.h> #include <StdBuf.h>
#include <StdMesh.h>
// texref-predef // texref-predef
class CStdDDraw; class CStdDDraw;
@ -295,7 +296,9 @@ class CStdDDraw
BOOL Blit(SURFACE sfcSource, float fx, float fy, float fwdt, float fhgt, BOOL Blit(SURFACE sfcSource, float fx, float fy, float fwdt, float fhgt,
SURFACE sfcTarget, float tx, float ty, float twdt, float thgt, SURFACE sfcTarget, float tx, float ty, float twdt, float thgt,
BOOL fSrcColKey=FALSE, CBltTransform *pTransform=NULL); BOOL fSrcColKey=FALSE, CBltTransform *pTransform=NULL);
BOOL RenderMesh(StdMeshInstance &instance, SURFACE sfcTarget, float tx, float ty, float twdt, float thgt);
virtual void PerformBlt(CBltData &rBltData, CTexRef *pTex, DWORD dwModClr, bool fMod2, bool fExact) = 0; virtual void PerformBlt(CBltData &rBltData, CTexRef *pTex, DWORD dwModClr, bool fMod2, bool fExact) = 0;
virtual void PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt) = 0;
BOOL Blit8(SURFACE sfcSource, int fx, int fy, int fwdt, int fhgt, // force 8bit-blit (inline) BOOL Blit8(SURFACE sfcSource, int fx, int fy, int fwdt, int fhgt, // force 8bit-blit (inline)
SURFACE sfcTarget, int tx, int ty, int twdt, int thgt, SURFACE sfcTarget, int tx, int ty, int twdt, int thgt,
BOOL fSrcColKey=FALSE, CBltTransform *pTransform=NULL); BOOL fSrcColKey=FALSE, CBltTransform *pTransform=NULL);

View File

@ -109,7 +109,8 @@ class CStdGL : public CStdDDraw
virtual CStdGLCtx *CreateContext(HWND hWindow, CStdApp *pApp); virtual CStdGLCtx *CreateContext(HWND hWindow, CStdApp *pApp);
#endif #endif
// Blit // Blit
void PerformBlt(CBltData &rBltData, CTexRef *pTex, DWORD dwModClr, bool fMod2, bool fExact); virtual void PerformBlt(CBltData &rBltData, CTexRef *pTex, DWORD dwModClr, bool fMod2, bool fExact);
virtual void PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt);
virtual void BlitLandscape(SURFACE sfcSource, SURFACE sfcSource2, SURFACE sfcLiquidAnimation, float fx, float fy, virtual void BlitLandscape(SURFACE sfcSource, SURFACE sfcSource2, SURFACE sfcLiquidAnimation, float fx, float fy,
SURFACE sfcTarget, float tx, float ty, float wdt, float hgt); SURFACE sfcTarget, float tx, float ty, float wdt, float hgt);
void FillBG(DWORD dwClr=0); void FillBG(DWORD dwClr=0);

View File

@ -41,6 +41,7 @@ public:
virtual bool PrepareRendering(SURFACE) { return true; } virtual bool PrepareRendering(SURFACE) { return true; }
virtual void FillBG(DWORD dwClr=0) { } virtual void FillBG(DWORD dwClr=0) { }
virtual void PerformBlt(CBltData &, CTexRef *, DWORD, bool, bool) { } virtual void PerformBlt(CBltData &, CTexRef *, DWORD, bool, bool) { }
virtual void PerformMesh(StdMeshInstance &, float, float, float, float) { }
virtual void PerformLine(SURFACE, float, float, float, float, DWORD) { } virtual void PerformLine(SURFACE, float, float, float, float, DWORD) { }
virtual void DrawQuadDw(SURFACE, float *, DWORD, DWORD, DWORD, DWORD) { } virtual void DrawQuadDw(SURFACE, float *, DWORD, DWORD, DWORD, DWORD) { }
virtual void PerformPix(SURFACE, float, float, DWORD) { } virtual void PerformPix(SURFACE, float, float, DWORD) { }

View File

@ -1050,6 +1050,26 @@ BOOL CStdDDraw::Blit(SURFACE sfcSource, float fx, float fy, float fwdt, float fh
return TRUE; return TRUE;
} }
BOOL CStdDDraw::RenderMesh(StdMeshInstance &instance, SURFACE sfcTarget, float tx, float ty, float twdt, float thgt)
{
// TODO: Emulate rendering
if (!sfcTarget->IsRenderTarget()) return FALSE;
// TODO: Clip
// prepare rendering to surface
if (!PrepareRendering(sfcTarget)) return FALSE;
// store current state
StoreStateBlock();
PerformMesh(instance, tx, ty, twdt, thgt);
// restore state
RestoreStateBlock();
// success
return TRUE;
}
BOOL CStdDDraw::Blit8(SURFACE sfcSource, int fx, int fy, int fwdt, int fhgt, BOOL CStdDDraw::Blit8(SURFACE sfcSource, int fx, int fy, int fwdt, int fhgt,
SURFACE sfcTarget, int tx, int ty, int twdt, int thgt, SURFACE sfcTarget, int tx, int ty, int twdt, int thgt,
BOOL fSrcColKey, CBltTransform *pTransform) BOOL fSrcColKey, CBltTransform *pTransform)

View File

@ -306,6 +306,82 @@ void CStdGL::PerformBlt(CBltData &rBltData, CTexRef *pTex, DWORD dwModClr, bool
} }
} }
void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt)
{
const StdMesh& mesh = instance.Mesh;
const StdMeshBox& box = mesh.GetBoundingBox();
glPushMatrix();
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glDisable(GL_BLEND); // TODO: Invert alpha instead in material loader
glEnable(GL_LIGHTING);
// TODO: Zoom, ClrMod, ...
//glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
// Scale so that the mesh fits in (tx,ty,twdt,thgt)
double rx = -box.x1 / (box.x2 - box.x1);
double ry = -box.y1 / (box.y2 - box.y1);
glTranslatef(tx + rx*twdt, ty + ry*thgt, 0.0f);
glScalef(twdt/(box.x2 - box.x1), thgt/(box.y2 - box.y1), 1.0f);
// Put a light source in front of the object
GLfloat light_position[] = { 0.0f, 0.0f, 6.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
// TODO: Find a working technique, we currently always use the
// first one:
const StdMeshMaterial& material = mesh.GetMaterial();
const StdMeshMaterialTechnique& technique = material.Techniques[0];
// Render each pass
for(unsigned int i = 0; i < technique.Passes.size(); ++i)
{
const StdMeshMaterialPass& pass = technique.Passes[i];
// Set up material
glMaterialfv(GL_FRONT, GL_AMBIENT, pass.Ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, pass.Diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, pass.Specular);
glMaterialfv(GL_FRONT, GL_EMISSION, pass.Emissive);
glMaterialf(GL_FRONT, GL_SHININESS, pass.Shininess);
// TODO: Set up texture units
// Render mesh
glBegin(GL_TRIANGLES);
for(unsigned int j = 0; j < mesh.GetNumFaces(); ++j)
{
const StdMeshFace& face = mesh.GetFace(j);
const StdMeshVertex& vtx1 = instance.GetVertex(face.Vertices[0]);
const StdMeshVertex& vtx2 = instance.GetVertex(face.Vertices[1]);
const StdMeshVertex& vtx3 = instance.GetVertex(face.Vertices[2]);
glTexCoord2f(vtx1.u, vtx1.v);
glNormal3f(vtx1.nx, vtx1.ny, vtx1.nz);
glVertex3f(vtx1.x, vtx1.y, vtx1.z);
glTexCoord2f(vtx2.u, vtx2.v);
glNormal3f(vtx2.nx, vtx2.ny, vtx2.nz);
glVertex3f(vtx2.x, vtx2.y, vtx2.z);
glTexCoord2f(vtx3.u, vtx3.v);
glNormal3f(vtx3.nx, vtx3.ny, vtx3.nz);
glVertex3f(vtx3.x, vtx3.y, vtx3.z);
}
glEnd(); // GL_TRIANGLES
}
glDisable(GL_LIGHT0);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glDisable(GL_NORMALIZE);
glEnable(GL_BLEND);
glPopMatrix();
// TODO: glScissor, so that we only clear the area the mesh covered.
glClear(GL_DEPTH_BUFFER_BIT);
}
void CStdGL::BlitLandscape(SURFACE sfcSource, SURFACE sfcSource2, SURFACE sfcLiquidAnimation, float fx, float fy, void CStdGL::BlitLandscape(SURFACE sfcSource, SURFACE sfcSource2, SURFACE sfcLiquidAnimation, float fx, float fy,
SURFACE sfcTarget, float tx, float ty, float wdt, float hgt) SURFACE sfcTarget, float tx, float ty, float wdt, float hgt)
{ {

View File

@ -116,6 +116,7 @@ bool CStdGLCtx::Select(bool verbose)
pGL->lpPrimary->Wdt=cx; pGL->lpPrimary->Hgt=cy; pGL->lpPrimary->Wdt=cx; pGL->lpPrimary->Hgt=cy;
// set some default states // set some default states
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glShadeModel(GL_FLAT); glShadeModel(GL_FLAT);
glDisable(GL_ALPHA_TEST); glDisable(GL_ALPHA_TEST);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
@ -266,6 +267,7 @@ bool CStdGLCtx::Select(bool verbose)
pGL->lpPrimary->Wdt=cx; pGL->lpPrimary->Hgt=cy; pGL->lpPrimary->Wdt=cx; pGL->lpPrimary->Hgt=cy;
// set some default states // set some default states
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glShadeModel(GL_FLAT); glShadeModel(GL_FLAT);
glDisable(GL_ALPHA_TEST); glDisable(GL_ALPHA_TEST);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);