Merge revisions r5337:r5415 from trunk to ogl-es.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@5416 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2017-04-12 15:33:31 +00:00
parent 63c2864db5
commit f1ee785039
74 changed files with 2003 additions and 713 deletions

View File

@ -9,6 +9,19 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point)
--------------------------
Changes in 1.9 (not yet released)
- Improve speed of draw3DBox (OpenGL and D3D9). Thanks @zerochen for patch (https://sourceforge.net/p/irrlicht/patches/256)
- Support more keys on OSX "[]\". Thanks @neoascetic for patch (#313).
- Fix IBillboardTextSceneNode::setTextColor which did nothing in the past. It now maps to setColor instead.
- Add access functions to IBillboardTextSceneNode (getText, getFont).
- Add access functions to ITextSceneNode (getText, getTextColor, setFont, getFont).
- Try harder to move Window to custom WindowPosition set in SIrrlichtCreationParameters on X11. Thx@ Hernan Ezequiel Di Giorgi for the patch (#304).
- Fix bug in virtual filessystem which prevented createFileList from working. Thx @Cube for reporting a problem.
- ITriangleSelector now can also return meshbuffer collision information.
- core::string::split now adds delimiter to token before delimiter when keepSeparators is true. That way we never end up with 2 tokens for an original string with a single character.
- Bugfix: SMesh::recalculateBoundingBox() does now ignore empty boundingboxes of meshbuffers instead of adding them.
- IIrrXMLReader::getAttributeValueAsInt and IIrrXMLReader::getAttributeValueAsFloat can now return a custom default-value when the attribute is not found.
- core::string::split now handles ignoreEmptyTokens=false correct. Thanks @manni63 for bugreport: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=51551&p=299375#p299375
- Bugfix: Previously when some material had a texture matrix and another didn't those materials were still considered identical. Which had prevented correct switching between materials with and without texture matrices.
- IWriteFile::write now returning size_t (like fwrite in c-lib). Also sizeToWrite parameter changed from u32 to size_t.
- IReadFile::read now returning size_t (like fread in c-lib). Also sizeToRead parameter changed from u32 to size_t.
- add clear function to strings.
@ -160,6 +173,17 @@ should now be fps independentn
--------------------------
Changes in 1.8.5
- Fix bug in cursor positions when compiled with newer Windows SDK's (v110 in VS2012) and running on Systems >= Windows Vista in windowed mode.
Thanks @Mustapha Tachouct for the bugreport and patch proposal. Also thanks @BakeMyCake for an earlier report.
- IOSOperator::getSysteMemory() no longer returns incorrect values with >2GB. Thanks @Eduline - human development for report and patch.
- Increase KEY_KEY_CODES_COUNT to fix problem with laptop keyboards which return the keycode 0xff for the function key. Thx @Klokancz for bugreport and patch.
- Fix bug when calling activateJoysticks on windows several times. It had appened joystick information instead of replacing it, thereby increasing joystick number on each call.
Only happened compiling with _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ (which is the default). Linux and SDL implementation not affected.
Thx @Andrea Demetrio for the bugreport.
- Fix bug in fast_atof when reading floating point numbers with more than 16 digits past the dot. Those produced completely wrong results (sometimes even causing INF numbers).
This bug also did cause many meshloaders to have problems with certain meshes (basically all text-based formats are affected).
- Accuracy of fast_atof is back to older Irrlicht versions (fixes test warnings, usually not a noticable problem).
- Fix crash in eventhandling when calling remove() on a contextmenu while it has focus.
- CImageLoaderJPG::isALoadableFileFormat uses a test which allows to load more jpg formats (for example uncompressed jpg's). Thx @Yaron Cohen-Tal for report, test-image and his help with the patch.
--------------------------
@ -255,7 +279,7 @@ Changes in 1.8 (7.11.2012)
- quaternion conversions to and from matrix4 no longer invert rotations.
To test if your code was affected by this you can set IRR_TEST_BROKEN_QUATERNION_USE in quaternion.h and try to compile your application.
Then on all compile-errors when you pass the matrix to the quaternion you can replace the matrix transposed matrix.
Then on all compile-errors when you pass the matrix to the quaternion you can replace the matrix with the transposed matrix.
For all errors you get on getMatrix() you can use quaternion::getMatrix_transposed instead.
- CGUIEnvironment::loadGui - loading a gui into a target-element no longer messes up when the gui-file contained guienvironment serialization.

View File

@ -36,6 +36,13 @@ enum
IDFlag_IsHighlightable = 1 << 1
};
/*
Some triangle selectors allow to get collisions either per mesh or per meshbuffer.
Getting them per mesh can be faster. But if you need information about the hit
material you have to get the meshbuffer information as well.
*/
const bool separateMeshBuffers = true;
int main()
{
// ask user for driver
@ -86,8 +93,34 @@ int main()
{
q3node->setPosition(core::vector3df(-1350,-130,-1400));
selector = smgr->createOctreeTriangleSelector(
q3node->getMesh(), q3node, 128);
/*
There is currently no way to split an octree by material.
So if we need that we have to create one octree per meshbuffer
and put them together in a MetaTriangleSelector.
*/
if ( separateMeshBuffers && q3node->getMesh()->getMeshBufferCount() > 1)
{
scene::IMetaTriangleSelector * metaSelector = smgr->createMetaTriangleSelector();
for ( irr::u32 m=0; m < q3node->getMesh()->getMeshBufferCount(); ++m )
{
scene::ITriangleSelector*
bufferSelector = smgr->createOctreeTriangleSelector(
q3node->getMesh()->getMeshBuffer(m), m, q3node);
if ( bufferSelector )
{
metaSelector->addTriangleSelector( bufferSelector );
bufferSelector->drop();
}
}
selector = metaSelector;
}
else
{
// Just one octree for the whole mesh.
// Can't get information which material got hit, but for many situations that's enough.
selector = smgr->createOctreeTriangleSelector(
q3node->getMesh(), q3node, 128);
}
q3node->setTriangleSelector(selector);
// We're not done with this selector yet, so don't drop it.
}
@ -138,7 +171,7 @@ int main()
if (selector)
{
scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
scene::ISceneNodeAnimatorCollisionResponse * anim = smgr->createCollisionResponseAnimator(
selector, camera, core::vector3df(30,50,30),
core::vector3df(0,-1000,0), core::vector3df(0,30,0));
selector->drop(); // As soon as we're done with the selector, drop it.
@ -183,7 +216,7 @@ int main()
// Now create a triangle selector for it. The selector will know that it
// is associated with an animated node, and will update itself as necessary.
selector = smgr->createTriangleSelector(node);
selector = smgr->createTriangleSelector(node, separateMeshBuffers);
node->setTriangleSelector(selector);
selector->drop(); // We're done with this selector, so drop it now.
@ -197,7 +230,7 @@ int main()
node->getMaterial(0).NormalizeNormals = true;
node->getMaterial(0).Lighting = true;
// Just do the same as we did above.
selector = smgr->createTriangleSelector(node);
selector = smgr->createTriangleSelector(node, separateMeshBuffers);
node->setTriangleSelector(selector);
selector->drop();
@ -208,11 +241,10 @@ int main()
node->setRotation(core::vector3df(0,-90,0)); // And turn it towards the camera.
node->setAnimationSpeed(20.f);
node->getMaterial(0).Lighting = true;
selector = smgr->createTriangleSelector(node);
selector = smgr->createTriangleSelector(node, separateMeshBuffers);
node->setTriangleSelector(selector);
selector->drop();
// And this mdl file uses skinned skeletal animation.
node = smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "yodan.mdl"),
0, IDFlag_IsPickable | IDFlag_IsHighlightable);
@ -222,7 +254,7 @@ int main()
node->setAnimationSpeed(20.f);
// Just do the same as we did above.
selector = smgr->createTriangleSelector(node);
selector = smgr->createTriangleSelector(node, separateMeshBuffers);
node->setTriangleSelector(selector);
selector->drop();
@ -237,7 +269,6 @@ int main()
// Remember which scene node is highlighted
scene::ISceneNode* highlightedSceneNode = 0;
scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();
int lastFPS = -1;
// draw the selection triangle only as wireframe
material.Wireframe=true;
@ -263,10 +294,6 @@ int main()
ray.start = camera->getPosition();
ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 1000.0f;
// Tracks the current intersection point with the level or a mesh
core::vector3df intersection;
// Used to show with triangle has been hit
core::triangle3df hitTriangle;
// This call is all you need to perform ray/triangle collision on every scene node
// that has a triangle selector, including the Quake level mesh. It finds the nearest
@ -274,25 +301,27 @@ int main()
// Irrlicht provides other types of selection, including ray/triangle selector,
// ray/box and ellipse/triangle selector, plus associated helpers.
// See the methods of ISceneCollisionManager
scene::ISceneNode * selectedSceneNode =
collMan->getSceneNodeAndCollisionPointFromRay(
irr::io::SNamedPath hitTextureName;
scene::SCollisionHit hitResult;
scene::ISceneNode * selectedSceneNode =collMan->getSceneNodeAndCollisionPointFromRay(
hitResult, // Returns all kind of info about the collision
ray,
intersection, // This will be the position of the collision
hitTriangle, // This will be the triangle hit in the collision
IDFlag_IsPickable, // This ensures that only nodes that we have
// set up to be pickable are considered
0); // Check the entire scene (this is actually the implicit default)
// If the ray hit anything, move the billboard to the collision position
// and draw the triangle that was hit.
if(selectedSceneNode)
{
bill->setPosition(intersection);
bill->setPosition(hitResult.Intersection); // Show the current intersection point with the level or a mesh
// We need to reset the transform before doing our own rendering.
driver->setTransform(video::ETS_WORLD, core::matrix4());
driver->setMaterial(material);
driver->draw3DTriangle(hitTriangle, video::SColor(0,255,0,0));
driver->draw3DTriangle(hitResult.Triangle, video::SColor(0,255,0,0)); // Show which triangle has been hit
// We can check the flags for the scene node that was hit to see if it should be
// highlighted. The animated nodes can be highlighted, but not the Quake level mesh
@ -304,23 +333,31 @@ int main()
// which means that it will be drawn with full brightness.
highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, false);
}
if ( hitResult.MeshBuffer && hitResult.Node && hitResult.Node->getMaterial(hitResult.MaterialIndex).TextureLayer[0].Texture )
{
// Note we are interested in the node material and not in the meshbuffer material.
// Otherwise we wouldn't get the fairy2 texture which is only set on the node.
hitTextureName = hitResult.Node->getMaterial(hitResult.MaterialIndex).TextureLayer[0].Texture->getName();
}
}
// We're all done drawing, so end the scene.
driver->endScene();
// Show some info in title-bar
int fps = driver->getFPS();
if (lastFPS != fps)
core::stringw str = L"Collision detection example - Irrlicht Engine [";
str += driver->getName();
str += "] FPS:";
str += fps;
if ( !hitTextureName.getInternalName().empty() )
{
core::stringw str = L"Collision detection example - Irrlicht Engine [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
str += " ";
irr::io::path texName(hitTextureName.getInternalName());
str += core::deletePathFromFilename(texName);
}
device->setWindowCaption(str.c_str());
}
device->drop();

View File

@ -30,6 +30,9 @@ namespace scene
//! Text Scene Node
ESNT_TEXT = MAKE_IRR_ID('t','e','x','t'),
//! Billboard text scene node
ESNT_BILLBOARD_TEXT = MAKE_IRR_ID('b','t','x','t'),
//! Water Surface Scene Node
ESNT_WATER_SURFACE = MAKE_IRR_ID('w','a','t','r'),

View File

@ -9,6 +9,12 @@
namespace irr
{
namespace gui
{
class IGUIFont;
}
namespace scene
{
@ -50,8 +56,18 @@ public:
//! sets the text string
virtual void setText(const wchar_t* text) = 0;
//! get the text string
virtual const wchar_t* getText() const = 0;
//! sets the color of the text
virtual void setTextColor(video::SColor color) = 0;
//! You can use setColor instead which does the same
virtual void setTextColor(video::SColor color)
{
setColor(color);
}
//! Get the font used to draw the text
virtual gui::IGUIFont* getFont() const = 0;
};
} // end namespace scene

View File

@ -38,10 +38,10 @@ public:
virtual bool getProcessorSpeedMHz(u32* MHz) const = 0;
//! Get the total and available system RAM
/** \param Total: will contain the total system memory
\param Avail: will contain the available memory
/** \param totalBytes: will contain the total system memory in bytes
\param availableBytes: will contain the available memory in bytes
\return True if successful, false if not */
virtual bool getSystemMemory(u32* Total, u32* Avail) const = 0;
virtual bool getSystemMemory(u32* totalBytes, u32* availableBytes) const = 0;
};

View File

@ -19,12 +19,45 @@ namespace scene
class ISceneNode;
class ICameraSceneNode;
class ITriangleSelector;
class IMeshBuffer;
struct SCollisionHit
{
//! Point of collision
core::vector3df Intersection;
//! Triangle with which we collided
core::triangle3df Triangle;
//! Triangle selector which contained the colliding triangle (useful when having MetaTriangleSelector)
ITriangleSelector* TriangleSelector;
//! Node which contained the triangle (is 0 when selector doesn't have that information)
ISceneNode* Node;
//! Meshbuffer which contained the triangle (is 0 when the selector doesn't have that information, only works when selectors are created per meshbuffer)
const IMeshBuffer* MeshBuffer;
//! Index of selected material of the triangle in the SceneNode. Usually only valid when MeshBuffer is also set, otherwise always 0
irr::u32 MaterialIndex;
SCollisionHit() : TriangleSelector(0), Node(0), MeshBuffer(0), MaterialIndex(0)
{}
};
//! The Scene Collision Manager provides methods for performing collision tests and picking on scene nodes.
class ISceneCollisionManager : public virtual IReferenceCounted
{
public:
//! Finds the nearest collision point of a line and lots of triangles, if there is one.
/** \param hitResult: Contains collision result when there was a collision detected.
\param ray: Line with which collisions are tested.
\param selector: TriangleSelector to be used for the collision check.
\return true if a collision was detected and false if not. */
virtual bool getCollisionPoint(SCollisionHit& hitResult, const core::line3d<f32>& ray,
ITriangleSelector* selector) = 0;
//! Finds the nearest collision point of a line and lots of triangles, if there is one.
/** \param ray: Line with which collisions are tested.
\param selector: TriangleSelector containing the triangles. It
@ -40,7 +73,18 @@ namespace scene
\return True if a collision was detected and false if not. */
virtual bool getCollisionPoint(const core::line3d<f32>& ray,
ITriangleSelector* selector, core::vector3df& outCollisionPoint,
core::triangle3df& outTriangle, ISceneNode*& outNode) =0;
core::triangle3df& outTriangle, ISceneNode*& outNode)
{
SCollisionHit hitResult;
if ( getCollisionPoint(hitResult, ray, selector) )
{
outCollisionPoint = hitResult.Intersection;
outTriangle = hitResult.Triangle;
outNode = hitResult.Node;
return true;
}
return false;
}
//! Collides a moving ellipsoid with a 3d world with gravity and returns the resulting new position of the ellipsoid.
/** This can be used for moving a character in a 3d world: The
@ -161,6 +205,7 @@ namespace scene
virtual ISceneNode* getSceneNodeFromCameraBB(const ICameraSceneNode* camera,
s32 idBitMask=0, bool bNoDebugObjects = false) = 0;
//! Perform a ray/box and ray/triangle collision check on a hierarchy of scene nodes.
/** This checks all scene nodes under the specified one, first by ray/bounding
box, and then by accurate ray/triangle collision, finding the nearest collision,
@ -173,6 +218,31 @@ namespace scene
You do not have to build a meta triangle selector; the individual triangle selectors
of each candidate scene node are used automatically.
\param ray: Line with which collisions are tested.
\param outCollisionPoint: If a collision is detected, this will contain the
position of the nearest collision.
\param outTriangle: If a collision is detected, this will contain the triangle
with which the ray collided.
\param idBitMask: Only scene nodes with an id which matches at least one of the
bits contained in this mask will be tested. However, if this parameter is 0, then
all nodes are checked.
\param collisionRootNode: the scene node at which to begin checking. Only this
node and its children will be checked. If you want to check the entire scene,
pass 0, and the root scene node will be used (this is the default).
\param noDebugObjects: when true, debug objects are not considered viable targets.
Debug objects are scene nodes with IsDebugObject() = true.
\return Returns the scene node containing the hit triangle nearest to ray.start.
If no collision is detected, then 0 is returned. */
virtual ISceneNode* getSceneNodeAndCollisionPointFromRay(
SCollisionHit& hitResult,
const core::line3df& ray,
s32 idBitMask = 0,
ISceneNode * collisionRootNode = 0,
bool noDebugObjects = false) = 0;
//! Perform a ray/box and ray/triangle collision check on a hierarchy of scene nodes.
/** Works same as other getSceneNodeAndCollisionPointFromRay but returns less information.
(was written before the other getSceneNodeAndCollisionPointFromRay implementation).
\param ray: Line with which collisions are tested.
\param outCollisionPoint: If a collision is detected, this will contain the
position of the nearest collision.
@ -194,12 +264,21 @@ namespace scene
core::triangle3df& outTriangle,
s32 idBitMask = 0,
ISceneNode * collisionRootNode = 0,
bool noDebugObjects = false) = 0;
};
bool noDebugObjects = false)
{
SCollisionHit hitResult;
ISceneNode* node = getSceneNodeAndCollisionPointFromRay(hitResult, ray, idBitMask, collisionRootNode, noDebugObjects);
if ( node )
{
outCollisionPoint = hitResult.Intersection;
outTriangle = hitResult.Triangle;
}
return node;
}
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -322,7 +322,7 @@ namespace scene
* files thanks to<br> the importer created by Jonas
* Petersen.
* Notes for<br> this version of the loader:<br>
* - It does not recognise/support user data in the
* - It does not recognize/support user data in the
* *.lmts files.<br>
* - The TGAs generated by LMTools don't work in
* Irrlicht for some reason (the textures are upside
@ -1271,19 +1271,30 @@ namespace scene
s->drop();
\endcode
\param mesh: Mesh of which the triangles are taken.
\param node: Scene node of which visibility and transformation is used.
\param node: Scene node of which transformation is used.
\param separateMeshbuffers: When true it's possible to get information which meshbuffer
got hit in collision tests. But has a slight speed cost.
\return The selector, or null if not successful.
If you no longer need the selector, you should call ITriangleSelector::drop().
See IReferenceCounted::drop() for more information. */
virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node) = 0;
virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node, bool separateMeshbuffers=false) = 0;
//! Creates a simple ITriangleSelector, based on a meshbuffer.
/**
This is a static selector which won't update when the mesh changes.
\param meshBuffer Triangles of that meshbuffer are used
\param materialIndex If you pass a material index that index can be returned by the triangle selector.
\para node: Scene node of which transformation is used.
*/
virtual ITriangleSelector* createTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node) = 0;
//! Creates a simple ITriangleSelector, based on an animated mesh scene node.
/** Details of the mesh associated with the node will be extracted internally.
Call ITriangleSelector::update() to have the triangle selector updated based
on the current frame of the animated mesh scene node.
\param node The animated mesh scene node from which to build the selector
\param separateMeshbuffers: When true it's possible to get information which meshbuffer
got hit in collision tests. But has a slight speed cost.
*/
virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node) = 0;
virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node, bool separateMeshbuffers=false) = 0;
//! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box.
@ -1323,6 +1334,33 @@ namespace scene
virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh,
ISceneNode* node, s32 minimalPolysPerNode=32) = 0;
//! Creates a Triangle Selector for a single meshbuffer, optimized by an octree.
/** Triangle selectors
can be used for doing collision detection. This triangle selector is
optimized for huge amounts of triangle, it organizes them in an octree.
Please note that the created triangle selector is not automatically attached
to the scene node. You will have to call ISceneNode::setTriangleSelector()
for this. To create and attach a triangle selector is done like this:
\code
ITriangleSelector* s = sceneManager->createOctreeTriangleSelector(yourMesh,
yourSceneNode);
yourSceneNode->setTriangleSelector(s);
s->drop();
\endcode
For more information and examples on this, take a look at the collision
tutorial in the SDK.
\param meshBuffer: Meshbuffer of which the triangles are taken.
\param materialIndex: Setting this value allows the triangle selector to return the material index
\param node: Scene node of which visibility and transformation is used.
\param minimalPolysPerNode: Specifies the minimal polygons contained a octree node.
If a node gets less polys than this value, it will not be split into
smaller nodes.
\return The selector, or null if not successful.
If you no longer need the selector, you should call ITriangleSelector::drop().
See IReferenceCounted::drop() for more information. */
virtual ITriangleSelector* createOctreeTriangleSelector(IMeshBuffer* meshBuffer, irr::u32 materialIndex,
ISceneNode* node, s32 minimalPolysPerNode=32) = 0;
//! //! Creates a Triangle Selector, optimized by an octree.
/** \deprecated Use createOctreeTriangleSelector instead. This method may be removed by Irrlicht 1.9. */
_IRR_DEPRECATED_ ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh,
@ -1589,7 +1627,7 @@ namespace scene
using ISceneManager::saveScene().
\param file File where the scene is loaded from.
\param userDataSerializer If you want to load user data
possibily saved in that file for some scene nodes in the file,
saved in that file for some scene nodes in the file,
implement the ISceneUserDataSerializer interface and provide it
as parameter here. Otherwise, simply specify 0 as this
parameter.

View File

@ -9,6 +9,12 @@
namespace irr
{
namespace gui
{
class IGUIFont;
}
namespace scene
{
@ -25,8 +31,20 @@ public:
//! sets the text string
virtual void setText(const wchar_t* text) = 0;
//! get the text string
virtual const wchar_t* getText() const = 0;
//! sets the color of the text
virtual void setTextColor(video::SColor color) = 0;
//! get the color of the text
virtual video::SColor getTextColor() const = 0;
//! set the font used to draw the text
virtual void setFont(gui::IGUIFont* font) = 0;
//! Get the font used to draw the text
virtual gui::IGUIFont* getFont() const = 0;
};
} // end namespace scene

View File

@ -10,6 +10,7 @@
#include "aabbox3d.h"
#include "matrix4.h"
#include "line3d.h"
#include "irrArray.h"
namespace irr
{
@ -17,6 +18,49 @@ namespace scene
{
class ISceneNode;
class ITriangleSelector;
class IMeshBuffer;
//! Additional information about the triangle arrays returned by ITriangleSelector::getTriangles
/** ITriangleSelector are free to fill out this information fully, partly or ignore it.
Usually they will try to fill it when they can and set values to 0 otherwise.
*/
struct SCollisionTriangleRange
{
SCollisionTriangleRange()
: RangeStart(0), RangeSize(0)
, Selector(0), SceneNode(0)
, MeshBuffer(0), MaterialIndex(0)
{}
//! Check if this triangle index inside the range
/**
\param triangleIndex Index to an element inside the array of triangles returned by ITriangleSelector::getTriangles
*/
bool isIndexInRange(irr::u32 triangleIndex) const
{
return triangleIndex >= RangeStart && triangleIndex < RangeStart+RangeSize;
}
//! First index in the array for which this struct is valid
irr::u32 RangeStart;
//! Number of elements in the array for which this struct is valid (starting with RangeStart)
irr::u32 RangeSize;
//! Real selector which contained those triangles (useful when working with MetaTriangleSelector)
ITriangleSelector* Selector;
//! SceneNode from which the triangles are from
ISceneNode* SceneNode;
//! Meshbuffer from which the triangles are from
//! Is 0 when the ITriangleSelector doesn't support meshbuffer selection
const IMeshBuffer* MeshBuffer;
//! Index of selected material in the SceneNode. Usually only valid when MeshBuffer is also set, otherwise always 0
irr::u32 MaterialIndex;
};
//! Interface to return triangles with specific properties.
/** Every ISceneNode may have a triangle selector, available with
@ -45,10 +89,18 @@ public:
into the array.
\param transform Pointer to matrix for transforming the triangles
before they are returned. Useful for example to scale all triangles
down into an ellipsoid space. If this pointer is null, no
transformation will be done. */
down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that
array is filled with additional information about the returned triangles.
One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer.
*/
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::matrix4* transform=0) const = 0;
s32& outTriangleCount, const core::matrix4* transform=0,
bool useNodeTransform=true,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo=0) const = 0;
//! Gets the triangles for one associated node which may lie within a specific bounding box.
/**
@ -68,11 +120,17 @@ public:
will be written into the array.
\param transform Pointer to matrix for transforming the triangles
before they are returned. Useful for example to scale all triangles
down into an ellipsoid space. If this pointer is null, no
transformation will be done. */
down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that
array is filled with additional information about the returned triangles.
One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer. */
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::aabbox3d<f32>& box,
const core::matrix4* transform=0) const = 0;
const core::matrix4* transform=0, bool useNodeTransform=true,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo=0) const = 0;
//! Gets the triangles for one associated node which have or may have contact with a 3d line.
/**
@ -92,22 +150,17 @@ public:
will be written into the array.
\param transform Pointer to matrix for transforming the triangles
before they are returned. Useful for example to scale all triangles
down into an ellipsoid space. If this pointer is null, no
transformation will be done. */
down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that
array is filled with additional information about the returned triangles.
One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer. */
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line,
const core::matrix4* transform=0) const = 0;
//! Get scene node associated with a given triangle.
/**
This allows to find which scene node (potentially of several) is
associated with a specific triangle.
\param triangleIndex: the index of the triangle for which you want to find
the associated scene node.
\return The scene node associated with that triangle.
*/
virtual ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const = 0;
const core::matrix4* transform=0, bool useNodeTransform=true,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo=0) const = 0;
//! Get number of TriangleSelectors that are part of this one
/** Only useful for MetaTriangleSelector, others return 1
@ -123,6 +176,17 @@ public:
/** Only useful for MetaTriangleSelector, others return 'this' or 0
*/
virtual const ITriangleSelector* getSelector(u32 index) const = 0;
//! Get scene node associated with a given triangle.
/** With CMetaTriangleSelector-selectors it's possible to find out a node
belonging to a certain triangle index.
NOTE: triangleIndex has nothing to do with the order of triangles returned by getTriangles functions!
So you can _not_ use this function to find out anything about to which node returned triangles belong.
Use STriangleCollisionInfo struct for that.
\param triangleIndex: the index of the triangle for which you want to find.
\return The scene node associated with that triangle.
*/
virtual ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const = 0;
};
} // end namespace scene

View File

@ -177,9 +177,10 @@ namespace irr
KEY_PLAY = 0xFA, // Play key
KEY_ZOOM = 0xFB, // Zoom key
KEY_PA1 = 0xFD, // PA1 key
KEY_OEM_CLEAR = 0xFE, // Clear key
KEY_OEM_CLEAR = 0xFE, // Clear key
KEY_NONE = 0xFF, // usually no key mapping, but some laptops use it for fn key
KEY_KEY_CODES_COUNT = 0xFF // this is not a key, but the amount of keycodes there are.
KEY_KEY_CODES_COUNT = 0x100 // this is not a key, but the amount of keycodes there are.
};
} // end namespace irr

View File

@ -165,8 +165,7 @@ namespace video
return true;
else
different |= (TextureMatrix != b.TextureMatrix) &&
TextureMatrix && b.TextureMatrix &&
(*TextureMatrix != *(b.TextureMatrix));
(!TextureMatrix || !b.TextureMatrix || (*TextureMatrix != *(b.TextureMatrix)));
return different;
}

View File

@ -83,13 +83,26 @@ namespace scene
//! recalculates the bounding box
void recalculateBoundingBox()
{
if (MeshBuffers.size())
bool hasMeshBufferBBox = false;
for (u32 i=0; i<MeshBuffers.size(); ++i)
{
BoundingBox = MeshBuffers[0]->getBoundingBox();
for (u32 i=1; i<MeshBuffers.size(); ++i)
BoundingBox.addInternalBox(MeshBuffers[i]->getBoundingBox());
const core::aabbox3df& bb = MeshBuffers[i]->getBoundingBox();
if ( !bb.isEmpty() )
{
if ( !hasMeshBufferBBox )
{
hasMeshBufferBBox = true;
BoundingBox = bb;
}
else
{
BoundingBox.addInternalBox(bb);
}
}
}
else
if ( !hasMeshBufferBBox )
BoundingBox.reset(0.0f, 0.0f, 0.0f);
}

View File

@ -17,7 +17,8 @@ namespace core
// the float-to-string code used there has to be rewritten first.
IRRLICHT_API extern irr::core::stringc LOCALE_DECIMAL_POINTS;
// we write [17] here instead of [] to work around a swig bug
#define IRR_ATOF_TABLE_SIZE 17
// we write [IRR_ATOF_TABLE_SIZE] here instead of [] to work around a swig bug
const float fast_atof_table[17] = {
0.f,
0.1f,
@ -323,8 +324,16 @@ inline const char* fast_atof_move(const char* in, f32& result)
if ( LOCALE_DECIMAL_POINTS.findFirst(*in) >= 0 )
{
const char* afterDecimal = ++in;
const f32 decimal = strtof10(in, &afterDecimal);
value += decimal * fast_atof_table[afterDecimal - in];
f32 decimal = strtof10(in, &afterDecimal);
size_t numDecimals = afterDecimal - in;
if (numDecimals < IRR_ATOF_TABLE_SIZE)
{
value += decimal * fast_atof_table[numDecimals];
}
else
{
value += decimal * (f32)pow(10.f, -(float)numDecimals);
}
in = afterDecimal;
}
@ -334,7 +343,8 @@ inline const char* fast_atof_move(const char* in, f32& result)
// Assume that the exponent is a whole number.
// strtol10() will deal with both + and - signs,
// but calculate as f32 to prevent overflow at FLT_MAX
value *= powf(10.f, (f32)strtol10(in, &in));
// Using pow with float cast instead of powf as otherwise accuracy decreases.
value *= (f32)pow(10.f, (f32)strtol10(in, &in));
}
result = negative?-value:value;

View File

@ -43,6 +43,7 @@ namespace core
//! Rounding error constant often used when comparing f32 values.
const s32 ROUNDING_ERROR_S32 = 0;
#ifdef __IRR_HAS_S64
const s64 ROUNDING_ERROR_S64 = 0;
#endif
@ -181,16 +182,85 @@ namespace core
b = c;
}
template <class T>
inline T roundingError();
template <>
inline f32 roundingError()
{
return ROUNDING_ERROR_f32;
}
template <>
inline f64 roundingError()
{
return ROUNDING_ERROR_f64;
}
template <>
inline s32 roundingError()
{
return ROUNDING_ERROR_S32;
}
template <>
inline u32 roundingError()
{
return ROUNDING_ERROR_S32;
}
#ifdef __IRR_HAS_S64
template <>
inline s64 roundingError()
{
return ROUNDING_ERROR_S64;
}
template <>
inline u64 roundingError()
{
return ROUNDING_ERROR_S64;
}
#endif
template <class T>
inline T relativeErrorFactor()
{
return 1;
}
template <>
inline f32 relativeErrorFactor()
{
return 4;
}
template <>
inline f64 relativeErrorFactor()
{
return 8;
}
//! returns if a equals b, taking possible rounding errors into account
inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
template <class T>
inline T equals(const T a, const T b, const T tolerance = roundingError<T>())
{
return (a + tolerance >= b) && (a - tolerance <= b);
}
//! returns if a equals b, taking possible rounding errors into account
inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
//! returns if a equals b, taking relative error in form of factor
//! this particular function does not involve any division.
template <class T>
inline bool equalsRelative( const T a, const T b, const T factor = relativeErrorFactor<T>())
{
return (a + tolerance >= b) && (a - tolerance <= b);
//https://eagergames.wordpress.com/2017/04/01/fast-parallel-lines-and-vectors-test/
const T maxi = max_( a, b);
const T mini = min_( a, b);
const T maxMagnitude = max_( maxi, -mini);
return (maxMagnitude*factor + maxi) == (maxMagnitude*factor + mini); // MAD Wise
}
union FloatIntUnion32
@ -233,39 +303,6 @@ namespace core
return false;
}
#if 0
//! returns if a equals b, not using any rounding tolerance
inline bool equals(const s32 a, const s32 b)
{
return (a == b);
}
//! returns if a equals b, not using any rounding tolerance
inline bool equals(const u32 a, const u32 b)
{
return (a == b);
}
#endif
//! returns if a equals b, taking an explicit rounding tolerance into account
inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
{
return (a + tolerance >= b) && (a - tolerance <= b);
}
//! returns if a equals b, taking an explicit rounding tolerance into account
inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
{
return (a + tolerance >= b) && (a - tolerance <= b);
}
#ifdef __IRR_HAS_S64
//! returns if a equals b, taking an explicit rounding tolerance into account
inline bool equals(const s64 a, const s64 b, const s64 tolerance = ROUNDING_ERROR_S64)
{
return (a + tolerance >= b) && (a - tolerance <= b);
}
#endif
//! returns if a equals zero, taking rounding errors into account
inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
{

View File

@ -1306,14 +1306,14 @@ public:
return used > 1 ? array[used-2] : 0;
}
//! split string into parts.
//! Split string into parts (tokens).
/** This method will split a string at certain delimiter characters
into the container passed in as reference. The type of the container
has to be given as template parameter. It must provide a push_back and
a size method.
\param ret The result container
\param c C-style string of delimiter characters
\param count Number of delimiter characters
\param ret The result container. Tokens are added, the container is not cleared.
\param delimiter C-style string of delimiter characters
\param countDelimiters Number of delimiter characters
\param ignoreEmptyTokens Flag to avoid empty substrings in the result
container. If two delimiters occur without a character in between, an
empty substring would be placed in the result. If this flag is set,
@ -1325,33 +1325,39 @@ public:
\return The number of resulting substrings
*/
template<class container>
u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
u32 split(container& ret, const T* const delimiter, u32 countDelimiters=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
{
if (!c)
if (!delimiter)
return 0;
const u32 oldSize=ret.size();
u32 lastpos = 0;
bool lastWasSeparator = false;
u32 tokenStartIdx = 0;
for (u32 i=0; i<used; ++i)
{
bool foundSeparator = false;
for (u32 j=0; j<count; ++j)
for (u32 j=0; j<countDelimiters; ++j)
{
if (array[i] == c[j])
if (array[i] == delimiter[j])
{
if ((!ignoreEmptyTokens || i - lastpos != 0) &&
!lastWasSeparator)
ret.push_back(string<T,TAlloc>(&array[lastpos], i - lastpos));
foundSeparator = true;
lastpos = (keepSeparators ? i : i + 1);
if ( keepSeparators )
{
ret.push_back(string<T,TAlloc>(&array[tokenStartIdx], i+1 - tokenStartIdx));
}
else
{
if (i - tokenStartIdx > 0)
ret.push_back(string<T,TAlloc>(&array[tokenStartIdx], i - tokenStartIdx));
else if ( !ignoreEmptyTokens )
ret.push_back(string<T,TAlloc>());
}
tokenStartIdx = i+1;
break;
}
}
lastWasSeparator = foundSeparator;
}
if ((used - 1) > lastpos)
ret.push_back(string<T,TAlloc>(&array[lastpos], (used - 1) - lastpos));
if ((used - 1) > tokenStartIdx)
ret.push_back(string<T,TAlloc>(&array[tokenStartIdx], (used - 1) - tokenStartIdx));
return ret.size()-oldSize;
}

View File

@ -316,27 +316,31 @@ namespace io
//! Returns the value of an attribute as integer.
/** \param name Name of the attribute.
\return Value of the attribute as integer, and 0 if an attribute with this name does not exist or
the value could not be interpreted as integer. */
virtual int getAttributeValueAsInt(const char_type* name) const = 0;
\param defaultNotFound Value returned when name does not exist
\return Value of the attribute as integer or value of defaultNotFound
when name was not found or 0 when value could not be interpreted as integer */
virtual int getAttributeValueAsInt(const char_type* name, int defaultNotFound=0) const = 0;
//! Returns the value of an attribute as integer.
/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
\return Value of the attribute as integer, and 0 if an attribute with this index does not exist or
the value could not be interpreted as integer. */
virtual int getAttributeValueAsInt(int idx) const = 0;
\param defaultNotFound Value returned when index does not exist.
\return Value of the attribute as integer or value of defaultNotFound parameter for invalid index
or 0 when value could not be interpreted as integer */
virtual int getAttributeValueAsInt(int idx, int defaultNotFound=0) const = 0;
//! Returns the value of an attribute as float.
/** \param name: Name of the attribute.
\return Value of the attribute as float, and 0 if an attribute with this name does not exist or
the value could not be interpreted as float. */
virtual float getAttributeValueAsFloat(const char_type* name) const = 0;
\param defaultNotFound Value returned when name does not exist.
\return Value of the attribute as float or value of defaultNotFound parameter on failure
or 0 when value could not be interpreted as float. */
virtual float getAttributeValueAsFloat(const char_type* name, float defaultNotFound=0.f) const = 0;
//! Returns the value of an attribute as float.
/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
\return Value of the attribute as float, and 0 if an attribute with this index does not exist or
the value could not be interpreted as float. */
virtual float getAttributeValueAsFloat(int idx) const = 0;
\param defaultNotFound Value returned when index does not exist.
\return Value of the attribute as float or value of defaultNotFound parameter on failure
or 0 when value could not be interpreted as float. */
virtual float getAttributeValueAsFloat(int idx, float defaultNotFound=0.f) const = 0;
//! Returns the name of the current node.
/** Only valid, if the node type is EXN_ELEMENT.

View File

@ -65,7 +65,85 @@ class line2d
//! Get the vector of the line.
/** \return The vector of the line. */
vector2d<T> getVector() const { return vector2d<T>(end.X - start.X, end.Y - start.Y); }
vector2d<T> getVector() const { return vector2d<T>( end.X - start.X, end.Y - start.Y); }
/*! Check if this segment intersects another segment,
or if segments are coincindent (colinear). */
bool intersectAsSegments( const line2d<T>& other) const
{
// Taken from:
// http://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
// Find the four orientations needed for general and
// special cases
s32 o1 = start.checkOrientation( end, other.start);
s32 o2 = start.checkOrientation( end, other.end);
s32 o3 = other.start.checkOrientation( other.end, start);
s32 o4 = other.start.checkOrientation( other.end, end);
// General case
if (o1 != o2 && o3 != o4)
return true;
// Special Cases to check if segments are coolinear
if (o1 == 0 && other.start.isBetweenPoints( start, end)) return true;
if (o2 == 0 && other.end.isBetweenPoints( start, end)) return true;
if (o3 == 0 && start.isBetweenPoints( other.start, other.end)) return true;
if (o4 == 0 && end.isBetweenPoints( other.start, other.end)) return true;
return false; // Doesn't fall in any of the above cases
}
/*! Check if 2 segments are incident (intersects in exactly 1 point).*/
bool incidentSegments( const line2d<T>& other) const
{
return
start.checkOrientation( end, other.start) != start.checkOrientation( end, other.end)
&& other.start.checkOrientation( other.end, start) != other.start.checkOrientation( other.end, end);
}
/*! Check if 2 lines/segments are parallel or nearly parallel.*/
bool nearlyParallel( const line2d<T>& line, const T factor = relativeErrorFactor<T>()) const
{
const vector2d<T> a = getVector();
const vector2d<T> b = line.getVector();
return a.nearlyParallel( b, factor);
}
/*! returns a intersection point of 2 lines (if lines are not parallel). Behaviour
undefined if lines are parallel or coincident.*/
vector2d<T> fastLinesIntersection( const line2d<T>& l) const
{
const f32 commonDenominator = (f32)((l.end.Y - l.start.Y)*(end.X - start.X) -
(l.end.X - l.start.X)*(end.Y - start.Y));
const f32 numeratorA = (f32)((l.end.X - l.start.X)*(start.Y - l.start.Y) -
(l.end.Y - l.start.Y)*(start.X - l.start.X));
const f32 numeratorB = (f32)((end.X - start.X)*(start.Y - l.start.Y) -
(end.Y - start.Y)*(start.X - l.start.X));
const f32 uA = numeratorA / commonDenominator;
const f32 uB = numeratorB / commonDenominator;
// Calculate the intersection point.
return vector2d<T> (
(T)(start.X + uA * (end.X - start.X)),
(T)(start.Y + uA * (end.Y - start.Y))
);
}
/*! Check if this line intersect a segment. The eventual intersection point is returned in "out".*/
bool lineIntersectSegment( const line2d<T>& segment, vector2d<T> & out) const
{
if (nearlyParallel( segment))
return false;
out = fastLinesIntersection( segment);
return out.isBetweenPoints( segment.start, segment.end);
}
//! Tests if this line intersects with another line.
/** \param l: Other line to test intersection with.
@ -209,7 +287,7 @@ class line2d
/** Assumes that the point is already somewhere on the line. */
bool isPointBetweenStartAndEnd(const vector2d<T>& point) const
{
return point.isBetweenPoints(start, end);
return point.isBetweenPoints(start, end);
}
//! Get the closest point on this line to a point

View File

@ -221,18 +221,25 @@ namespace core
void rotateVect(T *out,const core::vector3df &in) const;
//! Transforms the vector by this matrix
/** This operation is performed as if the vector was 4d with the 4th component =1 */
void transformVect( vector3df& vect) const;
//! Transforms input vector by this matrix and stores result in output vector
/** This operation is performed as if the vector was 4d with the 4th component =1 */
void transformVect( vector3df& out, const vector3df& in ) const;
//! An alternate transform vector method, writing into an array of 4 floats
/** This operation is performed as if the vector was 4d with the 4th component =1.
NOTE: out[3] will be written to (4th vector component)*/
void transformVect(T *out,const core::vector3df &in) const;
//! An alternate transform vector method, reading from and writing to an array of 3 floats
/** This operation is performed as if the vector was 4d with the 4th component =1
NOTE: out[3] will be written to (4th vector component)*/
void transformVec3(T *out, const T * in) const;
//! Translate a vector by the translation part of this matrix.
/** This operation is performed as if the vector was 4d with the 4th component =1 */
void translateVect( vector3df& vect ) const;
//! Transforms a plane by this matrix
@ -247,7 +254,7 @@ namespace core
void transformBox(core::aabbox3d<f32>& box) const;
//! Transforms a axis aligned bounding box
/** The result box of this operation should by accurate, but this operation
/** The result box of this operation should be accurate, but this operation
is slower than transformBox(). */
void transformBoxEx(core::aabbox3d<f32>& box) const;
@ -2233,6 +2240,8 @@ namespace core
{
#if defined ( USE_MATRIX_TEST )
definitelyIdentityMatrix = isDefinitelyIdentityMatrix;
#else
(void)isDefinitelyIdentityMatrix; // prevent compiler warning
#endif
}

View File

@ -108,6 +108,8 @@ class quaternion
//! Creates a matrix from this quaternion
matrix4 getMatrix() const;
#endif
//! Faster method to create a rotation matrix, you should normalize the quaternion before!
void getMatrixFast(matrix4 &dest) const;
//! Creates a matrix from this quaternion
void getMatrix( matrix4 &dest, const core::vector3df &translation=core::vector3df() ) const;
@ -349,12 +351,51 @@ inline matrix4 quaternion::getMatrix() const
}
#endif
//! Faster method to create a rotation matrix, you should normalize the quaternion before!
inline void quaternion::getMatrixFast( matrix4 &dest) const
{
// TODO:
// gpu quaternion skinning => fast Bones transform chain O_O YEAH!
// http://www.mrelusive.com/publications/papers/SIMD-From-Quaternion-to-Matrix-and-Back.pdf
dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z;
dest[1] = 2.0f*X*Y + 2.0f*Z*W;
dest[2] = 2.0f*X*Z - 2.0f*Y*W;
dest[3] = 0.0f;
dest[4] = 2.0f*X*Y - 2.0f*Z*W;
dest[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z;
dest[6] = 2.0f*Z*Y + 2.0f*X*W;
dest[7] = 0.0f;
dest[8] = 2.0f*X*Z + 2.0f*Y*W;
dest[9] = 2.0f*Z*Y - 2.0f*X*W;
dest[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y;
dest[11] = 0.0f;
dest[12] = 0.f;
dest[13] = 0.f;
dest[14] = 0.f;
dest[15] = 1.f;
dest.setDefinitelyIdentityMatrix(false);
}
/*!
Creates a matrix from this quaternion
*/
inline void quaternion::getMatrix(matrix4 &dest,
const core::vector3df &center) const
{
// ok creating a copy may be slower, but at least avoid internal
// state chance (also because otherwise we cannot keep this method "const").
quaternion q( *this);
q.normalize();
f32 X = q.X;
f32 Y = q.Y;
f32 Z = q.Z;
f32 W = q.W;
dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z;
dest[1] = 2.0f*X*Y + 2.0f*Z*W;
dest[2] = 2.0f*X*Z - 2.0f*Y*W;
@ -395,6 +436,13 @@ inline void quaternion::getMatrixCenter(matrix4 &dest,
const core::vector3df &center,
const core::vector3df &translation) const
{
quaternion q(*this);
q.normalize();
f32 X = q.X;
f32 Y = q.Y;
f32 Z = q.Z;
f32 W = q.W;
dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z;
dest[1] = 2.0f*X*Y + 2.0f*Z*W;
dest[2] = 2.0f*X*Z - 2.0f*Y*W;
@ -416,6 +464,13 @@ inline void quaternion::getMatrixCenter(matrix4 &dest,
// Creates a matrix from this quaternion
inline void quaternion::getMatrix_transposed(matrix4 &dest) const
{
quaternion q(*this);
q.normalize();
f32 X = q.X;
f32 Y = q.Y;
f32 Z = q.Z;
f32 W = q.W;
dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z;
dest[4] = 2.0f*X*Y + 2.0f*Z*W;
dest[8] = 2.0f*X*Z - 2.0f*Y*W;
@ -492,7 +547,7 @@ inline quaternion& quaternion::set(f32 x, f32 y, f32 z)
// sets new quaternion based on Euler angles
inline quaternion& quaternion::set(const core::vector3df& vec)
{
return set(vec.X, vec.Y, vec.Z);
return set( vec.X, vec.Y, vec.Z);
}
// sets new quaternion based on other quaternion
@ -505,28 +560,23 @@ inline quaternion& quaternion::set(const core::quaternion& quat)
//! returns if this quaternion equals the other one, taking floating point rounding errors into account
inline bool quaternion::equals(const quaternion& other, const f32 tolerance) const
{
return core::equals(X, other.X, tolerance) &&
core::equals(Y, other.Y, tolerance) &&
core::equals(Z, other.Z, tolerance) &&
core::equals(W, other.W, tolerance);
return core::equals( X, other.X, tolerance) &&
core::equals( Y, other.Y, tolerance) &&
core::equals( Z, other.Z, tolerance) &&
core::equals( W, other.W, tolerance);
}
// normalizes the quaternion
inline quaternion& quaternion::normalize()
{
const f32 n = X*X + Y*Y + Z*Z + W*W;
if (n == 1)
return *this;
//n = 1.0f / sqrtf(n);
return (*this *= reciprocal_squareroot ( n ));
// removed conditional branch since it may slow down and anyway the condition was
// false even after normalization in some cases.
return (*this *= reciprocal_squareroot ( X*X + Y*Y + Z*Z + W*W ));
}
// set this quaternion to the result of the linear interpolation between two quaternions
inline quaternion& quaternion::lerp(quaternion q1, quaternion q2, f32 time)
inline quaternion& quaternion::lerp( quaternion q1, quaternion q2, f32 time)
{
const f32 scale = 1.0f - time;
return (*this = (q1*scale) + (q2*time));
@ -534,7 +584,7 @@ inline quaternion& quaternion::lerp(quaternion q1, quaternion q2, f32 time)
// set this quaternion to the result of the interpolation between two quaternions
inline quaternion& quaternion::slerp(quaternion q1, quaternion q2, f32 time, f32 threshold)
inline quaternion& quaternion::slerp( quaternion q1, quaternion q2, f32 time, f32 threshold)
{
f32 angle = q1.dotProduct(q2);

View File

@ -127,6 +127,20 @@ public:
return X*other.X + Y*other.Y;
}
//! check if this vector is parallel to another vector
bool nearlyParallel( const vector2d<T> & other, const T factor = relativeErrorFactor<T>()) const
{
// https://eagergames.wordpress.com/2017/04/01/fast-parallel-lines-and-vectors-test/
// if a || b then a.x/a.y = b.x/b.y (similiar triangles)
// if a || b then either both x are 0 or both y are 0.
return equalsRelative( X*other.Y, other.X* Y, factor)
&& // a bit counterintuitive, but makes sure that
// only y or only x are 0, and at same time deals
// with the case where one vector is zero vector.
(X*other.X + Y*other.Y) != 0;
}
//! Gets distance from another point.
/** Here, the vector is interpreted as a point in 2-dimensional space.
\param other Other vector to measure from.
@ -259,15 +273,24 @@ public:
\return True if this vector is between begin and end, false if not. */
bool isBetweenPoints(const vector2d<T>& begin, const vector2d<T>& end) const
{
// . end
// /
// /
// /
// . begin
// -
// -
// . this point (am I inside or outside)?
//
if (begin.X != end.X)
{
return ((begin.X <= X && X <= end.X) ||
(begin.X >= X && X >= end.X));
(begin.X >= X && X >= end.X));
}
else
{
return ((begin.Y <= Y && Y <= end.Y) ||
(begin.Y >= Y && Y >= end.Y));
(begin.Y >= Y && Y >= end.Y));
}
}
@ -300,13 +323,55 @@ public:
(T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2));
}
/*! Test if this point and another 2 poitns taken as triplet
are colinear, clockwise, anticlockwise. This can be used also
to check winding order in triangles for 2D meshes.
\return 0 if points are colinear, 1 if clockwise, 2 if anticlockwise
*/
s32 checkOrientation( const vector2d<T> & b, const vector2d<T> & c) const
{
// Example of clockwise points
//
// ^ Y
// | A
// | . .
// | . .
// | C.....B
// +---------------> X
T val = (b.Y - Y) * (c.X - b.X) -
(b.X - X) * (c.Y - b.Y);
if (val == 0) return 0; // colinear
return (val > 0) ? 1 : 2; // clock or counterclock wise
}
/*! Returns true if points (a,b,c) are clockwise on the X,Y plane*/
inline bool areClockwise( const vector2d<T> & b, const vector2d<T> & c) const
{
T val = (b.Y - Y) * (c.X - b.X) -
(b.X - X) * (c.Y - b.Y);
return val > 0;
}
/*! Returns true if points (a,b,c) are counterclockwise on the X,Y plane*/
inline bool areCounterClockwise( const vector2d<T> & b, const vector2d<T> & c) const
{
T val = (b.Y - Y) * (c.X - b.X) -
(b.X - X) * (c.Y - b.Y);
return val < 0;
}
//! Sets this vector to the linearly interpolated vector between a and b.
/** \param a first vector to interpolate with, maximum at 1.0f
\param b second vector to interpolate with, maximum at 0.0f
\param d Interpolation value between 0.0f (all vector b) and 1.0f (all vector a)
Note that this is the opposite direction of interpolation to getInterpolated_quadratic()
*/
vector2d<T>& interpolate(const vector2d<T>& a, const vector2d<T>& b, f64 d)
vector2d<T>& interpolate( const vector2d<T>& a, const vector2d<T>& b, f64 d)
{
X = (T)((f64)b.X + ( ( a.X - b.X ) * d ));
Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d ));

View File

@ -50,7 +50,7 @@ namespace scene
{
BinaryFileReader(io::IReadFile* pFile) : file(pFile) { }
s32 readBuffer(void* buffer, s32 len)
size_t readBuffer(void* buffer, s32 len)
{
return file->read(buffer,len);
}

View File

@ -2830,6 +2830,47 @@ void CD3D9Driver::draw3DLine(const core::vector3df& start,
pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, v, sizeof(S3DVertex));
}
void CD3D9Driver::draw3DBox( const core::aabbox3d<f32>& box, SColor color)
{
core::vector3df edges[8];
box.getEdges(edges);
setVertexShader(EVT_STANDARD);
setRenderStates3DMode();
video::S3DVertex v[24];
for(u32 i = 0; i < 24; i++)
v[i].Color = color;
v[0].Pos = edges[5];
v[1].Pos = edges[1];
v[2].Pos = edges[1];
v[3].Pos = edges[3];
v[4].Pos = edges[3];
v[5].Pos = edges[7];
v[6].Pos = edges[7];
v[7].Pos = edges[5];
v[8].Pos = edges[0];
v[9].Pos = edges[2];
v[10].Pos = edges[2];
v[11].Pos = edges[6];
v[12].Pos = edges[6];
v[13].Pos = edges[4];
v[14].Pos = edges[4];
v[15].Pos = edges[0];
v[16].Pos = edges[1];
v[17].Pos = edges[0];
v[18].Pos = edges[3];
v[19].Pos = edges[2];
v[20].Pos = edges[7];
v[21].Pos = edges[6];
v[22].Pos = edges[5];
v[23].Pos = edges[4];
pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 12, v, sizeof(S3DVertex));
}
//! resets the device
bool CD3D9Driver::reset()

View File

@ -170,6 +170,9 @@ namespace video
virtual void draw3DLine(const core::vector3df& start,
const core::vector3df& end, SColor color = SColor(255,255,255,255)) _IRR_OVERRIDE_;
//! Draws a 3d box.
virtual void draw3DBox( const core::aabbox3d<f32>& box, SColor color = SColor(255,255,255,255 ) ) _IRR_OVERRIDE_;
//! initialises the Direct3D API
bool initDriver(HWND hwnd, bool pureSoftware);

View File

@ -5,6 +5,7 @@
#include "CDefaultSceneNodeFactory.h"
#include "ISceneManager.h"
#include "ITextSceneNode.h"
#include "IBillboardTextSceneNode.h"
#include "ITerrainSceneNode.h"
#include "IDummyTransformationSceneNode.h"
#include "ICameraSceneNode.h"
@ -33,6 +34,7 @@ CDefaultSceneNodeFactory::CDefaultSceneNodeFactory(ISceneManager* mgr)
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CUBE, "cube"));
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SPHERE, "sphere"));
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TEXT, "text"));
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_BILLBOARD_TEXT, "billboardText"));
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_WATER_SURFACE, "waterSurface"));
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TERRAIN, "terrain"));
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_BOX, "skyBox"));
@ -70,6 +72,8 @@ ISceneNode* CDefaultSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, IScene
return Manager->addSphereSceneNode(5, 16, parent);
case ESNT_TEXT:
return Manager->addTextSceneNode(0, L"example");
case ESNT_BILLBOARD_TEXT:
return Manager->addBillboardTextSceneNode(0, L"example");
case ESNT_WATER_SURFACE:
return Manager->addWaterSurfaceSceneNode(0, 2.0f, 300.0f, 10.0f, parent);
case ESNT_TERRAIN:

View File

@ -826,7 +826,7 @@ IFileList* CFileSystem::createFileList()
CFileList* r = 0;
io::path Path = getWorkingDirectory();
Path.replace('\\', '/');
if (Path.lastChar() != '/')
if (!Path.empty() && Path.lastChar() != '/')
Path.append('/');
//! Construct from native filesystem

View File

@ -285,22 +285,25 @@ bool CGUIContextMenu::OnEvent(const SEvent& event)
{
// set event parent of submenus
IGUIElement * p = EventParent ? EventParent : Parent;
setEventParent(p);
SEvent event;
event.EventType = EET_GUI_EVENT;
event.GUIEvent.Caller = this;
event.GUIEvent.Element = 0;
event.GUIEvent.EventType = EGET_ELEMENT_CLOSED;
if ( !p->OnEvent(event) )
if ( p ) // can be 0 when element got removed already
{
if ( CloseHandling & ECMC_HIDE )
setEventParent(p);
SEvent event;
event.EventType = EET_GUI_EVENT;
event.GUIEvent.Caller = this;
event.GUIEvent.Element = 0;
event.GUIEvent.EventType = EGET_ELEMENT_CLOSED;
if ( !p->OnEvent(event) )
{
setVisible(false);
}
if ( CloseHandling & ECMC_REMOVE )
{
remove();
if ( CloseHandling & ECMC_HIDE )
{
setVisible(false);
}
if ( CloseHandling & ECMC_REMOVE )
{
remove();
}
}
}

View File

@ -128,7 +128,7 @@ bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile* file) const
if (!(file && file->seek(0)))
return false;
unsigned char header[3];
int headerLen = file->read(header, sizeof(header));
size_t headerLen = file->read(header, sizeof(header));
return headerLen >= 3 && !memcmp(header, "\xFF\xD8\xFF", 3);
#endif
}

View File

@ -498,6 +498,11 @@ bool CIrrDeviceLinux::createWindow()
IrrPrintXGrabError(grabPointer, "XGrabPointer");
XWarpPointer(XDisplay, None, XWindow, 0, 0, 0, 0, 0, 0);
}
else if (CreationParams.WindowPosition.X >= 0 || CreationParams.WindowPosition.Y >= 0) // default is -1, -1
{
// Window managers are free to ignore positions above, so give it another shot
XMoveWindow(XDisplay,XWindow,x,y);
}
}
else
{

View File

@ -1395,6 +1395,10 @@ void CIrrDeviceMacOSX::initKeycodes()
KeyCodes[kVK_ANSI_KeypadDivide] = irr::KEY_DIVIDE;
KeyCodes[kVK_ANSI_KeypadEnter] = irr::KEY_RETURN;
KeyCodes[kVK_ANSI_KeypadMinus] = irr::KEY_SUBTRACT;
KeyCodes[kVK_ANSI_LeftBracket] = irr::KEY_OEM_4;
KeyCodes[kVK_ANSI_Backslash] = irr::KEY_OEM_5;
KeyCodes[kVK_ANSI_RightBracket] = irr::KEY_OEM_6;
}

View File

@ -455,6 +455,8 @@ irr::core::stringc SJoystickWin32Control::findJoystickName(int index, const JOYC
bool SJoystickWin32Control::activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
{
#if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_
joystickInfo.clear();
ActiveJoysticks.clear();
#ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_
if (!DirectInputDevice || (DirectInputDevice->EnumDevices(DI8DEVCLASS_GAMECTRL, SJoystickWin32Control::EnumJoysticks, this, DIEDFL_ATTACHEDONLY )))
{
@ -475,9 +477,6 @@ bool SJoystickWin32Control::activateJoysticks(core::array<SJoystickInfo> & joyst
}
return true;
#else
joystickInfo.clear();
ActiveJoysticks.clear();
const u32 numberOfJoysticks = ::joyGetNumDevs();
JOYINFOEX info;
info.dwSize = sizeof(info);
@ -2002,6 +2001,26 @@ void CIrrDeviceWin32::ReportLastWinApiError()
}
}
// Same function Windows offers in VersionHelpers.h, but we can't use that as it's not available in older sdk's (minimum is SDK 8.1)
bool CIrrDeviceWin32::isWindowsVistaOrGreater()
{
#if (_WIN32_WINNT >= 0x0500)
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 6; // Windows Vista
if ( !GetVersionEx((OSVERSIONINFO*)&osvi) )
{
return false;
}
return VerifyVersionInfo(&osvi, VER_MAJORVERSION, VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL));
#else
return false;
#endif
}
// Convert an Irrlicht texture to a Windows cursor
// Based on http://www.codeguru.com/cpp/w-p/win32/cursors/article.php/c4529/
HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot)

View File

@ -118,13 +118,16 @@ namespace irr
return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY, inputEvent );
}
//! switchs to fullscreen
//! Switch to fullscreen
bool switchToFullScreen(bool reset=false);
//! Check for and show last Windows API error to help internal debugging.
//! Does call GetLastError and on errors formats the errortext and displays it in a messagebox.
//! Does call GetLastError and on errors formats the error text and displays it in a messagebox.
static void ReportLastWinApiError();
//! Same function Windows offers in VersionHelpers.h, but we can't use that as it's not available before SDK 8.1
static bool isWindowsVistaOrGreater();
// convert an Irrlicht texture to a windows cursor
HCURSOR TextureToCursor(HWND hwnd, irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
@ -282,15 +285,21 @@ namespace irr
{
if (!fullscreen)
{
s32 paddingBorder = 0;
#if defined (SM_CXPADDEDBORDER)
if (CIrrDeviceWin32::isWindowsVistaOrGreater())
paddingBorder = GetSystemMetrics(SM_CXPADDEDBORDER);
#endif
if (resizable)
{
BorderX = GetSystemMetrics(SM_CXSIZEFRAME);
BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME);
BorderX = GetSystemMetrics(SM_CXSIZEFRAME) + paddingBorder;
BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME) + paddingBorder;
}
else
{
BorderX = GetSystemMetrics(SM_CXDLGFRAME);
BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME);
BorderX = GetSystemMetrics(SM_CXDLGFRAME) + paddingBorder;
BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME) + paddingBorder;
}
}
else

View File

@ -159,7 +159,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
// read whole file
u8* buffer = new u8[fileSize];
s32 read = file->read(buffer, fileSize);
long read = (long)file->read(buffer, fileSize);
if (read != fileSize)
{
delete [] buffer;

View File

@ -38,14 +38,27 @@ s32 CMetaTriangleSelector::getTriangleCount() const
//! Gets all triangles.
void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::matrix4* transform) const
s32& outTriangleCount, const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
s32 outWritten = 0;
irr::u32 outTriangleInfoSize = outTriangleInfo ? outTriangleInfo->size() : 0;
for (u32 i=0; i<TriangleSelectors.size(); ++i)
{
s32 t = 0;
TriangleSelectors[i]->getTriangles(triangles + outWritten,
arraySize - outWritten, t, transform);
arraySize - outWritten, t, transform, useNodeTransform, outTriangleInfo);
if ( outTriangleInfo )
{
irr::u32 newTriangleInfoSize = outTriangleInfo->size();
for ( u32 ti=outTriangleInfoSize; ti<newTriangleInfoSize; ++ti )
{
(*outTriangleInfo)[ti].RangeStart += outWritten;
}
outTriangleInfoSize = newTriangleInfoSize;
}
outWritten += t;
if (outWritten==arraySize)
break;
@ -58,14 +71,27 @@ void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 array
//! Gets all triangles which lie within a specific bounding box.
void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::aabbox3d<f32>& box,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
s32 outWritten = 0;
irr::u32 outTriangleInfoSize = outTriangleInfo ? outTriangleInfo->size() : 0;
for (u32 i=0; i<TriangleSelectors.size(); ++i)
{
s32 t = 0;
TriangleSelectors[i]->getTriangles(triangles + outWritten,
arraySize - outWritten, t, box, transform);
arraySize - outWritten, t, box, transform, useNodeTransform, outTriangleInfo);
if ( outTriangleInfo )
{
irr::u32 newTriangleInfoSize = outTriangleInfo->size();
for ( u32 ti=outTriangleInfoSize; ti<newTriangleInfoSize; ++ti )
{
(*outTriangleInfo)[ti].RangeStart += outWritten;
}
outTriangleInfoSize = newTriangleInfoSize;
}
outWritten += t;
if (outWritten==arraySize)
break;
@ -78,14 +104,27 @@ void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 array
//! Gets all triangles which have or may have contact with a 3d line.
void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
s32 outWritten = 0;
irr::u32 outTriangleInfoSize = outTriangleInfo ? outTriangleInfo->size() : 0;
for (u32 i=0; i<TriangleSelectors.size(); ++i)
{
s32 t = 0;
TriangleSelectors[i]->getTriangles(triangles + outWritten,
arraySize - outWritten, t, line, transform);
arraySize - outWritten, t, line, transform, useNodeTransform, outTriangleInfo);
if ( outTriangleInfo )
{
irr::u32 newTriangleInfoSize = outTriangleInfo->size();
for ( u32 ti=outTriangleInfoSize; ti<newTriangleInfoSize; ++ti )
{
(*outTriangleInfo)[ti].RangeStart += outWritten;
}
outTriangleInfoSize = newTriangleInfoSize;
}
outWritten += t;
if (outWritten==arraySize)
break;
@ -147,11 +186,9 @@ ISceneNode* CMetaTriangleSelector::getSceneNodeForTriangle(u32 triangleIndex) co
return TriangleSelectors[i]->getSceneNodeForTriangle(0);
}
// For lack of anything more sensible, return the first selector.
return TriangleSelectors[0]->getSceneNodeForTriangle(0);
return 0;
}
/* Return the number of TriangleSelectors that are inside this one,
Only useful for MetaTriangleSelector others return 1
*/

View File

@ -29,17 +29,20 @@ public:
//! Gets all triangles.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::matrix4* transform=0) const _IRR_OVERRIDE_;
s32& outTriangleCount, const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Gets all triangles which lie within a specific bounding box.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::aabbox3d<f32>& box,
const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Gets all triangles which have or may have contact with a 3d line.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line,
const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Adds a triangle selector to the collection of triangle selectors
//! in this metaTriangleSelector.

View File

@ -100,6 +100,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
bool mtlChanged=false;
bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS);
bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES);
irr::u32 lineNr = 1; // only counts non-empty lines, still useful in debugging to locate errors
while(bufPtr != bufEnd)
{
switch(bufPtr[0])
@ -289,6 +290,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
} // end switch(bufPtr[0])
// eat up rest of line
bufPtr = goNextLine(bufPtr, bufEnd);
++lineNr;
} // end while(bufPtr && (bufPtr-buf<filesize))
SMesh* mesh = new SMesh();

View File

@ -11,9 +11,9 @@
#else
#include <string.h>
#include <unistd.h>
#ifndef _IRR_SOLARIS_PLATFORM_
#ifndef _IRR_ANDROID_PLATFORM_
#include <sys/types.h>
#ifdef _IRR_OSX_PLATFORM_
#include <sys/sysctl.h>
#endif
#endif
@ -84,7 +84,7 @@ void COSOperator::copyToClipboard(const c8* text) const
#elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_)
NSString *str = nil;
NSPasteboard *board = nil;
if ((text != NULL) && (strlen(text) > 0))
{
str = [NSString stringWithCString:text encoding:NSWindowsCP1252StringEncoding];
@ -92,7 +92,7 @@ void COSOperator::copyToClipboard(const c8* text) const
[board declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:NSApp];
[board setString:str forType:NSStringPboardType];
}
#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_)
if ( IrrDeviceLinux )
IrrDeviceLinux->copyToClipboard(text);
@ -127,10 +127,10 @@ const c8* COSOperator::getTextFromClipboard() const
board = [NSPasteboard generalPasteboard];
str = [board stringForType:NSStringPboardType];
if (str != nil)
result = (char*)[str cStringUsingEncoding:NSWindowsCP1252StringEncoding];
return (result);
#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_)
@ -208,18 +208,32 @@ bool COSOperator::getProcessorSpeedMHz(u32* MHz) const
bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const
{
#if defined(_IRR_WINDOWS_API_) && !defined (_IRR_XBOX_PLATFORM_)
#if (_WIN32_WINNT >= 0x0500)
MEMORYSTATUSEX MemoryStatusEx;
MemoryStatusEx.dwLength = sizeof(MEMORYSTATUSEX);
// cannot fail
GlobalMemoryStatusEx(&MemoryStatusEx);
if (Total)
*Total = (u32)(MemoryStatusEx.ullTotalPhys>>10);
if (Avail)
*Avail = (u32)(MemoryStatusEx.ullAvailPhys>>10);
return true;
#else
MEMORYSTATUS MemoryStatus;
MemoryStatus.dwLength = sizeof(MEMORYSTATUS);
// cannot fail
// cannot fail
GlobalMemoryStatus(&MemoryStatus);
if (Total)
if (Total)
*Total = (u32)(MemoryStatus.dwTotalPhys>>10);
if (Avail)
if (Avail)
*Avail = (u32)(MemoryStatus.dwAvailPhys>>10);
return true;
return true;
#endif
#elif defined(_IRR_POSIX_API_) && !defined(__FreeBSD__)
#if defined(_SC_PHYS_PAGES) && defined(_SC_AVPHYS_PAGES)
@ -236,7 +250,7 @@ bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const
*Avail = (u32)((ps*(long long)ap)>>10);
return true;
#else
// TODO: implement for non-availablity of symbols/features
// TODO: implement for non-availability of symbols/features
return false;
#endif
#elif defined(_IRR_OSX_PLATFORM_)

View File

@ -15,8 +15,9 @@ namespace scene
//! constructor
COctreeTriangleSelector::COctreeTriangleSelector(const IMesh* mesh,
ISceneNode* node, s32 minimalPolysPerNode)
: CTriangleSelector(mesh, node), Root(0), NodeCount(0),
MinimalPolysPerNode(minimalPolysPerNode)
: CTriangleSelector(mesh, node, false)
, Root(0), NodeCount(0)
, MinimalPolysPerNode(minimalPolysPerNode)
{
#ifdef _DEBUG
setDebugName("COctreeTriangleSelector");
@ -38,6 +39,30 @@ COctreeTriangleSelector::COctreeTriangleSelector(const IMesh* mesh,
}
}
COctreeTriangleSelector::COctreeTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node, s32 minimalPolysPerNode)
: CTriangleSelector(meshBuffer, materialIndex, node)
, Root(0), NodeCount(0)
, MinimalPolysPerNode(minimalPolysPerNode)
{
#ifdef _DEBUG
setDebugName("COctreeTriangleSelector");
#endif
if (!Triangles.empty())
{
const u32 start = os::Timer::getRealTime();
// create the triangle octree
Root = new SOctreeNode();
Root->Triangles = Triangles;
constructOctree(Root);
c8 tmp[256];
sprintf(tmp, "Needed %ums to create OctreeTriangleSelector.(%d nodes, %u polys)",
os::Timer::getRealTime() - start, NodeCount, Triangles.size());
os::Printer::log(tmp, ELL_INFORMATION);
}
}
//! destructor
COctreeTriangleSelector::~COctreeTriangleSelector()
@ -111,15 +136,19 @@ void COctreeTriangleSelector::constructOctree(SOctreeNode* node)
void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount,
const core::aabbox3d<f32>& box,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
core::matrix4 mat(core::matrix4::EM4CONST_NOTHING);
core::aabbox3d<f32> invbox = box;
if (SceneNode)
if (SceneNode && useNodeTransform)
{
SceneNode->getAbsoluteTransformation().getInverse(mat);
mat.transformBoxEx(invbox);
if ( SceneNode->getAbsoluteTransformation().getInverse(mat) )
mat.transformBoxEx(invbox);
else
// TODO: case not handled well, we can only return all triangles
return CTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, transform, useNodeTransform, outTriangleInfo);
}
if (transform)
@ -127,7 +156,7 @@ void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles,
else
mat.makeIdentity();
if (SceneNode)
if (SceneNode && useNodeTransform)
mat *= SceneNode->getAbsoluteTransformation();
s32 trianglesWritten = 0;
@ -136,6 +165,17 @@ void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles,
getTrianglesFromOctree(Root, trianglesWritten,
arraySize, invbox, &mat, triangles);
if ( outTriangleInfo )
{
SCollisionTriangleRange triRange;
triRange.RangeSize = trianglesWritten;
triRange.Selector = const_cast<COctreeTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
triRange.MeshBuffer = MeshBuffer;
triRange.MaterialIndex = MaterialIndex;
outTriangleInfo->push_back(triRange);
}
outTriangleCount = trianglesWritten;
}
@ -180,7 +220,8 @@ void COctreeTriangleSelector::getTrianglesFromOctree(
// new version: from user Piraaate
void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
#if 0
core::aabbox3d<f32> box(line.start);
@ -194,7 +235,7 @@ void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arr
core::matrix4 mat ( core::matrix4::EM4CONST_NOTHING );
core::vector3df vectStartInv ( line.start ), vectEndInv ( line.end );
if (SceneNode)
if (SceneNode && useNodeTransform)
{
mat = SceneNode->getAbsoluteTransformation();
mat.makeInverse();
@ -208,7 +249,7 @@ void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arr
if (transform)
mat = (*transform);
if (SceneNode)
if (SceneNode && useNodeTransform)
mat *= SceneNode->getAbsoluteTransformation();
s32 trianglesWritten = 0;
@ -216,6 +257,17 @@ void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arr
if (Root)
getTrianglesFromOctree(Root, trianglesWritten, arraySize, invline, &mat, triangles);
if ( outTriangleInfo )
{
SCollisionTriangleRange triRange;
triRange.RangeSize = trianglesWritten;
triRange.Selector = const_cast<COctreeTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
triRange.MeshBuffer = MeshBuffer;
triRange.MaterialIndex = MaterialIndex;
outTriangleInfo->push_back(triRange);
}
outTriangleCount = trianglesWritten;
#endif
}
@ -262,4 +314,3 @@ void COctreeTriangleSelector::getTrianglesFromOctree(SOctreeNode* node,
} // end namespace scene
} // end namespace irr

View File

@ -22,16 +22,21 @@ public:
//! Constructs a selector based on a mesh
COctreeTriangleSelector(const IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode);
//! Constructs a selector based on a meshbuffer
COctreeTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node, s32 minimalPolysPerNode);
virtual ~COctreeTriangleSelector();
//! Gets all triangles which lie within a specific bounding box.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount,
const core::aabbox3d<f32>& box, const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::aabbox3d<f32>& box, const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Gets all triangles which have or may have contact with a 3d line.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line,
const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
private:

View File

@ -25,8 +25,6 @@ COpenGLCacheHandler::COpenGLCacheHandler(COpenGLDriver* driver) :
glAlphaFunc(AlphaMode, AlphaRef);
glDisable(GL_ALPHA_TEST);
glMatrixMode(MatrixMode);
Driver->irrGlClientActiveTexture(ClientActiveTexture);

View File

@ -1087,14 +1087,19 @@ void COpenGLDriver::renderArray(const void* indexList, u32 primitiveCount,
glPointSize(particleSize);
#ifdef GL_ARB_point_sprite
if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite])
glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE, GL_TRUE);
if (pType == scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite])
{
CacheHandler->setActiveTexture(GL_TEXTURE0_ARB);
glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE, GL_TRUE);
}
#endif
glDrawArrays(GL_POINTS, 0, primitiveCount);
#ifdef GL_ARB_point_sprite
if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite])
{
glDisable(GL_POINT_SPRITE_ARB);
CacheHandler->setActiveTexture(GL_TEXTURE0_ARB);
glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE, GL_FALSE);
}
#endif
@ -2098,8 +2103,6 @@ void COpenGLDriver::setMaterial(const SMaterial& material)
CacheHandler->getTextureCache().set(i, material.getTexture(i));
setTransform((E_TRANSFORMATION_STATE)(ETS_TEXTURE_0 + i), material.getTextureMatrix(i));
}
CacheHandler->setActiveTexture(GL_TEXTURE0_ARB);
}
@ -2148,6 +2151,8 @@ void COpenGLDriver::setRenderStates3DMode()
CacheHandler->setBlend(false);
CacheHandler->setAlphaTest(false);
CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
CacheHandler->setActiveTexture(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// switch back the matrices
CacheHandler->setMatrixMode(GL_MODELVIEW);
@ -2747,7 +2752,7 @@ void COpenGLDriver::setTextureRenderStates(const SMaterial& material, bool reset
{
// Set textures to TU/TIU and apply filters to them
for (s32 i = Feature.TextureUnit - 1; i>= 0; --i)
for (s32 i = Feature.TextureUnit - 1; i >= 0; --i)
{
bool fixedPipeline = false;
@ -2756,149 +2761,146 @@ void COpenGLDriver::setTextureRenderStates(const SMaterial& material, bool reset
const COpenGLTexture* tmpTexture = CacheHandler->getTextureCache().get(i);
if (!tmpTexture)
continue;
CacheHandler->setActiveTexture(GL_TEXTURE0 + i);
if (fixedPipeline)
if (tmpTexture)
{
const bool isRTT = tmpTexture->isRenderTarget();
CacheHandler->setActiveTexture(GL_TEXTURE0 + i);
CacheHandler->setMatrixMode(GL_TEXTURE);
if (!isRTT && Matrices[ETS_TEXTURE_0 + i].isIdentity())
glLoadIdentity();
else
if (fixedPipeline)
{
GLfloat glmat[16];
if (isRTT)
getGLTextureMatrix(glmat, Matrices[ETS_TEXTURE_0 + i] * TextureFlipMatrix);
const bool isRTT = tmpTexture->isRenderTarget();
CacheHandler->setMatrixMode(GL_TEXTURE);
if (!isRTT && Matrices[ETS_TEXTURE_0 + i].isIdentity())
glLoadIdentity();
else
getGLTextureMatrix(glmat, Matrices[ETS_TEXTURE_0 + i]);
glLoadMatrixf(glmat);
{
GLfloat glmat[16];
if (isRTT)
getGLTextureMatrix(glmat, Matrices[ETS_TEXTURE_0 + i] * TextureFlipMatrix);
else
getGLTextureMatrix(glmat, Matrices[ETS_TEXTURE_0 + i]);
glLoadMatrixf(glmat);
}
}
}
const GLenum tmpType = tmpTexture->getOpenGLTextureType();
const GLenum tmpType = tmpTexture->getOpenGLTextureType();
COpenGLTexture::SStatesCache& statesCache = tmpTexture->getStatesCache();
COpenGLTexture::SStatesCache& statesCache = tmpTexture->getStatesCache();
if (resetAllRenderstates)
statesCache.IsCached = false;
if (resetAllRenderstates)
statesCache.IsCached = false;
#ifdef GL_VERSION_2_1
if (Version>=210)
{
if (!statesCache.IsCached || material.TextureLayer[i].LODBias != statesCache.LODBias)
if (Version >= 210)
{
if (!statesCache.IsCached || material.TextureLayer[i].LODBias != statesCache.LODBias)
{
if (material.TextureLayer[i].LODBias)
{
const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias);
glTexParameterf(tmpType, GL_TEXTURE_LOD_BIAS, tmp);
}
else
glTexParameterf(tmpType, GL_TEXTURE_LOD_BIAS, 0.f);
statesCache.LODBias = material.TextureLayer[i].LODBias;
}
}
else if (FeatureAvailable[IRR_EXT_texture_lod_bias])
{
if (material.TextureLayer[i].LODBias)
{
const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias);
glTexParameterf(tmpType, GL_TEXTURE_LOD_BIAS, tmp);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmp);
}
else
glTexParameterf(tmpType, GL_TEXTURE_LOD_BIAS, 0.f);
statesCache.LODBias = material.TextureLayer[i].LODBias;
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.f);
}
}
else if (FeatureAvailable[IRR_EXT_texture_lod_bias])
{
if (material.TextureLayer[i].LODBias)
{
const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmp);
}
else
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.f);
}
#elif defined(GL_EXT_texture_lod_bias)
if (FeatureAvailable[IRR_EXT_texture_lod_bias])
{
if (material.TextureLayer[i].LODBias)
if (FeatureAvailable[IRR_EXT_texture_lod_bias])
{
const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmp);
if (material.TextureLayer[i].LODBias)
{
const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmp);
}
else
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.f);
}
else
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.f);
}
#endif
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter)
{
glTexParameteri(tmpType, GL_TEXTURE_MAG_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
}
if (material.UseMipMaps && tmpTexture->hasMipMaps())
{
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || !statesCache.MipMapStatus)
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter)
{
glTexParameteri(tmpType, GL_TEXTURE_MIN_FILTER,
material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :
material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :
GL_NEAREST_MIPMAP_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MipMapStatus = true;
}
}
else
{
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || statesCache.MipMapStatus)
{
glTexParameteri(tmpType, GL_TEXTURE_MIN_FILTER,
glTexParameteri(tmpType, GL_TEXTURE_MAG_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MipMapStatus = false;
}
}
if (material.UseMipMaps && tmpTexture->hasMipMaps())
{
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || !statesCache.MipMapStatus)
{
glTexParameteri(tmpType, GL_TEXTURE_MIN_FILTER,
material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :
material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :
GL_NEAREST_MIPMAP_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MipMapStatus = true;
}
}
else
{
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || statesCache.MipMapStatus)
{
glTexParameteri(tmpType, GL_TEXTURE_MIN_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MipMapStatus = false;
}
}
#ifdef GL_EXT_texture_filter_anisotropic
if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic] &&
(!statesCache.IsCached || material.TextureLayer[i].AnisotropicFilter != statesCache.AnisotropicFilter))
{
glTexParameteri(tmpType, GL_TEXTURE_MAX_ANISOTROPY_EXT,
material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1);
if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic] &&
(!statesCache.IsCached || material.TextureLayer[i].AnisotropicFilter != statesCache.AnisotropicFilter))
{
glTexParameteri(tmpType, GL_TEXTURE_MAX_ANISOTROPY_EXT,
material.TextureLayer[i].AnisotropicFilter > 1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1);
statesCache.AnisotropicFilter = material.TextureLayer[i].AnisotropicFilter;
}
statesCache.AnisotropicFilter = material.TextureLayer[i].AnisotropicFilter;
}
#endif
if (!statesCache.IsCached || material.TextureLayer[i].TextureWrapU != statesCache.WrapU)
{
glTexParameteri(tmpType, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[i].TextureWrapU));
statesCache.WrapU = material.TextureLayer[i].TextureWrapU;
}
if (!statesCache.IsCached || material.TextureLayer[i].TextureWrapU != statesCache.WrapU)
{
glTexParameteri(tmpType, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[i].TextureWrapU));
statesCache.WrapU = material.TextureLayer[i].TextureWrapU;
}
if (!statesCache.IsCached || material.TextureLayer[i].TextureWrapV != statesCache.WrapV)
{
glTexParameteri(tmpType, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[i].TextureWrapV));
statesCache.WrapV = material.TextureLayer[i].TextureWrapV;
}
if (!statesCache.IsCached || material.TextureLayer[i].TextureWrapV != statesCache.WrapV)
{
glTexParameteri(tmpType, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[i].TextureWrapV));
statesCache.WrapV = material.TextureLayer[i].TextureWrapV;
}
if (!statesCache.IsCached || material.TextureLayer[i].TextureWrapW != statesCache.WrapW)
{
glTexParameteri(tmpType, GL_TEXTURE_WRAP_R, getTextureWrapMode(material.TextureLayer[i].TextureWrapW));
statesCache.WrapW = material.TextureLayer[i].TextureWrapW;
}
if (!statesCache.IsCached || material.TextureLayer[i].TextureWrapW != statesCache.WrapW)
{
glTexParameteri(tmpType, GL_TEXTURE_WRAP_R, getTextureWrapMode(material.TextureLayer[i].TextureWrapW));
statesCache.WrapW = material.TextureLayer[i].TextureWrapW;
}
statesCache.IsCached = true;
statesCache.IsCached = true;
}
}
// be sure to leave in texture stage 0
CacheHandler->setActiveTexture(GL_TEXTURE0);
}
@ -2920,6 +2922,8 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
else
FixedPipelineState = COpenGLDriver::EOFPS_ENABLE;
bool resetAllRenderStates = false;
if (CurrentRenderMode != ERM_2D || Transformation3DChanged)
{
// unset last 3d material
@ -2928,6 +2932,7 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
if (static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size())
MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();
}
if (Transformation3DChanged)
{
CacheHandler->setMatrixMode(GL_PROJECTION);
@ -2940,32 +2945,40 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
CacheHandler->setMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375f, 0.375f, 0.0f);
// Make sure we set first texture matrix
CacheHandler->setActiveTexture(GL_TEXTURE0);
Transformation3DChanged = false;
}
if (!OverrideMaterial2DEnabled)
{
setBasicRenderStates(InitMaterial2D, LastMaterial, true);
LastMaterial = InitMaterial2D;
}
CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#ifdef GL_EXT_clip_volume_hint
if (FeatureAvailable[IRR_EXT_clip_volume_hint])
glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST);
#endif
resetAllRenderStates = true;
}
if (OverrideMaterial2DEnabled)
SMaterial currentMaterial = (!OverrideMaterial2DEnabled) ? InitMaterial2D : OverrideMaterial2D;
currentMaterial.Lighting = false;
if (texture)
{
OverrideMaterial2D.Lighting=false;
setBasicRenderStates(OverrideMaterial2D, LastMaterial, false);
LastMaterial = OverrideMaterial2D;
setTransform(ETS_TEXTURE_0, core::IdentityMatrix);
// Due to the transformation change, the previous line would call a reset each frame
// but we can safely reset the variable as it was false before
Transformation3DChanged = false;
}
else
{
CacheHandler->getTextureCache().set(0, 0);
}
setBasicRenderStates(currentMaterial, LastMaterial, resetAllRenderStates);
LastMaterial = currentMaterial;
// no alphaChannel without texture
alphaChannel &= texture;
@ -2984,23 +2997,14 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
if (texture)
{
if (OverrideMaterial2DEnabled)
setTextureRenderStates(OverrideMaterial2D, false);
else
setTextureRenderStates(InitMaterial2D, false);
Material.setTexture(0, const_cast<COpenGLTexture*>(CacheHandler->getTextureCache()[0]));
setTransform(ETS_TEXTURE_0, core::IdentityMatrix);
// Due to the transformation change, the previous line would call a reset each frame
// but we can safely reset the variable as it was false before
Transformation3DChanged=false;
CacheHandler->setActiveTexture(GL_TEXTURE0_ARB);
if (alphaChannel)
{
// if alpha and alpha texture just modulate, otherwise use only the alpha channel
if (alpha)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
else
{
@ -3008,26 +3012,26 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine])
{
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
// rgb always modulates
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
// rgb always modulates
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
#endif
}
else
#endif
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
}
else
@ -3038,21 +3042,21 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine])
{
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
// rgb always modulates
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
// rgb always modulates
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
#endif
}
else
@ -3532,6 +3536,67 @@ void COpenGLDriver::setFog(SColor c, E_FOG_TYPE fogType, f32 start,
glFogfv(GL_FOG_COLOR, data);
}
//! Draws a 3d box.
void COpenGLDriver::draw3DBox( const core::aabbox3d<f32>& box, SColor color )
{
core::vector3df edges[8];
box.getEdges(edges);
setRenderStates3DMode();
video::S3DVertex v[24];
for(u32 i = 0; i < 24; i++)
v[i].Color = color;
v[0].Pos = edges[5];
v[1].Pos = edges[1];
v[2].Pos = edges[1];
v[3].Pos = edges[3];
v[4].Pos = edges[3];
v[5].Pos = edges[7];
v[6].Pos = edges[7];
v[7].Pos = edges[5];
v[8].Pos = edges[0];
v[9].Pos = edges[2];
v[10].Pos = edges[2];
v[11].Pos = edges[6];
v[12].Pos = edges[6];
v[13].Pos = edges[4];
v[14].Pos = edges[4];
v[15].Pos = edges[0];
v[16].Pos = edges[1];
v[17].Pos = edges[0];
v[18].Pos = edges[3];
v[19].Pos = edges[2];
v[20].Pos = edges[7];
v[21].Pos = edges[6];
v[22].Pos = edges[5];
v[23].Pos = edges[4];
if (!FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra])
getColorBuffer(v, 24, EVT_STANDARD);
CacheHandler->setClientState(true, false, true, false);
glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(v))[0].Pos);
#ifdef GL_BGRA
const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4;
#else
const GLint colorSize=4;
#endif
if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])
glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(v))[0].Color);
else
{
_IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0);
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
}
glDrawArrays(GL_LINES, 0, 24);
}
//! Draws a 3d line.
void COpenGLDriver::draw3DLine(const core::vector3df& start,
@ -4287,7 +4352,7 @@ void COpenGLDriver::getColorFormatParameters(ECOLOR_FORMAT format, GLint& intern
case ECF_G32R32F:
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
{
internalFormat = GL_RG32F;
internalFormat = GL_RG32F;
pixelFormat = GL_RG;
pixelType = GL_FLOAT;
}
@ -4297,7 +4362,7 @@ void COpenGLDriver::getColorFormatParameters(ECOLOR_FORMAT format, GLint& intern
case ECF_A32B32G32R32F:
if (queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_float))
{
internalFormat = GL_RGBA32F_ARB;
internalFormat = GL_RGBA32F_ARB;
pixelFormat = GL_RGBA;
pixelType = GL_FLOAT;
}

View File

@ -198,6 +198,9 @@ namespace video
//! Draws a single pixel
virtual void drawPixel(u32 x, u32 y, const SColor & color) _IRR_OVERRIDE_;
//! Draws a 3d box
virtual void draw3DBox( const core::aabbox3d<f32>& box, SColor color = SColor(255,255,255,255 ) ) _IRR_OVERRIDE_;
//! Draws a 3d line.
virtual void draw3DLine(const core::vector3df& start,
const core::vector3df& end,

View File

@ -35,13 +35,6 @@ public:
Driver->disableTextures(1);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (resetAllRenderstates || (material.MaterialType != lastMaterial.MaterialType))
{
// thanks to Murphy, the following line removed some
// bugs with several OpenGL implementations.
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
}
protected:
@ -89,17 +82,19 @@ public:
Driver->getCacheHandler()->setBlendFunc(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact));
}
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (f32) modulate );
#else
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, (f32) modulate );
#endif
@ -109,33 +104,33 @@ public:
if (alphaSource==EAS_VERTEX_COLOR)
{
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
#endif
}
else if (alphaSource==EAS_TEXTURE)
{
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
#endif
}
else
{
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE);
#endif
}
}
@ -144,15 +139,18 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
#endif
Driver->getCacheHandler()->setBlend(false);
@ -195,23 +193,23 @@ public:
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB);
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
#endif
}
}
@ -222,13 +220,14 @@ public:
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
#endif
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
}
}
@ -258,9 +257,6 @@ public:
Driver->getCacheHandler()->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
Driver->getCacheHandler()->setBlend(true);
if ((material.MaterialType != lastMaterial.MaterialType) || resetAllRenderstates)
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
@ -303,35 +299,39 @@ public:
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
#endif
}
}
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
// default values
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE );
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE );
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE );
#else
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
#endif
Driver->getCacheHandler()->setBlend(false);
}
@ -370,34 +370,37 @@ public:
Driver->getCacheHandler()->setAlphaTest(true);
Driver->getCacheHandler()->setAlphaFunc(GL_GREATER, material.MaterialTypeParam);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates
|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates || material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
#else
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
#endif
}
}
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE );
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE );
#else
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
#endif
Driver->getCacheHandler()->setAlphaTest(false);
Driver->getCacheHandler()->setBlend(false);
@ -437,7 +440,6 @@ public:
{
Driver->getCacheHandler()->setAlphaTest(true);
Driver->getCacheHandler()->setAlphaFunc(GL_GREATER, 0.5f);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
}
@ -478,6 +480,8 @@ public:
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
// diffuse map
switch (material.MaterialType)
@ -511,7 +515,7 @@ public:
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
#else
@ -524,7 +528,7 @@ public:
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT);
#endif
@ -554,7 +558,6 @@ public:
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f);
#endif
}
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
}
}
}
@ -564,15 +567,17 @@ public:
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f );
#else
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f );
#endif
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
protected:
@ -602,12 +607,11 @@ public:
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
// diffuse map is default modulated
// detail map on second layer
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB);
#ifdef GL_ARB_texture_env_combine
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB);
@ -628,8 +632,8 @@ public:
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
}
}
@ -663,6 +667,8 @@ public:
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
@ -673,6 +679,8 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
}
@ -706,6 +714,7 @@ public:
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB);
#ifdef GL_ARB_texture_env_combine
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
@ -717,11 +726,12 @@ public:
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
#endif
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}
}
@ -730,13 +740,10 @@ public:
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
}
}
@ -769,20 +776,22 @@ public:
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
#ifdef GL_ARB_texture_env_combine
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
#else
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB);
#endif
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
@ -802,11 +811,12 @@ public:
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB);
#endif
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}
}
@ -815,14 +825,17 @@ public:
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
}
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
if (Driver->queryFeature(EVDF_MULTITEXTURE))
{
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
}
Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Driver->getCacheHandler()->setBlend(false);
}

View File

@ -469,7 +469,7 @@ void CPLYMeshFileLoader::fillBuffer()
if (EndOfFile)
return;
u32 length = (u32)(EndPointer - StartPointer);
size_t length = (size_t)(EndPointer - StartPointer);
if (length && StartPointer != Buffer)
{
// copy the remaining data to the start of the buffer
@ -486,7 +486,7 @@ void CPLYMeshFileLoader::fillBuffer()
else
{
// read data from the file
u32 count = File->read(EndPointer, PLY_INPUT_BUFFER_SIZE - length);
size_t count = File->read(EndPointer, PLY_INPUT_BUFFER_SIZE - length);
// increment the end pointer by the number of bytes read
EndPointer = EndPointer + count;

View File

@ -225,16 +225,12 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root,
ISceneNode* CSceneCollisionManager::getSceneNodeAndCollisionPointFromRay(
SCollisionHit& hitResult,
const core::line3df& ray,
core::vector3df & outCollisionPoint,
core::triangle3df & outTriangle,
s32 idBitMask,
ISceneNode * collisionRootNode,
bool noDebugObjects)
{
ISceneNode* bestNode = 0;
f32 bestDistanceSquared = FLT_MAX;
if(0 == collisionRootNode)
collisionRootNode = SceneManager->getRootSceneNode();
@ -261,23 +257,21 @@ ISceneNode* CSceneCollisionManager::getSceneNodeAndCollisionPointFromRay(
// node in order to find the nearest collision point, so sorting them by
// bounding box would be pointless.
f32 bestDistanceSquared = FLT_MAX;
core::line3df rayRest(ray);
getPickedNodeFromBBAndSelector(collisionRootNode, rayRest, idBitMask,
noDebugObjects, bestDistanceSquared, bestNode,
outCollisionPoint, outTriangle);
return bestNode;
getPickedNodeFromBBAndSelector(hitResult, collisionRootNode, rayRest, idBitMask,
noDebugObjects, bestDistanceSquared);
return hitResult.Node;
}
void CSceneCollisionManager::getPickedNodeFromBBAndSelector(
SCollisionHit& hitResult,
ISceneNode * root,
core::line3df & ray,
s32 bits,
bool noDebugObjects,
f32 & outBestDistanceSquared,
ISceneNode * & outBestNode,
core::vector3df & outBestCollisionPoint,
core::triangle3df & outBestTriangle)
f32 & outBestDistanceSquared)
{
const ISceneNodeList& children = root->getChildren();
@ -303,31 +297,26 @@ void CSceneCollisionManager::getPickedNodeFromBBAndSelector(
const core::aabbox3df& box = current->getBoundingBox();
core::vector3df candidateCollisionPoint;
core::triangle3df candidateTriangle;
SCollisionHit candidateHitResult;
// do intersection test in object space
ISceneNode * hitNode = 0;
if (box.intersectsWithLine(line) &&
getCollisionPoint(ray, selector, candidateCollisionPoint, candidateTriangle, hitNode))
getCollisionPoint(candidateHitResult, ray, selector))
{
const f32 distanceSquared = (candidateCollisionPoint - ray.start).getLengthSQ();
const f32 distanceSquared = (candidateHitResult.Intersection - ray.start).getLengthSQ();
if(distanceSquared < outBestDistanceSquared)
{
outBestDistanceSquared = distanceSquared;
outBestNode = current;
outBestCollisionPoint = candidateCollisionPoint;
outBestTriangle = candidateTriangle;
hitResult = candidateHitResult;
const core::vector3df rayVector = ray.getVector().normalize();
ray.end = ray.start + (rayVector * sqrtf(distanceSquared));
}
}
}
getPickedNodeFromBBAndSelector(current, ray, bits, noDebugObjects,
outBestDistanceSquared, outBestNode,
outBestCollisionPoint, outBestTriangle);
getPickedNodeFromBBAndSelector(hitResult, current, ray, bits, noDebugObjects,
outBestDistanceSquared);
}
}
@ -348,12 +337,7 @@ ISceneNode* CSceneCollisionManager::getSceneNodeFromCameraBB(
return getSceneNodeFromRayBB(core::line3d<f32>(start, end), idBitMask, noDebugObjects);
}
//! Finds the collision point of a line and lots of triangles, if there is one.
bool CSceneCollisionManager::getCollisionPoint(const core::line3d<f32>& ray,
ITriangleSelector* selector, core::vector3df& outIntersection,
core::triangle3df& outTriangle,
ISceneNode*& outNode)
bool CSceneCollisionManager::getCollisionPoint(SCollisionHit& hitResult, const core::line3d<f32>& ray, ITriangleSelector* selector)
{
if (!selector)
{
@ -367,12 +351,13 @@ bool CSceneCollisionManager::getCollisionPoint(const core::line3d<f32>& ray,
Triangles.set_used(totalcnt);
s32 cnt = 0;
selector->getTriangles(Triangles.pointer(), totalcnt, cnt, ray);
irr::core::array<SCollisionTriangleRange> outTriangleInfo;
selector->getTriangles(Triangles.pointer(), totalcnt, cnt, ray, 0, true, &outTriangleInfo);
const core::vector3df linevect = ray.getVector().normalize();
core::vector3df intersection;
f32 nearest = FLT_MAX;
bool found = false;
irr::s32 foundIndex = -1;
const f32 raylength = ray.getLengthSQ();
const f32 minX = core::min_(ray.start.X, ray.end.X);
@ -407,17 +392,34 @@ bool CSceneCollisionManager::getCollisionPoint(const core::line3d<f32>& ray,
if (tmp < raylength && tmp2 < raylength && tmp < nearest)
{
nearest = tmp;
outTriangle = triangle;
outIntersection = intersection;
outNode = selector->getSceneNodeForTriangle(i);
found = true;
hitResult.Triangle = triangle;
hitResult.Intersection = intersection;
foundIndex = i;
}
}
}
return found;
}
if ( foundIndex >= 0 )
{
for ( irr::u32 t=0; t<outTriangleInfo.size(); ++t )
{
if ( outTriangleInfo[t].isIndexInRange(foundIndex) )
{
hitResult.Node = outTriangleInfo[t].SceneNode;
hitResult.MeshBuffer = outTriangleInfo[t].MeshBuffer;
hitResult.MaterialIndex = outTriangleInfo[t].MaterialIndex;
hitResult.TriangleSelector = outTriangleInfo[t].Selector;
break;
}
}
return true;
}
return false;
}
//! Collides a moving ellipsoid with a 3d world with gravity and returns
//! the resulting new position of the ellipsoid.
@ -666,6 +668,8 @@ bool CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData,
// set result:
if (foundCollision)
{
++colData->triangleHits;
// distance to collision is t
f32 distToCollision = t*colData->velocity.getLength();
@ -677,7 +681,6 @@ bool CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData,
colData->intersectionPoint = collisionPoint;
colData->foundCollision = true;
colData->intersectionTriangle = triangle;
++colData->triangleHits;
return true;
}
}// end found collision
@ -712,7 +715,7 @@ core::vector3df CSceneCollisionManager::collideEllipsoidWithWorld(
colData.selector = selector;
colData.slidingSpeed = slidingSpeed;
colData.triangleHits = 0;
colData.triangleIndex = -1;
colData.node = 0;
core::vector3df eSpacePosition = colData.R3Position / colData.eRadius;
core::vector3df eSpaceVelocity = colData.R3Velocity / colData.eRadius;
@ -746,7 +749,7 @@ core::vector3df CSceneCollisionManager::collideEllipsoidWithWorld(
triout.pointA *= colData.eRadius;
triout.pointB *= colData.eRadius;
triout.pointC *= colData.eRadius;
outNode = selector->getSceneNodeForTriangle(colData.triangleIndex);
outNode = colData.node;
}
finalPos *= colData.eRadius;
@ -787,12 +790,30 @@ core::vector3df CSceneCollisionManager::collideWithWorld(s32 recursionDepth,
1.0f / colData.eRadius.Y,
1.0f / colData.eRadius.Z));
irr::core::array<SCollisionTriangleRange> outTriangleInfo;
s32 triangleCnt = 0;
colData.selector->getTriangles(Triangles.pointer(), totalTriangleCnt, triangleCnt, box, &scaleMatrix);
colData.selector->getTriangles(Triangles.pointer(), totalTriangleCnt, triangleCnt, box, &scaleMatrix, true, &outTriangleInfo);
// Find closest intersection
irr::s32 nearestTriangleIndex = -1;
for (s32 i=0; i<triangleCnt; ++i)
{
if(testTriangleIntersection(&colData, Triangles[i]))
colData.triangleIndex = i;
{
nearestTriangleIndex = i;
}
}
if ( nearestTriangleIndex >= 0 )
{
for ( irr::u32 t=0; t<outTriangleInfo.size(); ++t )
{
if ( outTriangleInfo[t].isIndexInRange(nearestTriangleIndex) )
{
colData.node = outTriangleInfo[t].SceneNode;
break;
}
}
}
//---------------- end collide with world

View File

@ -41,11 +41,9 @@ namespace scene
virtual ISceneNode* getSceneNodeFromCameraBB(const ICameraSceneNode* camera,
s32 idBitMask=0, bool bNoDebugObjects = false) _IRR_OVERRIDE_;
//! Finds the collision point of a line and lots of triangles, if there is one.
virtual bool getCollisionPoint(const core::line3d<f32>& ray,
ITriangleSelector* selector, core::vector3df& outCollisionPoint,
core::triangle3df& outTriangle,
ISceneNode* & outNode) _IRR_OVERRIDE_;
//! Finds the nearest collision point of a line and lots of triangles, if there is one.
virtual bool getCollisionPoint(SCollisionHit& hitResult, const core::line3d<f32>& ray,
ITriangleSelector* selector) _IRR_OVERRIDE_;
//! Collides a moving ellipsoid with a 3d world with gravity and returns
//! the resulting new position of the ellipsoid.
@ -72,13 +70,11 @@ namespace scene
//! Gets the scene node and nearest collision point for a ray based on
//! the nodes' id bitmasks, bounding boxes and triangle selectors.
virtual ISceneNode* getSceneNodeAndCollisionPointFromRay(
SCollisionHit& hitResult,
const core::line3df& ray,
core::vector3df& outCollisionPoint,
core::triangle3df& outTriangle,
s32 idBitMask = 0,
ISceneNode * collisionRootNode = 0,
bool noDebugObjects = false) _IRR_OVERRIDE_;
bool noDebugObjects = false) _IRR_OVERRIDE_;
private:
@ -88,14 +84,13 @@ namespace scene
f32& outbestdistance, ISceneNode*& outbestnode);
//! recursive method for going through all scene nodes
void getPickedNodeFromBBAndSelector(ISceneNode * root,
void getPickedNodeFromBBAndSelector(
SCollisionHit& hitResult,
ISceneNode * root,
core::line3df & ray,
s32 bits,
bool noDebugObjects,
f32 & outBestDistanceSquared,
ISceneNode * & outBestNode,
core::vector3df & outBestCollisionPoint,
core::triangle3df & outBestTriangle);
f32 & outBestDistanceSquared);
struct SCollisionData
@ -114,7 +109,7 @@ namespace scene
core::vector3df intersectionPoint;
core::triangle3df intersectionTriangle;
s32 triangleIndex;
irr::scene::ISceneNode* node;
s32 triangleHits;
f32 slidingSpeed;

View File

@ -1847,23 +1847,29 @@ IMeshManipulator* CSceneManager::getMeshManipulator()
//! Creates a simple ITriangleSelector, based on a mesh.
ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node)
ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node, bool separateMeshbuffers)
{
if (!mesh)
return 0;
return new CTriangleSelector(mesh, node);
return new CTriangleSelector(mesh, node, separateMeshbuffers);
}
ITriangleSelector* CSceneManager::createTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node)
{
if ( !meshBuffer)
return 0;
return new CTriangleSelector(meshBuffer, materialIndex, node);
}
//! Creates a simple and updatable ITriangleSelector, based on a the mesh owned by an
//! animated scene node
ITriangleSelector* CSceneManager::createTriangleSelector(IAnimatedMeshSceneNode* node)
//! Creates a ITriangleSelector, based on a the mesh owned by an animated scene node
ITriangleSelector* CSceneManager::createTriangleSelector(IAnimatedMeshSceneNode* node, bool separateMeshbuffers)
{
if (!node || !node->getMesh())
return 0;
return new CTriangleSelector(node);
return new CTriangleSelector(node, separateMeshbuffers);
}
@ -1887,6 +1893,14 @@ ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMesh* mesh,
return new COctreeTriangleSelector(mesh, node, minimalPolysPerNode);
}
ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMeshBuffer* meshBuffer, irr::u32 materialIndex,
ISceneNode* node, s32 minimalPolysPerNode)
{
if ( !meshBuffer)
return 0;
return new COctreeTriangleSelector(meshBuffer, materialIndex, node, minimalPolysPerNode);
}
//! Creates a meta triangle selector.
IMetaTriangleSelector* CSceneManager::createMetaTriangleSelector()

View File

@ -343,19 +343,26 @@ namespace scene
//! Creates a simple ITriangleSelector, based on a mesh.
virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node) _IRR_OVERRIDE_;
virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node, bool separateMeshbuffers) _IRR_OVERRIDE_;
//! Creates a simple ITriangleSelector, based on a meshbuffer.
virtual ITriangleSelector* createTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node) _IRR_OVERRIDE_;
//! Creates a simple ITriangleSelector, based on an animated mesh scene node.
//! Details of the mesh associated with the node will be extracted internally.
//! Call ITriangleSelector::update() to have the triangle selector updated based
//! on the current frame of the animated mesh scene node.
//! \param: The animated mesh scene node from which to build the selector
virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node) _IRR_OVERRIDE_;
virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node, bool separateMeshbuffers) _IRR_OVERRIDE_;
//! Creates a simple ITriangleSelector, based on a mesh.
virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh,
ISceneNode* node, s32 minimalPolysPerNode) _IRR_OVERRIDE_;
//! Creates a simple ITriangleSelector, based on a meshbuffer.
virtual ITriangleSelector* createOctreeTriangleSelector(IMeshBuffer* meshBuffer, irr::u32 materialIndex,
ISceneNode* node, s32 minimalPolysPerNode=32) _IRR_OVERRIDE_;
//! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box.
virtual ITriangleSelector* createTriangleSelectorFromBoundingBox(
ISceneNode* node) _IRR_OVERRIDE_;

View File

@ -202,7 +202,8 @@ void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 time
}
else
{
Falling = false;
if ( CollisionOccurred ) // f can also happen to be false when FallingVelocity was already 0 (p.e. at top of a jump)
Falling = false;
FallingVelocity.set(0, 0, 0);
}
}

View File

@ -77,7 +77,8 @@ void CTerrainTriangleSelector::setTriangleData(ITerrainSceneNode* node, s32 LOD)
//! Gets all triangles.
void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
s32 count = TrianglePatches.TotalTriangles;
@ -106,6 +107,15 @@ void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles,
}
}
if ( outTriangleInfo )
{
SCollisionTriangleRange triRange;
triRange.RangeSize = tIndex;
triRange.Selector = const_cast<CTerrainTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
outTriangleInfo->push_back(triRange);
}
outTriangleCount = tIndex;
}
@ -113,7 +123,9 @@ void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles,
//! Gets all triangles which lie within a specific bounding box.
void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount,
const core::aabbox3d<f32>& box, const core::matrix4* transform) const
const core::aabbox3d<f32>& box,
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
s32 count = TrianglePatches.TotalTriangles;
@ -143,6 +155,15 @@ void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles,
}
}
if ( outTriangleInfo )
{
SCollisionTriangleRange triRange;
triRange.RangeSize = tIndex;
triRange.Selector = const_cast<CTerrainTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
outTriangleInfo->push_back(triRange);
}
outTriangleCount = tIndex;
}
@ -150,7 +171,8 @@ void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles,
//! Gets all triangles which have or may have contact with a 3d line.
void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount, const core::line3d<f32>& line,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
const s32 count = core::min_((s32)TrianglePatches.TotalTriangles, arraySize);
@ -179,6 +201,15 @@ void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles,
}
}
if ( outTriangleInfo )
{
SCollisionTriangleRange triRange;
triRange.RangeSize = tIndex;
triRange.Selector = const_cast<CTerrainTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
outTriangleInfo->push_back(triRange);
}
outTriangleCount = tIndex;
}

View File

@ -22,7 +22,7 @@ class ITerrainSceneNode;
//! Triangle Selector for the TerrainSceneNode
/** The code for the TerrainTriangleSelector is based on the GeoMipMapSelector
developed by Spintz. He made it available for Irrlicht and allowed it to be
distributed under this licence. I only modified some parts. A lot of thanks go
distributed under this license. I only modified some parts. A lot of thanks go
to him.
*/
class CTerrainTriangleSelector : public ITriangleSelector
@ -40,16 +40,19 @@ public:
//! Gets all triangles.
void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount,
const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Gets all triangles which lie within a specific bounding box.
void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount,
const core::aabbox3d<f32>& box, const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::aabbox3d<f32>& box, const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Gets all triangles which have or may have contact with a 3d line.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line,
const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Returns amount of all available triangles in this selector
virtual s32 getTriangleCount() const _IRR_OVERRIDE_;

View File

@ -77,6 +77,11 @@ void CTextSceneNode::setText(const wchar_t* text)
Text = text;
}
//! get the text string
const wchar_t* CTextSceneNode::getText() const
{
return Text.c_str();
}
//! sets the color of the text
void CTextSceneNode::setTextColor(video::SColor color)
@ -84,6 +89,30 @@ void CTextSceneNode::setTextColor(video::SColor color)
Color = color;
}
//! get the color of the text
video::SColor CTextSceneNode::getTextColor() const
{
return Color;
}
void CTextSceneNode::setFont(gui::IGUIFont* font)
{
if ( font != Font )
{
if ( font )
font->grab();
if ( Font )
Font->drop();
Font = font;
}
}
//! Get the font used to draw the text
gui::IGUIFont* CTextSceneNode::getFont() const
{
return Font;
}
//!--------------------------------- CBillboardTextSceneNode ----------------------------------------------
@ -234,6 +263,11 @@ void CBillboardTextSceneNode::setText(const wchar_t* text)
}
}
//! get the text string
const wchar_t* CBillboardTextSceneNode::getText() const
{
return Text.c_str();
}
//! pre render event
void CBillboardTextSceneNode::OnAnimate(u32 timeMs)
@ -408,11 +442,10 @@ const core::dimension2d<f32>& CBillboardTextSceneNode::getSize() const
return Size;
}
//! sets the color of the text
void CBillboardTextSceneNode::setTextColor(video::SColor color)
//! Get the font used to draw the text
gui::IGUIFont* CBillboardTextSceneNode::getFont() const
{
Color = color;
return Font;
}
//! Set the color of all vertices of the billboard

View File

@ -41,9 +41,21 @@ namespace scene
//! sets the text string
virtual void setText(const wchar_t* text) _IRR_OVERRIDE_;
//! get the text string
virtual const wchar_t* getText() const _IRR_OVERRIDE_;
//! sets the color of the text
virtual void setTextColor(video::SColor color) _IRR_OVERRIDE_;
//! get the color of the text
virtual video::SColor getTextColor() const _IRR_OVERRIDE_;
//! set the font used to draw the text
virtual void setFont(gui::IGUIFont* font) _IRR_OVERRIDE_;
//! Get the font used to draw the text
virtual gui::IGUIFont* getFont() const _IRR_OVERRIDE_;
//! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ { return ESNT_TEXT; }
@ -83,8 +95,11 @@ namespace scene
//! sets the text string
virtual void setText(const wchar_t* text) _IRR_OVERRIDE_;
//! sets the color of the text
virtual void setTextColor(video::SColor color) _IRR_OVERRIDE_;
//! get the text string
virtual const wchar_t* getText() const _IRR_OVERRIDE_;
//! Get the font used to draw the text
virtual gui::IGUIFont* getFont() const _IRR_OVERRIDE_;
//! sets the size of the billboard
virtual void setSize(const core::dimension2d<f32>& size) _IRR_OVERRIDE_;
@ -98,7 +113,7 @@ namespace scene
virtual u32 getMaterialCount() const _IRR_OVERRIDE_;
//! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ { return ESNT_TEXT; }
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ { return ESNT_BILLBOARD_TEXT; }
//! Set the color of all vertices of the billboard
//! \param overallColor: the color to set
@ -129,7 +144,6 @@ namespace scene
private:
core::stringw Text;
video::SColor Color;
gui::IGUIFontBitmap* Font;
core::dimension2d<f32> Size;

View File

@ -21,60 +21,68 @@ CTriangleBBSelector::CTriangleBBSelector(ISceneNode* node)
Triangles.set_used(12); // a box has 12 triangles.
}
//! Gets all triangles.
void CTriangleBBSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
if (!SceneNode)
return;
// construct triangles
const core::aabbox3d<f32>& box = SceneNode->getBoundingBox();
core::vector3df edges[8];
box.getEdges(edges);
Triangles[0].set( edges[3], edges[0], edges[2]);
Triangles[1].set( edges[3], edges[1], edges[0]);
Triangles[2].set( edges[3], edges[2], edges[7]);
Triangles[3].set( edges[7], edges[2], edges[6]);
Triangles[4].set( edges[7], edges[6], edges[4]);
Triangles[5].set( edges[5], edges[7], edges[4]);
Triangles[6].set( edges[5], edges[4], edges[0]);
Triangles[7].set( edges[5], edges[0], edges[1]);
Triangles[8].set( edges[1], edges[3], edges[7]);
Triangles[9].set( edges[1], edges[7], edges[5]);
Triangles[10].set(edges[0], edges[6], edges[2]);
Triangles[11].set(edges[0], edges[4], edges[6]);
fillTriangles();
// call parent
CTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, transform);
CTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, transform, useNodeTransform, outTriangleInfo);
}
void CTriangleBBSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount,
const core::aabbox3d<f32>& box,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
return getTriangles(triangles, arraySize, outTriangleCount, transform);
fillTriangles();
return CTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, box, transform, useNodeTransform, outTriangleInfo);
}
void CTriangleBBSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount,
const core::line3d<f32>& line,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
return getTriangles(triangles, arraySize, outTriangleCount, transform);
fillTriangles();
return CTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, line, transform, useNodeTransform, outTriangleInfo);
}
void CTriangleBBSelector::fillTriangles() const
{
if (SceneNode)
{
// construct triangles
const core::aabbox3d<f32>& box = SceneNode->getBoundingBox();
core::vector3df edges[8];
box.getEdges(edges);
// yeah, not really const... Triangles are mutable
Triangles[0].set( edges[3], edges[0], edges[2]);
Triangles[1].set( edges[3], edges[1], edges[0]);
Triangles[2].set( edges[3], edges[2], edges[7]);
Triangles[3].set( edges[7], edges[2], edges[6]);
Triangles[4].set( edges[7], edges[6], edges[4]);
Triangles[5].set( edges[5], edges[7], edges[4]);
Triangles[6].set( edges[5], edges[4], edges[0]);
Triangles[7].set( edges[5], edges[0], edges[1]);
Triangles[8].set( edges[1], edges[3], edges[7]);
Triangles[9].set( edges[1], edges[7], edges[5]);
Triangles[10].set(edges[0], edges[6], edges[2]);
Triangles[11].set(edges[0], edges[4], edges[6]);
}
}
} // end namespace scene
} // end namespace irr

View File

@ -22,16 +22,22 @@ public:
//! Gets all triangles.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount,
const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Gets all triangles which lie within a specific bounding box.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount,
const core::aabbox3d<f32>& box, const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::aabbox3d<f32>& box, const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Gets all triangles which have or may have contact with a 3d line.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line,
const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
protected:
void fillTriangles() const;
};

View File

@ -15,7 +15,7 @@ namespace scene
//! constructor
CTriangleSelector::CTriangleSelector(ISceneNode* node)
: SceneNode(node), AnimatedNode(0), LastMeshFrame(0)
: SceneNode(node), MeshBuffer(0), MaterialIndex(0), AnimatedNode(0), LastMeshFrame(0)
{
#ifdef _DEBUG
setDebugName("CTriangleSelector");
@ -27,7 +27,7 @@ CTriangleSelector::CTriangleSelector(ISceneNode* node)
//! constructor
CTriangleSelector::CTriangleSelector(const core::aabbox3d<f32>& box, ISceneNode* node)
: SceneNode(node), AnimatedNode(0), LastMeshFrame(0)
: SceneNode(node), MeshBuffer(0), MaterialIndex(0), AnimatedNode(0), LastMeshFrame(0)
{
#ifdef _DEBUG
setDebugName("CTriangleSelector");
@ -39,18 +39,27 @@ CTriangleSelector::CTriangleSelector(const core::aabbox3d<f32>& box, ISceneNode*
//! constructor
CTriangleSelector::CTriangleSelector(const IMesh* mesh, ISceneNode* node)
: SceneNode(node), AnimatedNode(0), LastMeshFrame(0)
CTriangleSelector::CTriangleSelector(const IMesh* mesh, ISceneNode* node, bool separateMeshbuffers)
: SceneNode(node), MeshBuffer(0), MaterialIndex(0), AnimatedNode(0), LastMeshFrame(0)
{
#ifdef _DEBUG
setDebugName("CTriangleSelector");
#endif
createFromMesh(mesh);
createFromMesh(mesh, separateMeshbuffers);
}
CTriangleSelector::CTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node)
: SceneNode(node), MeshBuffer(meshBuffer), MaterialIndex(materialIndex), AnimatedNode(0), LastMeshFrame(0)
{
#ifdef _DEBUG
setDebugName("CTriangleSelector");
#endif
CTriangleSelector::CTriangleSelector(IAnimatedMeshSceneNode* node)
createFromMeshBuffer(meshBuffer);
}
CTriangleSelector::CTriangleSelector(IAnimatedMeshSceneNode* node, bool separateMeshbuffers)
: SceneNode(node), AnimatedNode(node), LastMeshFrame(0)
{
#ifdef _DEBUG
@ -68,22 +77,51 @@ CTriangleSelector::CTriangleSelector(IAnimatedMeshSceneNode* node)
IMesh* mesh = animatedMesh->getMesh(LastMeshFrame);
if (mesh)
createFromMesh(mesh);
createFromMesh(mesh, separateMeshbuffers);
}
void CTriangleSelector::createFromMesh(const IMesh* mesh)
void CTriangleSelector::createFromMesh(const IMesh* mesh, bool createBufferRanges)
{
BufferRanges.clear();
Triangles.clear();
const u32 cnt = mesh->getMeshBufferCount();
u32 totalFaceCount = 0;
for (u32 j=0; j<cnt; ++j)
totalFaceCount += mesh->getMeshBuffer(j)->getIndexCount();
totalFaceCount /= 3;
{
SCollisionTriangleRange range;
range.MeshBuffer = mesh->getMeshBuffer(j);
range.MaterialIndex = j;
range.RangeSize = range.MeshBuffer->getIndexCount() / 3;
if ( createBufferRanges )
{
range.RangeStart = totalFaceCount;
BufferRanges.push_back(range);
}
totalFaceCount += range.RangeSize;
}
Triangles.set_used(totalFaceCount);
updateFromMesh(mesh);
}
void CTriangleSelector::createFromMeshBuffer(const IMeshBuffer* meshBuffer)
{
BufferRanges.clear();
Triangles.clear();
if ( meshBuffer )
{
Triangles.set_used(meshBuffer->getIndexCount() / 3);
}
updateFromMeshBuffer(meshBuffer);
}
template <typename TIndex>
static void updateTriangles(u32& triangleCount, core::array<core::triangle3df>& triangles, u32 idxCnt, const TIndex* indices, const u8* vertices, u32 vertexPitch, const core::matrix4* bufferTransform)
{
@ -151,10 +189,41 @@ void CTriangleSelector::updateFromMesh(const IMesh* mesh) const
}
// Update bounding box
if ( triangleCount )
updateBoundingBox();
}
void CTriangleSelector::updateFromMeshBuffer(const IMeshBuffer* meshBuffer) const
{
if ( !meshBuffer )
return;
u32 idxCnt = meshBuffer->getIndexCount();
u32 vertexPitch = getVertexPitchFromType(meshBuffer->getVertexType());
u8* vertices = (u8*)meshBuffer->getVertices();
u32 triangleCount = 0;
switch ( meshBuffer->getIndexType() )
{
case video::EIT_16BIT:
{
const u16* indices = meshBuffer->getIndices();
updateTriangles(triangleCount, Triangles, idxCnt, indices, vertices, vertexPitch, 0);
}
break;
case video::EIT_32BIT:
{
const u32* indices = (u32*)meshBuffer->getIndices();
updateTriangles(triangleCount, Triangles, idxCnt, indices, vertices, vertexPitch, 0);
}
break;
}
}
void CTriangleSelector::updateBoundingBox() const
{
if ( !Triangles.empty() )
{
BoundingBox.reset( Triangles[0].pointA );
for (u32 i=0; i < triangleCount; ++i)
for (u32 i=0; i < Triangles.size(); ++i)
{
const core::triangle3df& tri = Triangles[i];
BoundingBox.addInternalPoint(tri.pointA);
@ -168,7 +237,6 @@ void CTriangleSelector::updateFromMesh(const IMesh* mesh) const
}
}
void CTriangleSelector::update(void) const
{
if (!AnimatedNode)
@ -194,7 +262,8 @@ void CTriangleSelector::update(void) const
//! Gets all triangles.
void CTriangleSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
// Update my triangles if necessary
update();
@ -206,7 +275,7 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles,
core::matrix4 mat;
if (transform)
mat = *transform;
if (SceneNode)
if (SceneNode&&useNodeTransform)
mat *= SceneNode->getAbsoluteTransformation();
for (u32 i=0; i<cnt; ++i)
@ -216,6 +285,43 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles,
mat.transformVect( triangles[i].pointC, Triangles[i].pointC );
}
if ( outTriangleInfo )
{
if ( BufferRanges.empty() )
{
SCollisionTriangleRange triRange;
triRange.RangeStart = 0;
triRange.RangeSize = cnt;
triRange.Selector = const_cast<CTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
triRange.MeshBuffer = MeshBuffer;
triRange.MaterialIndex = MaterialIndex;
outTriangleInfo->push_back(triRange);
}
else
{
irr::u32 rangeIndex = 0;
for (u32 i=0; i<cnt; )
{
while ( i >= (BufferRanges[rangeIndex].RangeStart + BufferRanges[rangeIndex].RangeSize) )
++rangeIndex;
SCollisionTriangleRange triRange;
triRange.MaterialIndex = BufferRanges[rangeIndex].MaterialIndex;
triRange.MeshBuffer = BufferRanges[rangeIndex].MeshBuffer;
triRange.RangeStart = BufferRanges[rangeIndex].RangeStart;
triRange.RangeSize = core::min_( cnt-BufferRanges[rangeIndex].RangeStart, BufferRanges[rangeIndex].RangeSize);
triRange.Selector = const_cast<CTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
outTriangleInfo->push_back(triRange);
i += triRange.RangeSize;
}
}
}
outTriangleCount = cnt;
}
@ -224,7 +330,8 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles,
void CTriangleSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount,
const core::aabbox3d<f32>& box,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
// Update my triangles if necessary
update();
@ -232,16 +339,23 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles,
core::matrix4 mat(core::matrix4::EM4CONST_NOTHING);
core::aabbox3df tBox(box);
if (SceneNode)
if (SceneNode && useNodeTransform)
{
SceneNode->getAbsoluteTransformation().getInverse(mat);
mat.transformBoxEx(tBox);
if ( SceneNode->getAbsoluteTransformation().getInverse(mat) )
mat.transformBoxEx(tBox);
else
{
// TODO: else is not yet handled optimally.
// If a node has an axis scaled to 0 we return all triangles without any check
return getTriangles(triangles, arraySize, outTriangleCount,
transform, useNodeTransform, outTriangleInfo );
}
}
if (transform)
mat = *transform;
else
mat.makeIdentity();
if (SceneNode)
if (SceneNode && useNodeTransform)
mat *= SceneNode->getAbsoluteTransformation();
outTriangleCount = 0;
@ -251,22 +365,80 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles,
s32 triangleCount = 0;
const u32 cnt = Triangles.size();
for (u32 i=0; i<cnt; ++i)
if ( outTriangleInfo && !BufferRanges.empty() )
{
// This isn't an accurate test, but it's fast, and the
// API contract doesn't guarantee complete accuracy.
if (Triangles[i].isTotalOutsideBox(tBox))
continue;
irr::u32 activeRange = 0;
SCollisionTriangleRange triRange;
triRange.Selector = const_cast<CTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
triRange.RangeStart = triangleCount;
triRange.MeshBuffer = BufferRanges[activeRange].MeshBuffer;
triRange.MaterialIndex = BufferRanges[activeRange].MaterialIndex;
triangles[triangleCount] = Triangles[i];
mat.transformVect(triangles[triangleCount].pointA);
mat.transformVect(triangles[triangleCount].pointB);
mat.transformVect(triangles[triangleCount].pointC);
for (u32 i=0; i<cnt; ++i)
{
// This isn't an accurate test, but it's fast, and the
// API contract doesn't guarantee complete accuracy.
if (Triangles[i].isTotalOutsideBox(tBox))
continue;
++triangleCount;
if ( i >= BufferRanges[activeRange].RangeStart + BufferRanges[activeRange].RangeSize )
{
triRange.RangeSize = triangleCount-triRange.RangeStart;
if ( triRange.RangeSize > 0 )
outTriangleInfo->push_back(triRange);
if (triangleCount == arraySize)
break;
++activeRange;
triRange.RangeStart = triangleCount;
triRange.MeshBuffer = BufferRanges[activeRange].MeshBuffer;
triRange.MaterialIndex = BufferRanges[activeRange].MaterialIndex;
}
triangles[triangleCount] = Triangles[i];
mat.transformVect(triangles[triangleCount].pointA);
mat.transformVect(triangles[triangleCount].pointB);
mat.transformVect(triangles[triangleCount].pointC);
++triangleCount;
if (triangleCount == arraySize)
break;
}
triRange.RangeSize = triangleCount-triRange.RangeStart;
if ( triRange.RangeSize > 0 )
outTriangleInfo->push_back(triRange);
}
else
{
for (u32 i=0; i<cnt; ++i)
{
// This isn't an accurate test, but it's fast, and the
// API contract doesn't guarantee complete accuracy.
if (Triangles[i].isTotalOutsideBox(tBox))
continue;
triangles[triangleCount] = Triangles[i];
mat.transformVect(triangles[triangleCount].pointA);
mat.transformVect(triangles[triangleCount].pointB);
mat.transformVect(triangles[triangleCount].pointC);
++triangleCount;
if (triangleCount == arraySize)
break;
}
if ( outTriangleInfo )
{
SCollisionTriangleRange triRange;
triRange.RangeSize = triangleCount;
triRange.Selector = const_cast<CTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
triRange.MeshBuffer = MeshBuffer;
triRange.MaterialIndex = MaterialIndex;
outTriangleInfo->push_back(triRange);
}
}
outTriangleCount = triangleCount;
@ -277,7 +449,8 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles,
void CTriangleSelector::getTriangles(core::triangle3df* triangles,
s32 arraySize, s32& outTriangleCount,
const core::line3d<f32>& line,
const core::matrix4* transform) const
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
// Update my triangles if necessary
update();
@ -287,7 +460,7 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles,
// TODO: Could be optimized for line a little bit more.
getTriangles(triangles, arraySize, outTriangleCount,
box, transform);
box, transform, useNodeTransform, outTriangleInfo);
}

View File

@ -27,27 +27,33 @@ public:
CTriangleSelector(ISceneNode* node);
//! Constructs a selector based on a mesh
CTriangleSelector(const IMesh* mesh, ISceneNode* node);
CTriangleSelector(const IMesh* mesh, ISceneNode* node, bool separateMeshbuffers);
//! Constructs a selector based on a meshbuffer
CTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node);
//! Constructs a selector based on an animated mesh scene node
//!\param node An animated mesh scene node, which must have a valid mesh
CTriangleSelector(IAnimatedMeshSceneNode* node);
CTriangleSelector(IAnimatedMeshSceneNode* node, bool separateMeshbuffers);
//! Constructs a selector based on a bounding box
CTriangleSelector(const core::aabbox3d<f32>& box, ISceneNode* node);
//! Gets all triangles.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount,
const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Gets all triangles which lie within a specific bounding box.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount,
const core::aabbox3d<f32>& box, const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::aabbox3d<f32>& box, const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Gets all triangles which have or may have contact with a 3d line.
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line,
const core::matrix4* transform=0) const _IRR_OVERRIDE_;
const core::matrix4* transform, bool useNodeTransform,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const _IRR_OVERRIDE_;
//! Returns amount of all available triangles in this selector
virtual s32 getTriangleCount() const _IRR_OVERRIDE_;
@ -66,20 +72,33 @@ public:
protected:
//! Create from a mesh
virtual void createFromMesh(const IMesh* mesh);
virtual void createFromMesh(const IMesh* mesh, bool createBufferRanges);
//! Create from a meshbuffer
virtual void createFromMeshBuffer(const IMeshBuffer* meshBuffer);
//! Update when the mesh has changed
virtual void updateFromMesh(const IMesh* mesh) const;
//! Update when the meshbuffer has changed
virtual void updateFromMeshBuffer(const IMeshBuffer* meshBuffer) const;
//! Update bounding box from triangles
void updateBoundingBox() const;
//! Update the triangle selector, which will only have an effect if it
//! was built from an animated mesh and that mesh's frame has changed
//! since the last time it was updated.
virtual void update(void) const;
irr::core::array<SCollisionTriangleRange> BufferRanges;
ISceneNode* SceneNode;
mutable core::array<core::triangle3df> Triangles; // (mutable for CTriangleBBSelector)
mutable core::aabbox3df BoundingBox; // Allows for trivial rejection
const IMeshBuffer* MeshBuffer; // non-zero when the selector is for a single meshbuffer
irr::u32 MaterialIndex; // Only set when MeshBuffer is non-zero
IAnimatedMeshSceneNode* AnimatedNode;
mutable u32 LastMeshFrame;
};
@ -87,6 +106,4 @@ protected:
} // end namespace scene
} // end namespace irr
#endif

View File

@ -111,7 +111,7 @@ bool CWriteFile::flush()
if (!isOpen())
return false;
return !(bool) fflush(File);
return fflush(File) == 0; // 0 indicates success, otherwise EOF and errno is set
}
IWriteFile* CWriteFile::createWriteFile(const io::path& fileName, bool append)

View File

@ -33,7 +33,7 @@ namespace io
//! Reads an amount of bytes from the file.
virtual int read(void* buffer, int sizeToRead)
{
return ReadFile->read(buffer, sizeToRead);
return (int)ReadFile->read(buffer, sizeToRead);
}
//! Returns size of file in bytes

View File

@ -136,11 +136,11 @@ public:
//! Returns the value of an attribute as integer.
virtual int getAttributeValueAsInt(const char_type* name) const _IRR_OVERRIDE_
virtual int getAttributeValueAsInt(const char_type* name, int defaultNotFound) const _IRR_OVERRIDE_
{
const SAttribute* attr = getAttributeByName(name);
if (!attr)
return 0;
return defaultNotFound;
core::stringc c(attr->Value.c_str());
return core::strtol10(c.c_str());
@ -148,11 +148,11 @@ public:
//! Returns the value of an attribute as integer.
virtual int getAttributeValueAsInt(int idx) const _IRR_OVERRIDE_
virtual int getAttributeValueAsInt(int idx, int defaultNotFound) const _IRR_OVERRIDE_
{
const char_type* attrvalue = getAttributeValue(idx);
if (!attrvalue)
return 0;
return defaultNotFound;
core::stringc c(attrvalue);
return core::strtol10(c.c_str());
@ -160,11 +160,11 @@ public:
//! Returns the value of an attribute as float.
virtual float getAttributeValueAsFloat(const char_type* name) const _IRR_OVERRIDE_
virtual float getAttributeValueAsFloat(const char_type* name, float defaultNotFound) const _IRR_OVERRIDE_
{
const SAttribute* attr = getAttributeByName(name);
if (!attr)
return 0;
return defaultNotFound;
core::stringc c = attr->Value.c_str();
return core::fast_atof(c.c_str());
@ -172,11 +172,11 @@ public:
//! Returns the value of an attribute as float.
virtual float getAttributeValueAsFloat(int idx) const _IRR_OVERRIDE_
virtual float getAttributeValueAsFloat(int idx, float defaultNotFound) const _IRR_OVERRIDE_
{
const char_type* attrvalue = getAttributeValue(idx);
if (!attrvalue)
return 0;
return defaultNotFound;
core::stringc c = attrvalue;
return core::fast_atof(c.c_str());

View File

@ -62,6 +62,7 @@
<ProjectName>Irrlicht</ProjectName>
<ProjectGuid>{E08E042A-6C45-411B-92BE-3CC31331019F}</ProjectGuid>
<RootNamespace>Irrlicht</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='SDL-Debug|Win32'" Label="Configuration">

View File

@ -131,10 +131,8 @@ void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1
int fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1])
{
unsigned int res = cx->mode;
hmac_sha_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx);
memset(cx, 0, sizeof(fcrypt_ctx)); /* clear the encryption context */
return MAC_LENGTH(res); /* return MAC length in bytes */
return MAC_LENGTH(cx->mode); /* return MAC length in bytes */
}

View File

@ -3,8 +3,12 @@ Target = tests
Sources = $(wildcard *.cpp)
CPPFLAGS = -I../include -I/usr/X11R6/include -pipe
# CXXFLAGS += -O3
CXXFLAGS += -Wall -ansi -pedantic -O0 -g -D_DEBUG -fno-exceptions
CXXFLAGS += -Wall -ansi -pedantic -fno-exceptions
ifndef NDEBUG
CXXFLAGS += -O0 -g -D_DEBUG
else
CXXFLAGS += -fexpensive-optimizations -O3
endif
ifeq ($(HOSTTYPE), x86_64)
LIBSELECT=64

View File

@ -148,6 +148,8 @@ bool test_fast_atof(void)
accurate &= testCalculation_atof("0000123456.789");
accurate &= testCalculation_atof("-0000123456.789");
accurate &= testCalculation_atof("-0.0690462109446526");
accurate &= testCalculation_atof("0.11999999731779099"); // more numbers past dot than in lookup table
accurate &= testCalculation_atof("0.119999997317790999");
if (!accurate)
{

View File

@ -113,6 +113,56 @@ static bool testSwap()
return result;
}
// add numbers to the array going down from size to 1
static void addInvNumbers(irr::core::array<int>& arr, irr::u32 size)
{
for ( irr::u32 i=0; i<size; ++i )
{
arr.push_back(size-i);
}
}
// Ensure numbers are sorted in ascending order
static bool validateSortedAscending(const irr::core::array<int>& arr)
{
for ( irr::u32 i=1; i< arr.size(); ++ i)
{
if ( arr[i-1] > arr[i] )
return false;
}
return true;
}
static bool testSort()
{
irr::core::array<int> arr;
for ( irr::u32 i=0; i<1000; ++i )
{
arr.clear();
addInvNumbers(arr, i);
arr.sort();
if ( !validateSortedAscending(arr) )
{
return false;
}
}
for ( irr::u32 i=0; i<1000; ++i )
{
arr.clear();
addInvNumbers(arr, i);
addInvNumbers(arr, i);
arr.sort();
if ( !validateSortedAscending(arr) )
{
return false;
}
}
return true;
}
// Test the functionality of core::array
bool testIrrArray(void)
{
@ -123,6 +173,7 @@ bool testIrrArray(void)
allExpected &= testSelfAssignment();
allExpected &= testSwap();
allExpected &= testErase();
allExpected &= testSort();
if(allExpected)
logTestString("\nAll tests passed\n");

79
tests/line2d.cpp Normal file
View File

@ -0,0 +1,79 @@
// Copyright (C) 2017 Dario Oliveri
// No rights reserved: this software is in the public domain.
#include "testUtils.h"
#include <iostream>
using namespace irr;
using namespace irr::core;
#define EXPECT( condition, value, name) if( condition != value) \
{ std::cout<< name << ": test failed"<< std::endl; return false;}
//! Tests the basic functionality of the software device.
bool line2DTest(void)
{
{
line2d< f32> a(0, 0, 0, 1);
line2d< f32> b(2, 0, 2, 1);
line2d< f32> c(2, 0, 2, 1 + 0.00001f);
EXPECT( a.nearlyParallel( b), true, "parallel Lines are parallel");
EXPECT( a.nearlyParallel( c, (f32)32), true, "nearly parallel lines are parallel");
}
{
line2d< f32> a( 0, 0, 0, 1);
line2d< f32> b( 0, 2, 2, 1);
EXPECT( a.nearlyParallel( b, 1), false, "orthogonal lines are NOT parallel");
}
{
line2d< f32> a( 0, 0, 100, 100);
line2d< f32> b( 100, 0, 0, 100);
EXPECT( a.nearlyParallel( b, 1), false, "orthogonal lines are NOT parallel 2");
vector2df t = a.fastLinesIntersection( b);
vector2df u = vector2df( 50.0f, 50.0f);
EXPECT( t.equals( u, roundingError<f32>() ), true, "fast intersection in known point");
EXPECT( a .intersectAsSegments(b), true, "intersect as Segments");
EXPECT( a.incidentSegments(b), true, "incidentSegments");
vector2df out;
EXPECT( a.lineIntersectSegment( b, out), true, "lineIntersectSegment");
EXPECT( t.equals( out), true, "line intersect segment in known point");
EXPECT( a.isPointBetweenStartAndEnd( out), true, "point isBetween StartEnd of first line");
EXPECT( b.isPointBetweenStartAndEnd( out), true, "point isBetween StartEnd of second line");
EXPECT( a.isPointOnLine( out), true, "is point on first line");
EXPECT( b.isPointOnLine( out), true, "is point on second line");
EXPECT( out.isBetweenPoints( a.start, a.end), true, "test point is on segment with first line");
EXPECT( out.isBetweenPoints( b.start, b.end), true, "test point is on segment with first line");
}
{
vector2df a( 0, 0);
vector2df b( 10, 0);
vector2df c( 0, 10);
vector2df d( 0, 40);
EXPECT( a.areClockwise( c, b), true, "test if points are clockwise");
EXPECT( a.areClockwise( b, c), false, "test if points are NOT clockwise");
EXPECT( a.areCounterClockwise( b, c), true, "test if points are counter clockwise");
EXPECT( a.areCounterClockwise( c, b), false, "test if points are NOT counter clockwise");
EXPECT( a.checkOrientation( c, b), 1, "test if orientation is clockwise");
EXPECT( a.checkOrientation( b, c), 2, "test if orientation is anticlockwise");
EXPECT( a.checkOrientation( c, d), 0, "test if orientation is colinear");
EXPECT( a.checkOrientation( d, c), 0, "test if orientation is colinear 2");
}
return true;
}

View File

@ -129,6 +129,7 @@ int main(int argumentCount, char * arguments[])
TEST(terrainSceneNode);
TEST(lightMaps);
TEST(triangleSelector);
TEST(line2DTest);
unsigned int numberOfTests = tests.size();
unsigned int testToRun = 0;

View File

@ -1,20 +1,16 @@
// Copyright (C) 2008-2012 Colin MacDonald
// No rights reserved: this software is in the public domain.
#if defined(_MSC_VER)
#define _CRT_SECURE_NO_WARNINGS 1
#define TESTING_ON_WINDOWS
#endif // _MSC_VER
#include "testUtils.h"
#include <memory.h>
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
#if defined(TESTING_ON_WINDOWS)
#if defined(_MSC_VER) || defined(_IRR_WINDOWS_API_)
#define _CRT_SECURE_NO_WARNINGS 1
#include <windows.h> // For OutputDebugString()
#endif // #if defined(TESTING_ON_WINDOWS)
#endif // _MSC_VER || _IRR_WINDOWS_API_
using namespace irr;

View File

@ -107,6 +107,7 @@
<Unit filename="irrString.cpp" />
<Unit filename="lightMaps.cpp" />
<Unit filename="lights.cpp" />
<Unit filename="line2d.cpp" />
<Unit filename="loadTextures.cpp" />
<Unit filename="main.cpp" />
<Unit filename="makeColorKeyTexture.cpp" />

View File

@ -179,6 +179,7 @@
<ClCompile Include="irrString.cpp" />
<ClCompile Include="lightMaps.cpp" />
<ClCompile Include="lights.cpp" />
<ClCompile Include="line2d.cpp" />
<ClCompile Include="loadTextures.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="makeColorKeyTexture.cpp" />

View File

@ -179,6 +179,7 @@
<ClCompile Include="irrString.cpp" />
<ClCompile Include="lightMaps.cpp" />
<ClCompile Include="lights.cpp" />
<ClCompile Include="line2d.cpp" />
<ClCompile Include="loadTextures.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="makeColorKeyTexture.cpp" />

View File

@ -179,6 +179,7 @@
<ClCompile Include="irrString.cpp" />
<ClCompile Include="lightMaps.cpp" />
<ClCompile Include="lights.cpp" />
<ClCompile Include="line2d.cpp" />
<ClCompile Include="loadTextures.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="makeColorKeyTexture.cpp" />

View File

@ -179,6 +179,7 @@
<ClCompile Include="irrString.cpp" />
<ClCompile Include="lightMaps.cpp" />
<ClCompile Include="lights.cpp" />
<ClCompile Include="line2d.cpp" />
<ClCompile Include="loadTextures.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="makeColorKeyTexture.cpp" />

View File

@ -132,7 +132,7 @@ inline u32 getTextureSizeFromSurfaceSize(u32 size)
wchar_t currentchar = ch;
if ( IsDBCSLeadByte((BYTE) ch))
continue; // surragate pairs unsupported
continue; // surrogate pairs unsupported
// get the dimensions
SIZE size;
@ -144,9 +144,9 @@ inline u32 getTextureSizeFromSurfaceSize(u32 size)
if (GetCharABCWidthsW(dc, currentchar, currentchar, &abc)) // for unicode fonts, get overhang, underhang, width
{
size.cx = abc.abcB;
fa.underhang = abc.abcA;
fa.overhang = abc.abcC;
size.cx = abc.abcB; // full font width (ignoring padding/underhang )
fa.underhang = abc.abcA; // underhang/padding left - can also be negative (in which case it's overhang left)
fa.overhang = abc.abcC; // overhang/padding right - can also be negative (in which case it's underhand right)
if (abc.abcB-abc.abcA+abc.abcC<1)
continue; // nothing of width 0
@ -236,7 +236,7 @@ inline u32 getTextureSizeFromSurfaceSize(u32 size)
{
s32 currentArea = (*it).getValue();
wchar_t wch = (*it).getKey();
// sloppy but I couldnt be bothered rewriting it
// sloppy but I couldn't be bothered rewriting it
if (Areas[currentArea].sourceimage == currentImage)
{
// draw letter

View File

@ -2,7 +2,7 @@
Tool for creating Irrlicht bitmap+vector fonts,
started by Gaz Davidson in December 2006
Due to my laziness and Microsoft's unituitive API, surragate pairs and
Due to my laziness and Microsoft's unintuitive API, surrogate pairs and
nonspacing diacritical marks are not supported!
Linux bitmap font support added by Neil Burlock Oct 2008