mirror of
https://github.com/minetest/irrlicht.git
synced 2025-07-01 15:50:27 +02:00
Merging r6288 through r6336 from trunk to ogl-es branch
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6337 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
@ -206,7 +206,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||
// As multiple scene nodes may be sharing the same skinned mesh, we have to
|
||||
// re-animate it every frame to ensure that this node gets the mesh that it needs.
|
||||
|
||||
CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh);
|
||||
CSkinnedMesh* skinnedMesh = static_cast<CSkinnedMesh*>(Mesh);
|
||||
|
||||
if (JointMode == EJUOR_CONTROL)//write to mesh
|
||||
skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
|
||||
@ -949,7 +949,7 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
|
||||
checkJoints();
|
||||
const f32 frame = getFrameNr(); //old?
|
||||
|
||||
CSkinnedMesh* skinnedMesh=reinterpret_cast<CSkinnedMesh*>(Mesh);
|
||||
CSkinnedMesh* skinnedMesh=static_cast<CSkinnedMesh*>(Mesh);
|
||||
|
||||
skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes );
|
||||
skinnedMesh->animateMesh(frame, 1.0f);
|
||||
|
@ -72,6 +72,20 @@ public:
|
||||
//! Get the real boundingbox used by the billboard (which depends on the active camera)
|
||||
virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) IRR_OVERRIDE;
|
||||
|
||||
//! Get the amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const IRR_OVERRIDE
|
||||
{
|
||||
return Buffer ? 1 : 0;
|
||||
}
|
||||
|
||||
//! Get pointer to the mesh buffer.
|
||||
virtual IMeshBuffer* getMeshBuffer(u32 nr) const IRR_OVERRIDE
|
||||
{
|
||||
if ( nr == 0 )
|
||||
return Buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const IRR_OVERRIDE;
|
||||
|
||||
|
@ -37,9 +37,10 @@ namespace scene
|
||||
//! constructor
|
||||
CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id, const core::vector3df& position,
|
||||
const core::vector3df& rotation, const core::vector3df& scale)
|
||||
const core::vector3df& rotation, const core::vector3df& scale,
|
||||
ECUBE_MESH_TYPE type)
|
||||
: IMeshSceneNode(parent, mgr, id, position, rotation, scale),
|
||||
Mesh(0), Shadow(0), Size(size)
|
||||
Mesh(0), Shadow(0), Size(size), MeshType(type)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCubeSceneNode");
|
||||
@ -62,7 +63,7 @@ void CCubeSceneNode::setSize()
|
||||
{
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size));
|
||||
Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size), MeshType);
|
||||
}
|
||||
|
||||
|
||||
@ -135,7 +136,7 @@ const core::aabbox3d<f32>& CCubeSceneNode::getBoundingBox() const
|
||||
|
||||
//! Removes a child from this scene node.
|
||||
//! Implemented here, to be able to remove the shadow properly, if there is one,
|
||||
//! or to remove attached childs.
|
||||
//! or to remove attached child.
|
||||
bool CCubeSceneNode::removeChild(ISceneNode* child)
|
||||
{
|
||||
if (child && Shadow == child)
|
||||
@ -199,17 +200,20 @@ void CCubeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeRea
|
||||
ISceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addFloat("Size", Size);
|
||||
out->addEnum("MeshType", (irr::s32)MeshType, CubeMeshTypeNames);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CCubeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
f32 newSize = in->getAttributeAsFloat("Size");
|
||||
f32 newSize = in->getAttributeAsFloat("Size", Size);
|
||||
ECUBE_MESH_TYPE newMeshType = (ECUBE_MESH_TYPE)in->getAttributeAsEnumeration("MeshType", CubeMeshTypeNames, (irr::s32)MeshType);
|
||||
newSize = core::max_(newSize, 0.0001f);
|
||||
if (newSize != Size)
|
||||
if (newSize != Size || newMeshType != MeshType)
|
||||
{
|
||||
Size = newSize;
|
||||
MeshType = newMeshType;
|
||||
setSize();
|
||||
}
|
||||
|
||||
@ -226,7 +230,7 @@ ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag
|
||||
newManager = SceneManager;
|
||||
|
||||
CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent,
|
||||
newManager, ID, RelativeTranslation);
|
||||
newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale, MeshType);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->getMaterial(0) = getMaterial(0);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "IMeshSceneNode.h"
|
||||
#include "SMesh.h"
|
||||
#include "IGeometryCreator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -20,7 +21,8 @@ namespace scene
|
||||
CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position = core::vector3df(0,0,0),
|
||||
const core::vector3df& rotation = core::vector3df(0,0,0),
|
||||
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f),
|
||||
ECUBE_MESH_TYPE type=ECMT_1BUF_12VTX_NA);
|
||||
|
||||
virtual ~CCubeSceneNode();
|
||||
|
||||
@ -84,6 +86,7 @@ namespace scene
|
||||
IMesh* Mesh;
|
||||
IShadowVolumeSceneNode* Shadow;
|
||||
f32 Size;
|
||||
ECUBE_MESH_TYPE MeshType;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
|
@ -1192,7 +1192,7 @@ void CD3D9Driver::removeOcclusionQuery(scene::ISceneNode* node)
|
||||
if (index != -1)
|
||||
{
|
||||
if (OcclusionQueries[index].PID != 0)
|
||||
reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Release();
|
||||
static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Release();
|
||||
CNullDriver::removeOcclusionQuery(node);
|
||||
}
|
||||
}
|
||||
@ -1210,10 +1210,10 @@ void CD3D9Driver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
|
||||
if (index != -1)
|
||||
{
|
||||
if (OcclusionQueries[index].PID)
|
||||
reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_BEGIN);
|
||||
static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_BEGIN);
|
||||
CNullDriver::runOcclusionQuery(node,visible);
|
||||
if (OcclusionQueries[index].PID)
|
||||
reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_END);
|
||||
static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_END);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1232,12 +1232,12 @@ void CD3D9Driver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
|
||||
bool available = block?true:false;
|
||||
int tmp=0;
|
||||
if (!block)
|
||||
available=(reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), 0)==S_OK);
|
||||
available=(static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), 0)==S_OK);
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
HRESULT hr = reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), D3DGETDATA_FLUSH);
|
||||
HRESULT hr = static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), D3DGETDATA_FLUSH);
|
||||
available = (hr == S_OK);
|
||||
if (hr!=S_FALSE)
|
||||
break;
|
||||
@ -2946,7 +2946,7 @@ bool CD3D9Driver::reset()
|
||||
{
|
||||
if (OcclusionQueries[i].PID)
|
||||
{
|
||||
reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[i].PID)->Release();
|
||||
static_cast<IDirect3DQuery9*>(OcclusionQueries[i].PID)->Release();
|
||||
OcclusionQueries[i].PID=0;
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,69 @@ IMesh* CGeometryCreator::createCubeMesh(const core::vector3df& size, ECUBE_MESH_
|
||||
buffer->drop();
|
||||
}
|
||||
}
|
||||
else if ( type == ECMT_1BUF_24VTX_NP )
|
||||
{
|
||||
SMeshBuffer* buffer = new SMeshBuffer();
|
||||
|
||||
// Create indices (pos, neg describes normal direction of front-face)
|
||||
const u16 u[36] = { 0,2,1, 0,3,2, // NEG_Z
|
||||
4,7,6, 4,5,7, // POS_X
|
||||
8,10,11, 8,9,10, // POS_Z
|
||||
15,13,12, 15,14,13, // NEG_X
|
||||
19,17,16, 19,18,17, // POS_Y
|
||||
20,23,22, 20,22,21}; // NEG_Y
|
||||
|
||||
buffer->Indices.set_used(36);
|
||||
|
||||
for (u32 i=0; i<36; ++i)
|
||||
buffer->Indices[i] = u[i];
|
||||
|
||||
// Create vertices
|
||||
buffer->Vertices.reallocate(24);
|
||||
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,0,0, 0, 0,-1, clr, 0, 1)); // 0
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,0,0, 0, 0,-1, clr, 1, 1)); // 1
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,1,0, 0, 0,-1, clr, 1, 0)); // 2
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,1,0, 0, 0,-1, clr, 0, 0)); // 3
|
||||
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,0,0, 1, 0, 0, clr, 1, 1)); // 4 (1)
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,1,0, 1, 0, 0, clr, 1, 0)); // 5 (2)
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,0,1, 1, 0, 0, clr, 0, 1)); // 6 (4)
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,1,1, 1, 0, 0, clr, 0, 0)); // 7 (5)
|
||||
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,0,1, 0, 0, 1, clr, 0, 1)); // 8 (4)
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,1,1, 0, 0, 1, clr, 0, 0)); // 9 (5)
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,1,1, 0, 0, 1, clr, 1, 0)); // 10 (6)
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,0,1, 0, 0, 1, clr, 1, 1)); // 11 (7)
|
||||
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,0,0, -1, 0, 0, clr, 0, 1)); // 12 (0)
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,1,0, -1, 0, 0, clr, 0, 0)); // 13 (3)
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,1,1, -1, 0, 0, clr, 1, 0)); // 14 (6)
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,0,1, -1, 0, 0, clr, 1, 1)); // 15 (7)
|
||||
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,1,0, 0, 1, 0, clr, 1, 0)); // 16 (2)
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,1,1, 0, 1, 0, clr, 0, 0)); // 17 (5)
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,1,1, 0, 1, 0, clr, 0, 1)); // 18 (8)
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,1,0, 0, 1, 0, clr, 1, 1)); // 19 (9)
|
||||
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,0,0, 0,-1, 0, clr, 0, 1)); // 20 (0)
|
||||
buffer->Vertices.push_back(video::S3DVertex(0,0,1, 0,-1, 0, clr, 1, 1)); // 21 (7)
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,0,1, 0,-1, 0, clr, 1, 0)); // 22 (10)
|
||||
buffer->Vertices.push_back(video::S3DVertex(1,0,0, 0,-1, 0, clr, 0, 0)); // 23 (11)
|
||||
|
||||
// Recalculate bounding box and set cube size
|
||||
buffer->BoundingBox.reset(0,0,0);
|
||||
|
||||
for (u32 i=0; i<24; ++i)
|
||||
{
|
||||
buffer->Vertices[i].Pos -= core::vector3df(0.5f, 0.5f, 0.5f);
|
||||
buffer->Vertices[i].Pos *= size;
|
||||
buffer->BoundingBox.addInternalPoint(buffer->Vertices[i].Pos);
|
||||
}
|
||||
|
||||
mesh->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
|
||||
mesh->recalculateBoundingBox();
|
||||
return mesh;
|
||||
|
@ -347,6 +347,60 @@ void CImage::fill(const SColor &color)
|
||||
memset32( Data, c, getImageDataSizeInBytes() );
|
||||
}
|
||||
|
||||
void CImage::flip(bool topBottom, bool leftRight)
|
||||
{
|
||||
if ( !topBottom && !leftRight)
|
||||
return;
|
||||
|
||||
const core::dimension2du dim(getDimension());
|
||||
if ( dim.Width == 0 || dim.Height == 0 )
|
||||
return;
|
||||
|
||||
u8* data = (u8*)getData();
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
const u32 bpp = getBytesPerPixel();
|
||||
const u32 pitch = getPitch();
|
||||
|
||||
if ( topBottom )
|
||||
{
|
||||
for ( u32 i=0; i<dim.Height/2; ++i)
|
||||
{
|
||||
// Reverse bottom/top lines
|
||||
u8* l1 = data+i*pitch;
|
||||
u8* l2 = data+(dim.Height-1-i)*pitch;
|
||||
for ( u32 b=0; b<pitch; ++b)
|
||||
{
|
||||
irr::u8 dummy = *l1;
|
||||
*l1 = *l2;
|
||||
*l2 = dummy;
|
||||
++l1;
|
||||
++l2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( leftRight )
|
||||
{
|
||||
for ( u32 i=0; i<dim.Height; ++i)
|
||||
{
|
||||
// Reverse left/right for each line
|
||||
u8* l1 = data+i*pitch;
|
||||
u8* l2 = l1+(dim.Width-1)*bpp;
|
||||
for ( u32 p=0; p<dim.Width/2; ++p)
|
||||
{
|
||||
for ( u32 b=0; b<bpp; ++b)
|
||||
{
|
||||
irr::u8 dummy = l1[b];
|
||||
l1[b] = l2[b];
|
||||
l2[b] = dummy;
|
||||
}
|
||||
l1 += bpp;
|
||||
l2 -= bpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! get a filtered pixel
|
||||
inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const
|
||||
|
@ -55,6 +55,9 @@ public:
|
||||
//! copies this surface into another, scaling it to fit, applying a box filter
|
||||
virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) IRR_OVERRIDE;
|
||||
|
||||
//! Flips (mirrors) the image in one or two directions
|
||||
virtual void flip(bool topBottom, bool leftRight) IRR_OVERRIDE;
|
||||
|
||||
//! fills the surface with given color
|
||||
virtual void fill(const SColor &color) IRR_OVERRIDE;
|
||||
|
||||
|
@ -1354,7 +1354,7 @@ bool CIrrDeviceWin32::present(video::IImage* image, void* windowId, core::rect<s
|
||||
{
|
||||
HWND hwnd = HWnd;
|
||||
if ( windowId )
|
||||
hwnd = reinterpret_cast<HWND>(windowId);
|
||||
hwnd = static_cast<HWND>(windowId);
|
||||
|
||||
HDC dc = GetDC(hwnd);
|
||||
|
||||
|
@ -577,8 +577,7 @@ void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resoluti
|
||||
}
|
||||
|
||||
|
||||
//! Clones a static IMesh into a modifyable SMesh.
|
||||
// not yet 32bit
|
||||
//! Clones a static IMesh into a modifiable SMesh.
|
||||
SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const
|
||||
{
|
||||
if (!mesh)
|
||||
@ -590,66 +589,10 @@ SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const
|
||||
|
||||
for ( u32 b=0; b<meshBufferCount; ++b)
|
||||
{
|
||||
const IMeshBuffer* const mb = mesh->getMeshBuffer(b);
|
||||
switch(mb->getVertexType())
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
{
|
||||
SMeshBuffer* buffer = new SMeshBuffer();
|
||||
buffer->Material = mb->getMaterial();
|
||||
const u32 vcount = mb->getVertexCount();
|
||||
buffer->Vertices.reallocate(vcount);
|
||||
video::S3DVertex* vertices = (video::S3DVertex*)mb->getVertices();
|
||||
for (u32 i=0; i < vcount; ++i)
|
||||
buffer->Vertices.push_back(vertices[i]);
|
||||
const u32 icount = mb->getIndexCount();
|
||||
buffer->Indices.reallocate(icount);
|
||||
const u16* indices = mb->getIndices();
|
||||
for (u32 i=0; i < icount; ++i)
|
||||
buffer->Indices.push_back(indices[i]);
|
||||
clone->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
{
|
||||
SMeshBufferLightMap* buffer = new SMeshBufferLightMap();
|
||||
buffer->Material = mb->getMaterial();
|
||||
const u32 vcount = mb->getVertexCount();
|
||||
buffer->Vertices.reallocate(vcount);
|
||||
video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)mb->getVertices();
|
||||
for (u32 i=0; i < vcount; ++i)
|
||||
buffer->Vertices.push_back(vertices[i]);
|
||||
const u32 icount = mb->getIndexCount();
|
||||
buffer->Indices.reallocate(icount);
|
||||
const u16* indices = mb->getIndices();
|
||||
for (u32 i=0; i < icount; ++i)
|
||||
buffer->Indices.push_back(indices[i]);
|
||||
clone->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
{
|
||||
SMeshBufferTangents* buffer = new SMeshBufferTangents();
|
||||
buffer->Material = mb->getMaterial();
|
||||
const u32 vcount = mb->getVertexCount();
|
||||
buffer->Vertices.reallocate(vcount);
|
||||
video::S3DVertexTangents* vertices = (video::S3DVertexTangents*)mb->getVertices();
|
||||
for (u32 i=0; i < vcount; ++i)
|
||||
buffer->Vertices.push_back(vertices[i]);
|
||||
const u32 icount = mb->getIndexCount();
|
||||
buffer->Indices.reallocate(icount);
|
||||
const u16* indices = mb->getIndices();
|
||||
for (u32 i=0; i < icount; ++i)
|
||||
buffer->Indices.push_back(indices[i]);
|
||||
clone->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
break;
|
||||
}// end switch
|
||||
|
||||
}// end for all mesh buffers
|
||||
IMeshBuffer* bufferClone = mesh->getMeshBuffer(b)->createClone();
|
||||
clone->addMeshBuffer(bufferClone);
|
||||
bufferClone->drop();
|
||||
}
|
||||
|
||||
clone->BoundingBox = mesh->getBoundingBox();
|
||||
return clone;
|
||||
|
@ -441,10 +441,7 @@ ITexture* CNullDriver::addTexture(const core::dimension2d<u32>& size, const io::
|
||||
IImage* image = new CImage(format, size);
|
||||
ITexture* t = 0;
|
||||
|
||||
core::array<IImage*> imageArray(1);
|
||||
imageArray.push_back(image);
|
||||
|
||||
if (checkImage(imageArray))
|
||||
if (checkImage(image->getColorFormat(), image->getDimension()))
|
||||
{
|
||||
t = createDeviceDependentTexture(name, image);
|
||||
}
|
||||
@ -473,18 +470,14 @@ ITexture* CNullDriver::addTexture(const io::path& name, IImage* image)
|
||||
|
||||
ITexture* t = 0;
|
||||
|
||||
core::array<IImage*> imageArray(1);
|
||||
imageArray.push_back(image);
|
||||
|
||||
if (checkImage(imageArray))
|
||||
if (checkImage(image->getColorFormat(), image->getDimension()))
|
||||
{
|
||||
t = createDeviceDependentTexture(name, image);
|
||||
}
|
||||
|
||||
if (t)
|
||||
{
|
||||
addTexture(t);
|
||||
t->drop();
|
||||
if (t)
|
||||
{
|
||||
addTexture(t);
|
||||
t->drop();
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
@ -509,12 +502,11 @@ ITexture* CNullDriver::addTextureCubemap(const io::path& name, IImage* imagePosX
|
||||
if (checkImage(imageArray))
|
||||
{
|
||||
t = createDeviceDependentTextureCubemap(name, imageArray);
|
||||
}
|
||||
|
||||
if (t)
|
||||
{
|
||||
addTexture(t);
|
||||
t->drop();
|
||||
if (t)
|
||||
{
|
||||
addTexture(t);
|
||||
t->drop();
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
@ -1434,88 +1426,91 @@ bool CNullDriver::checkPrimitiveCount(u32 prmCount) const
|
||||
|
||||
bool CNullDriver::checkImage(const core::array<IImage*>& image) const
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
if (image.size() > 0)
|
||||
{
|
||||
ECOLOR_FORMAT lastFormat = image[0]->getColorFormat();
|
||||
core::dimension2d<u32> lastSize = image[0]->getDimension();
|
||||
|
||||
for (u32 i = 0; i < image.size() && status; ++i)
|
||||
for (u32 i = 0; i < image.size(); ++i)
|
||||
{
|
||||
ECOLOR_FORMAT format = image[i]->getColorFormat();
|
||||
core::dimension2d<u32> size = image[i]->getDimension();
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case ECF_DXT1:
|
||||
case ECF_DXT2:
|
||||
case ECF_DXT3:
|
||||
case ECF_DXT4:
|
||||
case ECF_DXT5:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
|
||||
{
|
||||
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
|
||||
status = false;
|
||||
}
|
||||
else if (size.getOptimalSize(true, false) != size)
|
||||
{
|
||||
os::Printer::log("Invalid size of image for DXT texture, size of image must be power of two.", ELL_ERROR);
|
||||
status = false;
|
||||
}
|
||||
break;
|
||||
case ECF_PVRTC_RGB2:
|
||||
case ECF_PVRTC_ARGB2:
|
||||
case ECF_PVRTC_RGB4:
|
||||
case ECF_PVRTC_ARGB4:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC))
|
||||
{
|
||||
os::Printer::log("PVRTC texture compression not available.", ELL_ERROR);
|
||||
status = false;
|
||||
}
|
||||
else if (size.getOptimalSize(true, false) != size)
|
||||
{
|
||||
os::Printer::log("Invalid size of image for PVRTC compressed texture, size of image must be power of two and squared.", ELL_ERROR);
|
||||
status = false;
|
||||
}
|
||||
break;
|
||||
case ECF_PVRTC2_ARGB2:
|
||||
case ECF_PVRTC2_ARGB4:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC2))
|
||||
{
|
||||
os::Printer::log("PVRTC2 texture compression not available.", ELL_ERROR);
|
||||
status = false;
|
||||
}
|
||||
break;
|
||||
case ECF_ETC1:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC1))
|
||||
{
|
||||
os::Printer::log("ETC1 texture compression not available.", ELL_ERROR);
|
||||
status = false;
|
||||
}
|
||||
break;
|
||||
case ECF_ETC2_RGB:
|
||||
case ECF_ETC2_ARGB:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC2))
|
||||
{
|
||||
os::Printer::log("ETC2 texture compression not available.", ELL_ERROR);
|
||||
status = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (format != lastFormat || size != lastSize)
|
||||
status = false;
|
||||
return false;
|
||||
|
||||
if ( !checkImage(format, size) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CNullDriver::checkImage(ECOLOR_FORMAT format, const core::dimension2du& size) const
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
status = false;
|
||||
case ECF_DXT1:
|
||||
case ECF_DXT2:
|
||||
case ECF_DXT3:
|
||||
case ECF_DXT4:
|
||||
case ECF_DXT5:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
|
||||
{
|
||||
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
else if (size.getOptimalSize(true, false) != size)
|
||||
{
|
||||
os::Printer::log("Invalid size of image for DXT texture, size of image must be power of two.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ECF_PVRTC_RGB2:
|
||||
case ECF_PVRTC_ARGB2:
|
||||
case ECF_PVRTC_RGB4:
|
||||
case ECF_PVRTC_ARGB4:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC))
|
||||
{
|
||||
os::Printer::log("PVRTC texture compression not available.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
else if (size.getOptimalSize(true, false) != size)
|
||||
{
|
||||
os::Printer::log("Invalid size of image for PVRTC compressed texture, size of image must be power of two and squared.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ECF_PVRTC2_ARGB2:
|
||||
case ECF_PVRTC2_ARGB4:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC2))
|
||||
{
|
||||
os::Printer::log("PVRTC2 texture compression not available.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ECF_ETC1:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC1))
|
||||
{
|
||||
os::Printer::log("ETC1 texture compression not available.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ECF_ETC2_RGB:
|
||||
case ECF_ETC2_ARGB:
|
||||
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC2))
|
||||
{
|
||||
os::Printer::log("ETC2 texture compression not available.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Enables or disables a texture creation flag.
|
||||
@ -2097,10 +2092,10 @@ s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* na
|
||||
|
||||
|
||||
//! Sets the name of a material renderer.
|
||||
void CNullDriver::setMaterialRendererName(s32 idx, const char* name)
|
||||
void CNullDriver::setMaterialRendererName(u32 idx, const char* name)
|
||||
{
|
||||
if (idx < s32(sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ||
|
||||
idx >= (s32)MaterialRenderers.size())
|
||||
if (idx < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ||
|
||||
idx >= MaterialRenderers.size())
|
||||
return;
|
||||
|
||||
MaterialRenderers[idx].Name = name;
|
||||
|
@ -616,7 +616,7 @@ namespace video
|
||||
virtual bool writeImageToFile(IImage* image, io::IWriteFile * file, u32 param = 0) IRR_OVERRIDE;
|
||||
|
||||
//! Sets the name of a material renderer.
|
||||
virtual void setMaterialRendererName(s32 idx, const char* name) IRR_OVERRIDE;
|
||||
virtual void setMaterialRendererName(u32 idx, const char* name) IRR_OVERRIDE;
|
||||
|
||||
//! Swap the material renderers used for certain id's
|
||||
virtual void swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames) IRR_OVERRIDE;
|
||||
@ -710,6 +710,7 @@ namespace video
|
||||
bool checkPrimitiveCount(u32 prmcnt) const;
|
||||
|
||||
bool checkImage(const core::array<IImage*>& image) const;
|
||||
bool checkImage(ECOLOR_FORMAT format, const core::dimension2du& size) const;
|
||||
|
||||
// adds a material renderer and drops it afterwards. To be used for internal creation
|
||||
s32 addAndDropMaterialRenderer(IMaterialRenderer* m);
|
||||
|
@ -82,7 +82,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
core::array<core::vector3df, core::irrAllocatorFast<core::vector3df> > normalsBuffer(1000);
|
||||
core::array<core::vector2df, core::irrAllocatorFast<core::vector2df> > textureCoordBuffer(1000);
|
||||
|
||||
SObjMtl * currMtl = new SObjMtl();
|
||||
SObjMtl * currMtl = new SObjMtl(PreferredIndexType);
|
||||
Materials.push_back(currMtl);
|
||||
u32 smoothingGroup=0;
|
||||
|
||||
@ -224,6 +224,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
v.Color = currMtl->Meshbuffer->Material.DiffuseColor;
|
||||
|
||||
// get all vertices data in this face (current line of obj file)
|
||||
IVertexBuffer& mbVertexBuffer = currMtl->Meshbuffer->getVertexBuffer();
|
||||
IIndexBuffer& mbIndexBuffer = currMtl->Meshbuffer->getIndexBuffer();
|
||||
const core::stringc wordBuffer = copyLine(bufPtr, bufEnd);
|
||||
const c8* linePtr = wordBuffer.c_str();
|
||||
const c8* const endPtr = linePtr+wordBuffer.size();
|
||||
@ -272,8 +274,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
}
|
||||
else
|
||||
{
|
||||
currMtl->Meshbuffer->Vertices.push_back(v);
|
||||
vertLocation = currMtl->Meshbuffer->Vertices.size() -1;
|
||||
mbVertexBuffer.push_back(v);
|
||||
vertLocation = mbVertexBuffer.size() -1;
|
||||
currMtl->VertMap.insert(v, vertLocation);
|
||||
}
|
||||
|
||||
@ -292,9 +294,9 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
const int b = faceCorners[i];
|
||||
if (a != b && a != c && b != c) // ignore degenerated faces. We can get them when we merge vertices above in the VertMap.
|
||||
{
|
||||
currMtl->Meshbuffer->Indices.push_back(a);
|
||||
currMtl->Meshbuffer->Indices.push_back(b);
|
||||
currMtl->Meshbuffer->Indices.push_back(c);
|
||||
mbIndexBuffer.push_back(a);
|
||||
mbIndexBuffer.push_back(b);
|
||||
mbIndexBuffer.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -577,7 +579,7 @@ void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath)
|
||||
c8 mtlNameBuf[WORD_BUFFER_LENGTH];
|
||||
bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
|
||||
|
||||
currMaterial = new SObjMtl;
|
||||
currMaterial = new SObjMtl(PreferredIndexType);
|
||||
currMaterial->Name = mtlNameBuf;
|
||||
}
|
||||
break;
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "IFileSystem.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "irrString.h"
|
||||
#include "SMeshBuffer.h"
|
||||
#include "CDynamicMeshBuffer.h"
|
||||
#include "irrMap.h"
|
||||
|
||||
namespace irr
|
||||
@ -42,10 +42,10 @@ private:
|
||||
|
||||
struct SObjMtl
|
||||
{
|
||||
SObjMtl() : Meshbuffer(0), Bumpiness (1.0f), Illumination(0),
|
||||
SObjMtl(irr::video::E_INDEX_TYPE indexType) : IndexType(indexType), Meshbuffer(0), Bumpiness (1.0f), Illumination(0),
|
||||
RecalculateNormals(false)
|
||||
{
|
||||
Meshbuffer = new SMeshBuffer();
|
||||
Meshbuffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, IndexType);
|
||||
Meshbuffer->Material.Shininess = 0.0f;
|
||||
Meshbuffer->Material.AmbientColor = video::SColorf(0.2f, 0.2f, 0.2f, 1.0f).toSColor();
|
||||
Meshbuffer->Material.DiffuseColor = video::SColorf(0.8f, 0.8f, 0.8f, 1.0f).toSColor();
|
||||
@ -53,16 +53,17 @@ private:
|
||||
}
|
||||
|
||||
SObjMtl(const SObjMtl& o)
|
||||
: Name(o.Name), Group(o.Group),
|
||||
: IndexType(o.IndexType), Name(o.Name), Group(o.Group),
|
||||
Bumpiness(o.Bumpiness), Illumination(o.Illumination),
|
||||
RecalculateNormals(false)
|
||||
{
|
||||
Meshbuffer = new SMeshBuffer();
|
||||
Meshbuffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, IndexType);
|
||||
Meshbuffer->Material = o.Meshbuffer->Material;
|
||||
}
|
||||
|
||||
core::map<video::S3DVertex, int> VertMap;
|
||||
scene::SMeshBuffer *Meshbuffer;
|
||||
irr::video::E_INDEX_TYPE IndexType;
|
||||
scene::CDynamicMeshBuffer *Meshbuffer;
|
||||
core::stringc Name;
|
||||
core::stringc Group;
|
||||
f32 Bumpiness;
|
||||
|
@ -127,11 +127,26 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
|
||||
file->write(num.c_str(), num.size());
|
||||
file->write("\n",1);
|
||||
|
||||
unsigned int idx2=0, idx1=0, idx0 = 0;
|
||||
const u32 indexCount = buffer->getIndexCount();
|
||||
for (j=0; j<indexCount; j+=3)
|
||||
{
|
||||
switch(buffer->getIndexType())
|
||||
{
|
||||
case video::EIT_16BIT:
|
||||
idx2 = buffer->getIndices()[j+2]+allVertexCount;
|
||||
idx1 = buffer->getIndices()[j+1]+allVertexCount;
|
||||
idx0 = buffer->getIndices()[j+0]+allVertexCount;
|
||||
break;
|
||||
case video::EIT_32BIT:
|
||||
idx2 = ((u32*)buffer->getIndices())[j+2]+allVertexCount;
|
||||
idx1 = ((u32*)buffer->getIndices())[j+1]+allVertexCount;
|
||||
idx0 = ((u32*)buffer->getIndices())[j+0]+allVertexCount;
|
||||
break;
|
||||
}
|
||||
|
||||
file->write("f ",2);
|
||||
num = core::stringc(buffer->getIndices()[j+2]+allVertexCount);
|
||||
num = core::stringc(idx2);
|
||||
file->write(num.c_str(), num.size());
|
||||
file->write("/",1);
|
||||
file->write(num.c_str(), num.size());
|
||||
@ -139,7 +154,7 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
|
||||
file->write(num.c_str(), num.size());
|
||||
file->write(" ",1);
|
||||
|
||||
num = core::stringc(buffer->getIndices()[j+1]+allVertexCount);
|
||||
num = core::stringc(idx1);
|
||||
file->write(num.c_str(), num.size());
|
||||
file->write("/",1);
|
||||
file->write(num.c_str(), num.size());
|
||||
@ -147,7 +162,7 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
|
||||
file->write(num.c_str(), num.size());
|
||||
file->write(" ",1);
|
||||
|
||||
num = core::stringc(buffer->getIndices()[j+0]+allVertexCount);
|
||||
num = core::stringc(idx0);
|
||||
file->write(num.c_str(), num.size());
|
||||
file->write("/",1);
|
||||
file->write(num.c_str(), num.size());
|
||||
|
@ -102,18 +102,29 @@ IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file)
|
||||
|
||||
file->read(verts, sizeof(octVert) * header.numVerts);
|
||||
file->read(faces, sizeof(octFace) * header.numFaces);
|
||||
//TODO: Make sure id is in the legal range for Textures and Lightmaps
|
||||
|
||||
u32 i;
|
||||
for (i = 0; i < header.numTextures; i++) {
|
||||
octTexture t;
|
||||
file->read(&t, sizeof(octTexture));
|
||||
textures[t.id] = t;
|
||||
for (i = 0; i < header.numTextures; i++)
|
||||
{
|
||||
u32 id;
|
||||
file->read(&id, sizeof(id));
|
||||
if ( id >= header.numTextures )
|
||||
{
|
||||
os::Printer::log("COCTLoader: Invalid texture id", irr::ELL_WARNING);
|
||||
id = i;
|
||||
}
|
||||
file->read(&textures[id], sizeof(octTexture));
|
||||
}
|
||||
for (i = 0; i < header.numLightmaps; i++) {
|
||||
octLightmap t;
|
||||
file->read(&t, sizeof(octLightmap));
|
||||
lightmaps[t.id] = t;
|
||||
for (i = 0; i < header.numLightmaps; i++)
|
||||
{
|
||||
u32 id;
|
||||
file->read(&id, sizeof(id));
|
||||
if ( id >= header.numLightmaps )
|
||||
{
|
||||
os::Printer::log("COCTLoader: Invalid lightmap id", irr::ELL_WARNING);
|
||||
id = i;
|
||||
}
|
||||
file->read(&lightmaps[id], sizeof(octLightmap));
|
||||
}
|
||||
file->read(lights, sizeof(octLight) * header.numLights);
|
||||
|
||||
|
@ -115,12 +115,10 @@ namespace scene
|
||||
};
|
||||
|
||||
struct octTexture {
|
||||
u32 id;
|
||||
char fileName[64];
|
||||
};
|
||||
|
||||
struct octLightmap {
|
||||
u32 id;
|
||||
u8 data[128][128][3];
|
||||
};
|
||||
|
||||
|
@ -1099,7 +1099,7 @@ COGLES2Driver::~COGLES2Driver()
|
||||
testGLError(__LINE__);
|
||||
}
|
||||
|
||||
void COGLES2Driver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip)
|
||||
void COGLES2Driver::draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip)
|
||||
{
|
||||
if (!texture)
|
||||
return;
|
||||
|
@ -118,7 +118,7 @@ namespace video
|
||||
const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE;
|
||||
|
||||
// internally used
|
||||
virtual void draw2DImage(const video::ITexture* texture, u32 layer, bool flip);
|
||||
virtual void draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip);
|
||||
|
||||
//! draws a set of 2d images
|
||||
virtual void draw2DImageBatch(const video::ITexture* texture,
|
||||
|
@ -1032,7 +1032,7 @@ void COGLES1Driver::draw2DImage(const video::ITexture* texture, const core::rect
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
void COGLES1Driver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip)
|
||||
void COGLES1Driver::draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip)
|
||||
{
|
||||
if (!texture || !CacheHandler->getTextureCache().set(0, texture))
|
||||
return;
|
||||
|
@ -109,7 +109,8 @@ namespace video
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE;
|
||||
|
||||
virtual void draw2DImage(const video::ITexture* texture, u32 layer, bool flip);
|
||||
// internally used
|
||||
virtual void draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip);
|
||||
|
||||
//! draws a set of 2d images
|
||||
virtual void draw2DImageBatch(const video::ITexture* texture,
|
||||
|
@ -73,12 +73,16 @@ void COSOperator::copyToClipboard(const c8* text) const
|
||||
char * buffer;
|
||||
|
||||
clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(text)+1);
|
||||
buffer = (char*)GlobalLock(clipbuffer);
|
||||
|
||||
strcpy(buffer, text);
|
||||
|
||||
GlobalUnlock(clipbuffer);
|
||||
SetClipboardData(CF_TEXT, clipbuffer);
|
||||
if ( clipbuffer )
|
||||
{
|
||||
buffer = (char*)GlobalLock(clipbuffer);
|
||||
if ( buffer )
|
||||
{
|
||||
strcpy(buffer, text);
|
||||
}
|
||||
GlobalUnlock(clipbuffer);
|
||||
SetClipboardData(CF_TEXT, clipbuffer);
|
||||
}
|
||||
CloseClipboard();
|
||||
|
||||
#elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_)
|
||||
|
@ -328,7 +328,7 @@ public:
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
Driver->draw2DImage(this, layer, true);
|
||||
Driver->draw2DImageQuad(this, layer, true);
|
||||
|
||||
IImage* tmpImage = Driver->createImage(ECF_A8R8G8B8, Size);
|
||||
glReadPixels(0, 0, Size.Width, Size.Height, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->getData());
|
||||
|
@ -1446,7 +1446,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect
|
||||
}
|
||||
|
||||
|
||||
void COpenGLDriver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip)
|
||||
void COpenGLDriver::draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip)
|
||||
{
|
||||
if (!texture || !CacheHandler->getTextureCache().set(0, texture))
|
||||
return;
|
||||
@ -3971,7 +3971,7 @@ IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RE
|
||||
if (format==video::ECF_UNKNOWN)
|
||||
format=getColorFormat();
|
||||
|
||||
// TODO: Maybe we could support more formats (floating point and some of those beyond ECF_R8), didn't really try yet
|
||||
// TODO: Maybe we could support more formats (floating point and some of those beyond ECF_R8), didn't really try yet
|
||||
if (IImage::isCompressedFormat(format) || IImage::isDepthFormat(format) || IImage::isFloatingPointFormat(format) || format >= ECF_R8)
|
||||
return 0;
|
||||
|
||||
|
@ -148,7 +148,10 @@ namespace video
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE;
|
||||
|
||||
virtual void draw2DImage(const video::ITexture* texture, u32 layer, bool flip);
|
||||
// Was some helper function used in previous texture locking. Currently not accessible for users
|
||||
// and also no longer needed internally (unless we switch back to old texture lock code).
|
||||
// It seems to draw the texture to a fullscreen quad. Also allows drawing one side of a cubemap texture.
|
||||
void draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip);
|
||||
|
||||
//! draws a set of 2d images, using a color and the alpha channel of the
|
||||
//! texture if desired.
|
||||
|
@ -609,13 +609,14 @@ IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode(
|
||||
//! the returned pointer must not be dropped.
|
||||
IMeshSceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent,
|
||||
s32 id, const core::vector3df& position,
|
||||
const core::vector3df& rotation, const core::vector3df& scale)
|
||||
const core::vector3df& rotation, const core::vector3df& scale,
|
||||
ECUBE_MESH_TYPE type)
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_CUBE_SCENENODE_
|
||||
if (!parent)
|
||||
parent = this;
|
||||
|
||||
IMeshSceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale);
|
||||
IMeshSceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale, type);
|
||||
node->drop();
|
||||
|
||||
return node;
|
||||
|
@ -73,7 +73,8 @@ namespace scene
|
||||
virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1,
|
||||
const core::vector3df& position = core::vector3df(0,0,0),
|
||||
const core::vector3df& rotation = core::vector3df(0,0,0),
|
||||
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) IRR_OVERRIDE;
|
||||
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f),
|
||||
ECUBE_MESH_TYPE type=ECMT_1BUF_12VTX_NA) IRR_OVERRIDE;
|
||||
|
||||
//! Adds a sphere scene node to the scene.
|
||||
virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1,
|
||||
|
@ -947,14 +947,14 @@ REALINLINE size_t clipToFrustumTest(const s4DVertex* v)
|
||||
{
|
||||
size_t flag = 0;
|
||||
|
||||
flag |= v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_NEAR : 0;
|
||||
flag |= -v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_FAR : 0;
|
||||
flag |= v->Pos.z <= v->Pos.w ? (size_t)VERTEX4D_CLIP_NEAR : 0;
|
||||
flag |= -v->Pos.z <= v->Pos.w ? (size_t)VERTEX4D_CLIP_FAR : 0;
|
||||
|
||||
flag |= v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_LEFT : 0;
|
||||
flag |= -v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_RIGHT : 0;
|
||||
flag |= v->Pos.x <= v->Pos.w ? (size_t)VERTEX4D_CLIP_LEFT : 0;
|
||||
flag |= -v->Pos.x <= v->Pos.w ? (size_t)VERTEX4D_CLIP_RIGHT : 0;
|
||||
|
||||
flag |= v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_BOTTOM : 0;
|
||||
flag |= -v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_TOP : 0;
|
||||
flag |= v->Pos.y <= v->Pos.w ? (size_t)VERTEX4D_CLIP_BOTTOM : 0;
|
||||
flag |= -v->Pos.y <= v->Pos.w ? (size_t)VERTEX4D_CLIP_TOP : 0;
|
||||
|
||||
|
||||
/*
|
||||
|
@ -145,6 +145,18 @@ namespace scene
|
||||
|
||||
virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) IRR_OVERRIDE;
|
||||
|
||||
//! Get the amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const IRR_OVERRIDE
|
||||
{
|
||||
return Mesh ? Mesh->getMeshBufferCount() : 0;
|
||||
}
|
||||
|
||||
//! Get pointer to the mesh buffer.
|
||||
virtual IMeshBuffer* getMeshBuffer(u32 nr) const IRR_OVERRIDE
|
||||
{
|
||||
return Mesh ? Mesh->getMeshBuffer(nr) : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
void updateMesh(const irr::scene::ICameraSceneNode* camera);
|
||||
|
||||
|
@ -290,7 +290,7 @@ void CWebGL1Driver::draw2DImage(const video::ITexture* texture, const core::rect
|
||||
testGLError();
|
||||
}
|
||||
|
||||
void CWebGL1Driver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip)
|
||||
void CWebGL1Driver::draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip)
|
||||
{
|
||||
if (!texture )
|
||||
return;
|
||||
|
@ -64,7 +64,7 @@ namespace video
|
||||
const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE;
|
||||
|
||||
// internally used
|
||||
virtual void draw2DImage(const video::ITexture* texture, u32 layer, bool flip) IRR_OVERRIDE;
|
||||
virtual void draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip) IRR_OVERRIDE;
|
||||
|
||||
//! draws a set of 2d images
|
||||
virtual void draw2DImageBatch(const video::ITexture* texture,
|
||||
|
@ -549,7 +549,7 @@ private:
|
||||
pos = origstr.findNext(L'&', pos);
|
||||
}
|
||||
|
||||
if (oldPos < (int)origstr.size()-1)
|
||||
if (oldPos < (int)origstr.size())
|
||||
newstr.append(origstr.subString(oldPos, origstr.size()-oldPos));
|
||||
|
||||
return newstr;
|
||||
|
@ -844,6 +844,7 @@
|
||||
<ClInclude Include="..\..\include\EHardwareBufferFlags.h" />
|
||||
<ClInclude Include="..\..\include\EMaterialFlags.h" />
|
||||
<ClInclude Include="..\..\include\EMaterialTypes.h" />
|
||||
<ClInclude Include="..\..\include\EMeshBufferTypes.h" />
|
||||
<ClInclude Include="..\..\include\EReadFileType.h" />
|
||||
<ClInclude Include="..\..\include\EShaderTypes.h" />
|
||||
<ClInclude Include="..\..\include\fast_atof.h" />
|
||||
@ -859,8 +860,8 @@
|
||||
<ClInclude Include="..\..\include\IImageWriter.h" />
|
||||
<ClInclude Include="..\..\include\IIndexBuffer.h" />
|
||||
<ClInclude Include="..\..\include\ILightManager.h" />
|
||||
<ClInclude Include="..\..\include\IOctreeSceneNode.h" />
|
||||
<ClInclude Include="..\..\include\IProfiler.h" />
|
||||
<ClInclude Include="..\..\include\IOctreeSceneNode.h" />
|
||||
<ClInclude Include="..\..\include\IProfiler.h" />
|
||||
<ClInclude Include="..\..\include\ILogger.h" />
|
||||
<ClInclude Include="..\..\include\IMemoryReadFile.h" />
|
||||
<ClInclude Include="..\..\include\IOSOperator.h" />
|
||||
@ -869,7 +870,7 @@
|
||||
<ClInclude Include="..\..\include\IRenderTarget.h" />
|
||||
<ClInclude Include="..\..\include\IrrCompileConfig.h" />
|
||||
<ClInclude Include="..\..\include\irrlicht.h" />
|
||||
<ClInclude Include="..\..\include\leakHunter.h" />
|
||||
<ClInclude Include="..\..\include\leakHunter.h" />
|
||||
<ClInclude Include="..\..\include\IrrlichtDevice.h" />
|
||||
<ClInclude Include="..\..\include\irrTypes.h" />
|
||||
<ClInclude Include="..\..\include\ISceneUserDataSerializer.h" />
|
||||
@ -1035,7 +1036,7 @@
|
||||
<ClInclude Include="burning_shader_compile_triangle.h" />
|
||||
<ClInclude Include="burning_shader_compile_verify.h" />
|
||||
<ClInclude Include="CB3DMeshWriter.h" />
|
||||
<ClInclude Include="CBlit.h" />
|
||||
<ClInclude Include="CBlit.h" />
|
||||
<ClInclude Include="CD3D9RenderTarget.h" />
|
||||
<ClInclude Include="CDefaultSceneNodeAnimatorFactory.h" />
|
||||
<ClInclude Include="CDefaultSceneNodeFactory.h" />
|
||||
@ -1207,7 +1208,7 @@
|
||||
<ClInclude Include="COSOperator.h" />
|
||||
<ClInclude Include="CTimer.h" />
|
||||
<ClInclude Include="os.h" />
|
||||
<ClInclude Include="CProfiler.h" />
|
||||
<ClInclude Include="CProfiler.h" />
|
||||
<ClInclude Include="EProfileIDs.h" />
|
||||
<ClInclude Include="lzma\LzmaDec.h" />
|
||||
<ClInclude Include="lzma\Types.h" />
|
||||
@ -1484,7 +1485,7 @@
|
||||
<ClCompile Include="os.cpp" />
|
||||
<ClCompile Include="utf8.cpp" />
|
||||
<ClCompile Include="CProfiler.cpp" />
|
||||
<ClCompile Include="leakHunter.cpp" />
|
||||
<ClCompile Include="leakHunter.cpp" />
|
||||
<ClCompile Include="lzma\LzmaDec.c" />
|
||||
<ClCompile Include="zlib\adler32.c" />
|
||||
<ClCompile Include="zlib\compress.c" />
|
||||
|
@ -137,13 +137,13 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\leakHunter.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\IrrlichtDevice.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\irrTypes.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\ITimer.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
@ -1416,7 +1416,7 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="CBlit.h">
|
||||
<Filter>Irrlicht\video\Null</Filter>
|
||||
</ClInclude>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\fast_atof.h">
|
||||
<Filter>include\core</Filter>
|
||||
</ClInclude>
|
||||
@ -1483,6 +1483,9 @@
|
||||
<ClInclude Include="..\..\include\EDeviceTypes.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\EMeshBufferTypes.h">
|
||||
<Filter>include\scene</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\changes.txt">
|
||||
|
@ -356,67 +356,6 @@ bool GetDMFMaterials(const StringList& RawFile,
|
||||
}
|
||||
|
||||
|
||||
/**This function extract an array of dmfMaterial from a DMF file considering 1st an 2nd layer for water plains.
|
||||
You must give in input a StringList representing a DMF file loaded with LoadFromFile.
|
||||
\return true if function succeed or false on fail.*/
|
||||
bool GetDMFWaterMaterials(const StringList& RawFile /**<StringList representing a DMF file.*/,
|
||||
core::array<dmfMaterial>& materials/**<Materials returned.*/,
|
||||
int num_material/**<Number of materials contained in DMF file.*/
|
||||
)
|
||||
{
|
||||
int offs=4;
|
||||
StringList temp;
|
||||
StringList temp1;
|
||||
StringList temp2;
|
||||
//Checking if this is a DeleD map File of version >= 0.91
|
||||
temp=SubdivideString(RawFile[0],";");//file info
|
||||
|
||||
if ( temp[0] != "DeleD Map File" )
|
||||
return false;//not a deled file
|
||||
|
||||
temp.clear();
|
||||
temp=SubdivideString(RawFile[1]," ");//get version
|
||||
temp1=SubdivideString(temp[1],";");
|
||||
|
||||
if (atof(temp1[0].c_str()) < 0.91)
|
||||
return false;//not correct version
|
||||
|
||||
//end checking
|
||||
temp.clear();
|
||||
temp1.clear();
|
||||
|
||||
for(int i=0;i<num_material;i++)
|
||||
{
|
||||
temp = SubdivideString(RawFile[offs+i],";");
|
||||
materials[i].materialID=i;
|
||||
|
||||
temp1 = SubdivideString(temp[5],",");
|
||||
materials[i].textureFlag=atoi(temp1[0].c_str());
|
||||
temp2 = SubdivideString(temp1[1],"\\");
|
||||
|
||||
materials[i].textureName=temp2.getLast();
|
||||
temp1.clear();
|
||||
temp2.clear();
|
||||
int a=temp.size();
|
||||
if(a==7)
|
||||
{
|
||||
temp1=SubdivideString(temp[6],",");
|
||||
materials[i].lightmapFlag=atoi(temp1[0].c_str());
|
||||
temp2=SubdivideString(temp1[1],"\\");
|
||||
materials[i].lightmapName=temp2.getLast();
|
||||
}
|
||||
else
|
||||
{
|
||||
materials[i].lightmapFlag=1;
|
||||
materials[i].lightmapName="FFFFFFFF";
|
||||
}
|
||||
temp1.clear();
|
||||
temp2.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**This function extract an array of dmfVert and dmfFace from a DMF file.
|
||||
You must give in input a StringList representing a DMF file loaded with LoadFromFile and two arrays long enough.
|
||||
Please use GetDMFHeader() before this function to know number of vertices and faces.
|
||||
@ -501,6 +440,66 @@ bool GetDMFVerticesFaces(const StringList& RawFile/**<StringList representing a
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0 // functions unused and compiler gives us warnings about it. Keeping them in case anyone ever wants to improve support for this.
|
||||
/**This function extract an array of dmfMaterial from a DMF file considering 1st an 2nd layer for water plains.
|
||||
You must give in input a StringList representing a DMF file loaded with LoadFromFile.
|
||||
\return true if function succeed or false on fail.*/
|
||||
bool GetDMFWaterMaterials(const StringList& RawFile /**<StringList representing a DMF file.*/,
|
||||
core::array<dmfMaterial>& materials/**<Materials returned.*/,
|
||||
int num_material/**<Number of materials contained in DMF file.*/
|
||||
)
|
||||
{
|
||||
int offs=4;
|
||||
StringList temp;
|
||||
StringList temp1;
|
||||
StringList temp2;
|
||||
//Checking if this is a DeleD map File of version >= 0.91
|
||||
temp=SubdivideString(RawFile[0],";");//file info
|
||||
|
||||
if ( temp[0] != "DeleD Map File" )
|
||||
return false;//not a deled file
|
||||
|
||||
temp.clear();
|
||||
temp=SubdivideString(RawFile[1]," ");//get version
|
||||
temp1=SubdivideString(temp[1],";");
|
||||
|
||||
if (atof(temp1[0].c_str()) < 0.91)
|
||||
return false;//not correct version
|
||||
|
||||
//end checking
|
||||
temp.clear();
|
||||
temp1.clear();
|
||||
|
||||
for(int i=0;i<num_material;i++)
|
||||
{
|
||||
temp = SubdivideString(RawFile[offs+i],";");
|
||||
materials[i].materialID=i;
|
||||
|
||||
temp1 = SubdivideString(temp[5],",");
|
||||
materials[i].textureFlag=atoi(temp1[0].c_str());
|
||||
temp2 = SubdivideString(temp1[1],"\\");
|
||||
|
||||
materials[i].textureName=temp2.getLast();
|
||||
temp1.clear();
|
||||
temp2.clear();
|
||||
int a=temp.size();
|
||||
if(a==7)
|
||||
{
|
||||
temp1=SubdivideString(temp[6],",");
|
||||
materials[i].lightmapFlag=atoi(temp1[0].c_str());
|
||||
temp2=SubdivideString(temp1[1],"\\");
|
||||
materials[i].lightmapName=temp2.getLast();
|
||||
}
|
||||
else
|
||||
{
|
||||
materials[i].lightmapFlag=1;
|
||||
materials[i].lightmapName="FFFFFFFF";
|
||||
}
|
||||
temp1.clear();
|
||||
temp2.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**This function extract an array of dmfLights from a DMF file.
|
||||
You must give in input a StringList representing a DMF file loaded with
|
||||
@ -723,6 +722,7 @@ bool GetDMFWaterPlanes(const StringList& RawFile/**<StringList representing a DM
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // end namespace
|
||||
} // end namespace scene
|
||||
|
@ -1,380 +1,379 @@
|
||||
// Copyright (C) 2014 Lauri Kasanen
|
||||
// This file is part of the "Irrlicht Engine". The UTF-8 functions are from physfs,
|
||||
// under the zlib license, reproduced below.
|
||||
|
||||
#include "irrTypes.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
|
||||
/*
|
||||
Copyright (c) 2001-2011 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* From rfc3629, the UTF-8 spec:
|
||||
* http://www.ietf.org/rfc/rfc3629.txt
|
||||
*
|
||||
* Char. number range | UTF-8 octet sequence
|
||||
* (hexadecimal) | (binary)
|
||||
* --------------------+---------------------------------------------
|
||||
* 0000 0000-0000 007F | 0xxxxxxx
|
||||
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This may not be the best value, but it's one that isn't represented
|
||||
* in Unicode (0x10FFFF is the largest codepoint value). We return this
|
||||
* value from utf8codepoint() if there's bogus bits in the
|
||||
* stream. utf8codepoint() will turn this value into something
|
||||
* reasonable (like a question mark), for text that wants to try to recover,
|
||||
* whereas utf8valid() will use the value to determine if a string has bad
|
||||
* bits.
|
||||
*/
|
||||
#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF
|
||||
|
||||
/*
|
||||
* This is the codepoint we currently return when there was bogus bits in a
|
||||
* UTF-8 string. May not fly in Asian locales?
|
||||
*/
|
||||
#define UNICODE_BOGUS_CHAR_CODEPOINT '?'
|
||||
|
||||
static u32 utf8codepoint(const char **_str)
|
||||
{
|
||||
const char *str = *_str;
|
||||
u32 retval = 0;
|
||||
u32 octet = (u32) ((u8) *str);
|
||||
u32 octet2, octet3, octet4;
|
||||
|
||||
if (octet == 0) /* null terminator, end of string. */
|
||||
return 0;
|
||||
|
||||
else if (octet < 128) /* one octet char: 0 to 127 */
|
||||
{
|
||||
(*_str)++; /* skip to next possible start of codepoint. */
|
||||
return(octet);
|
||||
} /* else if */
|
||||
|
||||
else if ((octet > 127) && (octet < 192)) /* bad (starts with 10xxxxxx). */
|
||||
{
|
||||
/*
|
||||
* Apparently each of these is supposed to be flagged as a bogus
|
||||
* char, instead of just resyncing to the next valid codepoint.
|
||||
*/
|
||||
(*_str)++; /* skip to next possible start of codepoint. */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* else if */
|
||||
|
||||
else if (octet < 224) /* two octets */
|
||||
{
|
||||
octet -= (128+64);
|
||||
octet2 = (u32) ((u8) *(++str));
|
||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 2; /* skip to next possible start of codepoint. */
|
||||
retval = ((octet << 6) | (octet2 - 128));
|
||||
if ((retval >= 0x80) && (retval <= 0x7FF))
|
||||
return retval;
|
||||
} /* else if */
|
||||
|
||||
else if (octet < 240) /* three octets */
|
||||
{
|
||||
octet -= (128+64+32);
|
||||
octet2 = (u32) ((u8) *(++str));
|
||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet3 = (u32) ((u8) *(++str));
|
||||
if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 3; /* skip to next possible start of codepoint. */
|
||||
retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) );
|
||||
|
||||
/* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */
|
||||
switch (retval)
|
||||
{
|
||||
case 0xD800:
|
||||
case 0xDB7F:
|
||||
case 0xDB80:
|
||||
case 0xDBFF:
|
||||
case 0xDC00:
|
||||
case 0xDF80:
|
||||
case 0xDFFF:
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* switch */
|
||||
|
||||
/* 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. */
|
||||
if ((retval >= 0x800) && (retval <= 0xFFFD))
|
||||
return retval;
|
||||
} /* else if */
|
||||
|
||||
else if (octet < 248) /* four octets */
|
||||
{
|
||||
octet -= (128+64+32+16);
|
||||
octet2 = (u32) ((u8) *(++str));
|
||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet3 = (u32) ((u8) *(++str));
|
||||
if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet4 = (u32) ((u8) *(++str));
|
||||
if ((octet4 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 4; /* skip to next possible start of codepoint. */
|
||||
retval = ( ((octet << 18)) | ((octet2 - 128) << 12) |
|
||||
((octet3 - 128) << 6) | ((octet4 - 128)) );
|
||||
if ((retval >= 0x10000) && (retval <= 0x10FFFF))
|
||||
return retval;
|
||||
} /* else if */
|
||||
|
||||
/*
|
||||
* Five and six octet sequences became illegal in rfc3629.
|
||||
* We throw the codepoint away, but parse them to make sure we move
|
||||
* ahead the right number of bytes and don't overflow the buffer.
|
||||
*/
|
||||
|
||||
else if (octet < 252) /* five octets */
|
||||
{
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 5; /* skip to next possible start of codepoint. */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* else if */
|
||||
|
||||
else /* six octets */
|
||||
{
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 6; /* skip to next possible start of codepoint. */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* else if */
|
||||
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* utf8codepoint */
|
||||
|
||||
|
||||
static void PHYSFS_utf8ToUcs4(const char *src, u32 *dst, u64 len)
|
||||
{
|
||||
len -= sizeof (u32); /* save room for null char. */
|
||||
while (len >= sizeof (u32))
|
||||
{
|
||||
u32 cp = utf8codepoint(&src);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
*(dst++) = cp;
|
||||
len -= sizeof (u32);
|
||||
} /* while */
|
||||
|
||||
*dst = 0;
|
||||
} /* PHYSFS_utf8ToUcs4 */
|
||||
|
||||
|
||||
static void PHYSFS_utf8ToUcs2(const char *src, u16 *dst, u64 len)
|
||||
{
|
||||
len -= sizeof (u16); /* save room for null char. */
|
||||
while (len >= sizeof (u16))
|
||||
{
|
||||
u32 cp = utf8codepoint(&src);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
|
||||
/* !!! BLUESKY: UTF-16 surrogates? */
|
||||
if (cp > 0xFFFF)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
|
||||
*(dst++) = cp;
|
||||
len -= sizeof (u16);
|
||||
} /* while */
|
||||
|
||||
*dst = 0;
|
||||
} /* PHYSFS_utf8ToUcs2 */
|
||||
|
||||
static void utf8fromcodepoint(u32 cp, char **_dst, u64 *_len)
|
||||
{
|
||||
char *dst = *_dst;
|
||||
u64 len = *_len;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (cp > 0x10FFFF)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
else if ((cp == 0xFFFE) || (cp == 0xFFFF)) /* illegal values. */
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
else
|
||||
{
|
||||
/* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */
|
||||
switch (cp)
|
||||
{
|
||||
case 0xD800:
|
||||
case 0xDB7F:
|
||||
case 0xDB80:
|
||||
case 0xDBFF:
|
||||
case 0xDC00:
|
||||
case 0xDF80:
|
||||
case 0xDFFF:
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
} /* switch */
|
||||
} /* else */
|
||||
|
||||
/* Do the encoding... */
|
||||
if (cp < 0x80)
|
||||
{
|
||||
*(dst++) = (char) cp;
|
||||
len--;
|
||||
} /* if */
|
||||
|
||||
else if (cp < 0x800)
|
||||
{
|
||||
if (len < 2)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
*(dst++) = (char) ((cp >> 6) | 128 | 64);
|
||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
||||
len -= 2;
|
||||
} /* else */
|
||||
} /* else if */
|
||||
|
||||
else if (cp < 0x10000)
|
||||
{
|
||||
if (len < 3)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
*(dst++) = (char) ((cp >> 12) | 128 | 64 | 32);
|
||||
*(dst++) = (char) ((cp >> 6) & 0x3F) | 128;
|
||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
||||
len -= 3;
|
||||
} /* else */
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
if (len < 4)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
*(dst++) = (char) ((cp >> 18) | 128 | 64 | 32 | 16);
|
||||
*(dst++) = (char) ((cp >> 12) & 0x3F) | 128;
|
||||
*(dst++) = (char) ((cp >> 6) & 0x3F) | 128;
|
||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
||||
len -= 4;
|
||||
} /* else if */
|
||||
} /* else */
|
||||
|
||||
*_dst = dst;
|
||||
*_len = len;
|
||||
} /* utf8fromcodepoint */
|
||||
|
||||
#define UTF8FROMTYPE(typ, src, dst, len) \
|
||||
if (len == 0) return; \
|
||||
len--; \
|
||||
while (len) \
|
||||
{ \
|
||||
const u32 cp = (u32) ((typ) (*(src++))); \
|
||||
if (cp == 0) break; \
|
||||
utf8fromcodepoint(cp, &dst, &len); \
|
||||
} \
|
||||
*dst = '\0'; \
|
||||
|
||||
static void PHYSFS_utf8FromUcs4(const u32 *src, char *dst, u64 len)
|
||||
{
|
||||
UTF8FROMTYPE(u32, src, dst, len);
|
||||
} /* PHYSFS_utf8FromUcs4 */
|
||||
|
||||
static void PHYSFS_utf8FromUcs2(const u16 *src, char *dst, u64 len)
|
||||
{
|
||||
UTF8FROMTYPE(u64, src, dst, len);
|
||||
} /* PHYSFS_utf8FromUcs4 */
|
||||
|
||||
#undef UTF8FROMTYPE
|
||||
|
||||
void utf8ToWchar(const char *in, wchar_t *out, const u64 len)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
PHYSFS_utf8ToUcs2(in, (u16 *) out, len);
|
||||
#else
|
||||
PHYSFS_utf8ToUcs4(in, (u32 *) out, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wcharToUtf8(const wchar_t *in, char *out, const u64 len)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
PHYSFS_utf8FromUcs2((const u16 *) in, out, len);
|
||||
#else
|
||||
PHYSFS_utf8FromUcs4((const u32 *) in, out, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // end namespace core
|
||||
} // end namespace irr
|
||||
|
||||
// Copyright (C) 2014 Lauri Kasanen
|
||||
// This file is part of the "Irrlicht Engine". The UTF-8 functions are from physfs,
|
||||
// under the zlib license, reproduced below.
|
||||
|
||||
#include "irrTypes.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
|
||||
/*
|
||||
Copyright (c) 2001-2011 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* From rfc3629, the UTF-8 spec:
|
||||
* http://www.ietf.org/rfc/rfc3629.txt
|
||||
*
|
||||
* Char. number range | UTF-8 octet sequence
|
||||
* (hexadecimal) | (binary)
|
||||
* --------------------+---------------------------------------------
|
||||
* 0000 0000-0000 007F | 0xxxxxxx
|
||||
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This may not be the best value, but it's one that isn't represented
|
||||
* in Unicode (0x10FFFF is the largest codepoint value). We return this
|
||||
* value from utf8codepoint() if there's bogus bits in the
|
||||
* stream. utf8codepoint() will turn this value into something
|
||||
* reasonable (like a question mark), for text that wants to try to recover,
|
||||
* whereas utf8valid() will use the value to determine if a string has bad
|
||||
* bits.
|
||||
*/
|
||||
#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF
|
||||
|
||||
/*
|
||||
* This is the codepoint we currently return when there was bogus bits in a
|
||||
* UTF-8 string. May not fly in Asian locales?
|
||||
*/
|
||||
#define UNICODE_BOGUS_CHAR_CODEPOINT '?'
|
||||
|
||||
static u32 utf8codepoint(const char **_str)
|
||||
{
|
||||
const char *str = *_str;
|
||||
u32 retval = 0;
|
||||
u32 octet = (u32) ((u8) *str);
|
||||
u32 octet2, octet3, octet4;
|
||||
|
||||
if (octet == 0) /* null terminator, end of string. */
|
||||
return 0;
|
||||
|
||||
else if (octet < 128) /* one octet char: 0 to 127 */
|
||||
{
|
||||
(*_str)++; /* skip to next possible start of codepoint. */
|
||||
return(octet);
|
||||
} /* else if */
|
||||
|
||||
else if ((octet > 127) && (octet < 192)) /* bad (starts with 10xxxxxx). */
|
||||
{
|
||||
/*
|
||||
* Apparently each of these is supposed to be flagged as a bogus
|
||||
* char, instead of just resyncing to the next valid codepoint.
|
||||
*/
|
||||
(*_str)++; /* skip to next possible start of codepoint. */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* else if */
|
||||
|
||||
else if (octet < 224) /* two octets */
|
||||
{
|
||||
octet -= (128+64);
|
||||
octet2 = (u32) ((u8) *(++str));
|
||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 2; /* skip to next possible start of codepoint. */
|
||||
retval = ((octet << 6) | (octet2 - 128));
|
||||
if ((retval >= 0x80) && (retval <= 0x7FF))
|
||||
return retval;
|
||||
} /* else if */
|
||||
|
||||
else if (octet < 240) /* three octets */
|
||||
{
|
||||
octet -= (128+64+32);
|
||||
octet2 = (u32) ((u8) *(++str));
|
||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet3 = (u32) ((u8) *(++str));
|
||||
if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 3; /* skip to next possible start of codepoint. */
|
||||
retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) );
|
||||
|
||||
/* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */
|
||||
switch (retval)
|
||||
{
|
||||
case 0xD800:
|
||||
case 0xDB7F:
|
||||
case 0xDB80:
|
||||
case 0xDBFF:
|
||||
case 0xDC00:
|
||||
case 0xDF80:
|
||||
case 0xDFFF:
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* switch */
|
||||
|
||||
/* 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. */
|
||||
if ((retval >= 0x800) && (retval <= 0xFFFD))
|
||||
return retval;
|
||||
} /* else if */
|
||||
|
||||
else if (octet < 248) /* four octets */
|
||||
{
|
||||
octet -= (128+64+32+16);
|
||||
octet2 = (u32) ((u8) *(++str));
|
||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet3 = (u32) ((u8) *(++str));
|
||||
if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet4 = (u32) ((u8) *(++str));
|
||||
if ((octet4 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 4; /* skip to next possible start of codepoint. */
|
||||
retval = ( ((octet << 18)) | ((octet2 - 128) << 12) |
|
||||
((octet3 - 128) << 6) | ((octet4 - 128)) );
|
||||
if ((retval >= 0x10000) && (retval <= 0x10FFFF))
|
||||
return retval;
|
||||
} /* else if */
|
||||
|
||||
/*
|
||||
* Five and six octet sequences became illegal in rfc3629.
|
||||
* We throw the codepoint away, but parse them to make sure we move
|
||||
* ahead the right number of bytes and don't overflow the buffer.
|
||||
*/
|
||||
|
||||
else if (octet < 252) /* five octets */
|
||||
{
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 5; /* skip to next possible start of codepoint. */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* else if */
|
||||
|
||||
else /* six octets */
|
||||
{
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (u32) ((u8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 6; /* skip to next possible start of codepoint. */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* else if */
|
||||
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* utf8codepoint */
|
||||
|
||||
|
||||
static void PHYSFS_utf8ToUcs4(const char *src, u32 *dst, u64 len)
|
||||
{
|
||||
len -= sizeof (u32); /* save room for null char. */
|
||||
while (len >= sizeof (u32))
|
||||
{
|
||||
u32 cp = utf8codepoint(&src);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
*(dst++) = cp;
|
||||
len -= sizeof (u32);
|
||||
} /* while */
|
||||
|
||||
*dst = 0;
|
||||
} /* PHYSFS_utf8ToUcs4 */
|
||||
|
||||
|
||||
static void PHYSFS_utf8ToUcs2(const char *src, u16 *dst, u64 len)
|
||||
{
|
||||
len -= sizeof (u16); /* save room for null char. */
|
||||
while (len >= sizeof (u16))
|
||||
{
|
||||
u32 cp = utf8codepoint(&src);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
|
||||
/* !!! BLUESKY: UTF-16 surrogates? */
|
||||
if (cp > 0xFFFF)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
|
||||
*(dst++) = cp;
|
||||
len -= sizeof (u16);
|
||||
} /* while */
|
||||
|
||||
*dst = 0;
|
||||
} /* PHYSFS_utf8ToUcs2 */
|
||||
|
||||
static void utf8fromcodepoint(u32 cp, char **_dst, u64 *_len)
|
||||
{
|
||||
char *dst = *_dst;
|
||||
u64 len = *_len;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (cp > 0x10FFFF)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
else if ((cp == 0xFFFE) || (cp == 0xFFFF)) /* illegal values. */
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
else
|
||||
{
|
||||
/* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */
|
||||
switch (cp)
|
||||
{
|
||||
case 0xD800:
|
||||
case 0xDB7F:
|
||||
case 0xDB80:
|
||||
case 0xDBFF:
|
||||
case 0xDC00:
|
||||
case 0xDF80:
|
||||
case 0xDFFF:
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
} /* switch */
|
||||
} /* else */
|
||||
|
||||
/* Do the encoding... */
|
||||
if (cp < 0x80)
|
||||
{
|
||||
*(dst++) = (char) cp;
|
||||
len--;
|
||||
} /* if */
|
||||
|
||||
else if (cp < 0x800)
|
||||
{
|
||||
if (len < 2)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
*(dst++) = (char) ((cp >> 6) | 128 | 64);
|
||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
||||
len -= 2;
|
||||
} /* else */
|
||||
} /* else if */
|
||||
|
||||
else if (cp < 0x10000)
|
||||
{
|
||||
if (len < 3)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
*(dst++) = (char) ((cp >> 12) | 128 | 64 | 32);
|
||||
*(dst++) = (char) ((cp >> 6) & 0x3F) | 128;
|
||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
||||
len -= 3;
|
||||
} /* else */
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
if (len < 4)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
*(dst++) = (char) ((cp >> 18) | 128 | 64 | 32 | 16);
|
||||
*(dst++) = (char) ((cp >> 12) & 0x3F) | 128;
|
||||
*(dst++) = (char) ((cp >> 6) & 0x3F) | 128;
|
||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
||||
len -= 4;
|
||||
} /* else if */
|
||||
} /* else */
|
||||
|
||||
*_dst = dst;
|
||||
*_len = len;
|
||||
} /* utf8fromcodepoint */
|
||||
|
||||
#define UTF8FROMTYPE(typ, src, dst, len) \
|
||||
if (len == 0) return; \
|
||||
len--; \
|
||||
while (len) \
|
||||
{ \
|
||||
const u32 cp = (u32) ((typ) (*(src++))); \
|
||||
if (cp == 0) break; \
|
||||
utf8fromcodepoint(cp, &dst, &len); \
|
||||
} \
|
||||
*dst = '\0'; \
|
||||
|
||||
static void PHYSFS_utf8FromUcs4(const u32 *src, char *dst, u64 len)
|
||||
{
|
||||
UTF8FROMTYPE(u32, src, dst, len);
|
||||
} /* PHYSFS_utf8FromUcs4 */
|
||||
|
||||
static void PHYSFS_utf8FromUcs2(const u16 *src, char *dst, u64 len)
|
||||
{
|
||||
UTF8FROMTYPE(u64, src, dst, len);
|
||||
} /* PHYSFS_utf8FromUcs4 */
|
||||
|
||||
#undef UTF8FROMTYPE
|
||||
|
||||
void utf8ToWchar(const char *in, wchar_t *out, const u64 len)
|
||||
{
|
||||
switch ( sizeof(wchar_t) )
|
||||
{
|
||||
case 2: PHYSFS_utf8ToUcs2(in, (u16 *) out, len); break;
|
||||
case 4: PHYSFS_utf8ToUcs4(in, (u32 *) out, len); break;
|
||||
}
|
||||
}
|
||||
|
||||
void wcharToUtf8(const wchar_t *in, char *out, const u64 len)
|
||||
{
|
||||
switch ( sizeof(wchar_t) )
|
||||
{
|
||||
case 2: PHYSFS_utf8FromUcs2((const u16 *) in, out, len); break;
|
||||
case 4: PHYSFS_utf8FromUcs4((const u32 *) in, out, len); break;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace core
|
||||
} // end namespace irr
|
||||
|
Reference in New Issue
Block a user