mirror of
https://github.com/GabsPuNs/Project-Zenith-Main.git
synced 2026-06-10 20:11:58 +00:00
Improvements
Also a "rewrite" of Texture.cpp but im not happy with it
This commit is contained in:
@@ -14,10 +14,6 @@ Texture::Texture(const wstring &name, int mode, int width, int height, int depth
|
||||
|
||||
void Texture::_init(const wstring &name, int mode, int width, int height, int depth, int wrapMode, int format, int minFilter, int magFilter, bool mipMap)
|
||||
{
|
||||
#ifdef __PS3__
|
||||
if(g_texBlitJobQueuePort == nullptr)
|
||||
g_texBlitJobQueuePort = new C4JSpursJobQueue::Port("C4JSpursJob_Texture_blit");
|
||||
#endif
|
||||
this->name = name;
|
||||
this->mode = mode;
|
||||
this->width = width;
|
||||
@@ -29,25 +25,9 @@ void Texture::_init(const wstring &name, int mode, int width, int height, int de
|
||||
this->wrapMode = wrapMode;
|
||||
immediateUpdate = false;
|
||||
m_bInitialised = false;
|
||||
for( int i = 0 ; i < 10; i++ )
|
||||
{
|
||||
data[i] = nullptr;
|
||||
}
|
||||
|
||||
rect = new Rect2i(0, 0, width, height);
|
||||
// 4J Removed 1D and 3D
|
||||
//if (height == 1 && depth == 1)
|
||||
//{
|
||||
// type = GL_TEXTURE_1D;
|
||||
//}
|
||||
//else if(depth == 1)
|
||||
//{
|
||||
type = GL_TEXTURE_2D;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// type = GL_TEXTURE_3D;
|
||||
//}
|
||||
type = GL_TEXTURE_2D;
|
||||
|
||||
mipmapped = mipMap || (minFilter != GL_NEAREST && minFilter != GL_LINEAR) ||
|
||||
(magFilter != GL_NEAREST && magFilter != GL_LINEAR);
|
||||
@@ -67,13 +47,8 @@ void Texture::_init(const wstring &name, int mode, int width, int height, int de
|
||||
if(m_iMipLevels > MAX_MIP_LEVELS) m_iMipLevels = MAX_MIP_LEVELS;
|
||||
}
|
||||
|
||||
#ifdef __PSVITA__
|
||||
// vita doesn't have a mipmap conditional shader because it's too slow so make sure this texture don't look awful at the lower mips
|
||||
if( name == L"terrain" )
|
||||
{
|
||||
m_iMipLevels = 3;
|
||||
}
|
||||
#endif
|
||||
for( int i = 0 ; i < m_iMipLevels; i++ )
|
||||
data[i] = nullptr;
|
||||
|
||||
if (mode != TM_CONTAINER)
|
||||
{
|
||||
@@ -86,9 +61,7 @@ void Texture::_init(const wstring &name, int mode, int width, int height, int de
|
||||
glTexParameteri(type, GL_TEXTURE_WRAP_T, wrapMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
glId = -1;
|
||||
}
|
||||
|
||||
managerId = TextureManager::getInstance()->createTextureID();
|
||||
}
|
||||
@@ -98,63 +71,41 @@ void Texture::_init(const wstring &name, int mode, int width, int height, int de
|
||||
_init(name, mode, width, height, depth, wrapMode, format, minFilter, magFilter, mipMap);
|
||||
if (image == nullptr)
|
||||
{
|
||||
if (width == -1 || height == -1)
|
||||
if (width <= 0 || height <= 0)
|
||||
{
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
int baseSize = width * height * depth * 4;
|
||||
|
||||
data[0] = ByteBuffer::allocateDirect(baseSize);
|
||||
|
||||
memset(data[0]->getBuffer(), 0, baseSize);
|
||||
|
||||
data[0]->position(0)->limit(baseSize);
|
||||
|
||||
if(mipmapped)
|
||||
{
|
||||
byteArray tempBytes = byteArray(width * height * depth * 4);
|
||||
for (int index = 0; index < tempBytes.length; index++)
|
||||
for(unsigned int level = 1; level < m_iMipLevels; ++level)
|
||||
{
|
||||
tempBytes[index] = 0;
|
||||
}
|
||||
#ifdef __PS3__
|
||||
data[0] = new ByteBuffer_IO(tempBytes.length);
|
||||
#else
|
||||
data[0] = ByteBuffer::allocateDirect(tempBytes.length);
|
||||
#endif // __{S3__
|
||||
data[0]->clear();
|
||||
data[0]->put(tempBytes);
|
||||
data[0]->position(0)->limit(tempBytes.length);
|
||||
int ww = std::max(1, width >> level);
|
||||
int hh = std::max(1, height >> level);
|
||||
|
||||
delete [] tempBytes.data;
|
||||
int mipSize = ww * hh * depth * 4;
|
||||
|
||||
if(mipmapped)
|
||||
{
|
||||
for(unsigned int level = 1; level < m_iMipLevels; ++level)
|
||||
{
|
||||
int ww = width >> level;
|
||||
int hh = height >> height;
|
||||
data[level] = ByteBuffer::allocateDirect(mipSize);
|
||||
|
||||
byteArray tempBytes = byteArray(ww * hh * depth * 4);
|
||||
for (int index = 0; index < tempBytes.length; index++)
|
||||
{
|
||||
tempBytes[index] = 0;
|
||||
}
|
||||
memset(data[level]->getBuffer(), 0, mipSize);
|
||||
|
||||
#ifdef __PS3__
|
||||
data[level] = new ByteBuffer_IO(tempBytes.length);
|
||||
#else
|
||||
data[level] = ByteBuffer::allocateDirect(tempBytes.length);
|
||||
#endif // __PS3__
|
||||
data[level]->clear();
|
||||
data[level]->put(tempBytes);
|
||||
data[level]->position(0)->limit(tempBytes.length);
|
||||
|
||||
delete [] tempBytes.data;
|
||||
}
|
||||
}
|
||||
|
||||
if (immediateUpdate)
|
||||
{
|
||||
updateOnGPU();
|
||||
}
|
||||
else
|
||||
{
|
||||
updated = false;
|
||||
data[level]->position(0)->limit(mipSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (immediateUpdate)
|
||||
updateOnGPU();
|
||||
else
|
||||
updated = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -184,15 +135,14 @@ Texture::~Texture()
|
||||
{
|
||||
delete rect;
|
||||
|
||||
for(int i = 0; i < 10; i++ )
|
||||
for(int i = 0; i < m_iMipLevels; i++ )
|
||||
{
|
||||
if(data[i] != nullptr) delete data[i];
|
||||
delete data[i];
|
||||
data[i] = nullptr;
|
||||
}
|
||||
|
||||
if(glId >= 0)
|
||||
{
|
||||
glDeleteTextures(glId);
|
||||
}
|
||||
}
|
||||
|
||||
const Rect2i *Texture::getRect()
|
||||
@@ -202,160 +152,50 @@ const Rect2i *Texture::getRect()
|
||||
|
||||
void Texture::fill(const Rect2i *rect, int color)
|
||||
{
|
||||
// 4J Remove 3D
|
||||
//if (type == GL_TEXTURE_3D)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
if (data[0] == nullptr || rect == nullptr)
|
||||
return;
|
||||
|
||||
Rect2i *myRect = new Rect2i(0, 0, width, height);
|
||||
myRect->intersect(rect);
|
||||
data[0]->position(0);
|
||||
for (int y = myRect->getY(); y < (myRect->getY() + myRect->getHeight()); y++)
|
||||
Rect2i myRect(0, 0, width, height);
|
||||
myRect.intersect(rect);
|
||||
|
||||
int startX = myRect.getX();
|
||||
int startY = myRect.getY();
|
||||
int fillWidth = myRect.getWidth();
|
||||
int endY = startY + myRect.getHeight();
|
||||
|
||||
if (fillWidth <= 0 || startY >= endY)
|
||||
return;
|
||||
|
||||
BYTE b0 = static_cast<BYTE>((color >> 24) & 0xff);
|
||||
BYTE b1 = static_cast<BYTE>((color >> 16) & 0xff);
|
||||
BYTE b2 = static_cast<BYTE>((color >> 8) & 0xff);
|
||||
BYTE b3 = static_cast<BYTE>((color >> 0) & 0xff);
|
||||
|
||||
unsigned int finalColor = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
|
||||
|
||||
unsigned int* pixels = (unsigned int*)data[0]->getBuffer();
|
||||
|
||||
for (int y = startY; y < endY; y++)
|
||||
{
|
||||
int line = y * width * 4;
|
||||
for (int x = myRect->getX(); x < (myRect->getX() + myRect->getWidth()); x++)
|
||||
{
|
||||
data[0]->put(line + x * 4 + 0, static_cast<BYTE>((color >> 24) & 0x000000ff));
|
||||
data[0]->put(line + x * 4 + 1, static_cast<BYTE>((color >> 16) & 0x000000ff));
|
||||
data[0]->put(line + x * 4 + 2, static_cast<BYTE>((color >> 8) & 0x000000ff));
|
||||
data[0]->put(line + x * 4 + 3, static_cast<BYTE>((color >> 0) & 0x000000ff));
|
||||
}
|
||||
unsigned int* rowStart = pixels + (y * width) + startX;
|
||||
|
||||
std::fill(rowStart, rowStart + fillWidth, finalColor);
|
||||
}
|
||||
delete myRect;
|
||||
|
||||
if (immediateUpdate)
|
||||
{
|
||||
updateOnGPU();
|
||||
}
|
||||
else
|
||||
{
|
||||
updated = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::writeAsBMP(const wstring &name)
|
||||
{
|
||||
// 4J Don't need
|
||||
#if 0
|
||||
if (type == GL_TEXTURE_3D)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
File *outFile = new File(name);
|
||||
if (outFile.exists())
|
||||
{
|
||||
outFile.delete();
|
||||
}
|
||||
|
||||
DataOutputStream *outStream = nullptr;
|
||||
//try {
|
||||
outStream = new DataOutputStream(new FileOutputStream(outFile));
|
||||
//} catch (IOException e) {
|
||||
// Unable to open file for writing for some reason
|
||||
// return;
|
||||
//}
|
||||
|
||||
//try {
|
||||
// Write the header
|
||||
outStream->writeShort((short)0x424d); // 0x0000: ID - 'BM'
|
||||
int byteSize = width * height * 4 + 54;
|
||||
outStream->writeByte((BYTE)(byteSize >> 0)); // 0x0002: Raw file size
|
||||
outStream->writeByte((BYTE)(byteSize >> 8));
|
||||
outStream->writeByte((BYTE)(byteSize >> 16));
|
||||
outStream->writeByte((BYTE)(byteSize >> 24));
|
||||
outStream->writeInt(0); // 0x0006: Reserved
|
||||
outStream->writeByte(54); // 0x000A: Start of pixel data
|
||||
outStream->writeByte(0);
|
||||
outStream->writeByte(0);
|
||||
outStream->writeByte(0);
|
||||
outStream->writeByte(40); // 0x000E: Size of secondary header
|
||||
outStream->writeByte(0);
|
||||
outStream->writeByte(0);
|
||||
outStream->writeByte(0);
|
||||
outStream->writeByte((BYTE)(width >> 0)); // 0x0012: Image width, in pixels
|
||||
outStream->writeByte((BYTE)(width >> 8));
|
||||
outStream->writeByte((BYTE)(width >> 16));
|
||||
outStream->writeByte((BYTE)(width >> 24));
|
||||
outStream->writeByte((BYTE)(height >> 0)); // 0x0016: Image height, in pixels
|
||||
outStream->writeByte((BYTE)(height >> 8));
|
||||
outStream->writeByte((BYTE)(height >> 16));
|
||||
outStream->writeByte((BYTE)(height >> 24));
|
||||
outStream->writeByte(1); // 0x001A: Number of color planes, must be 1
|
||||
outStream->writeByte(0);
|
||||
outStream->writeByte(32); // 0x001C: Bit depth (32bpp)
|
||||
outStream->writeByte(0);
|
||||
outStream->writeInt(0); // 0x001E: Compression mode (BI_RGB, uncompressed)
|
||||
int bufSize = width * height * 4;
|
||||
outStream->writeInt((BYTE)(bufSize >> 0)); // 0x0022: Raw size of bitmap data
|
||||
outStream->writeInt((BYTE)(bufSize >> 8));
|
||||
outStream->writeInt((BYTE)(bufSize >> 16));
|
||||
outStream->writeInt((BYTE)(bufSize >> 24));
|
||||
outStream->writeInt(0); // 0x0026: Horizontal resolution in ppm
|
||||
outStream->writeInt(0); // 0x002A: Vertical resolution in ppm
|
||||
outStream->writeInt(0); // 0x002E: Palette size (0 to match bit depth)
|
||||
outStream->writeInt(0); // 0x0032: Number of important colors, 0 for all
|
||||
|
||||
// Pixels follow in inverted Y order
|
||||
BYTE[] bytes = new BYTE[width * height * 4];
|
||||
data.position(0);
|
||||
data.get(bytes);
|
||||
for (int y = height - 1; y >= 0; y--)
|
||||
{
|
||||
int line = y * width * 4;
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
outStream->writeByte(bytes[line + x * 4 + 2]);
|
||||
outStream->writeByte(bytes[line + x * 4 + 1]);
|
||||
outStream->writeByte(bytes[line + x * 4 + 0]);
|
||||
outStream->writeByte(bytes[line + x * 4 + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
outStream->close();
|
||||
//} catch (IOException e) {
|
||||
// Unable to write to the file for some reason
|
||||
// return;
|
||||
//}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Texture::writeAsPNG(const wstring &filename)
|
||||
{
|
||||
// 4J Don't need
|
||||
#if 0
|
||||
BufferedImage *image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
ByteBuffer *buffer = this->getData();
|
||||
BYTE[] bytes = new BYTE[width * height * 4];
|
||||
|
||||
buffer.position(0);
|
||||
buffer.get(bytes);
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
int pos = (y * width * 4) + x * 4;
|
||||
int col = 0;
|
||||
|
||||
col |= (bytes[pos + 2] & 0xFF) << 0;
|
||||
col |= (bytes[pos + 1] & 0xFF) << 8;
|
||||
col |= (bytes[pos + 0] & 0xFF) << 16;
|
||||
col |= (bytes[pos + 3] & 0xFF) << 24;
|
||||
|
||||
image.setRGB(x, y, col);
|
||||
}
|
||||
}
|
||||
|
||||
data.position(width * height * 4);
|
||||
|
||||
//try {
|
||||
ImageIO::write(image, L"png", new File(Minecraft.getWorkingDirectory(), filename));
|
||||
//} catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
//}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Texture::blit(int x, int y, Texture *source)
|
||||
@@ -365,17 +205,14 @@ void Texture::blit(int x, int y, Texture *source)
|
||||
|
||||
void Texture::blit(int x, int y, Texture *source, bool rotated)
|
||||
{
|
||||
// 4J Remove 3D
|
||||
//if (type == GL_TEXTURE_3D)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
if (source == nullptr) return;
|
||||
|
||||
for(unsigned int level = 0; level < m_iMipLevels; ++level)
|
||||
{
|
||||
ByteBuffer *srcBuffer = source->getData(level);
|
||||
|
||||
if(srcBuffer == nullptr) break;
|
||||
if(srcBuffer == nullptr || data[level] == nullptr)
|
||||
break;
|
||||
|
||||
int yy = y >> level;
|
||||
int xx = x >> level;
|
||||
@@ -384,210 +221,119 @@ void Texture::blit(int x, int y, Texture *source, bool rotated)
|
||||
int shh = source->getHeight() >> level;
|
||||
int sww = source->getWidth() >> level;
|
||||
|
||||
data[level]->position(0);
|
||||
srcBuffer->position(0);
|
||||
unsigned int* dstPixels = (unsigned int*)data[level]->getBuffer();
|
||||
unsigned int* srcPixels = (unsigned int*)srcBuffer->getBuffer();
|
||||
|
||||
#if defined __PS3__ && !defined DISABLE_SPU_CODE
|
||||
if(g_texBlitJobQueuePort->hasCompleted())
|
||||
if (!rotated)
|
||||
{
|
||||
// all outstanding blits have completed, so reset to the start of the blit list
|
||||
g_currentTexBlit = 0;
|
||||
}
|
||||
Texture_blit_DataIn& dataIn = g_textureBlitDataIn[g_currentTexBlit];
|
||||
g_currentTexBlit++;
|
||||
if(g_currentTexBlit >= sc_maxTextureBlits)
|
||||
{
|
||||
app.DebugPrintf("ran out of tex blit slots, stalling for completion\n");
|
||||
g_texBlitJobQueuePort->waitForCompletion();
|
||||
g_currentTexBlit = 0;
|
||||
}
|
||||
dataIn.pSrcData = srcBuffer->getBuffer();
|
||||
dataIn.pDstData = data[level]->getBuffer();
|
||||
dataIn.yy = yy;
|
||||
dataIn.xx = xx;
|
||||
dataIn.hh = hh;
|
||||
dataIn.ww = ww;
|
||||
dataIn.shh = shh;
|
||||
dataIn.sww = sww;
|
||||
dataIn.rotated = rotated;
|
||||
|
||||
C4JSpursJob_Texture_blit blitJob(&dataIn);
|
||||
g_texBlitJobQueuePort->submitJob(&blitJob);
|
||||
// p.waitForCompletion();
|
||||
|
||||
#elif __PSVITA__
|
||||
unsigned int *src = (unsigned int *) srcBuffer->getBuffer();
|
||||
unsigned int *dst = (unsigned int *) data[level]->getBuffer();
|
||||
|
||||
for (int srcY = 0; srcY < shh; srcY++)
|
||||
{
|
||||
int dstY = yy + srcY;
|
||||
int srcLine = srcY * sww;
|
||||
int dstLine = dstY * ww;
|
||||
|
||||
if (rotated)
|
||||
for (int srcY = 0; srcY < shh; srcY++)
|
||||
{
|
||||
dstY = yy + (shh - srcY);
|
||||
int dstY = yy + srcY;
|
||||
|
||||
if (dstY < 0 || dstY >= hh)
|
||||
continue;
|
||||
|
||||
unsigned int* dstRow = dstPixels + (dstY * ww + xx);
|
||||
unsigned int* srcRow = srcPixels + (srcY * sww);
|
||||
|
||||
memcpy(dstRow, srcRow, sww * sizeof(unsigned int));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int srcY = 0; srcY < shh; srcY++)
|
||||
{
|
||||
int dstY = yy + (shh - srcY);
|
||||
if (dstY < 0 || dstY >= hh)
|
||||
continue;
|
||||
|
||||
if (!rotated)
|
||||
{
|
||||
memcpy(dst + dstLine + xx, src + srcLine, sww * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int srcX = 0; srcX < sww; srcX++)
|
||||
{
|
||||
int dstPos = dstLine + (srcX + xx);
|
||||
int srcPos = srcLine + srcX;
|
||||
int dstIndex = xx + (srcX * ww) + dstY;
|
||||
int srcIndex = (srcY * sww) + srcX;
|
||||
|
||||
if (rotated)
|
||||
{
|
||||
dstPos = (xx + srcX * ww) + dstY;
|
||||
}
|
||||
|
||||
dst[dstPos] = src[srcPos];
|
||||
dstPixels[dstIndex] = srcPixels[srcIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
for (int srcY = 0; srcY < shh; srcY++)
|
||||
{
|
||||
int dstY = yy + srcY;
|
||||
int srcLine = srcY * sww * 4;
|
||||
int dstLine = dstY * ww * 4;
|
||||
|
||||
if (rotated)
|
||||
{
|
||||
dstY = yy + (shh - srcY);
|
||||
}
|
||||
|
||||
for (int srcX = 0; srcX < sww; srcX++)
|
||||
{
|
||||
int dstPos = dstLine + (srcX + xx) * 4;
|
||||
int srcPos = srcLine + srcX * 4;
|
||||
|
||||
if (rotated)
|
||||
{
|
||||
dstPos = (xx + srcX * ww * 4) + dstY * 4;
|
||||
}
|
||||
|
||||
data[level]->put(dstPos + 0, srcBuffer->get(srcPos + 0));
|
||||
data[level]->put(dstPos + 1, srcBuffer->get(srcPos + 1));
|
||||
data[level]->put(dstPos + 2, srcBuffer->get(srcPos + 2));
|
||||
data[level]->put(dstPos + 3, srcBuffer->get(srcPos + 3));
|
||||
}
|
||||
}
|
||||
// Don't delete this, as it belongs to the source texture
|
||||
//delete srcBuffer;
|
||||
#endif
|
||||
data[level]->position(ww * hh * 4);
|
||||
}
|
||||
|
||||
if (immediateUpdate)
|
||||
{
|
||||
updateOnGPU();
|
||||
}
|
||||
else
|
||||
{
|
||||
updated = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::transferFromBuffer(intArray buffer)
|
||||
{
|
||||
if (depth == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// #ifdef __PS3__
|
||||
// int byteRemapRGBA[] = { 3, 0, 1, 2 };
|
||||
// int byteRemapBGRA[] = { 3, 2, 1, 0 };
|
||||
// #else
|
||||
data[0]->position(0);
|
||||
|
||||
int byteRemapRGBA[] = { 0, 1, 2, 3 };
|
||||
int byteRemapBGRA[] = { 2, 1, 0, 3 };
|
||||
// #endif
|
||||
|
||||
int *byteRemap = ((format == TFMT_BGRA) ? byteRemapBGRA : byteRemapRGBA);
|
||||
|
||||
for (int z = 0; z < depth; z++)
|
||||
int totalPixels = width * height * depth;
|
||||
|
||||
for (int i = 0; i < totalPixels; i++)
|
||||
{
|
||||
int plane = z * height * width * 4;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
int column = plane + y * width * 4;
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int texel = column + x * 4;
|
||||
data[0]->position(0);
|
||||
data[0]->put(texel + byteRemap[0], static_cast<BYTE>((buffer[texel >> 2] >> 24) & 0xff));
|
||||
data[0]->put(texel + byteRemap[1], static_cast<BYTE>((buffer[texel >> 2] >> 16) & 0xff));
|
||||
data[0]->put(texel + byteRemap[2], static_cast<BYTE>((buffer[texel >> 2] >> 8) & 0xff));
|
||||
data[0]->put(texel + byteRemap[3], static_cast<BYTE>((buffer[texel >> 2] >> 0) & 0xff));
|
||||
}
|
||||
}
|
||||
int byteIndex = i * 4;
|
||||
unsigned int pixel = buffer[i];
|
||||
|
||||
data[0]->put(byteIndex + byteRemap[0], static_cast<BYTE>((pixel >> 24) & 0xff));
|
||||
data[0]->put(byteIndex + byteRemap[1], static_cast<BYTE>((pixel >> 16) & 0xff));
|
||||
data[0]->put(byteIndex + byteRemap[2], static_cast<BYTE>((pixel >> 8) & 0xff));
|
||||
data[0]->put(byteIndex + byteRemap[3], static_cast<BYTE>((pixel >> 0) & 0xff));
|
||||
}
|
||||
|
||||
data[0]->position(width * height * depth * 4);
|
||||
data[0]->position(totalPixels * 4);
|
||||
|
||||
updateOnGPU();
|
||||
}
|
||||
|
||||
void Texture::transferFromImage(BufferedImage *image)
|
||||
{
|
||||
// 4J Remove 3D
|
||||
//if (type == GL_TEXTURE_3D)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
int imgWidth = image->getWidth();
|
||||
int imgHeight = image->getHeight();
|
||||
if (imgWidth > width || imgHeight > height)
|
||||
{
|
||||
//Minecraft::GetInstance().getLogger().warning("transferFromImage called with a BufferedImage with dimensions (" +
|
||||
// imgWidth + ", " + imgHeight + ") larger than the Texture dimensions (" + width +
|
||||
// ", " + height + "). Ignoring.");
|
||||
app.DebugPrintf("transferFromImage called with a BufferedImage with dimensions (%d, %d) larger than the Texture dimensions (%d, %d). Ignoring.\n", imgWidth, imgHeight, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
// #ifdef __PS3__
|
||||
// int byteRemapRGBA[] = { 0, 1, 2, 3 };
|
||||
// int byteRemapBGRA[] = { 2, 1, 0, 3 };
|
||||
// #else
|
||||
#ifdef _XBOX
|
||||
int byteRemapRGBA[] = { 0, 1, 2, 3 };
|
||||
#else
|
||||
int byteRemapRGBA[] = { 3, 0, 1, 2 };
|
||||
#endif
|
||||
int byteRemapBGRA[] = { 3, 2, 1, 0 };
|
||||
// #endif
|
||||
int *byteRemap = ((format == TFMT_BGRA) ? byteRemapBGRA : byteRemapRGBA);
|
||||
|
||||
intArray tempPixels = intArray(width * height);
|
||||
int *byteRemap = ((format == TFMT_BGRA) ? byteRemapBGRA : byteRemapRGBA);
|
||||
int b0 = byteRemap[0], b1 = byteRemap[1], b2 = byteRemap[2], b3 = byteRemap[3];
|
||||
|
||||
int totalPixels = width * height;
|
||||
|
||||
intArray tempPixels = intArray(totalPixels);
|
||||
int transparency = image->getTransparency();
|
||||
image->getRGB(0, 0, width, height, tempPixels, 0, imgWidth);
|
||||
|
||||
byteArray tempBytes = byteArray(width * height * 4);
|
||||
for (int y = 0; y < height; y++)
|
||||
byteArray tempBytes = byteArray(totalPixels * 4);
|
||||
|
||||
BYTE* dst = tempBytes.data;
|
||||
int* src = tempPixels.data;
|
||||
for (int i = 0; i < totalPixels; i++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int intIndex = y * width + x;
|
||||
int byteIndex = intIndex * 4;
|
||||
|
||||
// Pull ARGB bytes into either RGBA or BGRA depending on format
|
||||
|
||||
tempBytes[byteIndex + byteRemap[0]] = static_cast<BYTE>((tempPixels[intIndex] >> 24) & 0xff);
|
||||
tempBytes[byteIndex + byteRemap[1]] = static_cast<BYTE>((tempPixels[intIndex] >> 16) & 0xff);
|
||||
tempBytes[byteIndex + byteRemap[2]] = static_cast<BYTE>((tempPixels[intIndex] >> 8) & 0xff);
|
||||
tempBytes[byteIndex + byteRemap[3]] = static_cast<BYTE>((tempPixels[intIndex] >> 0) & 0xff);
|
||||
}
|
||||
// Pull ARGB bytes into either RGBA or BGRA depending on format
|
||||
unsigned int pixel = src[i];
|
||||
dst[b0] = static_cast<BYTE>((pixel >> 24) & 0xff);
|
||||
dst[b1] = static_cast<BYTE>((pixel >> 16) & 0xff);
|
||||
dst[b2] = static_cast<BYTE>((pixel >> 8) & 0xff);
|
||||
dst[b3] = static_cast<BYTE>((pixel >> 0) & 0xff);
|
||||
dst += 4;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 10; i++ )
|
||||
for(int i = 0; i < m_iMipLevels; i++ )
|
||||
{
|
||||
if(data[i] != nullptr)
|
||||
{
|
||||
@@ -597,11 +343,7 @@ void Texture::transferFromImage(BufferedImage *image)
|
||||
}
|
||||
|
||||
MemSect(51);
|
||||
#ifdef __PS3__
|
||||
data[0] = new ByteBuffer_IO(tempBytes.length);
|
||||
#else
|
||||
data[0] = ByteBuffer::allocateDirect(tempBytes.length);
|
||||
#endif // __{S3__
|
||||
MemSect(0);
|
||||
data[0]->clear();
|
||||
data[0]->put(tempBytes);
|
||||
@@ -612,93 +354,94 @@ void Texture::transferFromImage(BufferedImage *image)
|
||||
if(mipmapped || image->getData(1) != nullptr)
|
||||
{
|
||||
mipmapped = true;
|
||||
|
||||
int maxMipPixels = (width >> 1) * (height >> 1);
|
||||
unsigned int *tempData = new unsigned int[maxMipPixels];
|
||||
|
||||
BYTE* mipBufferData = new BYTE[maxMipPixels * 4];
|
||||
|
||||
for(unsigned int level = 1; level < MAX_MIP_LEVELS; ++level)
|
||||
{
|
||||
int ww = width >> level;
|
||||
int hh = height >> level;
|
||||
int mipPixels = ww * hh;
|
||||
|
||||
byteArray tempBytes = byteArray(ww * hh * 4);
|
||||
unsigned int *tempData = new unsigned int[ww * hh];
|
||||
if (mipPixels == 0)
|
||||
break;
|
||||
|
||||
int mipLength = mipPixels * 4;
|
||||
BYTE* mipDst = mipBufferData;
|
||||
|
||||
if( image->getData( level ) )
|
||||
{
|
||||
memcpy( tempData, image->getData( level ), ww * hh * 4);
|
||||
for (int y = 0; y < hh; y++)
|
||||
memcpy( tempData, image->getData( level ), mipLength);
|
||||
for (int i = 0; i < mipPixels; i++)
|
||||
{
|
||||
for (int x = 0; x < ww; x++)
|
||||
{
|
||||
int intIndex = y * ww + x;
|
||||
int byteIndex = intIndex * 4;
|
||||
|
||||
// Pull ARGB bytes into either RGBA or BGRA depending on format
|
||||
|
||||
tempBytes[byteIndex + byteRemap[0]] = static_cast<BYTE>((tempData[intIndex] >> 24) & 0xff);
|
||||
tempBytes[byteIndex + byteRemap[1]] = static_cast<BYTE>((tempData[intIndex] >> 16) & 0xff);
|
||||
tempBytes[byteIndex + byteRemap[2]] = static_cast<BYTE>((tempData[intIndex] >> 8) & 0xff);
|
||||
tempBytes[byteIndex + byteRemap[3]] = static_cast<BYTE>((tempData[intIndex] >> 0) & 0xff);
|
||||
}
|
||||
// Pull ARGB bytes into either RGBA or BGRA depending on format
|
||||
unsigned int pixel = tempData[i];
|
||||
mipDst[b0] = static_cast<BYTE>((pixel >> 24) & 0xff);
|
||||
mipDst[b1] = static_cast<BYTE>((pixel >> 16) & 0xff);
|
||||
mipDst[b2] = static_cast<BYTE>((pixel >> 8) & 0xff);
|
||||
mipDst[b3] = static_cast<BYTE>((pixel >> 0) & 0xff);
|
||||
mipDst += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int ow = width >> (level - 1);
|
||||
|
||||
for (int x = 0; x < ww; x++)
|
||||
for (int y = 0; y < hh; y++)
|
||||
|
||||
for (int y = 0; y < hh; y++)
|
||||
{
|
||||
for (int x = 0; x < ww; x++)
|
||||
{
|
||||
unsigned int c0 = data[level - 1]->getInt(((x * 2 + 0) + (y * 2 + 0) * ow) * 4);
|
||||
unsigned int c1 = data[level - 1]->getInt(((x * 2 + 1) + (y * 2 + 0) * ow) * 4);
|
||||
unsigned int c2 = data[level - 1]->getInt(((x * 2 + 1) + (y * 2 + 1) * ow) * 4);
|
||||
unsigned int c3 = data[level - 1]->getInt(((x * 2 + 0) + (y * 2 + 1) * ow) * 4);
|
||||
#ifndef _XBOX
|
||||
int baseIndex = (x * 2) + (y * 2) * ow;
|
||||
|
||||
unsigned int c0 = data[level - 1]->getInt((baseIndex) * 4);
|
||||
unsigned int c1 = data[level - 1]->getInt((baseIndex + 1) * 4);
|
||||
unsigned int c2 = data[level - 1]->getInt((baseIndex + 1 + ow) * 4);
|
||||
unsigned int c3 = data[level - 1]->getInt((baseIndex + ow) * 4);
|
||||
|
||||
// 4J - convert our RGBA texels to ARGB that crispBlend is expecting
|
||||
c0 = ( ( c0 >> 8 ) & 0x00ffffff ) | ( c0 << 24 );
|
||||
c1 = ( ( c1 >> 8 ) & 0x00ffffff ) | ( c1 << 24 );
|
||||
c2 = ( ( c2 >> 8 ) & 0x00ffffff ) | ( c2 << 24 );
|
||||
c3 = ( ( c3 >> 8 ) & 0x00ffffff ) | ( c3 << 24 );
|
||||
#endif
|
||||
unsigned int col = crispBlend(crispBlend(c0, c1), crispBlend(c2, c3));
|
||||
// 4J - and back from ARGB -> RGBA
|
||||
//col = ( col << 8 ) | (( col >> 24 ) & 0xff);
|
||||
//tempData[x + y * ww] = col;
|
||||
|
||||
unsigned int intIndex = y * ww + x;
|
||||
unsigned int byteIndex = intIndex * 4;
|
||||
unsigned int col = crispBlend(crispBlend(c0, c1), crispBlend(c2, c3));
|
||||
|
||||
// Pull ARGB bytes into either RGBA or BGRA depending on format
|
||||
|
||||
tempBytes[byteIndex + byteRemap[0]] = static_cast<BYTE>((col >> 24) & 0xff);
|
||||
tempBytes[byteIndex + byteRemap[1]] = static_cast<BYTE>((col >> 16) & 0xff);
|
||||
tempBytes[byteIndex + byteRemap[2]] = static_cast<BYTE>((col >> 8) & 0xff);
|
||||
tempBytes[byteIndex + byteRemap[3]] = static_cast<BYTE>((col >> 0) & 0xff);
|
||||
mipDst[b0] = static_cast<BYTE>((col >> 24) & 0xff);
|
||||
mipDst[b1] = static_cast<BYTE>((col >> 16) & 0xff);
|
||||
mipDst[b2] = static_cast<BYTE>((col >> 8) & 0xff);
|
||||
mipDst[b3] = static_cast<BYTE>((col >> 0) & 0xff);
|
||||
mipDst += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MemSect(51);
|
||||
#ifdef __PS3__
|
||||
data[level] = new ByteBuffer_IO(tempBytes.length);
|
||||
#else
|
||||
data[level] = ByteBuffer::allocateDirect(tempBytes.length);
|
||||
#endif // __{S3__
|
||||
data[level] = ByteBuffer::allocateDirect(mipLength);
|
||||
MemSect(0);
|
||||
|
||||
data[level]->clear();
|
||||
data[level]->put(tempBytes);
|
||||
data[level]->limit(tempBytes.length);
|
||||
delete [] tempBytes.data;
|
||||
delete [] tempData;
|
||||
|
||||
byteArray currentMipBytes;
|
||||
currentMipBytes.data = mipBufferData;
|
||||
currentMipBytes.length = mipLength;
|
||||
|
||||
data[level]->put(currentMipBytes);
|
||||
data[level]->limit(mipLength);
|
||||
}
|
||||
delete [] mipBufferData;
|
||||
delete [] tempData;
|
||||
}
|
||||
|
||||
delete [] tempPixels.data;
|
||||
|
||||
if (immediateUpdate)
|
||||
{
|
||||
updateOnGPU();
|
||||
}
|
||||
else
|
||||
{
|
||||
updated = false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Texture::crispBlend(unsigned int c0, unsigned int c1)
|
||||
@@ -778,115 +521,70 @@ void Texture::setImmediateUpdate(bool immediateUpdate)
|
||||
|
||||
void Texture::bind(int mipMapIndex)
|
||||
{
|
||||
// 4J Removed 3D
|
||||
//if (depth == 1)
|
||||
//{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// glEnable(GL_TEXTURE_3D);
|
||||
//}
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + mipMapIndex);
|
||||
glBindTexture(type, glId);
|
||||
if (!updated)
|
||||
{
|
||||
updateOnGPU();
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::updateOnGPU()
|
||||
{
|
||||
data[0]->flip();
|
||||
if(mipmapped)
|
||||
{
|
||||
for (int level = 1; level < m_iMipLevels; level++)
|
||||
if(data[0] == nullptr)
|
||||
return;
|
||||
|
||||
data[0]->position(0);
|
||||
|
||||
// 4J Added check so we can differentiate between which RenderManager function to call
|
||||
if(!m_bInitialised)
|
||||
{
|
||||
RenderManager.TextureSetTextureLevels(m_iMipLevels); // 4J added
|
||||
|
||||
RenderManager.TextureData(width,height,data[0]->getBuffer(),0,C4JRender::TEXTURE_FORMAT_RxGyBzAw);
|
||||
|
||||
if(mipmapped)
|
||||
{
|
||||
if(data[level] == nullptr) break;
|
||||
|
||||
data[level]->flip();
|
||||
for (int level = 1; level < m_iMipLevels; level++)
|
||||
{
|
||||
if(data[level] == nullptr)
|
||||
break;
|
||||
|
||||
data[level]->position(0);
|
||||
|
||||
int levelWidth = width >> level;
|
||||
int levelHeight = height >> level;
|
||||
|
||||
RenderManager.TextureData(levelWidth,levelHeight,data[level]->getBuffer(),level,C4JRender::TEXTURE_FORMAT_RxGyBzAw);
|
||||
}
|
||||
}
|
||||
|
||||
m_bInitialised = true;
|
||||
}
|
||||
// 4J remove 3D and 1D
|
||||
//if (height != 1 && depth != 1)
|
||||
//{
|
||||
// glTexImage3D(type, 0, format, width, height, depth, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
//}
|
||||
//else if(height != 1)
|
||||
//{
|
||||
// 4J Added check so we can differentiate between which RenderManager function to call
|
||||
if(!m_bInitialised)
|
||||
{
|
||||
RenderManager.TextureSetTextureLevels(m_iMipLevels); // 4J added
|
||||
else
|
||||
{
|
||||
RenderManager.TextureDataUpdate(0, 0,width,height,data[0]->getBuffer(),0);
|
||||
|
||||
#ifdef __PSVITA__
|
||||
// AP - replace the dynamic ram buffer to one that points to a newly allocated video ram texture buffer. This means we don't have to memcpy
|
||||
// the ram based buffer to it any more inside RenderManager.TextureDataUpdate
|
||||
unsigned char *newData = RenderManager.TextureData(width,height,data[0]->getBuffer(),0,C4JRender::TEXTURE_FORMAT_RxGyBzAw);
|
||||
ByteBuffer *oldBuffer = data[0];
|
||||
data[0] = new ByteBuffer(data[0]->getSize(), (BYTE*) newData);
|
||||
delete oldBuffer;
|
||||
newData += width * height * 4;
|
||||
#else
|
||||
RenderManager.TextureData(width,height,data[0]->getBuffer(),0,C4JRender::TEXTURE_FORMAT_RxGyBzAw);
|
||||
#endif
|
||||
|
||||
if(mipmapped)
|
||||
if(mipmapped)
|
||||
{
|
||||
if (RenderManager.TextureGetTextureLevels() > 1)
|
||||
{
|
||||
for (int level = 1; level < m_iMipLevels; level++)
|
||||
{
|
||||
if(data[level] == nullptr)
|
||||
break;
|
||||
|
||||
data[level]->position(0);
|
||||
|
||||
int levelWidth = width >> level;
|
||||
int levelHeight = height >> level;
|
||||
|
||||
#ifdef __PSVITA__
|
||||
// AP - replace the dynamic ram buffer to one that points to a newly allocated video ram texture buffer. This means we don't have to memcpy
|
||||
// the ram based buffer to it any more inside RenderManager.TextureDataUpdate
|
||||
RenderManager.TextureDataUpdate(0, 0,levelWidth,levelHeight,data[level]->getBuffer(),level);
|
||||
ByteBuffer *oldBuffer = data[level];
|
||||
data[level] = new ByteBuffer(data[level]->getSize(), (BYTE*) newData);
|
||||
delete oldBuffer;
|
||||
newData += levelWidth * levelHeight * 4;
|
||||
#else
|
||||
RenderManager.TextureData(levelWidth,levelHeight,data[level]->getBuffer(),level,C4JRender::TEXTURE_FORMAT_RxGyBzAw);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
m_bInitialised = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _XBOX
|
||||
RenderManager.TextureDataUpdate(data[0]->getBuffer(),0);
|
||||
#else
|
||||
RenderManager.TextureDataUpdate(0, 0,width,height,data[0]->getBuffer(),0);
|
||||
#endif
|
||||
|
||||
if(mipmapped)
|
||||
{
|
||||
if (RenderManager.TextureGetTextureLevels() > 1)
|
||||
{
|
||||
for (int level = 1; level < m_iMipLevels; level++)
|
||||
{
|
||||
int levelWidth = width >> level;
|
||||
int levelHeight = height >> level;
|
||||
|
||||
#ifdef _XBOX
|
||||
RenderManager.TextureDataUpdate(data[level]->getBuffer(),level);
|
||||
#else
|
||||
RenderManager.TextureDataUpdate(0, 0,levelWidth,levelHeight,data[level]->getBuffer(),level);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//glTexImage2D(type, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// glTexImage1D(type, 0, format, width, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
//}
|
||||
}
|
||||
|
||||
updated = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -737,26 +737,42 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
|
||||
double d = 0.05;
|
||||
while (xa != 0 && level->getCubes(shared, bb->cloneMove(xa, -1.0, 0))->empty())
|
||||
{
|
||||
if (xa < d && xa >= -d) xa = 0;
|
||||
else if (xa > 0) xa -= d;
|
||||
else xa += d;
|
||||
if (xa < d && xa >= -d)
|
||||
xa = 0;
|
||||
else if (xa > 0)
|
||||
xa -= d;
|
||||
else
|
||||
xa += d;
|
||||
|
||||
xaOrg = xa;
|
||||
}
|
||||
while (za != 0 && level->getCubes(shared, bb->cloneMove(0, -1.0, za))->empty())
|
||||
{
|
||||
if (za < d && za >= -d) za = 0;
|
||||
else if (za > 0) za -= d;
|
||||
else za += d;
|
||||
if (za < d && za >= -d)
|
||||
za = 0;
|
||||
else if (za > 0)
|
||||
za -= d;
|
||||
else
|
||||
za += d;
|
||||
|
||||
zaOrg = za;
|
||||
}
|
||||
while (xa != 0 && za != 0 && level->getCubes(shared, bb->cloneMove(xa, -1.0, za))->empty())
|
||||
{
|
||||
if (xa < d && xa >= -d) xa = 0;
|
||||
else if (xa > 0) xa -= d;
|
||||
else xa += d;
|
||||
if (za < d && za >= -d) za = 0;
|
||||
else if (za > 0) za -= d;
|
||||
else za += d;
|
||||
if (xa < d && xa >= -d)
|
||||
xa = 0;
|
||||
else if (xa > 0)
|
||||
xa -= d;
|
||||
else
|
||||
xa += d;
|
||||
|
||||
if (za < d && za >= -d)
|
||||
za = 0;
|
||||
else if (za > 0)
|
||||
za -= d;
|
||||
else
|
||||
za += d;
|
||||
|
||||
xaOrg = xa;
|
||||
zaOrg = za;
|
||||
}
|
||||
@@ -771,36 +787,30 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
|
||||
{
|
||||
// 4J Stu - It's horrible that the client is doing any movement at all! But if we don't have the chunk
|
||||
// data then all the collision info will be incorrect as well
|
||||
for ( auto& it : *aABBs )
|
||||
for ( const auto& it : *aABBs )
|
||||
ya = it->clipYCollide(bb, ya);
|
||||
bb->move(0, ya, 0);
|
||||
}
|
||||
|
||||
if (!slide && yaOrg != ya)
|
||||
{
|
||||
xa = ya = za = 0;
|
||||
}
|
||||
|
||||
bool og = onGround || (yaOrg != ya && yaOrg < 0);
|
||||
|
||||
for ( auto& it : *aABBs )
|
||||
for ( const auto& it : *aABBs )
|
||||
xa = it->clipXCollide(bb, xa);
|
||||
|
||||
bb->move(xa, 0, 0);
|
||||
|
||||
if (!slide && xaOrg != xa)
|
||||
{
|
||||
xa = ya = za = 0;
|
||||
}
|
||||
|
||||
for ( auto& it : *aABBs )
|
||||
for ( const auto& it : *aABBs )
|
||||
za = it->clipZCollide(bb, za);
|
||||
bb->move(0, 0, za);
|
||||
|
||||
if (!slide && zaOrg != za)
|
||||
{
|
||||
xa = ya = za = 0;
|
||||
}
|
||||
|
||||
if (footSize > 0 && og && (isPlayerSneaking || ySlideOffset < 0.05f) && ((xaOrg != xa) || (zaOrg != za)))
|
||||
{
|
||||
@@ -822,45 +832,35 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
|
||||
{
|
||||
// 4J Stu - It's horrible that the client is doing any movement at all! But if we don't have the chunk
|
||||
// data then all the collision info will be incorrect as well
|
||||
for ( auto& it : *aABBs )
|
||||
for ( const auto& it : *aABBs )
|
||||
ya = it->clipYCollide(bb, ya);
|
||||
bb->move(0, ya, 0);
|
||||
}
|
||||
|
||||
if (!slide && yaOrg != ya)
|
||||
{
|
||||
xa = ya = za = 0;
|
||||
}
|
||||
|
||||
|
||||
for ( auto& it : *aABBs )
|
||||
for ( const auto& it : *aABBs )
|
||||
xa = it->clipXCollide(bb, xa);
|
||||
bb->move(xa, 0, 0);
|
||||
|
||||
if (!slide && xaOrg != xa)
|
||||
{
|
||||
xa = ya = za = 0;
|
||||
}
|
||||
|
||||
for ( auto& it : *aABBs )
|
||||
for ( const auto& it : *aABBs )
|
||||
za = it->clipZCollide(bb, za);
|
||||
bb->move(0, 0, za);
|
||||
|
||||
if (!slide && zaOrg != za)
|
||||
{
|
||||
xa = ya = za = 0;
|
||||
}
|
||||
|
||||
|
||||
if (!slide && yaOrg != ya)
|
||||
{
|
||||
xa = ya = za = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ya = -footSize;
|
||||
// LAND FIRST, then x and z
|
||||
for ( auto& it : *aABBs )
|
||||
for ( const auto& it : *aABBs )
|
||||
ya = it->clipYCollide(bb, ya);
|
||||
bb->move(0, ya, 0);
|
||||
}
|
||||
@@ -874,7 +874,6 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
x = (bb->x0 + bb->x1) / 2.0f;
|
||||
y = bb->y0 + heightOffset - ySlideOffset;
|
||||
z = (bb->z0 + bb->z1) / 2.0f;
|
||||
@@ -885,15 +884,17 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
|
||||
collision = horizontalCollision || verticalCollision;
|
||||
checkFallDamage(ya, onGround);
|
||||
|
||||
if (xaOrg != xa) xd = 0;
|
||||
if (yaOrg != ya) yd = 0;
|
||||
if (zaOrg != za) zd = 0;
|
||||
if (xaOrg != xa)
|
||||
xd = 0;
|
||||
if (yaOrg != ya)
|
||||
yd = 0;
|
||||
if (zaOrg != za)
|
||||
zd = 0;
|
||||
|
||||
double xm = x - xo;
|
||||
double ym = y - yo;
|
||||
double zm = z - zo;
|
||||
|
||||
|
||||
if (makeStepSound() && !isPlayerSneaking && riding == nullptr)
|
||||
{
|
||||
int xt = Mth::floor(x);
|
||||
@@ -904,14 +905,10 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
|
||||
{
|
||||
int renderShape = level->getTileRenderShape(xt, yt - 1, zt);
|
||||
if (renderShape == Tile::SHAPE_FENCE || renderShape == Tile::SHAPE_WALL || renderShape == Tile::SHAPE_FENCE_GATE)
|
||||
{
|
||||
t = level->getTile(xt, yt - 1, zt);
|
||||
}
|
||||
}
|
||||
if (t != Tile::ladder_Id)
|
||||
{
|
||||
ym = 0;
|
||||
}
|
||||
|
||||
walkDist += Mth::sqrt(xm * xm + zm * zm) * 0.6;
|
||||
moveDist += Mth::sqrt(xm * xm + ym * ym + zm * zm) * 0.6;
|
||||
@@ -940,15 +937,14 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
|
||||
if (!water)
|
||||
{
|
||||
onFire++;
|
||||
if (onFire == 0) setOnFire(8);
|
||||
if (onFire == 0)
|
||||
setOnFire(8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (onFire <= 0)
|
||||
{
|
||||
onFire = -flameTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (water && onFire > 0)
|
||||
@@ -967,22 +963,24 @@ void Entity::checkInsideTiles()
|
||||
int y1 = Mth::floor(bb->y1 - 0.001);
|
||||
int z1 = Mth::floor(bb->z1 - 0.001);
|
||||
|
||||
if (level->hasChunksAt(x0, y0, z0, x1, y1, z1))
|
||||
if (!level->hasChunksAt(x0, y0, z0, x1, y1, z1))
|
||||
return;
|
||||
|
||||
auto shared = shared_from_this();
|
||||
for (int x = x0; x <= x1; x++)
|
||||
{
|
||||
for (int x = x0; x <= x1; x++)
|
||||
for (int y = y0; y <= y1; y++)
|
||||
for (int z = z0; z <= z1; z++)
|
||||
{
|
||||
int t = level->getTile(x, y, z);
|
||||
if (t > 0)
|
||||
{
|
||||
Tile::tiles[t]->entityInside(level, x, y, z, shared_from_this());
|
||||
}
|
||||
}
|
||||
for (int y = y0; y <= y1; y++)
|
||||
{
|
||||
for (int z = z0; z <= z1; z++)
|
||||
{
|
||||
int t = level->getTile(x, y, z);
|
||||
if (t > 0)
|
||||
Tile::tiles[t]->entityInside(level, x, y, z, shared);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Entity::playStepSound(int xt, int yt, int zt, int t)
|
||||
{
|
||||
const Tile::SoundType *soundType = Tile::tiles[t]->soundType;
|
||||
@@ -994,10 +992,7 @@ void Entity::playStepSound(int xt, int yt, int zt, int t)
|
||||
unsigned int uiAnimOverrideBitmask=getAnimOverrideBitmask(); // this is masked for custom anim off, and force anim
|
||||
|
||||
if(( uiAnimOverrideBitmask& (1<<HumanoidModel::eAnim_NoLegAnim))!=0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
if (level->getTile(xt, yt + 1, zt) == Tile::topSnow_Id)
|
||||
{
|
||||
@@ -1032,10 +1027,8 @@ void Entity::checkFallDamage(double ya, bool onGround)
|
||||
fallDistance = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ya < 0) fallDistance -= static_cast<float>(ya);
|
||||
}
|
||||
else if (ya < 0)
|
||||
fallDistance -= static_cast<float>(ya);
|
||||
}
|
||||
|
||||
AABB *Entity::getCollideBox()
|
||||
@@ -1046,9 +1039,7 @@ AABB *Entity::getCollideBox()
|
||||
void Entity::burn(int dmg)
|
||||
{
|
||||
if (!fireImmune)
|
||||
{
|
||||
hurt(DamageSource::inFire, dmg);
|
||||
}
|
||||
}
|
||||
|
||||
bool Entity::isFireImmune()
|
||||
@@ -1061,7 +1052,6 @@ void Entity::causeFallDamage(float distance)
|
||||
if (rider.lock() != nullptr) rider.lock()->causeFallDamage(distance);
|
||||
}
|
||||
|
||||
|
||||
bool Entity::isInWaterOrRain()
|
||||
{
|
||||
return wasInWater || (level->isRainingAt( Mth::floor(x), Mth::floor(y), Mth::floor(z)) || level->isRainingAt(Mth::floor(x), Mth::floor(y + bbHeight), Mth::floor(z)));
|
||||
|
||||
@@ -10,6 +10,11 @@ std::deque<DataOutputStream *> McRegionChunkStorage::s_chunkDataQueue;
|
||||
int McRegionChunkStorage::s_runningThreadCount = 0;
|
||||
C4JThread *McRegionChunkStorage::s_saveThreads[3];
|
||||
|
||||
static bool s_running = true;
|
||||
static std::mutex s_queue;
|
||||
static std::condition_variable s_queueC;
|
||||
static std::condition_variable s_waitC;
|
||||
static std::condition_variable s_allSavedC;
|
||||
|
||||
McRegionChunkStorage::McRegionChunkStorage(ConsoleSaveFile *saveFile, const wstring &prefix) : m_prefix( prefix )
|
||||
{
|
||||
@@ -65,9 +70,17 @@ McRegionChunkStorage::McRegionChunkStorage(ConsoleSaveFile *saveFile, const wstr
|
||||
McRegionChunkStorage::~McRegionChunkStorage()
|
||||
{
|
||||
for(auto& it : m_entityData)
|
||||
{
|
||||
delete it.second.data;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_queue);
|
||||
s_running = false;
|
||||
}
|
||||
|
||||
s_queueC.notify_all();
|
||||
s_waitC.notify_all();
|
||||
s_allSavedC.notify_all();
|
||||
WaitForAllSaves();
|
||||
}
|
||||
|
||||
LevelChunk *McRegionChunkStorage::load(Level *level, int x, int z)
|
||||
@@ -193,9 +206,12 @@ void McRegionChunkStorage::save(Level *level, LevelChunk *levelChunk)
|
||||
PIXEndNamedEvent();
|
||||
|
||||
PIXBeginNamedEvent(0,"Updating chunk queue");
|
||||
EnterCriticalSection(&cs_memory);
|
||||
s_chunkDataQueue.push_back(output);
|
||||
LeaveCriticalSection(&cs_memory);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_queue);
|
||||
s_chunkDataQueue.push_back(output);
|
||||
}
|
||||
|
||||
s_queueC.notify_one();
|
||||
PIXEndNamedEvent();
|
||||
}
|
||||
else
|
||||
@@ -333,7 +349,6 @@ void McRegionChunkStorage::staticCtor()
|
||||
//saveThreads[j] = CreateThread(nullptr,0,runSaveThreadProc,&threadData[j],CREATE_SUSPENDED,&threadId[j]);
|
||||
s_saveThreads[i] = new C4JThread(runSaveThreadProc,nullptr,threadName);
|
||||
|
||||
|
||||
//app.DebugPrintf("Created new thread: %s\n",threadName);
|
||||
|
||||
// Threads 1,3 and 5 are generally idle so use them
|
||||
@@ -356,43 +371,42 @@ int McRegionChunkStorage::runSaveThreadProc(LPVOID lpParam)
|
||||
{
|
||||
Compression::CreateNewThreadStorage();
|
||||
|
||||
bool running = true;
|
||||
size_t lastQueueSize = 0;
|
||||
|
||||
DataOutputStream *dos = nullptr;
|
||||
while(running)
|
||||
while(s_running)
|
||||
{
|
||||
if( TryEnterCriticalSection(&cs_memory) )
|
||||
{
|
||||
lastQueueSize = s_chunkDataQueue.size();
|
||||
if(lastQueueSize > 0)
|
||||
{
|
||||
dos = s_chunkDataQueue.front();
|
||||
s_chunkDataQueue.pop_front();
|
||||
}
|
||||
s_runningThreadCount++;
|
||||
LeaveCriticalSection(&cs_memory);
|
||||
std::unique_lock<std::mutex> lock(s_queue);
|
||||
|
||||
s_queueC.wait(lock, []{return !s_chunkDataQueue.empty() || !s_running;});
|
||||
|
||||
if (!s_running && s_chunkDataQueue.empty())
|
||||
break;
|
||||
|
||||
dos = s_chunkDataQueue.front();
|
||||
s_chunkDataQueue.pop_front();
|
||||
s_runningThreadCount++;
|
||||
s_waitC.notify_all();
|
||||
}
|
||||
|
||||
if(dos)
|
||||
{
|
||||
PIXBeginNamedEvent(0,"Saving chunk");
|
||||
//app.DebugPrintf("Compressing chunk data (%d left)\n", lastQueueSize - 1);
|
||||
dos->close();
|
||||
dos->deleteChildStream();
|
||||
PIXEndNamedEvent();
|
||||
|
||||
if(dos)
|
||||
{
|
||||
PIXBeginNamedEvent(0,"Saving chunk");
|
||||
//app.DebugPrintf("Compressing chunk data (%d left)\n", lastQueueSize - 1);
|
||||
dos->close();
|
||||
dos->deleteChildStream();
|
||||
PIXEndNamedEvent();
|
||||
}
|
||||
delete dos;
|
||||
dos = nullptr;
|
||||
|
||||
EnterCriticalSection(&cs_memory);
|
||||
s_runningThreadCount--;
|
||||
LeaveCriticalSection(&cs_memory);
|
||||
}
|
||||
|
||||
// If there was more than one thing in the queue last time we checked, then we want to spin round again soon
|
||||
// Otherwise wait a bit longer
|
||||
if( (lastQueueSize -1) > 0) Sleep(1); // Sleep 1 to yield
|
||||
else Sleep(100);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_queue);
|
||||
s_runningThreadCount--;
|
||||
|
||||
if (s_chunkDataQueue.empty() && s_runningThreadCount == 0)
|
||||
s_allSavedC.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
Compression::ReleaseThreadStorage();
|
||||
@@ -413,33 +427,10 @@ void McRegionChunkStorage::WaitIfTooManyQueuedChunks()
|
||||
// Static
|
||||
void McRegionChunkStorage::WaitForAllSaves()
|
||||
{
|
||||
// Wait for there to be no more tasks to be processed...
|
||||
EnterCriticalSection(&cs_memory);
|
||||
size_t queueSize = s_chunkDataQueue.size();
|
||||
LeaveCriticalSection(&cs_memory);
|
||||
// Wait for there to be no more tasks or threads to be processed...
|
||||
std::unique_lock<std::mutex> lock(s_queue);
|
||||
|
||||
while(queueSize > 0)
|
||||
{
|
||||
Sleep(10);
|
||||
|
||||
EnterCriticalSection(&cs_memory);
|
||||
queueSize = s_chunkDataQueue.size();
|
||||
LeaveCriticalSection(&cs_memory);
|
||||
}
|
||||
|
||||
// And then wait for there to be no running threads that are processing these tasks
|
||||
EnterCriticalSection(&cs_memory);
|
||||
int runningThreadCount = s_runningThreadCount;
|
||||
LeaveCriticalSection(&cs_memory);
|
||||
|
||||
while(runningThreadCount > 0)
|
||||
{
|
||||
Sleep(10);
|
||||
|
||||
EnterCriticalSection(&cs_memory);
|
||||
runningThreadCount = s_runningThreadCount;
|
||||
LeaveCriticalSection(&cs_memory);
|
||||
}
|
||||
s_allSavedC.wait(lock, [] {return s_chunkDataQueue.empty() && (s_runningThreadCount == 0);});
|
||||
}
|
||||
|
||||
// Static
|
||||
@@ -449,19 +440,8 @@ void McRegionChunkStorage::WaitForSaves()
|
||||
static const int DESIRED_QUEUE_SIZE = 6;
|
||||
|
||||
// Wait for the queue to reduce to a level where we should add more elements
|
||||
EnterCriticalSection(&cs_memory);
|
||||
size_t queueSize = s_chunkDataQueue.size();
|
||||
LeaveCriticalSection(&cs_memory);
|
||||
std::unique_lock<std::mutex> lock(s_queue);
|
||||
|
||||
if( queueSize > MAX_QUEUE_SIZE )
|
||||
{
|
||||
while( queueSize > DESIRED_QUEUE_SIZE )
|
||||
{
|
||||
Sleep(10);
|
||||
|
||||
EnterCriticalSection(&cs_memory);
|
||||
queueSize = s_chunkDataQueue.size();
|
||||
LeaveCriticalSection(&cs_memory);
|
||||
}
|
||||
}
|
||||
if( s_chunkDataQueue.size() > MAX_QUEUE_SIZE )
|
||||
s_waitC.wait(lock, [] {return s_chunkDataQueue.size() <= DESIRED_QUEUE_SIZE;});
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using namespace std;
|
||||
#include "RegionFileCache.h"
|
||||
#include "com.mojang.nbt.h"
|
||||
#include "OldChunkStorage.h"
|
||||
#include <condition_variable>
|
||||
|
||||
class ConsoleSaveFile;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user