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:
cutealien
2022-04-15 18:51:09 +00:00
parent 67469c8899
commit 2d63fdba3d
115 changed files with 1828 additions and 1154 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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());

View File

@ -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);

View File

@ -115,12 +115,10 @@ namespace scene
};
struct octTexture {
u32 id;
char fileName[64];
};
struct octLightmap {
u32 id;
u8 data[128][128][3];
};

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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_)

View File

@ -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());

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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,

View File

@ -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;
/*

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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" />

View File

@ -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">

View File

@ -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

View File

@ -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