leocad/common/lc_texture.cpp

247 lines
5.4 KiB
C++
Raw Normal View History

2013-08-09 06:57:18 +02:00
#include "lc_global.h"
#include "lc_texture.h"
#include "lc_application.h"
#include "lc_library.h"
#include "image.h"
2015-05-09 21:54:29 +02:00
#include "lc_glextensions.h"
2013-08-09 06:57:18 +02:00
lcTexture* gGridTexture;
2014-10-05 07:21:51 +02:00
lcTexture* lcLoadTexture(const QString& FileName, int Flags)
{
lcTexture* Texture = new lcTexture();
if (!Texture->Load(FileName, Flags))
2014-10-05 07:21:51 +02:00
{
delete Texture;
Texture = nullptr;
2014-10-05 07:21:51 +02:00
}
else
{
strcpy(Texture->mName, QFileInfo(FileName).baseName().toLatin1());
Texture->SetTemporary(true);
}
2014-10-05 07:21:51 +02:00
return Texture;
}
void lcReleaseTexture(lcTexture* Texture)
{
if (Texture && !Texture->Release())
2014-10-05 07:21:51 +02:00
delete Texture;
}
2013-08-09 06:57:18 +02:00
lcTexture::lcTexture()
{
mTexture = 0;
mRefCount = 0;
mTemporary = false;
2013-08-09 06:57:18 +02:00
}
lcTexture::~lcTexture()
{
Unload();
}
void lcTexture::CreateGridTexture()
{
2020-03-23 04:18:52 +01:00
constexpr int NumLevels = 9;
mImages.resize(NumLevels);
2017-12-02 21:22:04 +01:00
quint8* Previous = nullptr;
for (int ImageLevel = 0; ImageLevel < NumLevels; ImageLevel++)
{
Image& GridImage = mImages[ImageLevel];
const int GridSize = 256 >> ImageLevel;
2021-11-15 04:10:16 +01:00
GridImage.Allocate(GridSize, GridSize, lcPixelFormat::A8);
2015-05-26 01:26:03 +02:00
if (Previous)
{
2020-03-23 04:18:52 +01:00
const int PreviousGridSize = 2 * GridSize;
2015-05-26 01:26:03 +02:00
for (int y = 0; y < GridSize - 1; y++)
{
2015-05-26 01:26:03 +02:00
for (int x = 0; x < GridSize - 1; x++)
{
2020-03-23 04:18:52 +01:00
const quint8 a = Previous[x * 2 + y * 2 * PreviousGridSize] > 64 ? 255 : 0;
const quint8 b = Previous[x * 2 + 1 + y * 2 * PreviousGridSize] > 64 ? 255 : 0;
const quint8 c = Previous[x * 2 + (y * 2 + 1) * PreviousGridSize] > 64 ? 255 : 0;
const quint8 d = Previous[x * 2 + 1 + (y * 2 + 1) * PreviousGridSize] > 64 ? 255 : 0;
2015-05-26 01:26:03 +02:00
GridImage.mData[x + y * GridSize] = (a + b + c + d) / 4;
}
int x = GridSize - 1;
2020-03-23 04:18:52 +01:00
const quint8 a = Previous[x * 2 + y * 2 * PreviousGridSize];
const quint8 c = Previous[x * 2 + (y * 2 + 1) * PreviousGridSize];
2015-05-26 01:26:03 +02:00
GridImage.mData[x + y * GridSize] = (a + c) / 2;
}
2015-05-26 01:26:03 +02:00
int y = GridSize - 1;
for (int x = 0; x < GridSize - 1; x++)
{
2020-03-23 04:18:52 +01:00
const quint8 a = Previous[x * 2 + y * 2 * PreviousGridSize];
const quint8 b = Previous[x * 2 + 1 + y * 2 * PreviousGridSize];
2015-05-26 01:26:03 +02:00
GridImage.mData[x + y * GridSize] = (a + b) / 2;
}
2015-05-26 01:26:03 +02:00
int x = GridSize - 1;
GridImage.mData[x + y * GridSize] = Previous[x + y * PreviousGridSize];
}
else
{
const float Radius1 = (80 >> ImageLevel) * (80 >> ImageLevel);
const float Radius2 = (72 >> ImageLevel) * (72 >> ImageLevel);
2017-12-02 21:22:04 +01:00
quint8* TempBuffer = new quint8[GridSize * GridSize];
2015-05-26 01:26:03 +02:00
for (int y = 0; y < GridSize; y++)
{
2017-12-02 21:22:04 +01:00
quint8* Pixel = TempBuffer + y * GridSize;
2015-05-26 01:26:03 +02:00
memset(Pixel, 0, GridSize);
const float y2 = (y - GridSize / 2) * (y - GridSize / 2);
2015-05-26 01:26:03 +02:00
if (Radius1 <= y2)
continue;
2015-05-26 01:26:03 +02:00
if (Radius2 <= y2)
{
2020-03-23 04:18:52 +01:00
const int x1 = sqrtf(Radius1 - y2);
2015-05-26 01:26:03 +02:00
for (int x = GridSize / 2 - x1; x < GridSize / 2 + x1; x++)
Pixel[x] = 255;
}
else
{
2020-03-23 04:18:52 +01:00
const int x1 = sqrtf(Radius1 - y2);
const int x2 = sqrtf(Radius2 - y2);
2015-05-26 01:26:03 +02:00
for (int x = GridSize / 2 - x1; x < GridSize / 2 - x2; x++)
Pixel[x] = 255;
for (int x = GridSize / 2 + x2; x < GridSize / 2 + x1; x++)
Pixel[x] = 255;
}
}
2015-05-26 01:26:03 +02:00
for (int y = 0; y < GridSize - 1; y++)
{
for (int x = 0; x < GridSize - 1; x++)
{
2020-03-23 04:18:52 +01:00
const quint8 a = TempBuffer[x + y * GridSize];
const quint8 b = TempBuffer[x + 1 + y * GridSize];
const quint8 c = TempBuffer[x + (y + 1) * GridSize];
const quint8 d = TempBuffer[x + 1 + (y + 1) * GridSize];
2015-05-26 01:26:03 +02:00
GridImage.mData[x + y * GridSize] = (a + b + c + d) / 4;
}
int x = GridSize - 1;
2020-03-23 04:18:52 +01:00
const quint8 a = TempBuffer[x + y * GridSize];
const quint8 c = TempBuffer[x + (y + 1) * GridSize];
2015-05-26 01:26:03 +02:00
GridImage.mData[x + y * GridSize] = (a + c) / 2;
}
int y = GridSize - 1;
for (int x = 0; x < GridSize - 1; x++)
{
2020-03-23 04:18:52 +01:00
const quint8 a = TempBuffer[x + y * GridSize];
const quint8 b = TempBuffer[x + 1 + y * GridSize];
2015-05-26 01:26:03 +02:00
GridImage.mData[x + y * GridSize] = (a + b) / 2;
}
int x = GridSize - 1;
2015-05-26 01:26:03 +02:00
GridImage.mData[x + y * GridSize] = TempBuffer[x + y * GridSize];
delete[] TempBuffer;
}
2015-05-26 01:26:03 +02:00
Previous = GridImage.mData;
}
mRefCount = 1;
mFlags = LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV | LC_TEXTURE_MIPMAPS | LC_TEXTURE_ANISOTROPIC;
2015-01-08 06:40:22 +01:00
lcContext* Context = lcContext::GetGlobalOffscreenContext();
Context->MakeCurrent();
Upload(Context);
}
2013-08-09 06:57:18 +02:00
bool lcTexture::Load()
{
return lcGetPiecesLibrary()->LoadTexture(this);
}
bool lcTexture::Load(const QString& FileName, int Flags)
2013-08-09 06:57:18 +02:00
{
2021-11-22 03:25:17 +01:00
Image Image;
2013-08-09 06:57:18 +02:00
2021-11-22 03:25:17 +01:00
if (!Image.FileLoad(FileName))
2013-08-09 06:57:18 +02:00
return false;
2021-11-22 03:25:17 +01:00
SetImage(std::move(Image), Flags);
return true;
2013-08-09 06:57:18 +02:00
}
bool lcTexture::Load(lcMemFile& File, int Flags)
{
2021-11-22 03:25:17 +01:00
Image Image;
2013-08-09 06:57:18 +02:00
2021-11-22 03:25:17 +01:00
if (!Image.FileLoad(File))
2013-08-09 06:57:18 +02:00
return false;
2021-11-22 03:25:17 +01:00
SetImage(std::move(Image), Flags);
return true;
2013-08-09 06:57:18 +02:00
}
2021-11-21 21:16:19 +01:00
void lcTexture::SetImage(Image&& Image, int Flags)
{
mImages.clear();
2021-11-21 21:16:19 +01:00
mImages.emplace_back(std::move(Image));
mFlags = Flags;
2021-11-22 03:25:17 +01:00
LoadImages();
}
2018-10-29 01:59:01 +01:00
void lcTexture::SetImage(std::vector<Image>&& Images, int Flags)
{
mImages = std::move(Images);
2021-11-21 21:16:19 +01:00
mFlags = Flags;
2018-10-29 01:59:01 +01:00
2021-11-22 03:25:17 +01:00
LoadImages();
2018-10-29 01:59:01 +01:00
}
void lcTexture::Upload(lcContext* Context)
2013-08-09 06:57:18 +02:00
{
2021-11-22 03:25:17 +01:00
if (!NeedsUpload())
return;
mWidth = mImages[0].mWidth;
mHeight = mImages[0].mHeight;
2013-08-09 06:57:18 +02:00
2021-11-22 03:25:17 +01:00
Context->UploadTexture(this);
2018-10-29 01:59:01 +01:00
2021-11-22 03:25:17 +01:00
mImages.clear();
2013-08-09 06:57:18 +02:00
}
2021-11-22 03:25:17 +01:00
bool lcTexture::LoadImages()
{
for (Image& Image : mImages)
Image.ResizePow2();
if (QThread::currentThread() == qApp->thread())
{
lcContext* Context = lcContext::GetGlobalOffscreenContext();
Context->MakeCurrent();
Upload(Context);
}
return true;
}
2013-08-09 06:57:18 +02:00
void lcTexture::Unload()
{
if (mTexture)
glDeleteTextures(1, &mTexture);
mTexture = 0;
}