Normal map support for lights

- The light direction change isn't really consistent, as I can only give
  GL the vectors at the triangle edges. So for deep rays, the light
  distribution often ends up being significantly different than for short
  rays.

- I *am* distorting the normal map vectors, quite badly actually. I'll leave
  it for the moment, because it definetely looks best for the light vectors,
  but I will have to correct that a bit once I have the time.
issue1247
Peter Wortmann 2012-09-05 21:51:25 +01:00
parent 18c8af73a8
commit d1c28227f3
8 changed files with 230 additions and 143 deletions

View File

@ -54,6 +54,13 @@ float queryMatMap(int pix)
#endif
}
float dotc(vec2 v1, vec2 v2)
{
vec3 v1p = normalize(vec3(v1, 0.3));
vec3 v2p = normalize(vec3(v2, 0.3));
return dot(v1p, v2p);
}
void main()
{
@ -112,19 +119,21 @@ void main()
vec4 lopx = texture2D(landscapeTex[0], otherCoo);
// Get material pixels
float mi = queryMatMap(f2i(lpx.r));
vec4 mpx = texture3D(materialTex, vec3(texCoo * resolution / vec2(512.0, 512.0) * vec2(4.0, 4.0), mi));
vec2 tcoo = texCoo * resolution / vec2(512.0, 512.0) * vec2(4.0, 4.0);
vec4 mpx = texture3D(materialTex, vec3(tcoo, mi));
vec4 npx = texture3D(materialTex, vec3(tcoo, mi+0.5));
float omi = queryMatMap(f2i(lopx.r));
vec4 ompx = texture3D(materialTex, vec3(texCoo * resolution / vec2(512.0, 512.0) * vec2(4.0, 4.0), omi));
vec4 ompx = texture3D(materialTex, vec3(tcoo, omi));
// Brightness
float ambientBright = texture2D(lightTex, gl_TexCoord[1].st).r*2.0, shadeBright = ambientBright;
vec2 normal = (2.0 * mix(rlpx.yz, lpx.yz, spx.a) - vec2(1.0, 1.0));
vec2 normal2 = (2.0 * lopx.yz - vec2(1.0, 1.0));
float bright = ambientBright + shadeBright * dot(normal, vec2(0.0, -1.0));
float bright2 = ambientBright + shadeBright * dot(normal2, vec2(0.0, -1.0));
// Brightness
vec4 lipx = texture2D(lightTex, gl_TexCoord[1].st);
float ambientBright = lipx.r, shadeBright = ambientBright;
vec2 normal = (mix(rlpx.yz, lpx.yz, spx.a) + npx.xy - vec2(1.0, 1.0));
vec2 normal2 = (lopx.yz + npx.xy - vec2(1.0, 1.0));
vec2 light_dir = vec2(1.0, 1.0) - lipx.yz * 3;
float bright = 2.0 * shadeBright * dotc(normal, light_dir);
float bright2 = 2.0 * shadeBright * dotc(normal2, light_dir);
gl_FragColor = mix(
vec4(bright2 * ompx.rgb, ompx.a),

View File

@ -230,7 +230,7 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
// Update FoW
if (pFoW)
{
pFoW->Set(C4Rect(
pFoW->Update(C4Rect(
int32_t(cgo.TargetX), int32_t(cgo.TargetY),
cgo.Wdt + 1, cgo.Hgt + 1));
@ -264,6 +264,8 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
// Draw overlay
if (!Game.C4S.Head.Film || !Game.C4S.Head.Replay) Game.DrawCursors(cgo, Player);
//pFoW->Render(&cgo);
if (fDrawOverlay)
{
// Determine zoom of overlay
@ -626,7 +628,7 @@ bool C4Viewport::Init(int32_t iPlayer, bool fSetTempOnly)
}
// Initialize FoW
if (::Landscape.pFoW)
pFoW = new C4FoWRegion(::Landscape.pFoW);
pFoW = new C4FoWRegion(::Landscape.pFoW, ::Players.Get(iPlayer));
return true;
}

View File

@ -617,8 +617,9 @@ void C4FoWRay::Prune(int32_t y)
iRightEndY = y;
}
C4FoWRegion::C4FoWRegion(C4FoW *pFoW)
C4FoWRegion::C4FoWRegion(C4FoW *pFoW, C4Player *pPlayer)
: pFoW(pFoW)
, pPlayer(pPlayer)
, hFrameBufDraw(0), hFrameBufRead(0)
, Region(0,0,0,0), OldRegion(0,0,0,0)
, pSurface(NULL), pBackSurface(NULL)
@ -630,7 +631,7 @@ C4FoWRegion::~C4FoWRegion()
Clear();
}
bool C4FoWRegion::Create()
bool C4FoWRegion::BindFramebuf()
{
// Flip texture
@ -691,6 +692,12 @@ void C4FoWRegion::Clear()
delete pBackSurface; pBackSurface = NULL;
}
void C4FoWRegion::Update(C4Rect r)
{
// Set the new region
Region = r;
}
void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
{
// Update FoW at interesting location
@ -705,7 +712,7 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
// Create & bind the frame buffer
pDraw->StorePrimaryClipper();
if(!Create())
if(!BindFramebuf())
{
pDraw->RestorePrimaryClipper();
return;
@ -722,8 +729,8 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
gluOrtho2D(0, getSurface()->Wdt, getSurface()->Hgt, 0);
// Clear texture contents
glClearColor(0.0, 0.0, 0.0, 1.0);
//glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.5f/1.5f, 0.5f/1.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Copy over the old state
if (OldRegion.Wdt > 0) {
@ -734,29 +741,33 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
dy1 = Region.y + Region.Hgt - OldRegion.y - OldRegion.Hgt;
glBlitFramebufferEXT(
Max(0, -dx0), Max(0, -dy0),
OldRegion.Wdt - Max(0, -dx1), OldRegion.Hgt - Max(0, -dy1),
Max(0, dx0), Max(0, dy0),
Region.Wdt - Max(0, dx1), Region.Hgt - Max(0, dy1),
Max(0, dx0), Max(0, -dy1),
OldRegion.Wdt - Max(0, -dx1), OldRegion.Hgt - Max(0, dy0),
Max(0, -dx0), Max(0, dy1),
Region.Wdt - Max(0, dx1), Region.Hgt - Max(0, -dy0),
GL_COLOR_BUFFER_BIT, GL_LINEAR);
glCheck();
// Fade out
glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
glColor4f(0.0f, 0.0f, 0.0f, 0.8f);
// Fade out. Note we constantly vary the alpha factor all the time -
// this is barely visible but makes it a lot less likely that we
// hit cases where we add the same thing every time, but still don't
// converge to the same color due to rounding.
int iAdd = (Game.FrameCounter/3) % 2;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.0f, 0.5f/1.5f, 0.5f/1.5f, 1.0f/16.0f+iAdd*1.0f/256.0f);
glBegin(GL_QUADS);
glVertex2i(0, 0);
glVertex2i(getSurface()->Wdt, 0);
glVertex2i(getSurface()->Wdt, getSurface()->Hgt);
glVertex2i(0, getSurface()->Hgt);
glEnd();
}
}
// Render FoW to frame buffer object
glBlendFunc(GL_ONE, GL_ONE);
pFoW->Render(this);
// Done!
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glMatrixMode(GL_PROJECTION);
@ -1265,112 +1276,168 @@ void C4FoWLightSection::Render(C4FoWRegion *pRegion, const C4TargetFacet *pOnScr
}
}
// Draw the fan
#define LIGHT if(pOnScreen) glColor3f(1.0f, 0.0f, 0.0f); else glColor3f(0.1f, 0.1f, 0.1f)
#define DARK if(pOnScreen) glColor3f(0.5f, 0.5f, 0.0f); else glColor3f(0.0f, 0.0f, 0.0f)
#define BEGIN_TRIANGLE if(pOnScreen) glBegin(GL_LINE_LOOP)
#define END_TRIANGLE if(pOnScreen) glEnd()
LIGHT;
glShadeModel(GL_FLAT);
glBegin(pOnScreen ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
if (!pOnScreen)
glVertex2f(float(pLight->getX() - pRegion->getRegion().x),
float(pLight->getY() - pRegion->getRegion().y));
for (i = 0; i < iRayCnt; i++) {
if (i == 0 || gFanRX[i-1] != gFanLX[i] || gFanRY[i-1] != gFanLY[i])
glVertex2f(gFanLX[i], gFanLY[i]);
if (gFanLX[i] != gFanRX[i] || gFanLY[i] != gFanRY[i])
glVertex2f(gFanRX[i], gFanRY[i]);
}
glEnd();
// Calculate position of the light in the buffer
float gLightX = transX(0,0) - pRegion->getRegion().x,
gLightY = transY(0,0) - pRegion->getRegion().y;
// Draw the fade
glShadeModel(GL_SMOOTH);
if(!pOnScreen) glBegin(GL_TRIANGLES);
// Here's the master plan for updating the lights texture. We
// want to add intensity (R channel) as well as the normal (GB channels).
// Normals are obviously meant to be though of as signed, though,
// so the equation we want would be something like
//
// R_new = BoundBy(R_old + R, 0.0, 1.0)
// G_new = BoundBy(G_old + G - 0.5, 0.0, 1.0)
// B_new = BoundBy(B_old + B - 0.5, 0.0, 1.0)
//
// It seems we can't get that directly though - glBlendFunc only talks
// about two operands. Even if we make two passes, we have to take
// care that that we don't over- or underflow in the intermediate pass.
//
// Therefore, we store G/1.5 instead of G, losing a bit of accuracy,
// but allowing us to formulate the following approximation without
// overflows:
//
// G_new = BoundBy(BoundBy(G_old + G / 1.5), 0.0, 1.0) - 0.5 / 1.5, 0.0, 1.0)
// B_new = BoundBy(BoundBy(B_old + B / 1.5), 0.0, 1.0) - 0.5 / 1.5, 0.0, 1.0)
for (i = 0; i < iRayCnt; i++) {
// Two passes
for(int iPass = 0; iPass < (pOnScreen ? 1 : 2); iPass++) {
// The quad. Will be empty if fan points match
if (gFanLX[i] != gFanRX[i] || gFanLY[i] != gFanRY[i]) {
// upper triangle
BEGIN_TRIANGLE;
LIGHT; glVertex2f(gFanLX[i], gFanLY[i]);
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
DARK; glVertex2f(gFadeLX[i], gFadeLY[i]);
END_TRIANGLE;
// lower triangle, if necessary
if (gFadeLX[i] != gFadeRX[i] || gFadeLY[i] != gFadeRY[i]) {
BEGIN_TRIANGLE;
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
DARK; glVertex2f(gFadeRX[i], gFadeRY[i]);
DARK; glVertex2f(gFadeLX[i], gFadeLY[i]);
END_TRIANGLE;
}
// Pass 2: Subtract
if (!pOnScreen && iPass == 1) {
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_ONE, GL_ONE);
}
// No intermediate fade for last point
if (i+1 >= iRayCnt) continue;
// Ascending?
if (fAscend[i]) {
// Lower fade triangle
BEGIN_TRIANGLE;
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
DARK; glVertex2f(gFadeIX[i], gFadeIY[i]);
DARK; glVertex2f(gFadeRX[i], gFadeRY[i]);
END_TRIANGLE;
// Intermediate fade triangle, if necessary
if (gFadeIY[i] != gFadeLY[i+1]) {
BEGIN_TRIANGLE;
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
DARK; glVertex2f(gFadeLX[i+1], gFadeLY[i+1]);
DARK; glVertex2f(gFadeIX[i], gFadeIY[i]);
END_TRIANGLE;
}
// Upper fade triangle
BEGIN_TRIANGLE;
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
LIGHT; glVertex2f(gFanLX[i+1], gFanLY[i+1]);
DARK; glVertex2f(gFadeLX[i+1], gFadeLY[i+1]);
END_TRIANGLE;
// Descending?
} else {
// Lower fade triangle
BEGIN_TRIANGLE;
LIGHT; glVertex2f(gFanLX[i+1], gFanLY[i+1]);
DARK; glVertex2f(gFadeLX[i+1], gFadeLY[i+1]);
DARK; glVertex2f(gFadeIX[i], gFadeIY[i]);
END_TRIANGLE;
// Intermediate fade triangle, if necessary
if (gFadeIY[i] != gFadeRY[i]) {
BEGIN_TRIANGLE;
LIGHT; glVertex2f(gFanLX[i+1], gFanLY[i+1]);
DARK; glVertex2f(gFadeIX[i], gFadeIY[i]);
DARK; glVertex2f(gFadeRX[i], gFadeRY[i]);
END_TRIANGLE;
}
// Upper fade triangle
BEGIN_TRIANGLE;
LIGHT; glVertex2f(gFanLX[i+1], gFanLY[i+1]);
DARK; glVertex2f(gFadeRX[i], gFadeRY[i]);
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
END_TRIANGLE;
// Help me! My brain can't program without local function definitions anymore!
#define VERTEX(x,y,light) \
if(pOnScreen) { \
if(light) glColor3f(1.0f, 0.0f, 0.0f); \
else glColor3f(0.5f, 0.5f, 0.0f); \
} else if(iPass == 0) { \
float dx = (x) - gLightX, dy = (y) - gLightY; \
float gDist = sqrt(dx*dx+dy*dy); \
float gMult = Min(0.5f / pLight->getSize(), 0.5f / gDist); \
float gNormX = (0.5f + dx * gMult) / 1.5f / 16.0f; \
float gNormY = (0.5f + dy * gMult) / 1.5f / 16.0f; \
if(light) glColor3f(0.1f, gNormX, gNormY); \
else glColor3f(0.0f, gNormX, gNormY); \
} else glColor3f(0.0f, 0.5f/1.5f/16.0f, 0.5f/1.5f/16.0f); \
glVertex2f(x,y)
#define DARK(x,y) VERTEX(x,y,false)
#define LIGHT(x,y) VERTEX(x,y,true)
#define BEGIN_TRIANGLE \
if(pOnScreen) glBegin(GL_LINE_LOOP)
#define END_TRIANGLE \
if(pOnScreen) glEnd()
// Draw the fan
glShadeModel(GL_SMOOTH);
glBegin(pOnScreen ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
if (!pOnScreen) {
LIGHT(gLightX, gLightY);
}
for (i = 0; i < iRayCnt; i++) {
if (i == 0 || gFanRX[i-1] != gFanLX[i] || gFanRY[i-1] != gFanLY[i]) {
LIGHT(gFanLX[i], gFanLY[i]);
}
if (gFanLX[i] != gFanRX[i] || gFanLY[i] != gFanRY[i]) {
LIGHT(gFanRX[i], gFanRY[i]);
}
}
glEnd();
// Draw the fade
glShadeModel(GL_SMOOTH);
if(!pOnScreen) glBegin(GL_TRIANGLES);
for (i = 0; i < iRayCnt; i++) {
// The quad. Will be empty if fan points match
if (gFanLX[i] != gFanRX[i] || gFanLY[i] != gFanRY[i]) {
// upper triangle
BEGIN_TRIANGLE;
LIGHT(gFanLX[i], gFanLY[i]);
LIGHT(gFanRX[i], gFanRY[i]);
DARK(gFadeLX[i], gFadeLY[i]);
END_TRIANGLE;
// lower triangle, if necessary
if (gFadeLX[i] != gFadeRX[i] || gFadeLY[i] != gFadeRY[i]) {
BEGIN_TRIANGLE;
LIGHT(gFanRX[i], gFanRY[i]);
DARK(gFadeRX[i], gFadeRY[i]);
DARK(gFadeLX[i], gFadeLY[i]);
END_TRIANGLE;
}
}
// No intermediate fade for last point
if (i+1 >= iRayCnt) continue;
// Ascending?
if (fAscend[i]) {
// Lower fade triangle
BEGIN_TRIANGLE;
LIGHT(gFanRX[i], gFanRY[i]);
DARK(gFadeIX[i], gFadeIY[i]);
DARK(gFadeRX[i], gFadeRY[i]);
END_TRIANGLE;
// Intermediate fade triangle, if necessary
if (gFadeIY[i] != gFadeLY[i+1]) {
BEGIN_TRIANGLE;
LIGHT(gFanRX[i], gFanRY[i]);
DARK(gFadeLX[i+1], gFadeLY[i+1]);
DARK(gFadeIX[i], gFadeIY[i]);
END_TRIANGLE;
}
// Upper fade triangle
BEGIN_TRIANGLE;
LIGHT(gFanRX[i], gFanRY[i]);
LIGHT(gFanLX[i+1], gFanLY[i+1]);
DARK(gFadeLX[i+1], gFadeLY[i+1]);
END_TRIANGLE;
// Descending?
} else {
// Lower fade triangle
BEGIN_TRIANGLE;
LIGHT(gFanLX[i+1], gFanLY[i+1]);
DARK(gFadeLX[i+1], gFadeLY[i+1]);
DARK(gFadeIX[i], gFadeIY[i]);
END_TRIANGLE;
// Intermediate fade triangle, if necessary
if (gFadeIY[i] != gFadeRY[i]) {
BEGIN_TRIANGLE;
LIGHT(gFanLX[i+1], gFanLY[i+1]);
DARK(gFadeIX[i], gFadeIY[i]);
DARK(gFadeRX[i], gFadeRY[i]);
END_TRIANGLE;
}
// Upper fade triangle
BEGIN_TRIANGLE;
LIGHT(gFanLX[i+1], gFanLY[i+1]);
DARK(gFadeRX[i], gFadeRY[i]);
LIGHT(gFanRX[i], gFanRY[i]);
END_TRIANGLE;
}
}
if (!pOnScreen)
glEnd(); // GL_TRIANGLES
}
if (!pOnScreen)
glEnd(); // GL_TRIANGLES
delete[] gFanLX;
// Reset GL state
glBlendEquation(GL_FUNC_ADD);
}

View File

@ -4,6 +4,7 @@
#include "C4Rect.h"
#include "C4Surface.h"
#include "C4DrawGL.h"
class C4FoW
{
@ -14,6 +15,8 @@ private:
class C4FoWLight *pLights;
public:
void Clear();
void Add(C4Object *pObj);
void Remove(C4Object *pObj);
void Update(C4Rect r);
@ -25,11 +28,12 @@ public:
class C4FoWRegion
{
public:
C4FoWRegion(C4FoW *pFoW);
C4FoWRegion(C4FoW *pFoW, C4Player *pPlayer);
~C4FoWRegion();
private:
C4FoW *pFoW;
C4Player *pPlayer;
C4Rect Region, OldRegion;
C4Surface *pSurface, *pBackSurface;
GLuint hFrameBufDraw, hFrameBufRead;
@ -39,12 +43,14 @@ public:
const C4Surface *getSurface() const { return pSurface; }
const C4Surface *getBackSurface() const { return pBackSurface; }
bool Create();
void Clear();
void Set(C4Rect r) { Region = r; }
void Update(C4Rect r);
void Render(const C4TargetFacet *pOnScreen = NULL);
private:
bool BindFramebuf();
};
class C4FoWLight

View File

@ -1451,6 +1451,7 @@ void C4Landscape::Default()
delete [] BridgeMatConversion[i];
BridgeMatConversion[i] = NULL;
}
delete pFoW; pFoW = NULL;
}
void C4Landscape::ClearMatCount()

View File

@ -170,8 +170,9 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
// Determine depth to use
iMaterialTextureDepth = 1;
while(iMaterialTextureDepth < int32_t(MaterialTextureMap.size()))
while(iMaterialTextureDepth < 2*int32_t(MaterialTextureMap.size()))
iMaterialTextureDepth <<= 1;
int32_t iNormalDepth = iMaterialTextureDepth / 2;
// Find the largest texture
C4Texture *pTex, *pRefTex; C4Surface *pRefSfc = NULL;
@ -207,14 +208,15 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
{
BYTE *p = pData + i * iTexSize;
// Get texture at position
const char *szTexture;
StdStrBuf Texture;
bool fNormal = i >= iNormalDepth;
if(i < int32_t(MaterialTextureMap.size()))
szTexture = MaterialTextureMap[i].getData();
else
szTexture = "";
Texture.Ref(MaterialTextureMap[i]);
else if(fNormal && i < iNormalDepth + int32_t(MaterialTextureMap.size()))
Texture.Format("%s_NRM", MaterialTextureMap[i-iNormalDepth].getData());
// Try to find the texture
C4Texture *pTex; C4Surface *pSurface;
if((pTex = pTexs->GetTexture(szTexture)) && (pSurface = pTex->Surface32))
if((pTex = pTexs->GetTexture(Texture.getData())) && (pSurface = pTex->Surface32))
{
#ifdef DEBUG_SOLID_COLOR_TEXTURES
// Just write a solid color that depends on the texture index
@ -230,7 +232,7 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
{
// Size recheck
if(pSurface->Wdt != iTexWdt || pSurface->Hgt != iTexHgt)
LogF(" gl: texture %s size mismatch (%dx%d vs %dx%d)!", szTexture, pSurface->Wdt, pSurface->Hgt, iTexWdt, iTexHgt);
LogF(" gl: texture %s size mismatch (%dx%d vs %dx%d)!", Texture.getData(), pSurface->Wdt, pSurface->Hgt, iTexWdt, iTexHgt);
// Copy bytes
DWORD *texdata = reinterpret_cast<DWORD *>(p);
pSurface->Lock();
@ -243,7 +245,7 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
#endif
}
// Seperator texture?
if(SEqual(szTexture, SEPERATOR_TEXTURE))
if(SEqual(Texture.getData(), SEPERATOR_TEXTURE))
{
// Make some ugly stripes
DWORD *texdata = reinterpret_cast<DWORD *>(p);
@ -252,8 +254,9 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
*texdata++ = ((x + y) % 32 < 16 ? RGBA(255, 0, 0, 255) : RGBA(0, 255, 255, 255));
continue;
}
// If we didn't "continue" yet, we haven't written the texture yet. Make it transparent.
memset(p, 0, iTexSize);
// If we didn't "continue" yet, we haven't written the texture yet.
// Make color texture transparent, and normal texture flat.
memset(p, fNormal ? 127 : 0, iTexSize);
}
// Clear error error(s?)

View File

@ -36,7 +36,6 @@
C4Texture::C4Texture()
{
Name[0]=0;
Surface32=NULL;
AvgColor = 0x00000000;
Next=NULL;
@ -134,7 +133,7 @@ bool C4TextureMap::AddTexture(const char *szTexture, C4Surface * sfcSurface)
{
C4Texture *pTexture;
if (!(pTexture=new C4Texture)) return false;
SCopy(szTexture,pTexture->Name,C4M_MaxName);
pTexture->Name.Copy(szTexture);
pTexture->Surface32=sfcSurface;
pTexture->Next=FirstTexture;
FirstTexture=pTexture;
@ -379,7 +378,7 @@ C4Texture * C4TextureMap::GetTexture(const char *szTexture)
{
C4Texture *pTexture;
for (pTexture=FirstTexture; pTexture; pTexture=pTexture->Next)
if (SEqualNoCase(pTexture->Name,szTexture))
if (SEqualNoCase(pTexture->Name.getData(),szTexture))
return pTexture;
return NULL;
}
@ -389,7 +388,7 @@ int32_t C4TextureMap::GetTextureIndex(const char *szName)
C4Texture *pTexture;
int32_t i=0;
for (pTexture=FirstTexture; pTexture; pTexture=pTexture->Next, i++)
if (SEqualNoCase(pTexture->Name,szName))
if (SEqualNoCase(pTexture->Name.getData(),szName))
return i;
return -1;
}
@ -398,7 +397,7 @@ bool C4TextureMap::CheckTexture(const char *szTexture)
{
C4Texture *pTexture;
for (pTexture=FirstTexture; pTexture; pTexture=pTexture->Next)
if (SEqualNoCase(pTexture->Name,szTexture))
if (SEqualNoCase(pTexture->Name.getData(),szTexture))
return true;
return false;
}
@ -409,7 +408,7 @@ const char* C4TextureMap::GetTexture(int32_t iIndex)
int32_t cindex;
for (pTexture=FirstTexture,cindex=0; pTexture; pTexture=pTexture->Next,cindex++)
if (cindex==iIndex)
return pTexture->Name;
return pTexture->Name.getData();
return NULL;
}

View File

@ -38,7 +38,7 @@ public:
uint32_t GetAverageColor() const { return AvgColor; }
protected:
char Name[C4M_MaxName+1];
StdStrBuf Name;
uint32_t AvgColor;
C4Texture *Next;
};