Esempio n. 1
0
	virtual C4Surface* LoadTexture(const char* filename)
	{
		if (!Group.AccessEntry(filename)) return NULL;
		C4Surface* surface = new C4Surface;
		// Suppress error message here, StdMeshMaterial loader
		// will show one.
		if (!surface->Read(Group, GetExtension(filename), C4SF_MipMap))
			{ delete surface; surface = NULL; }
		return surface;
	}
Esempio n. 2
0
bool C4FacetExSurface::CopyFromSfcMaxSize(C4Surface &srcSfc, int32_t iMaxSize,
                                          uint32_t dwColor) {
  // safety
  if (!srcSfc.Wdt || !srcSfc.Hgt) return false;
  Clear();
  // no scale?
  bool fNeedsScale = !(srcSfc.Wdt <= iMaxSize && srcSfc.Hgt <= iMaxSize);
  if (!fNeedsScale && !dwColor) {
    // no change necessary; just copy then
    Face.Copy(srcSfc);
  } else {
    // must scale down or colorize. Just blit.
    C4Facet fctSource;
    fctSource.Set(&srcSfc, 0, 0, srcSfc.Wdt, srcSfc.Hgt);
    int32_t iTargetWdt, iTargetHgt;
    if (fNeedsScale) {
      if (fctSource.Wdt > fctSource.Hgt) {
        iTargetWdt = iMaxSize;
        iTargetHgt = fctSource.Hgt * iTargetWdt / fctSource.Wdt;
      } else {
        iTargetHgt = iMaxSize;
        iTargetWdt = fctSource.Wdt * iTargetHgt / fctSource.Hgt;
      }
    } else {
      iTargetWdt = fctSource.Wdt;
      iTargetHgt = fctSource.Hgt;
    }
    if (dwColor) srcSfc.SetClr(dwColor);
    Create(iTargetWdt, iTargetHgt);
    lpDDraw->Blit(&srcSfc, 0.0f, 0.0f, float(fctSource.Wdt),
                  float(fctSource.Hgt), &Face, 0, 0, iTargetWdt, iTargetHgt);
  }
  Set(&Face, 0, 0, Face.Wdt, Face.Hgt);
  return true;
}
bool C4GraphicsResource::LoadFile(C4Surface& sfc, const char *szName, C4GroupSet &rGfxSet, int32_t &ridCurrSfc, int iFlags)
{
	// find
	char FileName[_MAX_FNAME]; int32_t ID = 0;
	C4Group *pGrp = FindSuitableFile(szName, rGfxSet, FileName, &ID);
	if (!pGrp)
	{
		LogF(LoadResStr("IDS_PRC_NOGFXFILE"), szName, LoadResStr("IDS_PRC_FILENOTFOUND"));
		return false;
	}
	// check group
	if (ID == ridCurrSfc)
		// already up-to-date
		return true;
	// load
	if (!sfc.Load(*pGrp, FileName, false, false, iFlags))
	{
		LogF(LoadResStr("IDS_PRC_NOGFXFILE"), FileName, LoadResStr("IDS_ERR_NOFILE"));
		return false;
	}
	ridCurrSfc = ID;
	Game.SetInitProgress(ProgressStart);
	ProgressStart += ProgressIncrement;
	return true;
}
Esempio n. 4
0
bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
{

	// Populate our map with all needed textures
	MaterialTextureMap.push_back(StdCopyStrBuf(""));
	AddTexturesFromMap(pTexs);

	// Determine depth to use
	iMaterialTextureDepth = 2*MaterialTextureMap.size();
	int32_t iNormalDepth = iMaterialTextureDepth / 2;

	// Find the largest texture
	C4Texture *pTex; C4Surface *pRefSfc = NULL;
	for(int iTexIx = 0; (pTex = pTexs->GetTexture(pTexs->GetTexture(iTexIx))); iTexIx++)
		if(C4Surface *pSfc = pTex->Surface32)
			if (!pRefSfc || pRefSfc->Wdt < pSfc->Wdt || pRefSfc->Hgt < pSfc->Hgt)
				pRefSfc = pSfc;
	if(!pRefSfc)
		return false;

	// Get size for our textures. We might be limited by hardware
	int iTexWdt = pRefSfc->Wdt, iTexHgt = pRefSfc->Hgt;
	GLint iMaxTexSize, iMaxTexLayers;
	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &iMaxTexSize);
	glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &iMaxTexLayers);
	if (iTexWdt > iMaxTexSize || iTexHgt > iMaxTexSize)
	{
		iTexWdt = std::min(iTexWdt, iMaxTexSize);
		iTexHgt = std::min(iTexHgt, iMaxTexSize);
		LogF("   gl: Material textures too large, GPU only supports %dx%d! Cropping might occur!", iMaxTexSize, iMaxTexSize);
	}
	if(iMaterialTextureDepth >= iMaxTexLayers)
	{
		LogF("   gl: Too many material textures! GPU only supports 3D texture depth of %d!", iMaxTexSize);
		return false;
	}
	iMaterialWidth = iTexWdt;
	iMaterialHeight = iTexHgt;

	// Compose together data of all textures
	const int iTexSize = iTexWdt * iTexHgt * C4Draw::COLOR_DEPTH_BYTES;
	const int iSize = iTexSize * iMaterialTextureDepth;
	BYTE *pData = new BYTE [iSize];
	for(int i = 0; i < iMaterialTextureDepth; i++)
	{
		BYTE *p = pData + i * iTexSize;
		// Get texture at position
		StdStrBuf Texture;
		bool fNormal = i >= iNormalDepth;
		if(i < int32_t(MaterialTextureMap.size()))
			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(Texture.getData())) && (pSurface = pTex->Surface32))
		{
#ifdef DEBUG_SOLID_COLOR_TEXTURES
			// Just write a solid color that depends on the texture index
			DWORD *texdata = reinterpret_cast<DWORD *>(p);
			for (int y = 0; y < iTexHgt; ++y)
				for (int x = 0; x < iTexWdt; ++x)
					*texdata++ = RGBA((iTex & 48), (iTex & 3) * 16, (i & 12) * 4, 255);
			continue;
#else
			// Size recheck. It's fine if this texture's size is a divisor
			// of the maximum texture size, because then we can just tile
			// the smaller texture.
			if(pSurface->Wdt != iTexWdt || pSurface->Hgt != iTexHgt)
				if (iTexWdt % pSurface->Wdt != 0 || iTexHgt % pSurface->Hgt != 0)
					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();
			for (int y = 0; y < iTexHgt; ++y)
				for (int x = 0; x < iTexWdt; ++x)
					*texdata++ = pSurface->GetPixDw(x % pSurface->Wdt, y % pSurface->Hgt, false);
			pSurface->Unlock();
			continue;
#endif
		}
		// Seperator texture?
		if(SEqual(Texture.getData(), SEPERATOR_TEXTURE))
		{
			// Make some ugly stripes
			DWORD *texdata = reinterpret_cast<DWORD *>(p);
			for (int y = 0; y < iTexHgt; ++y)
				for (int x = 0; x < iTexWdt; ++x)
					*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 color texture transparent, and normal texture flat.
		if (fNormal)
		{
			DWORD *texdata = reinterpret_cast<DWORD *>(p);
			for (int y = 0; y < iTexHgt; ++y)
				for (int x = 0; x < iTexWdt; ++x)
					*texdata++ = RGBA(127, 127, 255, 255);
		}
		else
			memset(p, 0, iTexSize);
	}

	// Clear error error(s?)
	while(glGetError()) {}
	
	// Alloc 1D matmap texture
	glGenTextures(1, &matMapTexture);

	// Alloc 2D texture array
	glGenTextures(1, &hMaterialTexture);

	// Generate textures
	int iSizeSum = 0;

	// Select texture
	glBindTexture(GL_TEXTURE_2D_ARRAY, hMaterialTexture);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	// We fully expect to tile these
	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);

	// Make it happen!
	glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, iTexWdt, iTexHgt, iMaterialTextureDepth, 0, GL_BGRA,
				GL_UNSIGNED_INT_8_8_8_8_REV,
				pData);

	glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
	   
	// Statistics
	iSizeSum += iTexWdt * iTexHgt * iMaterialTextureDepth * C4Draw::COLOR_DEPTH_BYTES;
	
	// Dispose of data
	delete [] pData;
	
	// Check whether we were successful
	if(int err = glGetError())
	{
		LogF("   gl: Could not load textures (error %d)", err);
		return false;
	}

	// Announce the good news
	LogF("  gl: Texturing uses %d slots at %dx%d (%d MB total)",
		static_cast<int>(MaterialTextureMap.size()),
		iMaterialWidth, iMaterialHeight,
		iSizeSum / 1000000);

	return true;
}
Esempio n. 5
0
bool C4FontLoader::InitFont(CStdFont &rFont, const char *szFontName, FontType eType, int32_t iSize, C4GroupSet *pGfxGroups, bool fDoShadow)
	{
	// safety
	if (!szFontName || !*szFontName)
		{
		LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
		return false;
		}
	// get font to load
	// pFontDefs may be NULL if no fonts are loaded; but then iFontDefCount is zero as well
	// the function must not be aborted, because a standard windows font may be loaded
	std::vector<C4FontDef>::iterator pFontDefC = FontDefs.begin(), pFontDef = FontDefs.end();
	while (pFontDefC != FontDefs.end())
		{
		// check font
		if (pFontDefC->Name == szFontName)
			{
			int32_t iSizeDiff = Abs(pFontDefC->iSize - iSize);
			// better match than last font?
			if (pFontDef == FontDefs.end() || Abs(pFontDef->iSize - iSize) >= iSizeDiff)
				pFontDef = pFontDefC;
			}
		// check next one
		++pFontDefC;
		}
	// if def has not been found, use the def as font name
	// determine font def string
	const char *szFontString = szFontName;
	// special: Fonts without shadow are always newly rendered
	if (!fDoShadow) { pFontDef=FontDefs.end(); }
	if (pFontDef!=FontDefs.end()) switch (eType)
		{
		case C4FT_Log:      szFontString = pFontDef->LogFont.getData(); break;
		case C4FT_MainSmall:szFontString = pFontDef->SmallFont.getData(); break;
		case C4FT_Main:     szFontString = pFontDef->Font.getData(); break;
		case C4FT_Caption:  szFontString = pFontDef->CaptionFont.getData(); break;
		case C4FT_Title:    szFontString = pFontDef->TitleFont.getData(); break;
		default: LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; // invalid call
		}
	// font not assigned?
	if (!*szFontString)
		{
		// invalid call or spec
		LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false;
		}
	// get font name
	char FontFaceName[C4MaxName+1], FontParam[C4MaxName+1];
	SCopyUntil(szFontString, FontFaceName, ',', C4MaxName);
	// is it an image file?
	const char *szExt = GetExtension(FontFaceName);
	if (SEqualNoCase(szExt, "png") || SEqualNoCase(szExt, "bmp"))
		{
		// image file name: load bitmap font from image file
		// if no graphics group is given, do not load yet
		if (!pGfxGroups)
			{
			LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
			return false;
			}
		// indent given?	
		int32_t iIndent = 0;
		if (SCopySegment(szFontString, 1, FontParam, ',', C4MaxName))
			sscanf(FontParam, "%i", &iIndent);
		// load font face from gfx group
		int32_t iGrpId;
		C4Group *pGrp = pGfxGroups->FindEntry(FontFaceName, NULL, &iGrpId);
		if (!pGrp)
			{
			LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
			return false;
			}
		// check if it's already loaded from that group with that parameters
		if (!rFont.IsSameAsID(FontFaceName, iGrpId, iIndent))
			{
			// it's not; so (re-)load it now!
			if (rFont.IsInitialized())
				{
				// reloading
				rFont.Clear();
				LogF(LoadResStr("IDS_PRC_UPDATEFONT"), FontFaceName, iIndent, 0);
				}
			C4Surface sfc;
			if (!sfc.Load(*pGrp, FontFaceName))
				{
				LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
				return false;
				}
			// init font from face
			try 
				{
				rFont.Init(GetFilenameOnly(FontFaceName), &sfc, iIndent);
				}
			catch (std::runtime_error & e)
				{
				LogFatal(e.what());
				LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
				return false;
				}
			rFont.id = iGrpId;
			}
		}
	else
		{
		int32_t iDefFontSize; DWORD dwDefWeight=FW_NORMAL;
#if defined(_WIN32) && !defined(HAVE_FREETYPE)
		switch (eType)
			{
			case C4FT_Log:     iDefFontSize = 8; break;
			case C4FT_MainSmall:iDefFontSize = iSize+1; break;
			case C4FT_Main:    iDefFontSize = iSize+4; break;
			case C4FT_Caption: iDefFontSize = iSize+6; dwDefWeight = FW_BOLD; break;
			case C4FT_Title:   iDefFontSize = iSize*3; break;
			default: LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; // invalid call
			}
#else
		switch (eType)
			{
			case C4FT_Log:     iDefFontSize = iSize*12/14; break;
			case C4FT_MainSmall:iDefFontSize = iSize*13/14; break;
			case C4FT_Main:    iDefFontSize = iSize; break;
			case C4FT_Caption: iDefFontSize = iSize*16/14; /*dwDefWeight = FW_MEDIUM;*/ break;
			case C4FT_Title:   iDefFontSize = iSize*22/14; /*dwDefWeight = FW_MEDIUM;*/ break;
			default: LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; // invalid call
			}
#endif
		// regular font name: let WinGDI or Freetype draw a font with the given parameters
		// font size given?	
		if (SCopySegment(szFontString, 1, FontParam, ',', C4MaxName))
			sscanf(FontParam, "%i", &iDefFontSize);
		// font weight given?
		if (SCopySegment(szFontString, 2, FontParam, ',', C4MaxName))
			sscanf(FontParam, "%i", &dwDefWeight);
		// check if it's already loaded from that group with that parameters
		if (!rFont.IsSameAs(FontFaceName, iDefFontSize, dwDefWeight))
			{
			// it's not; so (re-)load it now!
			if (rFont.IsInitialized())
				{
				// reloading
				rFont.Clear();
				LogF(LoadResStr("IDS_PRC_UPDATEFONT"), FontFaceName, iDefFontSize, dwDefWeight);
				}
			// init with given font name
			try 
				{
				// check if one of the internally listed fonts should be used
				C4VectorFont * pFont = pVectorFonts;
				while (pFont)
					{
					if (SEqual(pFont->Name.getData(), FontFaceName))
						{
						if (InitFont(rFont, pFont, iDefFontSize, dwDefWeight, fDoShadow)) break;
						}
					pFont = pFont->pNext;
					}
				// no internal font matching? Then create one using the given face/filename (using a system font)
				if (!pFont)
					{
					pFont = new C4VectorFont();
					if (pFont->Init(FontFaceName, iDefFontSize, dwDefWeight, Config.General.LanguageCharset))
						{
						AddVectorFont(pFont);
						if (!InitFont(rFont, pFont, iDefFontSize, dwDefWeight, fDoShadow))
						  throw std::runtime_error(FormatString("Error initializing font %s", FontFaceName).getData());
						}
					else
						{
						delete pFont;
						// no match for font face found
						throw std::runtime_error(FormatString("Font face %s undefined", FontFaceName).getData());
						}
					}
				}
			catch (std::runtime_error & e)
				{
				LogFatal(e.what());
				LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
				return false;
				}
			rFont.id = 0;
			}
		}
	// done, success
	return true;
	}