forked from Mirrors/openclonk
Allow objects to use a mesh instead of pixel-based graphics
parent
a3f1ccf66e
commit
01f2da1366
|
@ -85,6 +85,8 @@
|
|||
#define C4CFN_IconPNG "Icon.png"
|
||||
#define C4CFN_ScenarioObjects "Objects.txt"
|
||||
#define C4CFN_ScenarioDesc "Desc%s.rtf"
|
||||
#define C4CFN_DefMaterials "*.material"
|
||||
#define C4CFN_DefMesh "Graphics.mesh.xml"
|
||||
#define C4CFN_DefGraphics "Graphics.bmp"
|
||||
#define C4CFN_DefGraphicsPNG "Graphics.png"
|
||||
#define C4CFN_ClrByOwnerPNG "Overlay.png"
|
||||
|
|
|
@ -44,16 +44,30 @@ class C4DefGraphics
|
|||
|
||||
C4DefGraphics *GetLast(); // get last graphics in list
|
||||
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
|
||||
|
||||
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
|
||||
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 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
|
||||
C4DefGraphics *Get(const char *szGrpName); // get graphics by name
|
||||
void Clear(); // clear fields; delete additional graphics
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#ifndef INC_C4Game
|
||||
#define INC_C4Game
|
||||
|
||||
|
||||
#include <StdMeshMaterial.h>
|
||||
#include <C4GameParameters.h>
|
||||
#include <C4PlayerInfo.h>
|
||||
#include <C4RoundResults.h>
|
||||
|
@ -82,7 +82,7 @@ class C4Game
|
|||
|
||||
C4PathFinder PathFinder;
|
||||
C4TransferZones TransferZones;
|
||||
C4Group ScenarioFile;
|
||||
C4Group ScenarioFile;
|
||||
C4GroupSet GroupSet;
|
||||
C4Group *pParentGroup;
|
||||
C4Extra Extra;
|
||||
|
@ -94,6 +94,7 @@ class C4Game
|
|||
#endif
|
||||
C4Scoreboard Scoreboard;
|
||||
C4VideoPlayer VideoPlayer;
|
||||
StdMeshMatManager MaterialManager;
|
||||
class C4Network2Stats *pNetworkStatistics; // may be NULL if no statistics are recorded
|
||||
class C4KeyboardInput &KeyboardInput;
|
||||
class C4FileMonitor *pFileMonitor;
|
||||
|
|
|
@ -178,6 +178,7 @@ class C4Object
|
|||
C4NotifyingObjectList Contents;
|
||||
C4MaterialList *MaterialContents; // SyncClearance-NoSave //
|
||||
C4DefGraphics *pGraphics; // currently set object graphics
|
||||
StdMeshInstance* pMeshInstance; // Instance for mesh-type objects
|
||||
C4Effect *pEffects; // linked list of effects
|
||||
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 DrawActionFace(C4TargetFacet &cgo, float offX, float offY);
|
||||
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 ClearPointers(C4Object *ptr);
|
||||
BOOL ExecMovement();
|
||||
|
|
|
@ -605,7 +605,7 @@ BOOL C4Def::Load(C4Group &hGroup,
|
|||
|
||||
// Read surface 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));
|
||||
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 (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)
|
||||
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?
|
||||
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();
|
||||
|
||||
// draw overlays
|
||||
|
|
|
@ -42,6 +42,35 @@
|
|||
#include <C4GameObjects.h>
|
||||
#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(C4Def *pOwnDef)
|
||||
|
@ -49,6 +78,7 @@ C4DefGraphics::C4DefGraphics(C4Def *pOwnDef)
|
|||
// store def
|
||||
pDef = pOwnDef;
|
||||
// zero fields
|
||||
Type = TYPE_Bitmap;
|
||||
Bitmap = BitmapClr = NULL;
|
||||
pNext = NULL;
|
||||
fColorBitmapAutoCreated = false;
|
||||
|
@ -64,8 +94,17 @@ C4DefGraphics *C4DefGraphics::GetLast()
|
|||
void C4DefGraphics::Clear()
|
||||
{
|
||||
// zero own fields
|
||||
if (BitmapClr) { delete BitmapClr; BitmapClr=NULL; }
|
||||
if (Bitmap) { delete Bitmap; Bitmap=NULL; }
|
||||
switch (Type)
|
||||
{
|
||||
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
|
||||
C4AdditionalDefGraphics *pGrp2N = pNext, *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;
|
||||
fColorBitmapAutoCreated = true;
|
||||
}
|
||||
Type = TYPE_Bitmap;
|
||||
// success
|
||||
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
|
||||
if (!LoadBitmap(hGroup, C4CFN_DefGraphics, C4CFN_DefGraphicsPNG, C4CFN_ClrByOwnerPNG, fColorByOwner)) return false;
|
||||
|
||||
// load additional graphics
|
||||
// first, search all png-graphics in NewGfx
|
||||
char Filename[_MAX_PATH+1]; *Filename=0;
|
||||
C4DefGraphics *pLastGraphics = this;
|
||||
int32_t iWildcardPos;
|
||||
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)
|
||||
{
|
||||
if(Type != TYPE_Bitmap) return false;
|
||||
|
||||
SURFACE sfcBitmap = GetBitmap(); // first bitmap only
|
||||
if (sfcBitmap)
|
||||
{
|
||||
|
@ -265,6 +363,7 @@ C4PortraitGraphics *C4PortraitGraphics::Get(const char *szGrpName)
|
|||
|
||||
bool C4DefGraphics::CopyGraphicsFrom(C4DefGraphics &rSource)
|
||||
{
|
||||
if (Type != TYPE_Bitmap) return false; // TODO!
|
||||
// clear previous
|
||||
if (BitmapClr) { delete BitmapClr; BitmapClr=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)
|
||||
{
|
||||
if(Type != TYPE_Bitmap) return; // TODO
|
||||
// create facet and draw it
|
||||
C4Surface *pSfc = BitmapClr ? BitmapClr : Bitmap; if (!pSfc) return;
|
||||
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)
|
||||
{
|
||||
// safety
|
||||
if (!pGfxPortrait || !szFilename || !pGfxPortrait->Bitmap) return false;
|
||||
if (!pGfxPortrait || !szFilename || pGfxPortrait->Type != C4DefGraphics::TYPE_Bitmap || !pGfxPortrait->Bitmap) return false;
|
||||
// save files
|
||||
if (pGfxPortrait->fColorBitmapAutoCreated)
|
||||
{
|
||||
|
@ -616,6 +716,7 @@ void C4GraphicsOverlay::UpdateFacet()
|
|||
if (eMode == MODE_Object) return;
|
||||
// otherwise, source graphics must be specified
|
||||
if (!pSourceGfx) return;
|
||||
if (pSourceGfx->Type != C4DefGraphics::TYPE_Bitmap) return;
|
||||
C4Def *pDef = pSourceGfx->pDef;
|
||||
assert(pDef);
|
||||
fZoomToShape = false;
|
||||
|
|
|
@ -594,6 +594,7 @@ void C4Game::Clear()
|
|||
KeyboardInput.Clear();
|
||||
SetMusicLevel(100);
|
||||
PlayList.Clear();
|
||||
MaterialManager.Clear();
|
||||
|
||||
// global fullscreen class is not cleared, because it holds the carrier window
|
||||
// but the menu must be cleared (maybe move Fullscreen.Menu somewhere else?)
|
||||
|
|
|
@ -157,6 +157,7 @@ void C4Object::Default()
|
|||
pLayer=NULL;
|
||||
pSolidMaskData=NULL;
|
||||
pGraphics=NULL;
|
||||
pMeshInstance=NULL;
|
||||
pDrawTransform=NULL;
|
||||
pEffects=NULL;
|
||||
FirstRef=NULL;
|
||||
|
@ -186,6 +187,10 @@ BOOL C4Object::Init(C4Def *pDef, C4Object *pCreator,
|
|||
|
||||
// graphics
|
||||
pGraphics = &Def->Graphics;
|
||||
if(pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
||||
else
|
||||
pMeshInstance = NULL;
|
||||
BlitMode = Def->BlitMode;
|
||||
|
||||
// Position
|
||||
|
@ -418,6 +423,13 @@ void C4Object::UpdateGraphics(bool fGraphicsChanged, bool fTemp)
|
|||
// ensure SolidMask-rect lies within new graphics-rect
|
||||
CheckSolidMaskRect();
|
||||
}
|
||||
|
||||
delete pMeshInstance;
|
||||
if(pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
||||
else
|
||||
pMeshInstance = NULL;
|
||||
|
||||
// update face - this also puts any SolidMask
|
||||
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)
|
||||
{
|
||||
const float swdt = float(Def->Shape.Wdt);
|
||||
|
@ -488,10 +519,11 @@ void C4Object::DrawFace(C4TargetFacet &cgo, float offX, float offY, int32_t iPha
|
|||
// Straight
|
||||
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,
|
||||
cgo.Surface, tx, ty, twdt, thgt,
|
||||
TRUE, NULL);
|
||||
TRUE, NULL);*/
|
||||
}
|
||||
// Rotated or transformed
|
||||
else
|
||||
|
@ -506,10 +538,11 @@ void C4Object::DrawFace(C4TargetFacet &cgo, float offX, float offY, int32_t iPha
|
|||
{
|
||||
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,
|
||||
cgo.Surface, tx, ty, twdt, thgt,
|
||||
TRUE, &rot);
|
||||
TRUE, &rot);*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -554,10 +587,11 @@ void C4Object::DrawActionFace(C4TargetFacet &cgo, float offX, float offY)
|
|||
// Straight
|
||||
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,
|
||||
cgo.Surface, tx, ty, twdt, thgt,
|
||||
TRUE, NULL);
|
||||
TRUE, NULL);*/
|
||||
}
|
||||
// Rotated or transformed
|
||||
else
|
||||
|
@ -574,10 +608,11 @@ void C4Object::DrawActionFace(C4TargetFacet &cgo, float offX, float 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,
|
||||
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; }
|
||||
|
||||
// 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 //////////////////////////////////////////////////////////////////////
|
||||
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),
|
||||
TRUE);
|
||||
}
|
||||
else if (Action.Facet.Surface)
|
||||
else if (Action.Facet.Surface || GetGraphics()->Type != C4DefGraphics::TYPE_Bitmap)
|
||||
DrawActionFace(cgo, offX, offY);
|
||||
}
|
||||
|
||||
|
@ -3185,7 +3221,7 @@ void C4Object::Clear()
|
|||
if (pEffects) { delete pEffects; pEffects=NULL; }
|
||||
if (FrontParticles) FrontParticles.Clear();
|
||||
if (BackParticles) BackParticles.Clear();
|
||||
if (pSolidMaskData) { delete pSolidMaskData; pSolidMaskData=NULL; }
|
||||
if (pSolidMaskData) { delete pSolidMaskData; pSolidMaskData=NULL; }
|
||||
if (Menu) delete Menu; Menu=NULL;
|
||||
if (MaterialContents) delete MaterialContents; MaterialContents=NULL;
|
||||
// clear commands!
|
||||
|
@ -3196,7 +3232,8 @@ void C4Object::Clear()
|
|||
}
|
||||
if (pDrawTransform) { delete pDrawTransform; pDrawTransform=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)
|
||||
|
@ -3756,6 +3793,9 @@ void C4Object::SetSolidMask(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt,
|
|||
|
||||
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
|
||||
// the bounds-check is done in CStdDDraw::GetPixel()
|
||||
CSurface *sfcGraphics = GetGraphics()->GetBitmap();
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <StdSurface8.h>
|
||||
#include <StdFont.h>
|
||||
#include <StdBuf.h>
|
||||
#include <StdMesh.h>
|
||||
|
||||
// texref-predef
|
||||
class CStdDDraw;
|
||||
|
@ -295,7 +296,9 @@ class CStdDDraw
|
|||
BOOL Blit(SURFACE sfcSource, float fx, float fy, float fwdt, float fhgt,
|
||||
SURFACE sfcTarget, float tx, float ty, float twdt, float thgt,
|
||||
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 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)
|
||||
SURFACE sfcTarget, int tx, int ty, int twdt, int thgt,
|
||||
BOOL fSrcColKey=FALSE, CBltTransform *pTransform=NULL);
|
||||
|
|
|
@ -109,7 +109,8 @@ class CStdGL : public CStdDDraw
|
|||
virtual CStdGLCtx *CreateContext(HWND hWindow, CStdApp *pApp);
|
||||
#endif
|
||||
// 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,
|
||||
SURFACE sfcTarget, float tx, float ty, float wdt, float hgt);
|
||||
void FillBG(DWORD dwClr=0);
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
virtual bool PrepareRendering(SURFACE) { return true; }
|
||||
virtual void FillBG(DWORD dwClr=0) { }
|
||||
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 DrawQuadDw(SURFACE, float *, DWORD, DWORD, DWORD, DWORD) { }
|
||||
virtual void PerformPix(SURFACE, float, float, DWORD) { }
|
||||
|
|
|
@ -1050,6 +1050,26 @@ BOOL CStdDDraw::Blit(SURFACE sfcSource, float fx, float fy, float fwdt, float fh
|
|||
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,
|
||||
SURFACE sfcTarget, int tx, int ty, int twdt, int thgt,
|
||||
BOOL fSrcColKey, CBltTransform *pTransform)
|
||||
|
|
|
@ -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,
|
||||
SURFACE sfcTarget, float tx, float ty, float wdt, float hgt)
|
||||
{
|
||||
|
|
|
@ -116,6 +116,7 @@ bool CStdGLCtx::Select(bool verbose)
|
|||
pGL->lpPrimary->Wdt=cx; pGL->lpPrimary->Hgt=cy;
|
||||
// set some default states
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glShadeModel(GL_FLAT);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
@ -266,6 +267,7 @@ bool CStdGLCtx::Select(bool verbose)
|
|||
pGL->lpPrimary->Wdt=cx; pGL->lpPrimary->Hgt=cy;
|
||||
// set some default states
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glShadeModel(GL_FLAT);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
|
Loading…
Reference in New Issue