Merged revisions 4511-4534 from trunk. OpenGL bug fix, wchar filesystem fix, clone method fix, tris fix, heightmap optimization, x mesh loader fix
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@4535 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
a4b52c5c8a
commit
2ec010d0a5
|
@ -295,6 +295,32 @@ namespace scene
|
|||
\return A new mesh optimized for the vertex cache. */
|
||||
virtual IMesh* createForsythOptimizedMesh(const IMesh *mesh) const = 0;
|
||||
|
||||
//! Optimize the mesh with an algorithm tuned for heightmaps.
|
||||
/**
|
||||
This differs from usual simplification methods in two ways:
|
||||
- it's intended to be lossless
|
||||
- it has special care for the borders, which are useful with heightmap tiles
|
||||
|
||||
This function is thread-safe. Remember to weld afterwards - this
|
||||
function only moves vertices, it does not weld.
|
||||
|
||||
\param mesh Mesh to operate on.
|
||||
*/
|
||||
virtual void heightmapOptimizeMesh(IMesh * const mesh, const f32 tolerance = core::ROUNDING_ERROR_f32) const = 0;
|
||||
|
||||
//! Optimize the meshbuffer with an algorithm tuned for heightmaps.
|
||||
/**
|
||||
This differs from usual simplification methods in two ways:
|
||||
- it's intended to be lossless
|
||||
- it has special care for the borders, which are useful with heightmap tiles
|
||||
|
||||
This function is thread-safe. Remember to weld afterwards - this
|
||||
function only moves vertices, it does not weld.
|
||||
|
||||
\param mb Meshbuffer to operate on.
|
||||
*/
|
||||
virtual void heightmapOptimizeMesh(IMeshBuffer * const mb, const f32 tolerance = core::ROUNDING_ERROR_f32) const = 0;
|
||||
|
||||
//! Apply a manipulator on the Meshbuffer
|
||||
/** \param func A functor defining the mesh manipulation.
|
||||
\param buffer The Meshbuffer to apply the manipulator to.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "SAnimatedMesh.h"
|
||||
#include "os.h"
|
||||
#include "irrMap.h"
|
||||
#include "triangle3d.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
@ -916,13 +917,30 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const
|
|||
break;
|
||||
}
|
||||
|
||||
// write the buffer's index list
|
||||
// Clean up any degenerate tris
|
||||
core::array<u16> &Indices = *outIdx;
|
||||
|
||||
Indices.set_used(indexCount);
|
||||
for (u32 i=0; i<indexCount; ++i)
|
||||
Indices.clear();
|
||||
Indices.reallocate(indexCount);
|
||||
for (u32 i = 0; i < indexCount; i+=3)
|
||||
{
|
||||
Indices[i] = redirects[ indices[i] ];
|
||||
u16 a, b, c;
|
||||
a = redirects[indices[i]];
|
||||
b = redirects[indices[i+1]];
|
||||
c = redirects[indices[i+2]];
|
||||
|
||||
bool drop = false;
|
||||
|
||||
if (a == b || b == c || a == c)
|
||||
drop = true;
|
||||
|
||||
// Open for other checks
|
||||
|
||||
if (!drop)
|
||||
{
|
||||
Indices.push_back(a);
|
||||
Indices.push_back(b);
|
||||
Indices.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return clone;
|
||||
|
@ -1017,6 +1035,318 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNor
|
|||
return clone;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct height_edge
|
||||
{
|
||||
u32 far;
|
||||
|
||||
u32 polycount;
|
||||
u32 polys[2];
|
||||
core::vector3df normal[2];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
HEIGHT_TRIACCEL_MAX = 1024
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//! Optimizes the mesh using an algorithm tuned for heightmaps.
|
||||
void CMeshManipulator::heightmapOptimizeMesh(IMesh * const m, const f32 tolerance) const
|
||||
{
|
||||
const u32 max = m->getMeshBufferCount();
|
||||
|
||||
for (u32 i = 0; i < max; i++)
|
||||
{
|
||||
IMeshBuffer * const mb = m->getMeshBuffer(i);
|
||||
|
||||
heightmapOptimizeMesh(mb, tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
//! Optimizes the mesh using an algorithm tuned for heightmaps.
|
||||
void CMeshManipulator::heightmapOptimizeMesh(IMeshBuffer * const mb, const f32 tolerance) const
|
||||
{
|
||||
using namespace core;
|
||||
using namespace video;
|
||||
|
||||
array<height_edge> edges;
|
||||
|
||||
const u32 idxs = mb->getIndexCount();
|
||||
const u32 verts = mb->getVertexCount();
|
||||
|
||||
u16 *ind = mb->getIndices();
|
||||
S3DVertex *vert = (S3DVertex *) mb->getVertices();
|
||||
|
||||
// First an acceleration structure: given this vert, which triangles touch it?
|
||||
// Using this drops two exponents off the algorightm complexity, O(n^4) > O(n^2)
|
||||
// Other optimizations brought it down to O(n).
|
||||
u32 **accel = (u32 **) malloc(verts * sizeof(u32 *));
|
||||
for (u32 i = 0; i < verts; i++)
|
||||
{
|
||||
accel[i] = (u32 *) calloc(HEIGHT_TRIACCEL_MAX, sizeof(u32));
|
||||
for (u32 j = 0; j < HEIGHT_TRIACCEL_MAX; j++)
|
||||
{
|
||||
accel[i][j] = USHRT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
u16 *cur = (u16 *) calloc(verts, sizeof(u16));
|
||||
for (u32 j = 0; j < idxs; j+=3)
|
||||
{
|
||||
u32 v = ind[j];
|
||||
|
||||
if (cur[v] >= HEIGHT_TRIACCEL_MAX)
|
||||
{
|
||||
os::Printer::log("Too complex mesh to optimize, aborting.");
|
||||
goto donehere;
|
||||
}
|
||||
|
||||
accel[v][cur[v]] = j;
|
||||
cur[v]++;
|
||||
|
||||
// Unrolled tri loop, parts 2 and 3
|
||||
v = ind[j+1];
|
||||
|
||||
if (cur[v] >= HEIGHT_TRIACCEL_MAX)
|
||||
{
|
||||
os::Printer::log("Too complex mesh to optimize, aborting.");
|
||||
goto donehere;
|
||||
}
|
||||
|
||||
accel[v][cur[v]] = j;
|
||||
cur[v]++;
|
||||
|
||||
v = ind[j+2];
|
||||
|
||||
if (cur[v] >= HEIGHT_TRIACCEL_MAX)
|
||||
{
|
||||
os::Printer::log("Too complex mesh to optimize, aborting.");
|
||||
goto donehere;
|
||||
}
|
||||
|
||||
accel[v][cur[v]] = j;
|
||||
cur[v]++;
|
||||
}
|
||||
free(cur);
|
||||
|
||||
// Built, go
|
||||
for (u32 i = 0; i < verts; i++)
|
||||
{
|
||||
const vector3df &mypos = vert[i].Pos;
|
||||
|
||||
// find all edges of this vert
|
||||
edges.clear();
|
||||
|
||||
bool gotonext = false;
|
||||
u32 j;
|
||||
u16 cur;
|
||||
for (cur = 0; accel[i][cur] != USHRT_MAX && cur < HEIGHT_TRIACCEL_MAX; cur++)
|
||||
{
|
||||
j = accel[i][cur];
|
||||
|
||||
u32 far1 = -1, far2 = -1;
|
||||
if (ind[j] == i)
|
||||
{
|
||||
far1 = ind[j+1];
|
||||
far2 = ind[j+2];
|
||||
}
|
||||
else if (ind[j+1] == i)
|
||||
{
|
||||
far1 = ind[j];
|
||||
far2 = ind[j+2];
|
||||
}
|
||||
else if (ind[j+2] == i)
|
||||
{
|
||||
far1 = ind[j];
|
||||
far2 = ind[j+1];
|
||||
}
|
||||
|
||||
// Skip degenerate tris
|
||||
if (vert[i].Pos == vert[far1].Pos ||
|
||||
vert[far1].Pos == vert[far2].Pos)
|
||||
{
|
||||
// puts("skipping degenerate tri");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Edges found, check if we already added them
|
||||
const u32 ecount = edges.size();
|
||||
bool far1new = true, far2new = true;
|
||||
|
||||
for (u32 e = 0; e < ecount; e++)
|
||||
{
|
||||
if (edges[e].far == far1 ||
|
||||
edges[e].far == far2)
|
||||
{
|
||||
|
||||
// Skip if over 2 polys
|
||||
if (edges[e].polycount > 2)
|
||||
{
|
||||
gotonext = true;
|
||||
goto almostnext;
|
||||
}
|
||||
edges[e].polys[edges[e].polycount] = j;
|
||||
edges[e].normal[edges[e].polycount] =
|
||||
vert[i].Normal;
|
||||
edges[e].polycount++;
|
||||
|
||||
if (edges[e].far == far1)
|
||||
far1new = false;
|
||||
else
|
||||
far2new = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (far1new)
|
||||
{
|
||||
// New edge
|
||||
height_edge ed;
|
||||
|
||||
ed.far = far1;
|
||||
ed.polycount = 1;
|
||||
ed.polys[0] = j;
|
||||
ed.normal[0] = vert[i].Normal;
|
||||
|
||||
edges.push_back(ed);
|
||||
}
|
||||
if (far2new)
|
||||
{
|
||||
// New edge
|
||||
height_edge ed;
|
||||
|
||||
ed.far = far2;
|
||||
ed.polycount = 1;
|
||||
ed.polys[0] = j;
|
||||
ed.normal[0] = vert[i].Normal;
|
||||
|
||||
edges.push_back(ed);
|
||||
}
|
||||
}
|
||||
|
||||
almostnext:
|
||||
if (gotonext)
|
||||
continue;
|
||||
|
||||
// Edges found. Possible to simplify?
|
||||
|
||||
const u32 ecount = edges.size();
|
||||
// printf("Vert %u has %u edges\n", i, ecount);
|
||||
for (u32 e = 0; e < ecount; e++)
|
||||
{
|
||||
for (u32 f = 0; f < ecount; f++)
|
||||
{
|
||||
if (f == e) continue;
|
||||
|
||||
vector3df one = mypos - vert[edges[e].far].Pos;
|
||||
vector3df two = vert[edges[f].far].Pos - mypos;
|
||||
|
||||
one.normalize();
|
||||
two.normalize();
|
||||
|
||||
// Straight line ?
|
||||
if (!one.equals(two, tolerance) || one.getLengthSQ() < 0.5f)
|
||||
continue;
|
||||
|
||||
// All other edges must have two polys
|
||||
for (u32 g = 0; g < ecount; g++)
|
||||
{
|
||||
if (g == e || g == f)
|
||||
continue;
|
||||
|
||||
if (edges[g].polycount != 2)
|
||||
{
|
||||
// printf("%u: polycount not 2 (%u)\n",
|
||||
// g, edges[g].polycount);
|
||||
goto testnext;
|
||||
}
|
||||
|
||||
// Normals must match
|
||||
if (!edges[g].normal[0].equals(edges[g].normal[1],
|
||||
tolerance))
|
||||
{
|
||||
// puts("Normals don't match");
|
||||
goto testnext;
|
||||
}
|
||||
|
||||
// Normals must not flip
|
||||
for (u32 z = 0; z < edges[g].polycount; z++)
|
||||
{
|
||||
bool flat = false;
|
||||
vector3df pos[3];
|
||||
pos[0] =
|
||||
vert[ind[edges[g].polys[z]]].Pos;
|
||||
pos[1] =
|
||||
vert[ind[edges[g].polys[z] + 1]].Pos;
|
||||
pos[2] =
|
||||
vert[ind[edges[g].polys[z] + 2]].Pos;
|
||||
|
||||
for (u32 y = 0; y < 3; y++)
|
||||
{
|
||||
if (edges[g].polys[z] + y == i)
|
||||
{
|
||||
pos[y] = vert[edges[e].far].Pos;
|
||||
}
|
||||
else if (edges[g].polys[z] + y
|
||||
== edges[e].far)
|
||||
{
|
||||
flat = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flat)
|
||||
{
|
||||
triangle3df temp(pos[0],
|
||||
pos[1], pos[2]);
|
||||
vector3df N = temp.getNormal();
|
||||
N.normalize();
|
||||
// if (N.getLengthSQ() < 0.5f)
|
||||
// puts("empty");
|
||||
|
||||
if (N != edges[g].normal[z])
|
||||
{
|
||||
// puts("wouldflip");
|
||||
goto testnext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Must not be on model edge
|
||||
if (edges[g].polycount == 1)
|
||||
{
|
||||
goto testnext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Must not be on model edge
|
||||
if (edges[e].polycount == 1)
|
||||
{
|
||||
goto testnext;
|
||||
}
|
||||
|
||||
// OK, moving to welding position
|
||||
vert[i] = vert[edges[e].far];
|
||||
// printf("Contracted vert %u to %u\n",
|
||||
// i, edges[e].far);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
testnext:;
|
||||
}
|
||||
|
||||
donehere:
|
||||
for (u32 i = 0; i < verts; i++)
|
||||
{
|
||||
free(accel[i]);
|
||||
}
|
||||
free(accel);
|
||||
}
|
||||
|
||||
|
||||
//! Creates a copy of the mesh, which will only consist of S3DVertex2TCoords vertices.
|
||||
// not yet 32bit
|
||||
|
|
|
@ -86,6 +86,12 @@ public:
|
|||
|
||||
//! create a mesh optimized for the vertex cache
|
||||
virtual IMesh* createForsythOptimizedMesh(const scene::IMesh *mesh) const;
|
||||
|
||||
//! Optimizes the mesh using an algorithm tuned for heightmaps
|
||||
virtual void heightmapOptimizeMesh(IMesh * const m, const f32 tolerance = core::ROUNDING_ERROR_f32) const;
|
||||
|
||||
//! Optimizes the mesh using an algorithm tuned for heightmaps
|
||||
virtual void heightmapOptimizeMesh(IMeshBuffer * const m, const f32 tolerance = core::ROUNDING_ERROR_f32) const;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
|
|
|
@ -64,7 +64,7 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
|
|||
|
||||
// write OBJ MESH header
|
||||
|
||||
core::stringc name;
|
||||
io::path name;
|
||||
core::cutFilenameExtension(name,file->getFileName()) += ".mtl";
|
||||
file->write("# exported by Irrlicht\n",23);
|
||||
file->write("mtllib ",7);
|
||||
|
|
|
@ -34,6 +34,9 @@ namespace irr
|
|||
namespace video
|
||||
{
|
||||
|
||||
// Statics variables
|
||||
const u16 COpenGLDriver::Quad2DIndices[4] = { 0, 1, 2, 3 };
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// WINDOWS CONSTRUCTOR
|
||||
// -----------------------------------------------------------------------
|
||||
|
@ -756,22 +759,11 @@ bool COpenGLDriver::genericDriverInit()
|
|||
extGlProvokingVertex(GL_FIRST_VERTEX_CONVENTION_EXT);
|
||||
#endif
|
||||
|
||||
// Create built-in 2D quad and line for 2D rendering.
|
||||
|
||||
Quad2DIndices[0] = 0;
|
||||
Quad2DIndices[1] = 2;
|
||||
Quad2DIndices[2] = 3;
|
||||
Quad2DIndices[3] = 0;
|
||||
Quad2DIndices[4] = 1;
|
||||
Quad2DIndices[5] = 2;
|
||||
|
||||
Line2DIndices[0] = 0;
|
||||
Line2DIndices[1] = 1;
|
||||
|
||||
// Create built-in 2D quad for 2D rendering (both quads and lines).
|
||||
Quad2DVertices[0] = S3DVertex(core::vector3df(-1.0f, 1.0f, 0.0f), core::vector3df(0.0f, 0.0f, 0.0f), SColor(255,255,255,255), core::vector2df(0.0f, 1.0f));
|
||||
Quad2DVertices[0] = S3DVertex(core::vector3df(1.0f, 1.0f, 0.0f), core::vector3df(0.0f, 0.0f, 0.0f), SColor(255,255,255,255), core::vector2df(1.0f, 1.0f));
|
||||
Quad2DVertices[0] = S3DVertex(core::vector3df(1.0f, -1.0f, 0.0f), core::vector3df(0.0f, 0.0f, 0.0f), SColor(255,255,255,255), core::vector2df(1.0f, 0.0f));
|
||||
Quad2DVertices[0] = S3DVertex(core::vector3df(-1.0f, -1.0f, 0.0f), core::vector3df(0.0f, 0.0f, 0.0f), SColor(255,255,255,255), core::vector2df(0.0f, 0.0f));
|
||||
Quad2DVertices[1] = S3DVertex(core::vector3df(1.0f, 1.0f, 0.0f), core::vector3df(0.0f, 0.0f, 0.0f), SColor(255,255,255,255), core::vector2df(1.0f, 1.0f));
|
||||
Quad2DVertices[2] = S3DVertex(core::vector3df(1.0f, -1.0f, 0.0f), core::vector3df(0.0f, 0.0f, 0.0f), SColor(255,255,255,255), core::vector2df(1.0f, 0.0f));
|
||||
Quad2DVertices[3] = S3DVertex(core::vector3df(-1.0f, -1.0f, 0.0f), core::vector3df(0.0f, 0.0f, 0.0f), SColor(255,255,255,255), core::vector2df(0.0f, 0.0f));
|
||||
|
||||
// create material renderers
|
||||
createMaterialRenderers();
|
||||
|
@ -2069,7 +2061,7 @@ void COpenGLDriver::draw2DImageBatch(const video::ITexture* texture,
|
|||
Quad2DVertices[2].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
|
||||
Quad2DVertices[3].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2223,7 +2215,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture,
|
|||
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2308,7 +2300,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect
|
|||
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
|
||||
if (clipRect)
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
@ -2401,7 +2393,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture,
|
|||
Quad2DVertices[2].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
|
||||
Quad2DVertices[3].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
|
||||
targetPos.X += sourceRects[currentIndex].getWidth();
|
||||
}
|
||||
|
@ -2482,7 +2474,7 @@ void COpenGLDriver::draw2DRectangle(const core::rect<s32>& position,
|
|||
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2523,7 +2515,7 @@ void COpenGLDriver::draw2DLine(const core::position2d<s32>& start,
|
|||
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
|
||||
}
|
||||
|
||||
glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, Line2DIndices);
|
||||
glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3984,7 +3976,7 @@ void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor lef
|
|||
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
|
||||
clearBuffers(false, false, clearStencilBuffer, 0x0);
|
||||
|
||||
|
@ -4069,7 +4061,7 @@ void COpenGLDriver::draw3DLine(const core::vector3df& start,
|
|||
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
|
||||
}
|
||||
|
||||
glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, Line2DIndices);
|
||||
glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, Quad2DIndices);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -602,8 +602,7 @@ namespace video
|
|||
|
||||
//! Built-in 2D quad for 2D rendering.
|
||||
S3DVertex Quad2DVertices[4];
|
||||
u16 Quad2DIndices[6];
|
||||
u16 Line2DIndices[2];
|
||||
static const u16 Quad2DIndices[4];
|
||||
|
||||
#ifdef _IRR_WINDOWS_API_
|
||||
HDC HDc; // Private GDI Device Context
|
||||
|
|
|
@ -39,8 +39,11 @@ void CSceneNodeAnimatorDelete::animateNode(ISceneNode* node, u32 timeMs)
|
|||
|
||||
ISceneNodeAnimator* CSceneNodeAnimatorDelete::createClone(ISceneNode* node, ISceneManager* newManager)
|
||||
{
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CSceneNodeAnimatorDelete* newAnimator =
|
||||
new CSceneNodeAnimatorDelete(SceneManager, FinishTime);
|
||||
new CSceneNodeAnimatorDelete(newManager, FinishTime);
|
||||
|
||||
return newAnimator;
|
||||
}
|
||||
|
|
|
@ -2269,6 +2269,8 @@ void CXMeshFileLoader::readUntilEndOfLine()
|
|||
|
||||
u16 CXMeshFileLoader::readBinWord()
|
||||
{
|
||||
if (P>=End)
|
||||
return 0;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
const u16 tmp = os::Byteswap::byteswap(*(u16 *)P);
|
||||
#else
|
||||
|
@ -2281,6 +2283,8 @@ u16 CXMeshFileLoader::readBinWord()
|
|||
|
||||
u32 CXMeshFileLoader::readBinDWord()
|
||||
{
|
||||
if (P>=End)
|
||||
return 0;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
const u32 tmp = os::Byteswap::byteswap(*(u32 *)P);
|
||||
#else
|
||||
|
|
Loading…
Reference in New Issue