diff --git a/changes.txt b/changes.txt index f557b015..a938f625 100644 --- a/changes.txt +++ b/changes.txt @@ -1,4 +1,17 @@ -Changes in version 1.5 (...12.2008) +Changes in version 1.6 + + - ISceneNodeAnimatorCollisionResponse exposes the target node. Setting the node again resets the last position, allowing the node to be teleported. + + - Add a hitPosition out parameter to ISceneCollisionManager::getCollisionResultPosition() - this is a (small) API breaking change. + +----------------------------------- +Changes in version 1.5 (15.12.2008) + + - Construction calls for FPS camera changed to take speed in units/milliseconds, just as the setSpeed method does. + + - Code::Blocks workspaces added. C::B projects (using gcc) now output to /lib/gcc and /bin/gcc, when built on either Windows or Linux. + + - Added a test suite in the /tests directory. This can be used to perform regression tests, and should be updated with new tests to verify fixes or validate new features. - Changed the preferred way of altering light node's radius: Use the new member methods of ILightSceneNode instead of directly modifying the SLight structure. diff --git a/doc/upgrade-guide.txt b/doc/upgrade-guide.txt index 1c294f5b..482065b5 100644 --- a/doc/upgrade-guide.txt +++ b/doc/upgrade-guide.txt @@ -2,7 +2,7 @@ This file contains API changes between consecutive versions. You can get the relevant information about all changes to the public Irrlicht API needed for upgrading your code (esp. custom scene nodes and GUI elements) to a new Irrlicht version. Since all changes are incremental you should skip forward to the -version you use right now and check all each note until you reach the desired +version you use right now and check each note until you reach the desired version. Please note that the changes described here do not contain functional changes, but only syntactical ones. Also, new methods are not documented here and @@ -1314,3 +1314,273 @@ IrrlichtDevice.h Changed signature (Return value bool instead of void). Returns whether the event has been handled somewhere. virtual bool postEventFromUser(const SEvent& event) = 0; +Changes for Version 1.5 +----------------------- +Another major release, so expect API breaks at several places. The changes +herein are described as a difference to Irrlicht 1.4.2. + +The most noticeable changes are the speed factor of the FPS camera (now units/ms +instead of units/s, so divide the parameter by 1000.f) and the new interfaces +of the camera nodes, based on scene node animators. Custom camera nodes should +be adpated to this new scheme, although they might still work. Also, particle +sizes are now set and handled by the emitters, which requires a change of the +particle system constructor call or adaption of the setParticleSize method to +work on the emitters. A deprecation method is issued if the old scheme is used. +Light setting has also changed, the SLight struct is used in even less +situations than before, instead use methods in ILightSceneNode. + +Other changes did change major parts of the underlying structures, but might go +unnoticed on the user level. This includes 32bit indices and Vertex Buffer +Objects. However, VBOs require the user to call setDirty on Meshes or +MeshBuffers after changes to the vertex or index data. The all need only to be +done once before the next render call, but again after subsequent changes later +on. + + +All Mesh types and MeshBuffers: +New methods for VBO support. Once VBOs are enabled for a meshbuffer, changes +will only be effective after a call to setDirty(). VBOs are enabled by default +for some scene nodes. + virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); + +All MeshBuffers: +Due to the 32bit support, it might happen that indices are stored as 32bit integers. The actual index type can be queried from a mesh buffer. + virtual video::E_INDEX_TYPE getIndexType() const + +IrrCompileConfig.h +Some new defines for configuring Irrlicht +_IRR_USE_WINDOWS_CE_DEVICE_ for Windows CE API based device +_IRR_COMPILE_WITH_JOYSTICK_EVENTS_ to enable joystick support (enabled by default) +_IRR_COMPILE_WITH_LWO_LOADER_ to enable the LWO mesh loader (enabled by default) +_IRR_COMPILE_WITH_OBJ_WRITER_ to enable the OBJ mesh writer (enabled by default) +_IRR_COMPILE_WITH_WAL_LOADER_ to enable the WAL image loader (enabled by default) +_IRR_USE_NVIDIA_PERFHUD_ for support of the PerfHUD tool (disabled by default) + +SceneParameters.h +New parameter scene::OBJ_LOADER_IGNORE_GROUPS, which allows to ignore the group structure of obj files. It's disabled by default, meaning obj groups will be represented by separate meshbuffers. + +SColor.h +Renamed method names of the SColorHSL class + void fromRGB(const SColor &color); + void toRGB(SColor &color) const; + +ITexture.h +Added new parameter + virtual void* lock(bool readOnly = false) = 0; + +IMeshManipulator.h +Renamed methods (the old ones still exist, but are deprecated). The new methods also work on meshbuffers, not just meshes. +(renamed from scaleMesh) + virtual void scale(IMesh* mesh, const core::vector3df& factor) const = 0; +(renamed from transformMesh) + virtual void transform(IMesh* mesh, const core::matrix4& m) const = 0; +Changed signature (Added new parameters to adjust the algorithm) + virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const = 0; + +IBillboardTextSceneNode.h +New interface replacing the multiple inheritance from bliiboard and text scene node previously used by the billboard text scene node. + +IParticleSystemSceneNode.h +All emitters have minStartSize and maxStartSize parameters now, since partice size is handled by the emitters now. +Default value added + virtual void setParticlesAreGlobal(bool global=true) = 0; + +fast_atof.h +Signature change (return value changed from u32) +inline s32 strtol10(const char* in, const char** out=0) +Signature change (parameter changed from float) +inline const char* fast_atof_move( const char * in, f32 & out) + +IAnimatedMeshSceneNode.h +Added new parameter (dummy node used for simplifying shadow calculation) + virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0, + s32 id=-1, bool zfailmethod=true, f32 infinity=10000.0f) = 0; + +ISceneManager.h +Removed extra render passes for quake shaders +Changed scene node from ISceneNode to IMeshSceneNode + virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, ...) + virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ...) +Changed default value (from 256 to 512, for efficiency on common gfx hardware) + virtual ISceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; +Changed default value (from 500.f, to adapt the changed speed scale) + virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, + f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, s32 id=-1, ...) +Added default values + virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, + u32 horiRes=16, u32 vertRes=8, + f64 texturePercentage=0.9, f64 spherePercentage=2.0, + ISceneNode* parent=0, s32 id=-1) = 0; +Changed return value (from ITextSceneNode, due to changed inheritance) + virtual IBillboardTextSceneNode* addBillboardTextSceneNode( gui::IGUIFont* font, const wchar_t* text, ...) +Changed default value (gravity, from -100.f) + virtual ISceneNodeAnimatorCollisionResponse* createCollisionResponseAnimator( + ITriangleSelector* world, ISceneNode* sceneNode, + const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), + const core::vector3df& gravityPerSecond = core::vector3df(0,-10.0f,0), + const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0), + f32 slidingValue = 0.0005f) = 0; + +ISceneNodeAnimator.h +Changed inheritance (for interactive animators) + class ISceneNodeAnimator : public io::IAttributeExchangingObject, public IEventReceiver +Changed to pure virtual (bug fix) + virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0) = 0; + +IVideoModeList.h +Changed return value (constification) + virtual const core::dimension2d& getDesktopResolution() const = 0; + +IBoneSceneNode.h +Deprecation: Use getName instead. + virtual const c8* getBoneName() const; + +vector3d.h +Changed return value (return *this) + vector3d& set(const T nx, const T ny, const T nz) {X=nx; Y=ny; Z=nz; return *this;} + vector3d& set(const vector3d& p) {X=p.X; Y=p.Y; Z=p.Z;return *this;} + vector3d& setLength(T newlength) + vector3d& invert() +Added default value + void rotateXZBy(f64 degrees, const vector3d& center=vector3d()) + void rotateXYBy(f64 degrees, const vector3d& center=vector3d()) + void rotateYZBy(f64 degrees, const vector3d& center=vector3d()) +Changed parameter type (interpolation factor must not be integral) + vector3d getInterpolated(const vector3d& other, f64 d) const + vector3d getInterpolated_quadratic(const vector3d& v2, const vector3d& v3, f64 d) const +Method made const + vector3d getHorizontalAngle() const + +SLight.h +Attenuation can be overridden by ILightSceneMethod setRadius() Attenuation will +change to (0,1.f/radius,0). Can be overridden after radius was set. +The following members are read-only now: + f32 Radius; + E_LIGHT_TYPE Type; + bool CastShadows; + +ITerrainSceneNode.h +Parameter type changed (diue to possible 32bit indices) + virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD=0) const =0; +Added dafault value (highest detail) + virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0) =0; + +SExposedVideoData.h +Changed member attributes (from s32, to fix 64bit architecture problems) + void* HWnd; + void* HDc; + void* HRc; + void* HWnd; + +IAnimatedMeshMD3.h +Changed return value (constification) + const SMD3QuaterionTag& operator[](u32 index) const + +IQ3Shader.h +Changed default q3 shader values (from LIGHTMAP_M2) + const video::E_MATERIAL_TYPE defaultMaterialType = video::EMT_LIGHTMAP_M4; + const video::E_MODULATE_FUNC defaultModulate = video::EMFN_MODULATE_4X; + +ISceneNode.h +Method made virtual + virtual const core::matrix4& getAbsoluteTransformation() const +Changed return value (constified) + virtual const core::vector3df& getScale() const + virtual const core::vector3df& getPosition() const + +IEventReceiver.h +Removed member from UserEvent + f32 UserData3; + +SMaterial.h +Changed member type (from u32) + char ZBuffer; + +IGUISkin.h +Added parameter (for alignment) + virtual void draw3DTabButton(IGUIElement* element, bool active, + const core::rect& rect, const core::rect* clip=0, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT) = 0; + virtual void draw3DTabBody(IGUIElement* element, bool border, bool background, + const core::rect& rect, const core::rect* clip=0, s32 tabHeight=-1, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT ) = 0; + +quaternion.h +Renamed method (from getDotProduct) + inline f32 dotProduct(const quaternion& other) const; +Changed return value (return *this) + quaternion& set(f32 x, f32 y, f32 z, f32 w); + quaternion& set(f32 x, f32 y, f32 z); + quaternion& set(const core::vector3df& vec); + quaternion& makeInverse(); + quaternion& slerp( quaternion q1, quaternion q2, f32 interpolate ); + quaternion& fromAngleAxis (f32 angle, const vector3df& axis); + quaternion& makeIdentity(); + quaternion& rotationFromTo(const vector3df& from, const vector3df& to); + +IVideoDriver.h +Added parameters (moved from endScene) and added default values + virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, + SColor color=SColor(255,0,0,0), void* windowId=0, + core::rect* sourceRect=0) = 0; +Removed parameter (move to beginScene) + virtual bool endScene() = 0; +Renamed method (note, also affects ReferenceCount behavior!) +Use addRenderTargetTexture instead of createRenderTargetTexture + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const c8* name=0) =0; +Changed parameters (for 32bit index support) + virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primCount, E_VERTEX_TYPE vType, + scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) = 0; +Changed parameter (colors are const pointers now) + virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, + const core::rect& sourceRect, const core::rect* clipRect = 0, + const video::SColor * const colors=0, bool useAlphaChannelOfTexture=false) = 0; + +IQ3LevelMesh.h +Added default value + virtual const quake3::SShader* getShader( const c8* filename, bool fileNameIsValid=true ) = 0; + +ICameraSceneNode.h +Added method parameter (required to set orthogonal together with projection to avoid inconsistencies) + virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal = false) = 0; +Removed method (use new parameter in setProjectionMatrix) + void setIsOrthogonal( bool orthogonal ) +Constified return value + virtual const core::vector3df& getTarget() const = 0; + virtual const core::vector3df& getUpVector() const = 0; + +matrix4.h +Removed method (use transformPlane) + void transformPlane_new( core::plane3d &plane) const; +Changed qulifications (to enable use under Win32 systems, too) + IRRLICHT_API extern const matrix4 IdentityMatrix; + +SIrrCreationParameters.h +Changed member attribute types + u8 Bits; + const c8* const SDK_version_do_not_use; + +IGUIElement.h +Renamed method from setRelativePosition (to distinguish rather different parameter interpretation) + void setRelativePositionProportional(const core::rect& r) + +irrString.h +Constructors made explicit (use core::stringc(var) in places where var was used before) + explicit string(const double number) + explicit string(int number) + explicit string(unsigned int number) +Added parameter (allows use of method for stringw, and other things) + string& trim(const string & whitespace = " \t\n\r") + +vector2d.h +Changed return value (return *this) + vector2d& set(T nx, T ny) {X=nx; Y=ny; return *this; } + vector2d& set(const vector2d& p) { X=p.X; Y=p.Y; return *this; } +Added default value + vector2d& rotateBy(f64 degrees, const vector2d& center=vector2d()) +Changed parameter type (interpolation factor must not be int) + vector2d getInterpolated(const vector2d& other, f64 d) const + vector2d getInterpolated_quadratic(const vector2d& v2, const vector2d& v3, f64 d) const + vector2d& interpolate(const vector2d& a, const vector2d& b, f64 d) + diff --git a/examples/01.HelloWorld/HelloWorld.cbp b/examples/01.HelloWorld/HelloWorld.cbp new file mode 100644 index 00000000..61e9a815 --- /dev/null +++ b/examples/01.HelloWorld/HelloWorld.cbp @@ -0,0 +1,39 @@ + + + + + + diff --git a/examples/01.HelloWorld/HelloWorld.vcproj b/examples/01.HelloWorld/HelloWorld.vcproj index cb94d2b8..3a2fdb0e 100644 --- a/examples/01.HelloWorld/HelloWorld.vcproj +++ b/examples/01.HelloWorld/HelloWorld.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/02.Quake3Map/Quake3Map.cbp b/examples/02.Quake3Map/Quake3Map.cbp new file mode 100644 index 00000000..89c1581b --- /dev/null +++ b/examples/02.Quake3Map/Quake3Map.cbp @@ -0,0 +1,38 @@ + + + + + + diff --git a/examples/02.Quake3Map/Quake3Map.vcproj b/examples/02.Quake3Map/Quake3Map.vcproj index 13acaa44..4416fbb4 100644 --- a/examples/02.Quake3Map/Quake3Map.vcproj +++ b/examples/02.Quake3Map/Quake3Map.vcproj @@ -39,7 +39,7 @@ - - - - - - diff --git a/examples/03.CustomSceneNode/CustomSceneNode.cbp b/examples/03.CustomSceneNode/CustomSceneNode.cbp new file mode 100644 index 00000000..f3c7a1d7 --- /dev/null +++ b/examples/03.CustomSceneNode/CustomSceneNode.cbp @@ -0,0 +1,35 @@ + + + + + + diff --git a/examples/03.CustomSceneNode/CustomSceneNode.vcproj b/examples/03.CustomSceneNode/CustomSceneNode.vcproj index 32c879ad..890d308b 100644 --- a/examples/03.CustomSceneNode/CustomSceneNode.vcproj +++ b/examples/03.CustomSceneNode/CustomSceneNode.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/04.Movement/Movement.cbp b/examples/04.Movement/Movement.cbp new file mode 100644 index 00000000..8b4d2bdc --- /dev/null +++ b/examples/04.Movement/Movement.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/04.Movement/Movement.vcproj b/examples/04.Movement/Movement.vcproj index ff0eb434..105c6258 100644 --- a/examples/04.Movement/Movement.vcproj +++ b/examples/04.Movement/Movement.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/04.Movement/main.cpp b/examples/04.Movement/main.cpp index 82ba9c70..63fe3760 100644 --- a/examples/04.Movement/main.cpp +++ b/examples/04.Movement/main.cpp @@ -149,13 +149,13 @@ int main() a md2 model, which uses a 'fly straight' animator to run between to points. */ scene::IAnimatedMeshSceneNode* anms = - smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/sydney.md2")); + smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/ninja.b3d")); if (anms) { scene::ISceneNodeAnimator* anim = smgr->createFlyStraightAnimator(core::vector3df(100,0,60), - core::vector3df(-100,0,60), 2500, true); + core::vector3df(-100,0,60), 3500, true); if (anim) { anms->addAnimator(anim); @@ -176,12 +176,13 @@ int main() */ anms->setMaterialFlag(video::EMF_LIGHTING, false); - anms->setFrameLoop(160, 183); - anms->setAnimationSpeed(40); - anms->setMD2Animation(scene::EMAT_RUN); + anms->setFrameLoop(0, 14); + anms->setAnimationSpeed(15); +// anms->setMD2Animation(scene::EMAT_RUN); - anms->setRotation(core::vector3df(0,180.0f,0)); - anms->setMaterialTexture(0, driver->getTexture("../../media/sydney.bmp")); + anms->setScale(core::vector3df(2.f,2.f,2.f)); + anms->setRotation(core::vector3df(0,-90,0)); +// anms->setMaterialTexture(0, driver->getTexture("../../media/sydney.bmp")); } @@ -190,7 +191,7 @@ int main() To be able to look at and move around in this scene, we create a first person shooter style camera and make the mouse cursor invisible. */ - smgr->addCameraSceneNodeFPS(0, 100.0f, 100.0f); + smgr->addCameraSceneNodeFPS(0, 100.0f, .1f); device->getCursorControl()->setVisible(false); /* diff --git a/examples/05.UserInterface/UserInterface.cbp b/examples/05.UserInterface/UserInterface.cbp new file mode 100644 index 00000000..9abb74a7 --- /dev/null +++ b/examples/05.UserInterface/UserInterface.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/05.UserInterface/UserInterface.vcproj b/examples/05.UserInterface/UserInterface.vcproj index 049d2cbb..44281698 100644 --- a/examples/05.UserInterface/UserInterface.vcproj +++ b/examples/05.UserInterface/UserInterface.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/06.2DGraphics/2DGraphics.cbp b/examples/06.2DGraphics/2DGraphics.cbp new file mode 100644 index 00000000..d5dfd230 --- /dev/null +++ b/examples/06.2DGraphics/2DGraphics.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/06.2DGraphics/2DGraphics.vcproj b/examples/06.2DGraphics/2DGraphics.vcproj index 9862430f..b21c3517 100644 --- a/examples/06.2DGraphics/2DGraphics.vcproj +++ b/examples/06.2DGraphics/2DGraphics.vcproj @@ -41,7 +41,7 @@ - - - - - - diff --git a/examples/07.Collision/Collision.cbp b/examples/07.Collision/Collision.cbp new file mode 100644 index 00000000..633b3325 --- /dev/null +++ b/examples/07.Collision/Collision.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/07.Collision/Collision.vcproj b/examples/07.Collision/Collision.vcproj index 40b558c1..a4e4b076 100644 --- a/examples/07.Collision/Collision.vcproj +++ b/examples/07.Collision/Collision.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/07.Collision/main.cpp b/examples/07.Collision/main.cpp index 526c00f4..80e56ada 100644 --- a/examples/07.Collision/main.cpp +++ b/examples/07.Collision/main.cpp @@ -130,7 +130,7 @@ int main() // Set a jump speed of 3 units per second, which gives a fairly realistic jump // when used with the gravity of (0, -10, 0) in the collision response animator. scene::ICameraSceneNode* camera = - smgr->addCameraSceneNodeFPS(0, 100.0f, 300.0f, -1, 0, 0, true, 3.f); + smgr->addCameraSceneNodeFPS(0, 100.0f, .3f, -1, 0, 0, true, 3.f); camera->setPosition(core::vector3df(-100,50,-150)); if (selector) diff --git a/examples/08.SpecialFX/SpecialFX.cbp b/examples/08.SpecialFX/SpecialFX.cbp new file mode 100644 index 00000000..bc11bfdd --- /dev/null +++ b/examples/08.SpecialFX/SpecialFX.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/08.SpecialFX/SpecialFX.vcproj b/examples/08.SpecialFX/SpecialFX.vcproj index abffc78b..e22266e3 100644 --- a/examples/08.SpecialFX/SpecialFX.vcproj +++ b/examples/08.SpecialFX/SpecialFX.vcproj @@ -41,7 +41,7 @@ - - - - - - diff --git a/examples/09.Meshviewer/Meshviewer.cbp b/examples/09.Meshviewer/Meshviewer.cbp new file mode 100644 index 00000000..d80be847 --- /dev/null +++ b/examples/09.Meshviewer/Meshviewer.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/09.Meshviewer/Meshviewer.vcproj b/examples/09.Meshviewer/Meshviewer.vcproj index 12a56536..4077b860 100644 --- a/examples/09.Meshviewer/Meshviewer.vcproj +++ b/examples/09.Meshviewer/Meshviewer.vcproj @@ -41,7 +41,7 @@ - - - - - - diff --git a/examples/09.Meshviewer/main.cpp b/examples/09.Meshviewer/main.cpp index 672af4f7..4df2785e 100644 --- a/examples/09.Meshviewer/main.cpp +++ b/examples/09.Meshviewer/main.cpp @@ -32,10 +32,53 @@ IrrlichtDevice *Device = 0; core::stringc StartUpModelFile; core::stringw MessageText; core::stringw Caption; -scene::IAnimatedMeshSceneNode* Model = 0; +scene::ISceneNode* Model = 0; scene::ISceneNode* SkyBox = 0; +bool Octree=false; -scene::ICameraSceneNode* Camera[2] = { 0, 0}; +scene::ICameraSceneNode* Camera[2] = {0, 0}; + +// Values used to identify individual GUI elements +enum +{ + GUI_ID_DIALOG_ROOT_WINDOW = 0x10000, + + GUI_ID_X_SCALE, + GUI_ID_Y_SCALE, + GUI_ID_Z_SCALE, + + GUI_ID_OPEN_MODEL, + GUI_ID_SET_MODEL_ARCHIVE, + GUI_ID_LOAD_AS_OCTREE, + + GUI_ID_SKY_BOX_VISIBLE, + GUI_ID_TOGGLE_DEBUG_INFO, + + GUI_ID_DEBUG_OFF, + GUI_ID_DEBUG_BOUNDING_BOX, + GUI_ID_DEBUG_NORMALS, + GUI_ID_DEBUG_SKELETON, + GUI_ID_DEBUG_WIRE_OVERLAY, + GUI_ID_DEBUG_HALF_TRANSPARENT, + GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES, + GUI_ID_DEBUG_ALL, + + GUI_ID_MODEL_MATERIAL_SOLID, + GUI_ID_MODEL_MATERIAL_TRANSPARENT, + GUI_ID_MODEL_MATERIAL_REFLECTION, + + GUI_ID_CAMERA_MAYA, + GUI_ID_CAMERA_FIRST_PERSON, + + GUI_ID_POSITION_TEXT, + + GUI_ID_ABOUT, + GUI_ID_QUIT, + + // And some magic numbers + MAX_FRAMERATE = 1000, + DEFAULT_FRAMERATE = 30 +}; /* Toggle between various cameras @@ -45,7 +88,8 @@ void setActiveCamera(scene::ICameraSceneNode* newActive) if (0 == Device) return; - Device->getSceneManager()->getActiveCamera(); + scene::ICameraSceneNode * active = Device->getSceneManager()->getActiveCamera(); + active->setInputReceiverEnabled(false); newActive->setInputReceiverEnabled(true); Device->getSceneManager()->setActiveCamera(newActive); @@ -82,15 +126,11 @@ void loadModel(const c8* fn) extension.make_lower(); // if a texture is loaded apply it to the current model.. - if (extension == ".jpg" || - extension == ".pcx" || - extension == ".png" || - extension == ".ppm" || - extension == ".pgm" || - extension == ".pbm" || - extension == ".psd" || - extension == ".tga" || - extension == ".bmp") + if (extension == ".jpg" || extension == ".pcx" || + extension == ".png" || extension == ".ppm" || + extension == ".pgm" || extension == ".pbm" || + extension == ".psd" || extension == ".tga" || + extension == ".bmp" || extension == ".wal") { video::ITexture * texture = Device->getVideoDriver()->getTexture( filename.c_str() ); @@ -104,12 +144,15 @@ void loadModel(const c8* fn) } return; } - // if a archive is loaded add it to the FileSystems.. - if (extension == ".pk3" || - extension == ".zip") + else if (extension == ".pk3" || extension == ".zip") { - Device->getFileSystem()->addZipFileArchive( filename.c_str() ); + Device->getFileSystem()->addZipFileArchive(filename.c_str()); + return; + } + else if (extension == ".pak") + { + Device->getFileSystem()->addPakFileArchive(filename.c_str()); return; } @@ -135,11 +178,27 @@ void loadModel(const c8* fn) // set default material properties - Model = Device->getSceneManager()->addAnimatedMeshSceneNode(m); + if (Octree) + Model = Device->getSceneManager()->addOctTreeSceneNode(m->getMesh(0)); + else + { + scene::IAnimatedMeshSceneNode* animModel = Device->getSceneManager()->addAnimatedMeshSceneNode(m); + animModel->setAnimationSpeed(30); + Model = animModel; + } Model->setMaterialFlag(video::EMF_LIGHTING, false); // Model->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); Model->setDebugDataVisible(scene::EDS_OFF); - Model->setAnimationSpeed(30); + + // we need to uncheck the menu entries. would be cool to fake a menu event, but + // that's not so simple. so we do it brute force + gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_TOGGLE_DEBUG_INFO, true); + if (menu) + for(int item = 1; item < 6; ++item) + menu->setItemChecked(item, false); + Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_X_SCALE, true)->setText(L"1.0"); + Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_Y_SCALE, true)->setText(L"1.0"); + Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_Z_SCALE, true)->setText(L"1.0"); } @@ -153,39 +212,48 @@ void createToolBox() // remove tool box if already there IGUIEnvironment* env = Device->getGUIEnvironment(); IGUIElement* root = env->getRootGUIElement(); - IGUIElement* e = root->getElementFromId(5000, true); + IGUIElement* e = root->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true); if (e) e->remove(); // create the toolbox window - IGUIWindow* wnd = env->addWindow(core::rect(600,25,800,480), - false, L"Toolset", 0, 5000); + IGUIWindow* wnd = env->addWindow(core::rect(600,45,800,480), + false, L"Toolset", 0, GUI_ID_DIALOG_ROOT_WINDOW); // create tab control and tabs IGUITabControl* tab = env->addTabControl( core::rect(2,20,800-602,480-7), wnd, true, true); - IGUITab* t1 = tab->addTab(L"Scale"); + IGUITab* t1 = tab->addTab(L"Config"); // add some edit boxes and a button to tab one - env->addEditBox(L"1.0", core::rect(40,50,130,70), true, t1, 901); - env->addEditBox(L"1.0", core::rect(40,80,130,100), true, t1, 902); - env->addEditBox(L"1.0", core::rect(40,110,130,130), true, t1, 903); + env->addStaticText(L"Scale:", + core::rect(10,20,150,45), false, false, t1); + env->addStaticText(L"X:", core::rect(22,48,40,66), false, false, t1); + env->addEditBox(L"1.0", core::rect(40,46,130,66), true, t1, GUI_ID_X_SCALE); + env->addStaticText(L"Y:", core::rect(22,82,40,GUI_ID_OPEN_MODEL), false, false, t1); + env->addEditBox(L"1.0", core::rect(40,76,130,96), true, t1, GUI_ID_Y_SCALE); + env->addStaticText(L"Z:", core::rect(22,108,40,126), false, false, t1); + env->addEditBox(L"1.0", core::rect(40,106,130,126), true, t1, GUI_ID_Z_SCALE); - env->addButton(core::rect(10,150,100,190), t1, 1101, L"set"); + env->addButton(core::rect(10,134,85,165), t1, 1101, L"Set"); - // add senseless checkbox - env->addCheckBox(true, core::rect(10,220,200,240), t1, -1, - L"Senseless Checkbox"); - - // add undocumented transparent control - env->addStaticText(L"Transparent Control:", - core::rect(10,240,150,260), true, false, t1); + // add transparency control + env->addStaticText(L"GUI Transparency Control:", + core::rect(10,200,150,225), true, false, t1); IGUIScrollBar* scrollbar = env->addScrollBar(true, - core::rect(10,260,150,275), t1, 104); + core::rect(10,225,150,240), t1, 104); scrollbar->setMax(255); scrollbar->setPos(255); + // add framerate control + env->addStaticText(L"Framerate:", + core::rect(10,240,150,265), true, false, t1); + scrollbar = env->addScrollBar(true, + core::rect(10,265,150,280), t1, 105); + scrollbar->setMax(MAX_FRAMERATE); + scrollbar->setPos(DEFAULT_FRAMERATE); + // bring irrlicht engine logo to front, because it // now may be below the newly created toolbox root->bringToFront(root->getElementFromId(666, true)); @@ -196,7 +264,7 @@ void createToolBox() To get all the events sent by the GUI Elements, we need to create an event receiver. This one is really simple. If an event occurs, it checks the id of the caller and the event type, and starts an action based on these values. For -example, if a menu item with id 100 was selected, if opens a file-open-dialog. +example, if a menu item with id GUI_ID_OPEN_MODEL was selected, if opens a file-open-dialog. */ class MyEventReceiver : public IEventReceiver { @@ -205,18 +273,29 @@ public: { // Escape swaps Camera Input if (event.EventType == EET_KEY_INPUT_EVENT && - event.KeyInput.Key == irr::KEY_ESCAPE && event.KeyInput.PressedDown == false) { - if (Device) + if (event.KeyInput.Key == irr::KEY_ESCAPE) { - scene::ICameraSceneNode * camera = - Device->getSceneManager()->getActiveCamera(); - if (camera) + if (Device) { - camera->setInputReceiverEnabled( !camera->isInputReceiverEnabled() ); + scene::ICameraSceneNode * camera = + Device->getSceneManager()->getActiveCamera(); + if (camera) + { + camera->setInputReceiverEnabled( !camera->isInputReceiverEnabled() ); + } + return true; + } + } + else if (event.KeyInput.Key == irr::KEY_F1) + { + if (Device) + { + IGUIElement* elem = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_POSITION_TEXT); + if (elem) + elem->setVisible(!elem->isVisible()); } - return true; } } @@ -236,70 +315,93 @@ public: switch(id) { - case 100: // File -> Open Model + case GUI_ID_OPEN_MODEL: // File -> Open Model env->addFileOpenDialog(L"Please select a model file to open"); break; - case 101: // File -> Set Model Archive + case GUI_ID_SET_MODEL_ARCHIVE: // File -> Set Model Archive env->addFileOpenDialog(L"Please select your game archive/directory"); break; - case 200: // File -> Quit + case GUI_ID_LOAD_AS_OCTREE: // File -> LoadAsOctree + Octree = !Octree; + menu->setItemChecked(menu->getSelectedItem(), Octree); + break; + case GUI_ID_QUIT: // File -> Quit Device->closeDevice(); break; - case 300: // View -> Skybox + case GUI_ID_SKY_BOX_VISIBLE: // View -> Skybox + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); SkyBox->setVisible(!SkyBox->isVisible()); break; - case 400: // View -> Debug Information + case GUI_ID_DEBUG_OFF: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem()+1, false); + menu->setItemChecked(menu->getSelectedItem()+2, false); + menu->setItemChecked(menu->getSelectedItem()+3, false); + menu->setItemChecked(menu->getSelectedItem()+4, false); + menu->setItemChecked(menu->getSelectedItem()+5, false); + menu->setItemChecked(menu->getSelectedItem()+6, false); if (Model) Model->setDebugDataVisible(scene::EDS_OFF); break; - case 410: // View -> Debug Information + case GUI_ID_DEBUG_BOUNDING_BOX: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX)); break; - case 420: // View -> Debug Information + case GUI_ID_DEBUG_NORMALS: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_NORMALS)); break; - case 430: // View -> Debug Information + case GUI_ID_DEBUG_SKELETON: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_SKELETON)); break; - case 440: // View -> Debug Information + case GUI_ID_DEBUG_WIRE_OVERLAY: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY)); break; - case 450: // View -> Debug Information + case GUI_ID_DEBUG_HALF_TRANSPARENT: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_HALF_TRANSPARENCY)); break; - case 460: // View -> Debug Information + case GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX_BUFFERS)); break; - case 499: // View -> Debug Information + case GUI_ID_DEBUG_ALL: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem()-1, true); + menu->setItemChecked(menu->getSelectedItem()-2, true); + menu->setItemChecked(menu->getSelectedItem()-3, true); + menu->setItemChecked(menu->getSelectedItem()-4, true); + menu->setItemChecked(menu->getSelectedItem()-5, true); + menu->setItemChecked(menu->getSelectedItem()-6, true); if (Model) Model->setDebugDataVisible(scene::EDS_FULL); break; - case 500: // Help->About + case GUI_ID_ABOUT: // Help->About showAboutText(); break; - case 610: // View -> Material -> Solid + case GUI_ID_MODEL_MATERIAL_SOLID: // View -> Material -> Solid if (Model) Model->setMaterialType(video::EMT_SOLID); break; - case 620: // View -> Material -> Transparent + case GUI_ID_MODEL_MATERIAL_TRANSPARENT: // View -> Material -> Transparent if (Model) Model->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); break; - case 630: // View -> Material -> Reflection + case GUI_ID_MODEL_MATERIAL_REFLECTION: // View -> Material -> Reflection if (Model) Model->setMaterialType(video::EMT_SPHERE_MAP); break; - case 1000: + case GUI_ID_CAMERA_MAYA: setActiveCamera(Camera[0]); break; - case 1100: + case GUI_ID_CAMERA_FIRST_PERSON: setActiveCamera(Camera[1]); break; @@ -321,7 +423,7 @@ public: // control skin transparency if (id == 104) { - s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); + const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); for (s32 i=0; igetSkin()->getColor((EGUI_DEFAULT_COLOR)i); @@ -329,6 +431,12 @@ public: env->getSkin()->setColor((EGUI_DEFAULT_COLOR)i, col); } } + else if (id == 105) + { + const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); + if (scene::ESNT_ANIMATED_MESH == Model->getType()) + ((scene::IAnimatedMeshSceneNode*)Model)->setAnimationSpeed((f32)pos); + } break; case EGET_COMBO_BOX_CHANGED: @@ -388,11 +496,11 @@ public: core::vector3df scale; core::stringc s; - s = root->getElementFromId(901, true)->getText(); + s = root->getElementFromId(GUI_ID_X_SCALE, true)->getText(); scale.X = (f32)atof(s.c_str()); - s = root->getElementFromId(902, true)->getText(); + s = root->getElementFromId(GUI_ID_Y_SCALE, true)->getText(); scale.Y = (f32)atof(s.c_str()); - s = root->getElementFromId(903, true)->getText(); + s = root->getElementFromId(GUI_ID_Z_SCALE, true)->getText(); scale.Z = (f32)atof(s.c_str()); if (Model) @@ -480,7 +588,7 @@ int main(int argc, char* argv[]) driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); smgr->addLightSceneNode(); - smgr->addLightSceneNode(0, core::vector3df(50,-50,100), + smgr->addLightSceneNode(0, core::vector3df(50,-50,GUI_ID_OPEN_MODEL), video::SColorf(1.0f,1.0f,1.0f),20000); // add our media directory as "search path" Device->getFileSystem()->addFolderFileArchive("../../media/"); @@ -564,37 +672,38 @@ int main(int argc, char* argv[]) gui::IGUIContextMenu* submenu; submenu = menu->getSubMenu(0); - submenu->addItem(L"Open Model File & Texture...", 100); - submenu->addItem(L"Set Model Archive...", 101); + submenu->addItem(L"Open Model File & Texture...", GUI_ID_OPEN_MODEL); + submenu->addItem(L"Set Model Archive...", GUI_ID_SET_MODEL_ARCHIVE); + submenu->addItem(L"Load as Octree", GUI_ID_LOAD_AS_OCTREE); submenu->addSeparator(); - submenu->addItem(L"Quit", 200); + submenu->addItem(L"Quit", GUI_ID_QUIT); submenu = menu->getSubMenu(1); - submenu->addItem(L"toggle sky box visibility", 300); - submenu->addItem(L"toggle model debug information", -1, true, true); + submenu->addItem(L"sky box visible", GUI_ID_SKY_BOX_VISIBLE, true, false, true); + submenu->addItem(L"toggle model debug information", GUI_ID_TOGGLE_DEBUG_INFO, true, true); submenu->addItem(L"model material", -1, true, true ); submenu = submenu->getSubMenu(1); - submenu->addItem(L"Off", 400); - submenu->addItem(L"Bounding Box", 410); - submenu->addItem(L"Normals", 420); - submenu->addItem(L"Skeleton", 430); - submenu->addItem(L"Wire overlay", 440); - submenu->addItem(L"Half-Transparent", 450); - submenu->addItem(L"Buffers bounding boxes", 460); - submenu->addItem(L"All", 499); + submenu->addItem(L"Off", GUI_ID_DEBUG_OFF); + submenu->addItem(L"Bounding Box", GUI_ID_DEBUG_BOUNDING_BOX); + submenu->addItem(L"Normals", GUI_ID_DEBUG_NORMALS); + submenu->addItem(L"Skeleton", GUI_ID_DEBUG_SKELETON); + submenu->addItem(L"Wire overlay", GUI_ID_DEBUG_WIRE_OVERLAY); + submenu->addItem(L"Half-Transparent", GUI_ID_DEBUG_HALF_TRANSPARENT); + submenu->addItem(L"Buffers bounding boxes", GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES); + submenu->addItem(L"All", GUI_ID_DEBUG_ALL); submenu = menu->getSubMenu(1)->getSubMenu(2); - submenu->addItem(L"Solid", 610); - submenu->addItem(L"Transparent", 620); - submenu->addItem(L"Reflection", 630); + submenu->addItem(L"Solid", GUI_ID_MODEL_MATERIAL_SOLID); + submenu->addItem(L"Transparent", GUI_ID_MODEL_MATERIAL_TRANSPARENT); + submenu->addItem(L"Reflection", GUI_ID_MODEL_MATERIAL_REFLECTION); submenu = menu->getSubMenu(2); - submenu->addItem(L"Maya Style", 1000); - submenu->addItem(L"First Person", 1100); + submenu->addItem(L"Maya Style", GUI_ID_CAMERA_MAYA); + submenu->addItem(L"First Person", GUI_ID_CAMERA_FIRST_PERSON); submenu = menu->getSubMenu(3); - submenu->addItem(L"About", 500); + submenu->addItem(L"About", GUI_ID_ABOUT); /* Below the menu we want a toolbar, onto which we can place colored @@ -649,7 +758,11 @@ int main(int argc, char* argv[]) // create fps text IGUIStaticText* fpstext = env->addStaticText(L"", - core::rect(400,4,570,23), true, false, bar); + core::rect(GUI_ID_TOGGLE_DEBUG_INFO,4,570,23), true, false, bar); + + IGUIStaticText* postext = env->addStaticText(L"", + core::rect(10,50,470,80),false, false, 0, GUI_ID_POSITION_TEXT); + postext->setVisible(false); // set window caption @@ -668,7 +781,7 @@ int main(int argc, char* argv[]) // show about message box and load default model if (argc==1) - showAboutText(); + showAboutText(); loadModel(StartUpModelFile.c_str()); // add skybox @@ -684,8 +797,14 @@ int main(int argc, char* argv[]) // add a camera scene node Camera[0] = smgr->addCameraSceneNodeMaya(); Camera[0]->setFarValue(20000.f); + // Maya cameras reposition themselves relative to their target, so target the location + // where the mesh scene node is placed. + Camera[0]->setTarget(core::vector3df(0,30,0)); + Camera[1] = smgr->addCameraSceneNodeFPS(); Camera[1]->setFarValue(20000.f); + Camera[1]->setPosition(core::vector3df(0,0,-70)); + Camera[1]->setTarget(core::vector3df(0,30,0)); setActiveCamera(Camera[0]); @@ -716,6 +835,21 @@ int main(int argc, char* argv[]) str += L" Tris: "; str.append(core::stringw(driver->getPrimitiveCountDrawn())); fpstext->setText(str.c_str()); + + scene::ICameraSceneNode* cam = Device->getSceneManager()->getActiveCamera(); + str = L"Pos: "; + str.append(core::stringw(cam->getPosition().X)); + str += L" "; + str.append(core::stringw(cam->getPosition().Y)); + str += L" "; + str.append(core::stringw(cam->getPosition().Z)); + str += L" Tgt: "; + str.append(core::stringw(cam->getTarget().X)); + str += L" "; + str.append(core::stringw(cam->getTarget().Y)); + str += L" "; + str.append(core::stringw(cam->getTarget().Z)); + postext->setText(str.c_str()); } else Device->yield(); diff --git a/examples/10.Shaders/Shaders.cbp b/examples/10.Shaders/Shaders.cbp new file mode 100644 index 00000000..818d5116 --- /dev/null +++ b/examples/10.Shaders/Shaders.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/10.Shaders/Shaders.vcproj b/examples/10.Shaders/Shaders.vcproj index a5f9b601..e730a2f9 100644 --- a/examples/10.Shaders/Shaders.vcproj +++ b/examples/10.Shaders/Shaders.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/10.Shaders/main.cpp b/examples/10.Shaders/main.cpp index 8b3ef85c..2964d3c8 100644 --- a/examples/10.Shaders/main.cpp +++ b/examples/10.Shaders/main.cpp @@ -380,7 +380,7 @@ int main() // add a camera and disable the mouse cursor - scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(0, 100.0f, 100.0f); + scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(0, 100.0f, .1f); cam->setPosition(core::vector3df(-100,50,100)); cam->setTarget(core::vector3df(0,0,0)); device->getCursorControl()->setVisible(false); diff --git a/examples/11.PerPixelLighting/PerPixelLighting.cbp b/examples/11.PerPixelLighting/PerPixelLighting.cbp new file mode 100644 index 00000000..65698401 --- /dev/null +++ b/examples/11.PerPixelLighting/PerPixelLighting.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/11.PerPixelLighting/PerPixelLighting.vcproj b/examples/11.PerPixelLighting/PerPixelLighting.vcproj index f1f86501..94d7e6a7 100644 --- a/examples/11.PerPixelLighting/PerPixelLighting.vcproj +++ b/examples/11.PerPixelLighting/PerPixelLighting.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/11.PerPixelLighting/main.cpp b/examples/11.PerPixelLighting/main.cpp index 39f2f7da..298d7db7 100644 --- a/examples/11.PerPixelLighting/main.cpp +++ b/examples/11.PerPixelLighting/main.cpp @@ -208,7 +208,7 @@ int main() // add camera scene::ICameraSceneNode* camera = - smgr->addCameraSceneNodeFPS(0,100.0f,300.0f); + smgr->addCameraSceneNodeFPS(0, 100.0f, .3f); camera->setPosition(core::vector3df(-200,200,-200)); // disable mouse cursor @@ -414,8 +414,6 @@ int main() scene::IParticleSystemSceneNode* ps = smgr->addParticleSystemSceneNode(false, light2); - ps->setParticleSize(core::dimension2d(30.0f, 40.0f)); - // create and set emitter scene::IParticleEmitter* em = ps->createBoxEmitter( core::aabbox3d(-3,0,-3,3,1,3), @@ -423,6 +421,9 @@ int main() 80,100, video::SColor(0,255,255,255), video::SColor(0,255,255,255), 400,1100); + em->setMinStartSize(core::dimension2d(30.0f, 40.0f)); + em->setMaxStartSize(core::dimension2d(30.0f, 40.0f)); + ps->setEmitter(em); em->drop(); diff --git a/examples/12.TerrainRendering/TerrainRendering.cbp b/examples/12.TerrainRendering/TerrainRendering.cbp new file mode 100644 index 00000000..264bcecd --- /dev/null +++ b/examples/12.TerrainRendering/TerrainRendering.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/12.TerrainRendering/TerrainRendering.vcproj b/examples/12.TerrainRendering/TerrainRendering.vcproj index adc293d7..22005623 100644 --- a/examples/12.TerrainRendering/TerrainRendering.vcproj +++ b/examples/12.TerrainRendering/TerrainRendering.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/12.TerrainRendering/main.cpp b/examples/12.TerrainRendering/main.cpp index 137ce1cb..dee05058 100644 --- a/examples/12.TerrainRendering/main.cpp +++ b/examples/12.TerrainRendering/main.cpp @@ -133,7 +133,7 @@ int main() // add camera scene::ICameraSceneNode* camera = - smgr->addCameraSceneNodeFPS(0,100.0f,1200.f); + smgr->addCameraSceneNodeFPS(0,100.0f,1.2f); camera->setPosition(core::vector3df(2700*2,255*2,2600*2)); camera->setTarget(core::vector3df(2397*2,343*2,2700*2)); @@ -208,6 +208,14 @@ int main() camera->addAnimator(anim); anim->drop(); + /* If you need access to the terrain data you can also do this directly via the following code fragment. + */ + scene::CDynamicMeshBuffer* buffer = new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); + terrain->getMeshBufferForLOD(*buffer, 0); + video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData(); + // Work on data or get the IndexBuffer with a similar call. + buffer->drop(); // When done drop the buffer again. + /* To make the user be able to switch between normal and wireframe mode, we create an instance of the event reciever from above and let Irrlicht diff --git a/examples/13.RenderToTexture/RenderToTexture.cbp b/examples/13.RenderToTexture/RenderToTexture.cbp new file mode 100644 index 00000000..aec392c7 --- /dev/null +++ b/examples/13.RenderToTexture/RenderToTexture.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/13.RenderToTexture/RenderToTexture.vcproj b/examples/13.RenderToTexture/RenderToTexture.vcproj index 2b1a23ae..8fd8e6c2 100644 --- a/examples/13.RenderToTexture/RenderToTexture.vcproj +++ b/examples/13.RenderToTexture/RenderToTexture.vcproj @@ -41,7 +41,7 @@ - - - - - - diff --git a/examples/14.Win32Window/Win32Window.cbp b/examples/14.Win32Window/Win32Window.cbp new file mode 100644 index 00000000..d34716b3 --- /dev/null +++ b/examples/14.Win32Window/Win32Window.cbp @@ -0,0 +1,36 @@ + + + + + + diff --git a/examples/14.Win32Window/Win32Window.vcproj b/examples/14.Win32Window/Win32Window.vcproj index a17c9ff4..42592a6e 100644 --- a/examples/14.Win32Window/Win32Window.vcproj +++ b/examples/14.Win32Window/Win32Window.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/15.LoadIrrFile/LoadIrrFile.cbp b/examples/15.LoadIrrFile/LoadIrrFile.cbp new file mode 100644 index 00000000..9f1a33c5 --- /dev/null +++ b/examples/15.LoadIrrFile/LoadIrrFile.cbp @@ -0,0 +1,38 @@ + + + + + + diff --git a/examples/15.LoadIrrFile/LoadIrrFile.vcproj b/examples/15.LoadIrrFile/LoadIrrFile.vcproj index 2a9038c4..f0ca0a6d 100644 --- a/examples/15.LoadIrrFile/LoadIrrFile.vcproj +++ b/examples/15.LoadIrrFile/LoadIrrFile.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/15.LoadIrrFile/main.cpp b/examples/15.LoadIrrFile/main.cpp index feca0cbf..77616c27 100644 --- a/examples/15.LoadIrrFile/main.cpp +++ b/examples/15.LoadIrrFile/main.cpp @@ -74,7 +74,7 @@ int main() Now we'll create a camera, and give it a collision response animator that's built from the mesh nodes in the scene we just loaded. */ - scene::ICameraSceneNode * camera = smgr->addCameraSceneNodeFPS(0, 50, 100); + scene::ICameraSceneNode * camera = smgr->addCameraSceneNodeFPS(0, 50.f, 0.1f); // Create a meta triangle selector to hold several triangle selectors. scene::IMetaTriangleSelector * meta = smgr->createMetaTriangleSelector(); diff --git a/examples/16.Quake3MapShader/Quake3MapShader.cbp b/examples/16.Quake3MapShader/Quake3MapShader.cbp new file mode 100644 index 00000000..95a27fd8 --- /dev/null +++ b/examples/16.Quake3MapShader/Quake3MapShader.cbp @@ -0,0 +1,34 @@ + + + + + + diff --git a/examples/16.Quake3MapShader/Quake3MapShader.vcproj b/examples/16.Quake3MapShader/Quake3MapShader.vcproj index 1286deaf..4d46421c 100644 --- a/examples/16.Quake3MapShader/Quake3MapShader.vcproj +++ b/examples/16.Quake3MapShader/Quake3MapShader.vcproj @@ -33,7 +33,7 @@ + + + + + diff --git a/examples/18.SplitScreen/SplitScreen.vcproj b/examples/18.SplitScreen/SplitScreen.vcproj index 9073e470..8efc546c 100644 --- a/examples/18.SplitScreen/SplitScreen.vcproj +++ b/examples/18.SplitScreen/SplitScreen.vcproj @@ -33,7 +33,7 @@ addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0)); //User-controlled camera[3] = smgr->addCameraSceneNodeFPS(); + // don't start at sydney's position + if (camera[3]) + camera[3]->setPosition(core::vector3df(-50,0,-50)); /* Create a variable for counting the fps and hide the mouse: @@ -237,10 +240,11 @@ Sounds a little complicated, but you'll see it isn't: //Get and show fps if (driver->getFPS() != lastFPS) { - lastFPS = driver->getFPS(); - wchar_t tmp[1024]; - swprintf( tmp, 1024, L"Irrlicht SplitScreen-Example (FPS: %d)", lastFPS); - device->setWindowCaption(tmp); + lastFPS = driver->getFPS(); + core::stringw tmp = L"Irrlicht SplitScreen-Example (FPS: "; + tmp += lastFPS; + tmp += ")"; + device->setWindowCaption(tmp.c_str()); } } //Delete device diff --git a/examples/19.MouseAndJoystick/MouseAndJoystick.cbp b/examples/19.MouseAndJoystick/MouseAndJoystick.cbp new file mode 100644 index 00000000..846236d3 --- /dev/null +++ b/examples/19.MouseAndJoystick/MouseAndJoystick.cbp @@ -0,0 +1,38 @@ + + + + + + diff --git a/examples/19.MouseAndJoystick/MouseAndJoystick.vcproj b/examples/19.MouseAndJoystick/MouseAndJoystick.vcproj index 260b8e61..b9ccad40 100644 --- a/examples/19.MouseAndJoystick/MouseAndJoystick.vcproj +++ b/examples/19.MouseAndJoystick/MouseAndJoystick.vcproj @@ -40,7 +40,7 @@ - - - - - - diff --git a/examples/19.MouseAndJoystick/main.cpp b/examples/19.MouseAndJoystick/main.cpp index 08b82289..073aaa4f 100644 --- a/examples/19.MouseAndJoystick/main.cpp +++ b/examples/19.MouseAndJoystick/main.cpp @@ -123,7 +123,7 @@ int main() case 'e': driverType = video::EDT_BURNINGSVIDEO;break; case 'f': driverType = video::EDT_NULL; break; default: return 0; - } + } // create device MyEventReceiver receiver; @@ -171,9 +171,10 @@ int main() std::cout << "Joystick support is not enabled." << std::endl; } - wchar_t tmp[1024]; - swprintf(tmp, 1024, L"Irrlicht Joystick Example (%u joysticks)", joystickInfo.size()); - device->setWindowCaption(tmp); + core::stringw tmp = L"Irrlicht Joystick Example ("; + tmp += joystickInfo.size(); + tmp += " joysticks)"; + device->setWindowCaption(tmp.c_str()); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); @@ -208,15 +209,21 @@ int main() const SEvent::SJoystickEvent & joystickData = receiver.GetJoystickState(); - // Use the analog range of the axes, and a 5% dead zone - moveHorizontal = + // We receive the full analog range of the axes, and so have to implement our + // own dead zone. This is an empirical value, since some joysticks have more + // jitter or creep around the center point than others. We'll use 5% of the + // range as the dead zone, but generally you would want to give the user the + // option to change this. + const f32 DEAD_ZONE = 0.05f; + + moveHorizontal = (f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_X] / 32767.f; - if(fabs(moveHorizontal) < 0.05f) + if(fabs(moveHorizontal) < DEAD_ZONE) moveHorizontal = 0.f; - moveVertical = + moveVertical = (f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_Y] / -32767.f; - if(fabs(moveVertical) < 0.05f) + if(fabs(moveVertical) < DEAD_ZONE) moveVertical = 0.f; // POV hat info is only currently supported on Windows, but the value is @@ -267,12 +274,9 @@ int main() } node->setPosition(nodePosition); - + // Turn lighting on and off depending on whether the left mouse button is down. - if(receiver.GetMouseState().LeftButtonDown) - node->setMaterialFlag(video::EMF_LIGHTING, true); - else - node->setMaterialFlag(video::EMF_LIGHTING, false); + node->setMaterialFlag(video::EMF_LIGHTING, receiver.GetMouseState().LeftButtonDown); driver->beginScene(true, true, video::SColor(255,113,113,133)); smgr->drawAll(); // draw the 3d scene @@ -283,6 +287,6 @@ int main() In the end, delete the Irrlicht device. */ device->drop(); - + return 0; } diff --git a/examples/BuildAllExamples.workspace b/examples/BuildAllExamples.workspace new file mode 100644 index 00000000..9b2b13b5 --- /dev/null +++ b/examples/BuildAllExamples.workspace @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/Demo/CDemo.cpp b/examples/Demo/CDemo.cpp index 39bd0948..fa08cf70 100644 --- a/examples/Demo/CDemo.cpp +++ b/examples/Demo/CDemo.cpp @@ -324,7 +324,7 @@ void CDemo::switchToNextScene() keyMap[8].Action = EKA_JUMP_UP; keyMap[8].KeyCode = KEY_KEY_J; - camera = sm->addCameraSceneNodeFPS(0, 100.0f, 400.0f, -1, keyMap, 9, false, 3.f); + camera = sm->addCameraSceneNodeFPS(0, 100.0f, .4f, -1, keyMap, 9, false, 3.f); camera->setPosition(core::vector3df(108,140,-140)); scene::ISceneNodeAnimatorCollisionResponse* collider = @@ -533,13 +533,14 @@ void CDemo::loadSceneData() campFire->setPosition(core::vector3df(100,120,600)); campFire->setScale(core::vector3df(2,2,2)); - campFire->setParticleSize(core::dimension2d(20.0f, 10.0f)); scene::IParticleEmitter* em = campFire->createBoxEmitter( core::aabbox3d(-7,0,-7,7,1,7), core::vector3df(0.0f,0.06f,0.0f), 80,100, video::SColor(0,255,255,255),video::SColor(0,255,255,255), 800,2000); + em->setMinStartSize(core::dimension2d(20.0f, 10.0f)); + em->setMaxStartSize(core::dimension2d(20.0f, 10.0f)); campFire->setEmitter(em); em->drop(); diff --git a/examples/Demo/CDemo.h b/examples/Demo/CDemo.h index ab22e0de..02356bb9 100644 --- a/examples/Demo/CDemo.h +++ b/examples/Demo/CDemo.h @@ -63,7 +63,7 @@ private: #ifdef USE_IRRKLANG void startIrrKlang(); - irrklang::ISoundEngine* irrKlang; + irrklang::ISoundEngine* irrKlang; irrklang::ISoundSource* ballSound; irrklang::ISoundSource* impactSound; #endif diff --git a/examples/Demo/Demo.vcproj b/examples/Demo/Demo.vcproj index ed35f993..fe55b37f 100644 --- a/examples/Demo/Demo.vcproj +++ b/examples/Demo/Demo.vcproj @@ -41,7 +41,7 @@ - - - - - - diff --git a/examples/buildAllExamples.sh b/examples/buildAllExamples.sh index a2d682ba..992ffa10 100755 --- a/examples/buildAllExamples.sh +++ b/examples/buildAllExamples.sh @@ -1,4 +1,4 @@ -#! /bin/sh +#! /bin/bash [ -z $1 ] || TARGET=$1 [ -z $TARGET ] && TARGET=all for i in [01]* Demo; do diff --git a/include/CVertexBuffer.h b/include/CVertexBuffer.h index c1610911..2bcab457 100644 --- a/include/CVertexBuffer.h +++ b/include/CVertexBuffer.h @@ -72,12 +72,15 @@ namespace scene public: IVertexList *Vertices; - CVertexBuffer(video::E_VERTEX_TYPE vertexType) :Vertices(0), MappingHint(EHM_NEVER), ChangedID(1) + CVertexBuffer(video::E_VERTEX_TYPE vertexType) : Vertices(0), + MappingHint(EHM_NEVER), ChangedID(1) { setType(vertexType); } - CVertexBuffer(const IVertexBuffer &VertexBufferCopy) :Vertices(0), MappingHint(EHM_NEVER), ChangedID(1) + CVertexBuffer(const IVertexBuffer &VertexBufferCopy) : + Vertices(0), MappingHint(EHM_NEVER), + ChangedID(1) { setType(VertexBufferCopy.getType()); reallocate(VertexBufferCopy.size()); @@ -91,7 +94,6 @@ namespace scene delete Vertices; } - //virtual void setType(video::E_VERTEX_TYPE vertexType); virtual void setType(video::E_VERTEX_TYPE vertexType) { diff --git a/include/ICameraSceneNode.h b/include/ICameraSceneNode.h index f9fb928f..2bd21ac3 100644 --- a/include/ICameraSceneNode.h +++ b/include/ICameraSceneNode.h @@ -15,10 +15,10 @@ namespace scene struct SViewFrustum; //! Scene Node which is a (controlable) camera. - /** The whole scene will be - rendered from the cameras point of view. Because the ICameraScenNode - is a SceneNode, it can be attached to any other scene node, and will - follow its parents movement, rotation and so on. + /** The whole scene will be rendered from the cameras point of view. + Because the ICameraScenNode is a SceneNode, it can be attached to any + other scene node, and will follow its parents movement, rotation and so + on. */ class ICameraSceneNode : public ISceneNode, public IEventReceiver { @@ -32,13 +32,16 @@ namespace scene : ISceneNode(parent, mgr, id, position, rotation, scale), IsOrthogonal(false) {} //! Sets the projection matrix of the camera. - /** The core::matrix4 class has some methods - to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH. - Note that the matrix will only stay as set by this method until one of - the following Methods are called: setNearValue, setFarValue, setAspectRatio, setFOV. + /** The core::matrix4 class has some methods to build a + projection matrix. e.g: + core::matrix4::buildProjectionMatrixPerspectiveFovLH. + Note that the matrix will only stay as set by this method until + one of the following Methods are called: setNearValue, + setFarValue, setAspectRatio, setFOV. \param projection The new projection matrix of the camera. \param isOrthogonal Set this to true if the matrix is an - orthogonal one (e.g. from matrix4::buildProjectionMatrixOrtho... */ + orthogonal one (e.g. from matrix4::buildProjectionMatrixOrtho). + */ virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal = false) = 0; //! Gets the current projection matrix of the camera. @@ -52,8 +55,8 @@ namespace scene //! It is possible to send mouse and key events to the camera. /** Most cameras may ignore this input, but camera scene nodes which are created for example with - ISceneManager::addMayaCameraSceneNode or - ISceneManager::addMeshViewerCameraSceneNode, may want to get + ISceneManager::addCameraSceneNodeMaya or + ISceneManager::addCameraSceneNodeFPS, may want to get this input for changing their position, look at target or whatever. */ virtual bool OnEvent(const SEvent& event) = 0; @@ -62,18 +65,19 @@ namespace scene /** If the camera's target and rotation are bound ( @see bindTargetAndRotation() ) then calling this will also change the camera's scene node rotation to match the target. - \param pos Look at target of the camera. */ + \param pos Look at target of the camera, in world co-ordinates. */ virtual void setTarget(const core::vector3df& pos) = 0; //! Sets the rotation of the node. /** This only modifies the relative rotation of the node. - If the camera's target and rotation are bound ( @see bindTargetAndRotation() ) - then calling this will also change the camera's target to match the rotation. + If the camera's target and rotation are bound ( @see + bindTargetAndRotation() ) then calling this will also change + the camera's target to match the rotation. \param rotation New rotation of the node in degrees. */ virtual void setRotation(const core::vector3df& rotation) = 0; //! Gets the current look at target of the camera - /** \return The current look at target of the camera */ + /** \return The current look at target of the camera, in world co-ordinates */ virtual const core::vector3df& getTarget() const = 0; //! Sets the up vector of the camera. @@ -81,7 +85,7 @@ namespace scene virtual void setUpVector(const core::vector3df& pos) = 0; //! Gets the up vector of the camera. - /** \return The up vector of the camera. */ + /** \return The up vector of the camera, in world space. */ virtual const core::vector3df& getUpVector() const = 0; //! Gets the value of the near plane of the camera. @@ -122,8 +126,8 @@ namespace scene virtual const SViewFrustum* getViewFrustum() const = 0; //! Disables or enables the camera to get key or mouse inputs. - /** If this is set to true, the camera will respond to key inputs - otherwise not. */ + /** If this is set to true, the camera will respond to key + inputs otherwise not. */ virtual void setInputReceiverEnabled(bool enabled) = 0; //! Checks if the input receiver of the camera is currently enabled. @@ -137,10 +141,13 @@ namespace scene } //! Binds the camera scene node's rotation to its target position and vice vera, or unbinds them. - /** When bound, calling setRotation() will update the camera's target position to be along - its +Z axis, and likewise calling setTarget() will update its rotation so that its +Z axis - will point at the target point. FPS camera use this binding by default; other cameras do not. - \param binding true to bind the camera's scene node rotation and targetting, false to unbind them. + /** When bound, calling setRotation() will update the camera's + target position to be along its +Z axis, and likewise calling + setTarget() will update its rotation so that its +Z axis will + point at the target point. FPS camera use this binding by + default; other cameras do not. + \param binding true to bind the camera's scene node rotation + and targetting, false to unbind them. @see getTargetAndRotationBinding() */ virtual void bindTargetAndRotation(bool bound) = 0; diff --git a/include/IEventReceiver.h b/include/IEventReceiver.h index f4c38491..33e5380e 100644 --- a/include/IEventReceiver.h +++ b/include/IEventReceiver.h @@ -269,11 +269,11 @@ struct SEvent /** For AXIS_X, AXIS_Y, AXIS_Z, AXIS_R, AXIS_U and AXIS_V * Values are in the range -32768 to 32767, with 0 representing - * the center position. You will usually want to add a dead - * zone around this center range. Axes not supported by this - * joystick will always have a value of 0. - * On Linux, POV hats are represented as axes, usually the - * last two active axis. + * the center position. You will receive the raw value from the + * joystick, and so will usually want to implement a dead zone around + * the center of the range. Axes not supported by this joystick will + * always have a value of 0. On Linux, POV hats are represented as axes, + * usually the last two active axis. */ s16 Axis[NUMBER_OF_AXES]; diff --git a/include/ISceneCollisionManager.h b/include/ISceneCollisionManager.h index 8d2b822f..b9c7ee13 100644 --- a/include/ISceneCollisionManager.h +++ b/include/ISceneCollisionManager.h @@ -70,6 +70,7 @@ namespace scene const core::vector3df& ellipsoidRadius, const core::vector3df& ellipsoidDirectionAndSpeed, core::triangle3df& triout, + core::vector3df& hitPosition, bool& outFalling, f32 slidingSpeed = 0.0005f, const core::vector3df& gravityDirectionAndSpeed diff --git a/include/ISceneManager.h b/include/ISceneManager.h index 53a9f813..5cf411c3 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -47,7 +47,7 @@ namespace scene //! Enumeration for render passes. /** A parameter passed to the registerNodeForRendering() method of the ISceneManager, - specifying when the mode wants to be drawn in relation to the other nodes. */ + specifying when the node wants to be drawn in relation to the other nodes. */ enum E_SCENE_NODE_RENDER_PASS { //! Camera pass. The active view is set up here. The very first pass. @@ -156,7 +156,7 @@ namespace scene * * 3D Studio (.3ds) * Loader for 3D-Studio files which lots of 3D packages - * are able to export. Only static meshes are currently + * are able to export. Only static meshes are currently * supported by this importer. * * @@ -170,7 +170,7 @@ namespace scene * architecture and calculating lighting. Irrlicht can * directly import .csm files thanks to the IrrCSM library * created by Saurav Mohapatra which is now integrated - * directly in Irrlicht. If you are using this loader, + * directly in Irrlicht. If you are using this loader, * please note that you'll have to set the path of the * textures before loading .csm files. You can do this * using @@ -180,52 +180,51 @@ namespace scene * * COLLADA (.dae, .xml) * COLLADA is an open Digital Asset Exchange Schema for - * the interactive 3D industry. There are exporters and - * importers for this format available for most of the - * big 3d packagesat http://collada.org. Irrlicht can - * import COLLADA files by using the - * ISceneManager::getMesh() method. COLLADA files need - * not contain only one single mesh but multiple meshes - * and a whole scene setup with lights, cameras and mesh - * instances, this loader can set up a scene as - * described by the COLLADA file instead of loading and - * returning one single mesh. By default, this loader - * behaves like the other loaders and does not create - * instances, but it can be switched into this mode by - * using - * SceneManager->getParameters()->setParameter(COLLADA_CREATE_SCENE_INSTANCES, true); - * Created scene nodes will be named as the names of the - * nodes in the COLLADA file. The returned mesh is just - * a dummy object in this mode. Meshes included in the - * scene will be added into the scene manager with the - * following naming scheme: - * path/to/file/file.dea#meshname. The loading of such - * meshes is logged. Currently, this loader is able to - * create meshes (made of only polygons), lights, and - * cameras. Materials and animations are currently not - * supported but this will change with future releases. + * the interactive 3D industry. There are exporters and + * importers for this format available for most of the + * big 3d packagesat http://collada.org. Irrlicht can + * import COLLADA files by using the + * ISceneManager::getMesh() method. COLLADA files need + * not contain only one single mesh but multiple meshes + * and a whole scene setup with lights, cameras and mesh + * instances, this loader can set up a scene as + * described by the COLLADA file instead of loading and + * returning one single mesh. By default, this loader + * behaves like the other loaders and does not create + * instances, but it can be switched into this mode by + * using + * SceneManager->getParameters()->setParameter(COLLADA_CREATE_SCENE_INSTANCES, true); + * Created scene nodes will be named as the names of the + * nodes in the COLLADA file. The returned mesh is just + * a dummy object in this mode. Meshes included in the + * scene will be added into the scene manager with the + * following naming scheme: + * path/to/file/file.dea#meshname. The loading of such + * meshes is logged. Currently, this loader is able to + * create meshes (made of only polygons), lights, and + * cameras. Materials and animations are currently not + * supported but this will change with future releases. * * * * Delgine DeleD (.dmf) * DeleD (delgine.com) is a 3D editor and level-editor - * combined into one and is specifically designed for 3D - * game-development. With this loader, it is possible to - * directly load all geometry is as well as textures and - * lightmaps from .dmf files. To set texture and - * material paths, see scene::DMF_USE_MATERIALS_DIRS and - * scene::DMF_TEXTURE_PATH. It is also possible to flip - * the alpha texture by setting - * scene::DMF_FLIP_ALPHA_TEXTURES to true and to set the - * material transparent reference value by setting - * scene::DMF_ALPHA_CHANNEL_REF to a float between 0 and - * 1. The loader is based on Salvatore Russo's .dmf - * loader, I just changed some parts of it. Thanks to - * Salvatore for his work and for allowing me to use his - * code in Irrlicht and put it under Irrlicht's license. - * For newer and more enchanced versions of the loader, - * take a look at delgine.com. - * + * combined into one and is specifically designed for 3D + * game-development. With this loader, it is possible to + * directly load all geometry is as well as textures and + * lightmaps from .dmf files. To set texture and + * material paths, see scene::DMF_USE_MATERIALS_DIRS and + * scene::DMF_TEXTURE_PATH. It is also possible to flip + * the alpha texture by setting + * scene::DMF_FLIP_ALPHA_TEXTURES to true and to set the + * material transparent reference value by setting + * scene::DMF_ALPHA_CHANNEL_REF to a float between 0 and + * 1. The loader is based on Salvatore Russo's .dmf + * loader, I just changed some parts of it. Thanks to + * Salvatore for his work and for allowing me to use his + * code in Irrlicht and put it under Irrlicht's license. + * For newer and more enchanced versions of the loader, + * take a look at delgine.com. * * * DirectX (.x) @@ -234,7 +233,7 @@ namespace scene * and there are several tools for them available, e.g. * the Maya exporter included in the DX SDK. * .x files can include skeletal animations and Irrlicht - * is able to play and display them. Currently, Irrlicht + * is able to play and display them. Currently, Irrlicht * only supports uncompressed .x files. * * @@ -249,91 +248,90 @@ namespace scene * .MS3D files contain models and sometimes skeletal * animations from the Milkshape 3D modeling and animation * software. This importer for Irrlicht can display and/or - * animate these files. + * animate these files. * * - * My3D (.my3d) - * .my3D is a flexible 3D file format. The My3DTools - * contains plug-ins to export .my3D files from several - * 3D packages. With this built-in importer, Irrlicht - * can read and display those files directly. This - * loader was written by Zhuck Dimitry who also created - * the whole My3DTools package. If you are using this - * loader, please note that you can set the path of the - * textures before loading .my3d files. You can do this - * using - * SceneManager->getParameters()->setParameter(scene::MY3D_TEXTURE_PATH, - * "path/to/your/textures"); - * - * - * - * OCT (.oct) - * The oct file format contains 3D geometry and - * lightmaps and can be loaded directly by Irrlicht. OCT - * files
can be created by FSRad, Paul Nette's - * radiosity processor or exported from Blender using - * OCTTools which can be found in the exporters/OCTTools - * directory of the SDK. Thanks to Murphy McCauley for - * creating all this. - * - * - * OGRE Meshes (.mesh) - * Ogre .mesh files contain 3D data for the OGRE 3D - * engine. Irrlicht can read and display them directly - * with this importer. To define materials for the mesh, - * copy a .material file named like the corresponding - * .mesh file where the .mesh file is. (For example - * ogrehead.material for ogrehead.mesh). Thanks to - * Christian Stehno who wrote and contributed this - * loader. - * - * - * Pulsar LMTools (.lmts) - * LMTools is a set of tools (Windows & Linux) for - * creating lightmaps. Irrlicht can directly read .lmts - * files thanks to
the importer created by Jonas - * Petersen. If you are using this loader, please note - * that you can set the path of the textures before - * loading .lmts files. You can do this using - * SceneManager->getParameters()->setParameter(scene::LMTS_TEXTURE_PATH, - * "path/to/your/textures"); - * Notes for
this version of the loader:
- * - It does not recognise/support user data in the - * *.lmts files.
- * - The TGAs generated by LMTools don't work in - * Irrlicht for some reason (the textures are upside - * down). Opening and resaving them in a graphics app - * will solve the problem. - * - * - * Quake 3 levels (.bsp) - * Quake 3 is a popular game by IDSoftware, and .pk3 - * files contain .bsp files and textures/lightmaps - * describing huge prelighted levels. Irrlicht can read - * .pk3 and .bsp files directly and thus render Quake 3 - * levels directly. Written by Nikolaus Gebhardt - * enhanced by Dean P. Macri with the curved surfaces - * feature. - * - * - * Quake 2 models (.md2) - * Quake 2 models are characters with morph target - * animation. Irrlicht can read, display and animate - * them directly with this importer. - * - * + * My3D (.my3d) + * .my3D is a flexible 3D file format. The My3DTools + * contains plug-ins to export .my3D files from several + * 3D packages. With this built-in importer, Irrlicht + * can read and display those files directly. This + * loader was written by Zhuck Dimitry who also created + * the whole My3DTools package. If you are using this + * loader, please note that you can set the path of the + * textures before loading .my3d files. You can do this + * using + * SceneManager->getParameters()->setParameter(scene::MY3D_TEXTURE_PATH, + * "path/to/your/textures"); + * + * + * OCT (.oct) + * The oct file format contains 3D geometry and + * lightmaps and can be loaded directly by Irrlicht. OCT + * files
can be created by FSRad, Paul Nette's + * radiosity processor or exported from Blender using + * OCTTools which can be found in the exporters/OCTTools + * directory of the SDK. Thanks to Murphy McCauley for + * creating all this. + * + * + * OGRE Meshes (.mesh) + * Ogre .mesh files contain 3D data for the OGRE 3D + * engine. Irrlicht can read and display them directly + * with this importer. To define materials for the mesh, + * copy a .material file named like the corresponding + * .mesh file where the .mesh file is. (For example + * ogrehead.material for ogrehead.mesh). Thanks to + * Christian Stehno who wrote and contributed this + * loader. + * + * + * Pulsar LMTools (.lmts) + * LMTools is a set of tools (Windows & Linux) for + * creating lightmaps. Irrlicht can directly read .lmts + * files thanks to
the importer created by Jonas + * Petersen. If you are using this loader, please note + * that you can set the path of the textures before + * loading .lmts files. You can do this using + * SceneManager->getParameters()->setParameter(scene::LMTS_TEXTURE_PATH, + * "path/to/your/textures"); + * Notes for
this version of the loader:
+ * - It does not recognise/support user data in the + * *.lmts files.
+ * - The TGAs generated by LMTools don't work in + * Irrlicht for some reason (the textures are upside + * down). Opening and resaving them in a graphics app + * will solve the problem. + * + * + * Quake 3 levels (.bsp) + * Quake 3 is a popular game by IDSoftware, and .pk3 + * files contain .bsp files and textures/lightmaps + * describing huge prelighted levels. Irrlicht can read + * .pk3 and .bsp files directly and thus render Quake 3 + * levels directly. Written by Nikolaus Gebhardt + * enhanced by Dean P. Macri with the curved surfaces + * feature. + * + * + * Quake 2 models (.md2) + * Quake 2 models are characters with morph target + * animation. Irrlicht can read, display and animate + * them directly with this importer. + * + * * - * To load and display a mesh quickly, just do this: - * \code - * SceneManager->addAnimatedMeshSceneNode( + * To load and display a mesh quickly, just do this: + * \code + * SceneManager->addAnimatedMeshSceneNode( * SceneManager->getMesh("yourmesh.3ds")); - * \endcode - * If you would like to implement and add your own file format loader to Irrlicht, - * see addExternalMeshLoader(). - * \param filename: Filename of the mesh to load. - * \return Returns NULL if failed and the pointer to the mesh if - * successful. - * This pointer should not be dropped. See IReferenceCounted::drop() for more information. + * \endcode + * If you would like to implement and add your own file format loader to Irrlicht, + * see addExternalMeshLoader(). + * \param filename: Filename of the mesh to load. + * \return Returns NULL if failed and the pointer to the mesh if + * successful. + * This pointer should not be dropped. See IReferenceCounted::drop() for more information. **/ virtual IAnimatedMesh* getMesh(const c8* filename) = 0; @@ -341,7 +339,7 @@ namespace scene /** Works just as getMesh(const char* filename). If you want to remove a loaded mesh from the cache again, use removeMesh(). \param file File handle of the mesh to load. - \return NULL if failed and pointer to the mesh if successful. + \return 0 if failed and pointer to the mesh if successful. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh* getMesh(io::IReadFile* file) = 0; @@ -367,8 +365,8 @@ namespace scene /** Example Usage: scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(NULL, -1, 32, 32, //Subdivide U/V - video::SColor(0, 180, 180, 180), //foot color - video::SColor(0, 0, 0, 0) //tail color + video::SColor(0, 180, 180, 180), //foot color + video::SColor(0, 0, 0, 0) //tail color ); if (n) { @@ -527,71 +525,77 @@ namespace scene const core::vector3df& lookat = core::vector3df(0,0,100), s32 id=-1) = 0; //! Adds a maya style user controlled camera scene node to the scene graph. - /** This is a standard camera with an animator that provides mouse control similar - to camera in the 3D Software Maya by Alias Wavefront. - \param parent: Parent scene node of the camera. Can be null. - \param rotateSpeed: Rotation speed of the camera. - \param zoomSpeed: Zoom speed of the camera. - \param translationSpeed: TranslationSpeed of the camera. - \param id: id of the camera. This id can be used to identify the camera. - \return Returns a pointer to the interface of the camera if successful, otherwise 0. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + /** This is a standard camera with an animator that provides + mouse control similar to camera in the 3D Software Maya. + \param parent: Parent scene node of the camera. Can be null. + \param rotateSpeed: Rotation speed of the camera. + \param zoomSpeed: Zoom speed of the camera. + \param translationSpeed: Translation speed of the camera. + \param id: id of the camera. This id can be used to identify the camera. + \return Pointer to the interface of the camera if successful, otherwise 0. + This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ virtual ICameraSceneNode* addCameraSceneNodeMaya(ISceneNode* parent = 0, f32 rotateSpeed = -1500.0f, f32 zoomSpeed = 200.0f, f32 translationSpeed = 1500.0f, s32 id=-1) = 0; //! Adds a camera scene node with an animator which provides mouse and keyboard control appropriate for first person shooters (FPS). - /** This FPS camera is intended to provide a demonstration of a camera that behaves - like a typical First Person Shooter. It is useful for simple demos and prototyping but is not - intended to provide a full solution for a production quality game. It binds the camera scene node - rotation to the look-at target; @see ICameraSceneNode::bindTargetAndRotation(). - With this camera, you look with the mouse, and move with cursor keys. If you want to - change the key layout, you can specify your own keymap. For example to make the camera - be controlled by the cursor keys AND the keys W,A,S, and D, do something - like this: - \code - SKeyMap keyMap[8]; - keyMap[0].Action = EKA_MOVE_FORWARD; - keyMap[0].KeyCode = KEY_UP; - keyMap[1].Action = EKA_MOVE_FORWARD; - keyMap[1].KeyCode = KEY_KEY_W; + /** This FPS camera is intended to provide a demonstration of a + camera that behaves like a typical First Person Shooter. It is + useful for simple demos and prototyping but is not intended to + provide a full solution for a production quality game. It binds + the camera scene node rotation to the look-at target; @see + ICameraSceneNode::bindTargetAndRotation(). With this camera, + you look with the mouse, and move with cursor keys. If you want + to change the key layout, you can specify your own keymap. For + example to make the camera be controlled by the cursor keys AND + the keys W,A,S, and D, do something like this: + \code + SKeyMap keyMap[8]; + keyMap[0].Action = EKA_MOVE_FORWARD; + keyMap[0].KeyCode = KEY_UP; + keyMap[1].Action = EKA_MOVE_FORWARD; + keyMap[1].KeyCode = KEY_KEY_W; - keyMap[2].Action = EKA_MOVE_BACKWARD; - keyMap[2].KeyCode = KEY_DOWN; - keyMap[3].Action = EKA_MOVE_BACKWARD; - keyMap[3].KeyCode = KEY_KEY_S; + keyMap[2].Action = EKA_MOVE_BACKWARD; + keyMap[2].KeyCode = KEY_DOWN; + keyMap[3].Action = EKA_MOVE_BACKWARD; + keyMap[3].KeyCode = KEY_KEY_S; - keyMap[4].Action = EKA_STRAFE_LEFT; - keyMap[4].KeyCode = KEY_LEFT; - keyMap[5].Action = EKA_STRAFE_LEFT; - keyMap[5].KeyCode = KEY_KEY_A; + keyMap[4].Action = EKA_STRAFE_LEFT; + keyMap[4].KeyCode = KEY_LEFT; + keyMap[5].Action = EKA_STRAFE_LEFT; + keyMap[5].KeyCode = KEY_KEY_A; - keyMap[6].Action = EKA_STRAFE_RIGHT; - keyMap[6].KeyCode = KEY_RIGHT; - keyMap[7].Action = EKA_STRAFE_RIGHT; - keyMap[7].KeyCode = KEY_KEY_D; + keyMap[6].Action = EKA_STRAFE_RIGHT; + keyMap[6].KeyCode = KEY_RIGHT; + keyMap[7].Action = EKA_STRAFE_RIGHT; + keyMap[7].KeyCode = KEY_KEY_D; - camera = sceneManager->addCameraSceneNodeFPS(0, 100, 500, -1, keyMap, 8); - \endcode - \param parent: Parent scene node of the camera. Can be null. - \param rotateSpeed: Speed with which the camera is rotated. This can be done - only with the mouse. - \param moveSpeed: Speed with which the camera is moved. Movement is done with - the cursor keys. - \param id: id of the camera. This id can be used to identify the camera. - \param keyMapArray: Optional pointer to an array of a keymap, specifying what - keys should be used to move the camera. If this is null, the default keymap - is used. You can define actions more then one time in the array, to bind - multiple keys to the same action. - \param keyMapSize: Amount of items in the keymap array. - \param noVerticalMovement: Setting this to true makes the camera only move within a - horizontal plane, and disables vertical movement as known from most ego shooters. Default - is 'false', with which it is possible to fly around in space, if no gravity is there. - \param jumpSpeed: Speed with which the camera is moved when jumping. - \return Returns a pointer to the interface of the camera if successful, otherwise 0. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + camera = sceneManager->addCameraSceneNodeFPS(0, 100, 500, -1, keyMap, 8); + \endcode + \param parent: Parent scene node of the camera. Can be null. + \param rotateSpeed: Speed in degress with which the camera is + rotated. This can be done only with the mouse. + \param moveSpeed: Speed in units per millisecond with which + the camera is moved. Movement is done with the cursor keys. + \param id: id of the camera. This id can be used to identify the camera. + \param keyMapArray: Optional pointer to an array of a keymap, specifying what + keys should be used to move the camera. If this is null, the default keymap + is used. You can define actions more then one time in the array, to bind + multiple keys to the same action. + \param keyMapSize: Amount of items in the keymap array. + \param noVerticalMovement: Setting this to true makes the + camera only move within a horizontal plane, and disables + vertical movement as known from most ego shooters. Default is + 'false', with which it is possible to fly around in space, if + no gravity is there. + \param jumpSpeed: Speed with which the camera is moved when jumping. + \return Pointer to the interface of the camera if successful, otherwise 0. + This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, - f32 rotateSpeed = 100.0f, f32 moveSpeed = 500.0f, s32 id=-1, + f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, f32 jumpSpeed = 0.f) = 0; @@ -670,8 +674,9 @@ namespace scene \return Returns a pointer to the sky dome if successful, otherwise NULL. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, - u32 horiRes, u32 vertRes, f64 texturePercentage, f64 spherePercentage, - ISceneNode* parent = 0, s32 id=-1) = 0; + u32 horiRes=16, u32 vertRes=8, + f64 texturePercentage=0.9, f64 spherePercentage=2.0, + ISceneNode* parent=0, s32 id=-1) = 0; //! Adds a particle system scene node to the scene graph. /** \param withDefaultEmitter: Creates a default working point emitter @@ -828,11 +833,11 @@ namespace scene ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1) = 0; - //! Adds a text scene node, which uses billboards. The node, and the text on it, will scale with distance. + //! Adds a text scene node, which uses billboards. The node, and the text on it, will scale with distance. /** \param font The font to use on the billboard. Pass 0 to use the GUI environment's default font. \param text The text to display on the billboard. - \param parent The billboard's parent. Pass 0 to use the root scene node. + \param parent The billboard's parent. Pass 0 to use the root scene node. \param size The billboard's width and height. \param position The billboards position relative to its parent. \param colorTop: The color of the vertices at the top of the billboard (default: white). @@ -1077,7 +1082,9 @@ namespace scene ISceneManager::createTriangleSelector(); \param sceneNode: SceneNode which should be manipulated. After you added this animator to the scene node, the scene node will not be able to move through walls and is - affected by gravity. + affected by gravity. If you need to teleport the scene node to a new position without + it being effected by the collision geometry, then call sceneNode->setPosition(); then + animator->setTargetNode(sceneNode); \param ellipsoidRadius: Radius of the ellipsoid with which collision detection and response is done. If you have got a scene node, and you are unsure about how big the radius should be, you could use the following code to determine @@ -1086,8 +1093,8 @@ namespace scene const core::aabbox3d& box = yourSceneNode->getBoundingBox(); core::vector3df radius = box.MaxEdge - box.getCenter(); \endcode - \param gravityPerSecond: Sets the gravity of the environment, as an acceleration in - units per second per second. If your units are equivalent to metres, then + \param gravityPerSecond: Sets the gravity of the environment, as an acceleration in + units per second per second. If your units are equivalent to metres, then core::vector3df(0,-10.0f,0) would give an approximately realistic gravity. You can disable gravity by setting it to core::vector3df(0,0,0). \param ellipsoidTranslation: By default, the ellipsoid for collision detection is created around diff --git a/include/ISceneNode.h b/include/ISceneNode.h index 94425478..459d9b94 100644 --- a/include/ISceneNode.h +++ b/include/ISceneNode.h @@ -676,6 +676,10 @@ namespace scene return 0; // to be implemented by derived classes } + //! Retrieve the scene manager for this node. + /** \return The node's scene manager. */ + virtual ISceneManager* getSceneManager(void) const { return SceneManager; } + protected: //! A clone function for the ISceneNode members. diff --git a/include/ISceneNodeAnimator.h b/include/ISceneNodeAnimator.h index 394c5305..c8346367 100644 --- a/include/ISceneNodeAnimator.h +++ b/include/ISceneNodeAnimator.h @@ -46,8 +46,8 @@ namespace scene virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0) = 0; //! Returns true if this animator receives events. - /** When attached to the an active camera, this animator will be able to respond to events - such as mouse and keyboard events. */ + /** When attached to an active camera, this animator will be + able to respond to events such as mouse and keyboard events. */ virtual bool isEventReceiverEnabled() const { return false; diff --git a/include/ISceneNodeAnimatorCameraFPS.h b/include/ISceneNodeAnimatorCameraFPS.h index ee8a2485..7676d570 100644 --- a/include/ISceneNodeAnimatorCameraFPS.h +++ b/include/ISceneNodeAnimatorCameraFPS.h @@ -16,8 +16,8 @@ namespace scene { //! Special scene node animator for FPS cameras - /** This scene node animator can be attached to a camera to make it act like a first - person shooter + /** This scene node animator can be attached to a camera to make it act + like a first person shooter */ class ISceneNodeAnimatorCameraFPS : public ISceneNodeAnimator { @@ -29,21 +29,24 @@ namespace scene //! Sets the speed of movement in units per millisecond virtual void setMoveSpeed(f32 moveSpeed) = 0; - //! Returns the rotation speed + //! Returns the rotation speed in degrees + /** The degrees are equivalent to a half screen movement of the mouse, + i.e. if the mouse cursor had been moved to the border of the screen since + the last animation. */ virtual f32 getRotateSpeed() const = 0; - //! Set the rotation speed + //! Set the rotation speed in degrees virtual void setRotateSpeed(f32 rotateSpeed) = 0; //! Sets the keyboard mapping for this animator - //! \param keymap: an array of keyboard mappings, see SKeyMap - //! \param count: the size of the keyboard map array + /** \param keymap Array of keyboard mappings, see SKeyMap + \param count Size of the keyboard map array */ virtual void setKeyMap(SKeyMap *map, u32 count) = 0; //! Sets whether vertical movement should be allowed. - //! If vertical movement is enabled then the camera may fight with - //! gravity causing camera shake. Disable this if the camera has - //! a collision animator with gravity enabled. + /** If vertical movement is enabled then the camera may fight with + gravity causing camera shake. Disable this if the camera has + a collision animator with gravity enabled. */ virtual void setVerticalMovement(bool allow) = 0; }; } // end namespace scene diff --git a/include/ISceneNodeAnimatorCameraMaya.h b/include/ISceneNodeAnimatorCameraMaya.h index a6367826..41698148 100644 --- a/include/ISceneNodeAnimatorCameraMaya.h +++ b/include/ISceneNodeAnimatorCameraMaya.h @@ -13,18 +13,20 @@ namespace irr namespace scene { - //! Special scene node animator for FPS cameras - /** This scene node animator can be attached to a camera to make it act like a first - person shooter + //! Special scene node animator for Maya-style cameras + /** This scene node animator can be attached to a camera to make it act like a 3d + modelling tool. + The camera is moving relative to the target with the mouse, by pressing either + of the three buttons. */ class ISceneNodeAnimatorCameraMaya : public ISceneNodeAnimator { public: - //! Returns the speed of movement in units per millisecond + //! Returns the speed of movement virtual f32 getMoveSpeed() const = 0; - //! Sets the speed of movement in units per millisecond + //! Sets the speed of movement virtual void setMoveSpeed(f32 moveSpeed) = 0; //! Returns the rotation speed diff --git a/include/ISceneNodeAnimatorCollisionResponse.h b/include/ISceneNodeAnimatorCollisionResponse.h index e7ad068c..f8a2d97b 100644 --- a/include/ISceneNodeAnimatorCollisionResponse.h +++ b/include/ISceneNodeAnimatorCollisionResponse.h @@ -13,14 +13,19 @@ namespace scene { //! Special scene node animator for doing automatic collision detection and response. - /** This scene node animator can be attached to any scene node - modifying it in that way, that it cannot move through walls of the - world, is influenced by gravity and acceleration. This animator is - useful for example for first person shooter games. Attach it for - example to a first person shooter camera, and the camera will behave as - the player control in a first person shooter game: The camera stops and - slides at walls, walks up stairs, falls down if there is no floor under - it, and so on. */ + /** This scene node animator can be attached to any single scene node + and will then prevent it from moving through specified collision geometry + (e.g. walls and floors of the) world, as well as having it fall under gravity. + This animator provides a simple implementation of first person shooter cameras. + Attach it to a camera, and the camera will behave as the player control in a + first person shooter game: The camera stops and slides at walls, walks up stairs, + falls down if there is no floor under it, and so on. + + The animator will treat any change in the position of its target scene + node as movement, including a setPosition(), as movement. If you want to + teleport the target scene node manually to a location without it being effected + by collision geometry, then call setTargetNode(node) after calling node->setPosition(). + */ class ISceneNodeAnimatorCollisionResponse : public ISceneNodeAnimator { public: @@ -92,6 +97,17 @@ namespace scene //! Get the current triangle selector containing all triangles for collision detection. virtual ITriangleSelector* getWorld() const = 0; + + //! Set the single node that this animator will act on. + /** \param node The new target node. Setting this will force the animator to update + its last target position for the node, allowing setPosition() to teleport + the node through collision geometry. */ + virtual void setTargetNode(ISceneNode * node) = 0; + + //! Gets the single node that this animator is acting on. + /** \return The node that this animator is acting on. */ + virtual ISceneNode* getTargetNode(void) const = 0; + }; diff --git a/include/ITerrainSceneNode.h b/include/ITerrainSceneNode.h index aac7019f..75f29add 100644 --- a/include/ITerrainSceneNode.h +++ b/include/ITerrainSceneNode.h @@ -33,8 +33,8 @@ namespace scene * * This scene node is capable of very quickly loading * terrains and updating the indices at runtime to enable viewing very large terrains. It uses a - * CLOD ( Continuous Level of Detail ) algorithm which updates the indices for each patch based on - * a LOD ( Level of Detail ) which is determined based on a patch's distance from the camera. + * CLOD (Continuous Level of Detail) algorithm which updates the indices for each patch based on + * a LOD (Level of Detail) which is determined based on a patch's distance from the camera. * * The Patch Size of the terrain must always be a size of ( 2^N+1, i.e. 8+1(9), 16+1(17), etc. ). * The MaxLOD available is directly dependent on the patch size of the terrain. LOD 0 contains all @@ -49,7 +49,6 @@ namespace scene class ITerrainSceneNode : public ISceneNode { public: - //! Constructor ITerrainSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0.0f, 0.0f, 0.0f), @@ -57,34 +56,30 @@ namespace scene const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f) ) : ISceneNode (parent, mgr, id, position, rotation, scale) {} - //! Destructor - virtual ~ITerrainSceneNode() {} - //! Get the bounding box of the terrain. /** \return The bounding box of the entire terrain. */ - virtual const core::aabbox3d& getBoundingBox() const = 0; + virtual const core::aabbox3d& getBoundingBox() const =0; //! Get the bounding box of a patch /** \return The bounding box of the chosen patch. */ - virtual const core::aabbox3d& getBoundingBox(s32 patchX, s32 patchZ) const = 0; + virtual const core::aabbox3d& getBoundingBox(s32 patchX, s32 patchZ) const =0; //! Get the number of indices currently in the meshbuffer /** \return The index count. */ - virtual u32 getIndexCount() const = 0; + virtual u32 getIndexCount() const =0; //! Get pointer to the mesh /** \return Pointer to the mesh. */ - virtual IMesh* getMesh() = 0; + virtual IMesh* getMesh() =0; - - //! Returns a pointer to the buffer used by the terrain (most users will not need this) - virtual IMeshBuffer* getRenderBuffer() = 0; + //! Get pointer to the buffer used by the terrain (most users will not need this) + virtual IMeshBuffer* getRenderBuffer() =0; //! Gets the meshbuffer data based on a specified level of detail. - /** \param mb A reference to an SMeshBuffer object + /** \param mb A reference to an IDynamicMeshBuffer object \param LOD The level of detail you want the indices from. */ - virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD) const = 0; + virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD=0) const =0; //! Gets the indices for a specified patch at a specified Level of Detail. /** \param indices A reference to an array of u32 indices. @@ -93,42 +88,42 @@ namespace scene \param LOD The level of detail to get for that patch. If -1, then get the CurrentLOD. If the CurrentLOD is set to -1, meaning it's not shown, then it will retrieve the triangles at - the highest LOD ( 0 ). + the highest LOD (0). \return Number of indices put into the buffer. */ virtual s32 getIndicesForPatch(core::array& indices, - s32 patchX, s32 patchZ, s32 LOD = 0 ) = 0; + s32 patchX, s32 patchZ, s32 LOD=0) =0; //! Populates an array with the CurrentLOD of each patch. /** \param LODs A reference to a core::array to hold the values \return Number of elements in the array */ - virtual s32 getCurrentLODOfPatches(core::array& LODs) const = 0; + virtual s32 getCurrentLODOfPatches(core::array& LODs) const =0; //! Manually sets the LOD of a patch /** \param patchX Patch x coordinate. \param patchZ Patch z coordinate. \param LOD The level of detail to set the patch to. */ - virtual void setLODOfPatch( s32 patchX, s32 patchZ, s32 LOD ) = 0; + virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0) =0; //! Get center of terrain. - virtual const core::vector3df& getTerrainCenter() const = 0; + virtual const core::vector3df& getTerrainCenter() const =0; //! Get height of a point of the terrain. - virtual f32 getHeight( f32 x, f32 y ) const = 0; + virtual f32 getHeight(f32 x, f32 y) const =0; //! Sets the movement camera threshold. /** It is used to determine when to recalculate indices for the scene node. The default value is 10.0f. */ - virtual void setCameraMovementDelta(f32 delta) = 0; + virtual void setCameraMovementDelta(f32 delta) =0; //! Sets the rotation camera threshold. /** It is used to determine when to recalculate indices for the scene node. The default value is 1.0f. */ - virtual void setCameraRotationDelta(f32 delta) = 0; + virtual void setCameraRotationDelta(f32 delta) =0; //! Sets whether or not the node should dynamically update its associated selector when the geomipmap data changes. /** \param bVal: Boolean value representing whether or not to update selector dynamically. */ - virtual void setDynamicSelectorUpdate(bool bVal) = 0; + virtual void setDynamicSelectorUpdate(bool bVal) =0; //! Override the default generation of distance thresholds. /** For determining the LOD a patch is rendered at. If any LOD @@ -137,7 +132,7 @@ namespace scene then apply a scale to the scene node, it is your responsibility to update the new distances to work best with your new terrain size. */ - virtual bool overrideLODDistance(s32 LOD, f64 newDistance) = 0; + virtual bool overrideLODDistance(s32 LOD, f64 newDistance) =0; //! Scales the base texture, similar to makePlanarTextureMapping. /** \param scale The scaling amount. Values above 1.0 @@ -149,15 +144,33 @@ namespace scene second texture coordinate set to the same values as in the first set. If this is another value than zero, it will scale the second texture coordinate set by this value. */ - virtual void scaleTexture(f32 scale = 1.0f, f32 scale2 = 0.0f) = 0; + virtual void scaleTexture(f32 scale = 1.0f, f32 scale2=0.0f) =0; //! Initializes the terrain data. Loads the vertices from the heightMapFile. + /** The file must contain a loadable image of the heightmap. The heightmap + must be square. + \param file The file to read the image from. File is not rewinded. + \param vertexColor Color of all vertices. + \param smoothFactor Number of smoothing passes. */ virtual bool loadHeightMap(io::IReadFile* file, - video::SColor vertexColor = video::SColor ( 255, 255, 255, 255 ), s32 smoothFactor = 0 ) =0; + video::SColor vertexColor=video::SColor(255,255,255,255), + s32 smoothFactor=0) =0; //! Initializes the terrain data. Loads the vertices from the heightMapFile. - virtual bool loadHeightMapRAW(io::IReadFile* file, s32 bitsPerPixel = 16, - video::SColor vertexColor = video::SColor ( 255, 255, 255, 255 ), s32 smoothFactor = 0 ) =0; + /** The data is interpreted as (signed) integers of the given bit size or + floats (with 32bits, signed). Allowed bitsizes for integers are + 8, 16, and 32. The heightmap must be square. + \param file The file to read the RAW data from. File is not rewinded. + \param bitsPerPixel Size of data if integers used, for floats always use 32. + \param signedData Whether we use signed or unsigned ints, ignored for floats. + \param floatVals Whether the data is float or int. + \param width Width (and also Height, as it must be square) of the heightmap. Use 0 for autocalculating from the filesize. + \param vertexColor Color of all vertices. + \param smoothFactor Number of smoothing passes. */ + virtual bool loadHeightMapRAW(io::IReadFile* file, s32 bitsPerPixel=16, + bool signedData=false, bool floatVals=false, s32 width=0, + video::SColor vertexColor=video::SColor(255,255,255,255), + s32 smoothFactor=0) =0; }; diff --git a/include/IVideoDriver.h b/include/IVideoDriver.h index 25a71726..329a6a38 100644 --- a/include/IVideoDriver.h +++ b/include/IVideoDriver.h @@ -667,7 +667,7 @@ namespace video Specifies where fog starts. \param end Only used in linear fog mode (linearFog=true). Specifies where fog ends. - \param density Only used in expotential fog mode + \param density Only used in exponential fog mode (linearFog=false). Must be a value between 0 and 1. \param pixelFog Set this to false for vertex fog, and true if you want per-pixel fog. diff --git a/include/IXMLWriter.h b/include/IXMLWriter.h index da4acd81..1fc906d2 100644 --- a/include/IXMLWriter.h +++ b/include/IXMLWriter.h @@ -15,9 +15,8 @@ namespace io { //! Interface providing methods for making it easier to write XML files. - /** This XML Writer only writes UTF-16 xml files, because these are - parsed faster than all other formats by IXMLReader. - */ + /** This XML Writer writes xml files using in the platform dependent + wchar_t format and sets the xml-encoding correspondingly. */ class IXMLWriter : public virtual IReferenceCounted { public: diff --git a/include/IrrCompileConfig.h b/include/IrrCompileConfig.h index 5fe6b084..38a731f6 100644 --- a/include/IrrCompileConfig.h +++ b/include/IrrCompileConfig.h @@ -6,7 +6,7 @@ #define __IRR_COMPILE_CONFIG_H_INCLUDED__ //! Irrlicht SDK Version -#define IRRLICHT_SDK_VERSION "1.5.beta" +#define IRRLICHT_SDK_VERSION "1.5" #include // TODO: Although included elsewhere this is required at least for mingw diff --git a/include/SColor.h b/include/SColor.h index 605b4c9c..d10255bf 100644 --- a/include/SColor.h +++ b/include/SColor.h @@ -106,6 +106,8 @@ namespace video //! Returns the alpha component from A1R5G5B5 color + /** In Irrlicht, alpha refers to opacity. + \return The alpha value of the color. 0 is transparent, 1 is opaque. */ inline u32 getAlpha(u16 color) { return ((color >> 15)&0x1); @@ -146,6 +148,7 @@ namespace video //! Class representing a 32 bit ARGB color. /** The color values for alpha, red, green, and blue are stored in a single u32. So all four values may be between 0 and 255. + Alpha in Irrlicht is opacity, so 0 is fully transparent, 255 is fully opaque (solid). This class is used by most parts of the Irrlicht Engine to specify a color. Another way is using the class SColorf, which stores the color values in 4 floats. @@ -168,9 +171,8 @@ namespace video : color(clr) {} //! Returns the alpha component of the color. - /** The alpha component defines how transparent a color should - be. 255 means not transparent (opaque), 0 means fully - transparent. */ + /** The alpha component defines how opaque a color is. + \return The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */ u32 getAlpha() const { return color>>24; } //! Returns the red component of the color. @@ -201,10 +203,8 @@ namespace video } //! Sets the alpha component of the Color. - /** The alpha component defines how transparent a color should - be. - \param a: Has to be a value between 0 and 255. - 255 means not transparent (opaque), 0 means fully transparent. */ + /** The alpha component defines how transparent a color should be. + \param a The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */ void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); } //! Sets the red component of the Color. @@ -431,7 +431,7 @@ namespace video } } - //! Returns the alpha component of the color in the range 0.0 to 1.0 + //! Returns the alpha component of the color in the range 0.0 (transparent) to 1.0 (opaque) f32 getAlpha() const { return a; } //! Returns the red component of the color in the range 0.0 to 1.0 diff --git a/include/SSharedMeshBuffer.h b/include/SSharedMeshBuffer.h index 06aad1af..4afe711d 100644 --- a/include/SSharedMeshBuffer.h +++ b/include/SSharedMeshBuffer.h @@ -16,7 +16,7 @@ namespace scene struct SSharedMeshBuffer : public IMeshBuffer { //! constructor - SSharedMeshBuffer() : IMeshBuffer(), ChangedID_Vertex(1), ChangedID_Index(1), MappingHint(Never), Vertices(0) + SSharedMeshBuffer() : IMeshBuffer(), ChangedID_Vertex(1), ChangedID_Index(1), Vertices(0), MappingHint(EHM_NEVER) { #ifdef _DEBUG setDebugName("SSharedMeshBuffer"); @@ -141,9 +141,9 @@ namespace scene //! flags the mesh as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX) { - if (E_BUFFER_TYPE Buffer==EBT_VERTEX_AND_INDEX || E_BUFFER_TYPE Buffer==EBT_VERTEX) + if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_VERTEX) ++ChangedID_Vertex; - if (E_BUFFER_TYPE Buffer==EBT_VERTEX_AND_INDEX || E_BUFFER_TYPE Buffer==EBT_INDEX) + if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) ++ChangedID_Index; } diff --git a/include/irrMath.h b/include/irrMath.h index 50387e44..7da1c81f 100644 --- a/include/irrMath.h +++ b/include/irrMath.h @@ -158,6 +158,12 @@ namespace core return min_ (max_(value,low), high); } + //! 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_64) + { + 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_32) { diff --git a/include/irrString.h b/include/irrString.h index d6d3788a..26ea4bcb 100644 --- a/include/irrString.h +++ b/include/irrString.h @@ -826,18 +826,16 @@ public: //! trims the string. - /** Removes whitespace from begin and end of the string. */ - string& trim() + /** Removes the specified characters (by default, Latin-1 whitespace) + from the begining and the end of the string. */ + string& trim(const string & whitespace = " \t\n\r") { - const c8 whitespace[] = " \t\n\r"; - const u32 whitespacecount = 4; - - // find start and end of real string without whitespace - const s32 begin = findFirstCharNotInList(whitespace, whitespacecount); + // find start and end of the substring without the specified characters + const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used); if (begin == -1) return (*this=""); - const s32 end = findLastCharNotInList(whitespace, whitespacecount); + const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used); return (*this = subString(begin, (end +1) - begin)); } diff --git a/include/irrlicht.h b/include/irrlicht.h index 5608b6ad..96a51582 100644 --- a/include/irrlicht.h +++ b/include/irrlicht.h @@ -31,28 +31,41 @@ #include "IrrCompileConfig.h" #include "aabbox3d.h" +#include "CDynamicMeshBuffer.h" +#include "CIndexBuffer.h" +#include "CMeshBuffer.h" #include "coreutil.h" -#include "irrArray.h" -#include "irrMap.h" -#include "irrMath.h" -#include "irrString.h" -#include "irrTypes.h" -#include "SColor.h" -#include "SLight.h" +#include "CVertexBuffer.h" #include "dimension2d.h" +#include "ECullingTypes.h" +#include "EDebugSceneTypes.h" +#include "EDriverFeatures.h" #include "EDriverTypes.h" -#include "IAttributes.h" -#include "IAttributeExchangingObject.h" +#include "EGUIAlignment.h" +#include "EGUIElementTypes.h" +#include "EHardwareBufferFlags.h" +#include "EMaterialFlags.h" +#include "EMaterialTypes.h" +#include "EMeshWriterEnums.h" +#include "EMessageBoxFlags.h" +#include "ESceneNodeAnimatorTypes.h" +#include "ESceneNodeTypes.h" +#include "ETerrainElements.h" +#include "fast_atof.h" +#include "heapsort.h" #include "IAnimatedMesh.h" #include "IAnimatedMeshMD2.h" #include "IAnimatedMeshMD3.h" -#include "IQ3LevelMesh.h" #include "IAnimatedMeshSceneNode.h" +#include "IAttributeExchangingObject.h" +#include "IAttributes.h" #include "IBillboardSceneNode.h" #include "IBillboardTextSceneNode.h" #include "IBoneSceneNode.h" #include "ICameraSceneNode.h" +#include "ICursorControl.h" #include "IDummyTransformationSceneNode.h" +#include "IDynamicMeshBuffer.h" #include "IEventReceiver.h" #include "IFileList.h" #include "IFileSystem.h" @@ -83,6 +96,9 @@ #include "IGUIToolbar.h" #include "IGUIWindow.h" #include "IImage.h" +#include "IImageLoader.h" +#include "IImageWriter.h" +#include "IIndexBuffer.h" #include "ILightSceneNode.h" #include "ILogger.h" #include "IMaterialRenderer.h" @@ -90,29 +106,44 @@ #include "IMesh.h" #include "IMeshBuffer.h" #include "IMeshCache.h" -#include "IMeshSceneNode.h" +#include "IMeshLoader.h" #include "IMeshManipulator.h" +#include "IMeshSceneNode.h" #include "IMeshWriter.h" #include "IMetaTriangleSelector.h" +#include "IOSOperator.h" +#include "IParticleSystemSceneNode.h" // also includes all emitters and attractors +#include "IQ3LevelMesh.h" +#include "IQ3Shader.h" #include "IReadFile.h" +#include "IReferenceCounted.h" +#include "irrArray.h" #include "IrrlichtDevice.h" +#include "irrList.h" +#include "irrMap.h" +#include "irrMath.h" +#include "irrString.h" +#include "irrTypes.h" +#include "irrXML.h" +#include "ISceneCollisionManager.h" #include "ISceneManager.h" #include "ISceneNode.h" -#include "ISceneUserDataSerializer.h" -#include "ITriangleSelector.h" #include "ISceneNodeAnimator.h" -#include "ISceneCollisionManager.h" -#include "ISceneNodeFactory.h" -#include "ISceneNodeAnimatorFactory.h" +#include "ISceneNodeAnimatorCameraFPS.h" +#include "ISceneNodeAnimatorCameraMaya.h" #include "ISceneNodeAnimatorCollisionResponse.h" +#include "ISceneNodeAnimatorFactory.h" +#include "ISceneNodeFactory.h" +#include "ISceneUserDataSerializer.h" #include "IShaderConstantSetCallBack.h" #include "IShadowVolumeSceneNode.h" -#include "IParticleSystemSceneNode.h" // also includes all emitters and attractors #include "ISkinnedMesh.h" #include "ITerrainSceneNode.h" #include "ITextSceneNode.h" #include "ITexture.h" -#include "IReferenceCounted.h" +#include "ITimer.h" +#include "ITriangleSelector.h" +#include "IVertexBuffer.h" #include "IVideoDriver.h" #include "IVideoModeList.h" #include "IVolumeLightSceneNode.h" @@ -122,27 +153,34 @@ #include "Keycodes.h" #include "line2d.h" #include "line3d.h" -#include "irrList.h" #include "matrix4.h" #include "plane3d.h" -#include "vector2d.h" -#include "vector3d.h" -#include "triangle3d.h" #include "position2d.h" #include "quaternion.h" #include "rect.h" #include "S3DVertex.h" #include "SAnimatedMesh.h" +#include "SceneParameters.h" +#include "SColor.h" #include "SExposedVideoData.h" +#include "SIrrCreationParameters.h" #include "SKeyMap.h" +#include "SLight.h" #include "SMaterial.h" #include "SMesh.h" #include "SMeshBuffer.h" #include "SMeshBufferLightMap.h" #include "SMeshBufferTangents.h" +#include "SParticle.h" +#include "SSharedMeshBuffer.h" +#include "SSkinMeshBuffer.h" +#include "SVertexIndex.h" #include "SViewFrustum.h" +#include "triangle3d.h" +#include "vector2d.h" +#include "vector3d.h" -/*! \mainpage Irrlicht Engine 1.5.beta API documentation +/*! \mainpage Irrlicht Engine 1.5 API documentation * *
* diff --git a/include/matrix4.h b/include/matrix4.h index fb261b5c..980ed8b3 100644 --- a/include/matrix4.h +++ b/include/matrix4.h @@ -179,9 +179,6 @@ namespace core //! Transforms a plane by this matrix void transformPlane( core::plane3d &plane) const; - //! Transforms a plane by this matrix ( some problems to solve..) - void transformPlane_new( core::plane3d &plane) const; - //! Transforms a plane by this matrix void transformPlane( const core::plane3d &in, core::plane3d &out) const; @@ -712,8 +709,8 @@ namespace core } - //! Returns a rotation that is equivalent to that set by setRotationDegrees(). - /** This code was sent in by Chev. Note that it does not necessarily return + //! Returns a rotation that is equivalent to that set by setRotationDegrees(). + /** This code was sent in by Chev. Note that it does not necessarily return the *same* Euler angles as those set by setRotationDegrees(), but the rotation will be equivalent, i.e. will have the same result when used to rotate a vector or node. */ template @@ -930,31 +927,15 @@ namespace core inline void CMatrix4::transformPlane( core::plane3d &plane) const { vector3df member; + // Transform the plane member point, i.e. rotate, translate and scale it. transformVect(member, plane.getMemberPoint()); - vector3df origin(0,0,0); - transformVect(plane.Normal); - transformVect(origin); + // Transform the normal by the transposed inverse of the matrix + CMatrix4 transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED); + vector3df normal = plane.Normal; + transposedInverse.transformVect(normal); - plane.Normal -= origin; - plane.D = - member.dotProduct(plane.Normal); - } - - //! Transforms a plane by this matrix - template - inline void CMatrix4::transformPlane_new( core::plane3d &plane) const - { - // rotate normal -> rotateVect ( plane.n ); - vector3df n; - n.X = plane.Normal.X*M[0] + plane.Normal.Y*M[4] + plane.Normal.Z*M[8]; - n.Y = plane.Normal.X*M[1] + plane.Normal.Y*M[5] + plane.Normal.Z*M[9]; - n.Z = plane.Normal.X*M[2] + plane.Normal.Y*M[6] + plane.Normal.Z*M[10]; - - // compute new d. -> getTranslation(). dotproduct ( plane.n ) - plane.D -= M[12] * n.X + M[13] * n.Y + M[14] * n.Z; - plane.Normal.X = n.X; - plane.Normal.Y = n.Y; - plane.Normal.Z = n.Z; + plane.setPlane(member, normal); } //! Transforms a plane by this matrix @@ -1735,7 +1716,7 @@ namespace core //! Typedef for f32 matrix typedef CMatrix4 matrix4; //! global const identity matrix - extern const matrix4 IdentityMatrix; + IRRLICHT_API extern const matrix4 IdentityMatrix; } // end namespace core } // end namespace irr diff --git a/include/plane3d.h b/include/plane3d.h index 6a3c98ba..2c5aa608 100644 --- a/include/plane3d.h +++ b/include/plane3d.h @@ -32,15 +32,21 @@ class plane3d // Constructors plane3d(): Normal(0,1,0) { recalculateD(vector3d(0,0,0)); } + plane3d(const vector3d& MPoint, const vector3d& Normal) : Normal(Normal) { recalculateD(MPoint); } + plane3d(T px, T py, T pz, T nx, T ny, T nz) : Normal(nx, ny, nz) { recalculateD(vector3d(px, py, pz)); } + plane3d(const vector3d& point1, const vector3d& point2, const vector3d& point3) { setPlane(point1, point2, point3); } + + plane3d(const vector3d & normal, const T d) : Normal(normal), D(d) { } // operators - inline bool operator==(const plane3d& other) const { return (D==other.D && Normal==other.Normal);} - inline bool operator!=(const plane3d& other) const { return !(D==other.D && Normal==other.Normal);} + inline bool operator==(const plane3d& other) const { return (equals(D, other.D) && Normal==other.Normal);} + + inline bool operator!=(const plane3d& other) const { return !(*this == other);} // functions diff --git a/include/vector2d.h b/include/vector2d.h index e78e3ec6..9f55626a 100644 --- a/include/vector2d.h +++ b/include/vector2d.h @@ -59,8 +59,8 @@ public: bool operator<(const vector2d&other) const { return X(const vector2d&other) const { return X>other.X && Y>other.Y; } - bool operator==(const vector2d& other) const { return other.X==X && other.Y==Y; } - bool operator!=(const vector2d& other) const { return other.X!=X || other.Y!=Y; } + bool operator==(const vector2d& other) const { return equals(other); } + bool operator!=(const vector2d& other) const { return !equals(other); } // functions @@ -111,20 +111,20 @@ public: return vector2d(X - other.X, Y - other.Y).getLengthSQ(); } - //! rotates the point around a center by an amount of degrees. - /** \param degrees Amount of degrees to rotate by. + //! rotates the point anticlockwise around a center by an amount of degrees. + /** \param degrees Amount of degrees to rotate by, anticlockwise. \param center Rotation center. \return This vector after transformation. */ - vector2d& rotateBy(f64 degrees, const vector2d& center) + vector2d& rotateBy(f64 degrees, const vector2d& center=vector2d()) { degrees *= DEGTORAD64; - const T cs = (T)cos(degrees); - const T sn = (T)sin(degrees); + const f64 cs = cos(degrees); + const f64 sn = sin(degrees); X -= center.X; Y -= center.Y; - set(X*cs - Y*sn, X*sn + Y*cs); + set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs)); X += center.X; Y += center.Y; @@ -136,12 +136,12 @@ public: \return Reference to this vector, after normalization. */ vector2d& normalize() { - T l = X*X + Y*Y; - if (l == 0) + f32 length = (f32)(X*X + Y*Y); + if (core::equals(length, 0.f)) return *this; - l = core::reciprocal_squareroot ( (f32)l ); - X *= l; - Y *= l; + length = core::reciprocal_squareroot ( length ); + X = (T)(X * length); + Y = (T)(Y * length); return *this; } @@ -233,41 +233,45 @@ public: } } - //! Get the interpolated vector - /** \param other Other vector to interpolate with. - \param d Value between 0.0f and 1.0f. - \return Interpolated vector. */ - vector2d getInterpolated(const vector2d& other, f32 d) const + //! Creates an interpolated vector between this vector and another vector. + /** \param other The other vector to interpolate with. + \param d Interpolation value between 0.0f (all the other vector) and 1.0f (all this vector). + Note that this is the opposite direction of interpolation to getInterpolated_quadratic() + \return An interpolated vector. This vector is not modified. */ + vector2d getInterpolated(const vector2d& other, f64 d) const { - T inv = (T) 1.0 - d; - return vector2d(other.X*inv + X*d, other.Y*inv + Y*d); + f64 inv = 1.0f - d; + return vector2d((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d)); } - //! Returns (quadratically) interpolated vector between this and the two given ones. - /** \param v2 Second vector to interpolate with - \param v3 Third vector to interpolate with - \param d Value between 0.0f and 1.0f. - \return Interpolated vector. */ - vector2d getInterpolated_quadratic(const vector2d& v2, const vector2d& v3, const T d) const + //! Creates a quadratically interpolated vector between this and two other vectors. + /** \param v2 Second vector to interpolate with. + \param v3 Third vector to interpolate with (maximum at 1.0f) + \param d Interpolation value between 0.0f (all this vector) and 1.0f (all the 3rd vector). + Note that this is the opposite direction of interpolation to getInterpolated() and interpolate() + \return An interpolated vector. This vector is not modified. */ + vector2d getInterpolated_quadratic(const vector2d& v2, const vector2d& v3, f64 d) const { // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d; - const T inv = (T) 1.0 - d; - const T mul0 = inv * inv; - const T mul1 = (T) 2.0 * d * inv; - const T mul2 = d * d; + const f64 inv = 1.0f - d; + const f64 mul0 = inv * inv; + const f64 mul1 = 2.0f * d * inv; + const f64 mul2 = d * d; - return vector2d ( X * mul0 + v2.X * mul1 + v3.X * mul2, - Y * mul0 + v2.Y * mul1 + v3.Y * mul2); + return vector2d ( (T)(X * mul0 + v2.X * mul1 + v3.X * mul2), + (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2)); } //! Sets this vector to the linearly interpolated vector between a and b. - /** \param a first vector to interpolate with - \param b second vector to interpolate with - \param t value between 0.0f and 1.0f. */ - vector2d& interpolate(const vector2d& a, const vector2d& b, const f32 t) + /** \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& interpolate(const vector2d& a, const vector2d& b, f64 d) { - X = b.X + ( ( a.X - b.X ) * t ); - Y = b.Y + ( ( a.Y - b.Y ) * t ); + X = (T)((f64)b.X + ( ( a.X - b.X ) * d )); + Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d )); return *this; } diff --git a/include/vector3d.h b/include/vector3d.h index 27996f06..1cc026ce 100644 --- a/include/vector3d.h +++ b/include/vector3d.h @@ -13,6 +13,11 @@ namespace core { //! 3d vector template class with lots of operators and methods. + /** The vector3d class is used in Irrlicht for three main purposes: + 1) As a direction vector (most of the methods assume this). + 2) As a position in 3d space (which is synonymous with a direction vector from the origin to this position). + 3) To hold three Euler rotations, where X is pitch, Y is yaw and Z is roll. + */ template class vector3d { @@ -132,17 +137,16 @@ namespace core //! Normalizes the vector. /** In case of the 0 vector the result is still 0, otherwise the length of the vector will be 1. - TODO: 64 Bit template doesnt work.. need specialized template \return Reference to this vector after normalization. */ vector3d& normalize() { - T l = X*X + Y*Y + Z*Z; - if (l == 0) + f32 length = (f32)(X*X + Y*Y + Z*Z); + if (core::equals(length, 0.f)) return *this; - l = (T) reciprocal_squareroot ( (f32)l ); - X *= l; - Y *= l; - Z *= l; + length = core::reciprocal_squareroot ( (f32)length ); + X = (T)(X * length); + Y = (T)(Y * length); + Z = (T)(Z * length); return *this; } @@ -168,11 +172,11 @@ namespace core void rotateXZBy(f64 degrees, const vector3d& center=vector3d()) { degrees *= DEGTORAD64; - T cs = (T)cos(degrees); - T sn = (T)sin(degrees); + f64 cs = cos(degrees); + f64 sn = sin(degrees); X -= center.X; Z -= center.Z; - set(X*cs - Z*sn, Y, X*sn + Z*cs); + set((T)(X*cs - Z*sn), Y, (T)(X*sn + Z*cs)); X += center.X; Z += center.Z; } @@ -183,11 +187,11 @@ namespace core void rotateXYBy(f64 degrees, const vector3d& center=vector3d()) { degrees *= DEGTORAD64; - T cs = (T)cos(degrees); - T sn = (T)sin(degrees); + f64 cs = cos(degrees); + f64 sn = sin(degrees); X -= center.X; Y -= center.Y; - set(X*cs - Y*sn, X*sn + Y*cs, Z); + set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs), Z); X += center.X; Y += center.Y; } @@ -198,45 +202,74 @@ namespace core void rotateYZBy(f64 degrees, const vector3d& center=vector3d()) { degrees *= DEGTORAD64; - T cs = (T)cos(degrees); - T sn = (T)sin(degrees); + f64 cs = cos(degrees); + f64 sn = sin(degrees); Z -= center.Z; Y -= center.Y; - set(X, Y*cs - Z*sn, Y*sn + Z*cs); + set(X, (T)(Y*cs - Z*sn), (T)(Y*sn + Z*cs)); Z += center.Z; Y += center.Y; } - //! Returns interpolated vector. - /** \param other Other vector to interpolate between - \param d Value between 0.0f and 1.0f. */ - vector3d getInterpolated(const vector3d& other, const T d) const + //! Creates an interpolated vector between this vector and another vector. + /** \param other The other vector to interpolate with. + \param d Interpolation value between 0.0f (all the other vector) and 1.0f (all this vector). + Note that this is the opposite direction of interpolation to getInterpolated_quadratic() + \return An interpolated vector. This vector is not modified. */ + vector3d getInterpolated(const vector3d& other, f64 d) const { - const T inv = (T) 1.0 - d; - return vector3d(other.X*inv + X*d, other.Y*inv + Y*d, other.Z*inv + Z*d); + const f64 inv = 1.0 - d; + return vector3d((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d), (T)(other.Z*inv + Z*d)); } - //! Returns interpolated vector. ( quadratic ) - /** \param v2 Second vector to interpolate with - \param v3 Third vector to interpolate with - \param d Value between 0.0f and 1.0f. */ - vector3d getInterpolated_quadratic(const vector3d& v2, const vector3d& v3, const T d) const + //! Creates a quadratically interpolated vector between this and two other vectors. + /** \param v2 Second vector to interpolate with. + \param v3 Third vector to interpolate with (maximum at 1.0f) + \param d Interpolation value between 0.0f (all this vector) and 1.0f (all the 3rd vector). + Note that this is the opposite direction of interpolation to getInterpolated() and interpolate() + \return An interpolated vector. This vector is not modified. */ + vector3d getInterpolated_quadratic(const vector3d& v2, const vector3d& v3, f64 d) const { // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d; - const T inv = (T) 1.0 - d; - const T mul0 = inv * inv; - const T mul1 = (T) 2.0 * d * inv; - const T mul2 = d * d; + const f64 inv = (T) 1.0 - d; + const f64 mul0 = inv * inv; + const f64 mul1 = (T) 2.0 * d * inv; + const f64 mul2 = d * d; - return vector3d ( X * mul0 + v2.X * mul1 + v3.X * mul2, - Y * mul0 + v2.Y * mul1 + v3.Y * mul2, - Z * mul0 + v2.Z * mul1 + v3.Z * mul2); + return vector3d ((T)(X * mul0 + v2.X * mul1 + v3.X * mul2), + (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2), + (T)(Z * mul0 + v2.Z * mul1 + v3.Z * mul2)); } - //! Gets the Y and Z rotations of a vector. - /** Thanks to Arras on the Irrlicht forums for this method. - \return A vector representing the rotation in degrees of - this vector. The Z component of the vector will always be 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() + */ + vector3d& interpolate(const vector3d& a, const vector3d& b, f64 d) + { + X = (T)((f64)b.X + ( ( a.X - b.X ) * d )); + Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d )); + Z = (T)((f64)b.Z + ( ( a.Z - b.Z ) * d )); + return *this; + } + + + //! Get the rotations that would make a (0,0,1) direction vector point in the same direction as this direction vector. + /** Thanks to Arras on the Irrlicht forums for this method. This utility method is very useful for + orienting scene nodes towards specific targets. For example, if this vector represents the difference + between two scene nodes, then applying the result of getHorizontalAngle() to one scene node will point + it at the other one. + Example code: + // Where target and seeker are of type ISceneNode* + const vector3df toTarget(target->getAbsolutePosition() - seeker->getAbsolutePosition()); + const vector3df requiredRotation = toTarget.getHorizontalAngle(); + seeker->setRotation(requiredRotation); + + \return A rotation vector containing the X (pitch) and Y (raw) rotations (in degrees) that when applied to a + +Z (e.g. 0, 0, 1) direction vector would make it point in the same direction as this vector. The Z (roll) rotation + is always 0, since two Euler rotations are sufficient to point in any given direction. */ vector3d getHorizontalAngle() const { vector3d angle; @@ -261,15 +294,13 @@ namespace core } //! Builds a direction vector from (this) rotation vector. - /** This vector is assumed to hold 3 Euler angle rotations, in degrees. - The implementation performs the same calculations as using a matrix to - do the rotation. - \param[in] forwards The direction representing "forwards" which will be - rotated by this vector. If you do not provide a - direction, then the positive Z axis (0, 0, 1) will - be assumed to be fowards. - \return A vector calculated by rotating the forwards direction by - the 3 Euler angles that this vector is assumed to represent. */ + /** This vector is assumed to be a rotation vector composed of 3 Euler angle rotations, in degrees. + The implementation performs the same calculations as using a matrix to do the rotation. + + \param[in] forwards The direction representing "forwards" which will be rotated by this vector. + If you do not provide a direction, then the +Z axis (0, 0, 1) will be assumed to be forwards. + \return A direction vector calculated by rotating the forwards direction by the 3 Euler angles + (in degrees) represented by this vector. */ vector3d rotationToDirection(const vector3d & forwards = vector3d(0, 0, 1)) const { const f64 cr = cos( core::DEGTORAD64 * X ); diff --git a/media/ninja animation ranges.txt b/media/ninja animation ranges.txt new file mode 100644 index 00000000..ea09f50c --- /dev/null +++ b/media/ninja animation ranges.txt @@ -0,0 +1,34 @@ +hey guys heres all the ranges for the ninja model, 20 ranges and 300 frames....Phew!! + +you may need to scale or rotate the model and change animation speeds for various 3D game engines... + +Please check the numbers carefully cus they dont follow any order and in between ranges often skip a few frames, this as how I achieved certain moves in Character FX its not a mistake :) + +1-14 Walk (normal) +15-30 Stealth Walk +32-44 Punch and swipe sword +45-59 Swipe and spin sword +60-68 Overhead twohanded downswipe +69-72 Up to block position (play backwards to lower sword if you want) +73-83 Forward kick +84-93 Pick up from floor (or down to crouch at frame 87) +94-102 Jump +103-111 Jump without height (for programmer controlled jumps) +112-125 High jump to Sword Kill (Finish em off move??) +126-133 Side Kick +134-145 Spinning Sword attack (might wanna speed this up in game) +146-158 Backflip +159-165 Climb wall +166-173 Death 1 - Fall back onto ground +174-182 Death 2 - Fall forward onto ground +184-205 Idle 1 - Breathe heavily +206-250 Idle 2 +251-300 Idle 3 + +Ok there it is, have fun and maybe drop by my forums hang out, ask questions, post your own work etc + +Feel free to use however you like, commercial etc, credits are Appreciated as a LOT of work went into this! ;-) + +Psionic + +http://www.psionic3d.co.uk diff --git a/media/ninja.b3d b/media/ninja.b3d new file mode 100644 index 00000000..fbc78724 Binary files /dev/null and b/media/ninja.b3d differ diff --git a/media/nskinbl.jpg b/media/nskinbl.jpg new file mode 100644 index 00000000..b701adb9 Binary files /dev/null and b/media/nskinbl.jpg differ diff --git a/media/nskinrd.jpg b/media/nskinrd.jpg new file mode 100644 index 00000000..458dbfcd Binary files /dev/null and b/media/nskinrd.jpg differ diff --git a/readme.txt b/readme.txt index 1c85aa68..141c308b 100644 --- a/readme.txt +++ b/readme.txt @@ -1,5 +1,5 @@ ========================================================================== -The Irrlicht Engine SDK version 1.4.2 +The Irrlicht Engine SDK version 1.5 ========================================================================== Welcome the Irrlicht Engine SDK. @@ -21,9 +21,9 @@ The Irrlicht Engine SDK version 1.4.2 You will find some directories after uncompressing the archive of the SDK. These are: - - \bin The compiled library Irrlicht.DLL and some compiled demo - and example applications, just start them to see the + + \bin The compiled library Irrlicht.DLL and some compiled demo + and example applications, just start them to see the Irrlicht Engine in action. Windows only. \doc Documentation of the Irrlicht Engine. \examples Examples and tutorials showing how to use the engine with @@ -39,7 +39,7 @@ The Irrlicht Engine SDK version 1.4.2 \source The source code of the Irrlicht Engine. This code is not needed to develop applications with the engine, but it is included to enable recompilation and - debugging, if necessary. + debugging, if necessary. \tools Useful tools (with sourcecode) for the engine. @@ -52,8 +52,8 @@ The Irrlicht Engine SDK version 1.4.2 directory, and start some applications. There should also be an application named Demo.exe which should show the most interesting features of Irrlicht. - - To start developing own applications and games with the engine take + + To start developing own applications and games with the engine take a look at the 01.HelloWorld example in the \examples directory. There is also a .html file with a tutorial which should be easily comprehensible. @@ -64,7 +64,7 @@ The Irrlicht Engine SDK version 1.4.2 subfolder source/Irrlicht. After this you should be able to 'make' all example applications in /examples. You can run the examples directly from the directory they are created in. - + It is also possible to use Irrlicht as shared object (libIrrlicht.so.versionNumber). Use the proper makefile target for this by running 'make sharedlib' in the source folder. See the Makefile for details. @@ -91,32 +91,32 @@ The Irrlicht Engine SDK version 1.4.2 If you ever want to (re)compile the engine yourself (which means you don't want to use the precompiled version) you need the following: - + * Windows: - * Needed: PlatformSDK (which usually comes with all IDEs, download + * Needed: PlatformSDK (which usually comes with all IDEs, download it separately for MSVC Express 2005) - * Optional: DirectX SDK, for D3D9 support - * Optional: DirectX SDK prior to May 2006, for D3D8 support - + * Optional: DirectX SDK, for D3D9 support + * Optional: DirectX SDK prior to May 2006, for D3D8 support + * Linux: - * Needed: XServer with include files - * Optional: OpenGL headers and libraries (libGL.so), for OpenGL support - * GLX + XF86VidMode or XRandr extension (X11 support libraries, - the latter two for fullscreen mode) + * Needed: XServer with include files + * Optional: OpenGL headers and libraries (libGL.so), for OpenGL support + * GLX + XF86VidMode or XRandr extension (X11 support libraries, + the latter two for fullscreen mode) * OSX: - * Needed: XCode and Cocoa framework + * Needed: XCode and Cocoa framework * Needed: OpenGL headers and libraries ========================================================================== 4. Release Notes ========================================================================== - Informations about changes in this new version of the engine can be + Informations about changes in this new version of the engine can be found in changes.txt. Please note that the textures, 3D models and levels are copyright - by their authors and not covered by the Irrlicht engine license. + by their authors and not covered by the Irrlicht engine license. ========================================================================== 5. License @@ -127,9 +127,9 @@ The Irrlicht Engine SDK version 1.4.2 using the Irrlicht Engine in your product, an acknowledgement would be highly appreciated. - Please note that the Irrlicht Engine is based in part on the work of + Please note that the Irrlicht Engine is based in part on the work of the Independent JPEG Group, the zlib, and libpng. This means that if you use - the Irrlicht Engine in your product, you must acknowledge somewhere + the Irrlicht Engine in your product, you must acknowledge somewhere in your documentation that you've used the IJG code and libpng. It would also be nice to mention that you use the Irrlicht Engine and the zlib. See the README files in the jpeglib and the zlib for @@ -139,7 +139,7 @@ The Irrlicht Engine SDK version 1.4.2 The Irrlicht Engine License =========================== - Copyright (C) 2002-2007 Nikolaus Gebhardt + Copyright (C) 2002-2008 Nikolaus Gebhardt This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -156,21 +156,20 @@ The Irrlicht Engine SDK version 1.4.2 2. Altered source versions must be clearly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. - - + ========================================================================== 6. Contact ========================================================================== - If you have problems, questions or suggestions, please visit the + If you have problems, questions or suggestions, please visit the official homepage of the Irrlicht Engine: - + http://irrlicht.sourceforge.net - + You will find forums, bugtrackers, patches, tutorials, and other stuff which will help you out. - + If want to contact the team of the engine, please send an email to Nikolaus Gebhardt: @@ -180,56 +179,60 @@ The Irrlicht Engine SDK version 1.4.2 by other people. Especially: (There are probably more people, sorry if I forgot one. See http://irrlicht.sourceforge.net/author.html for more informations) - Christian Stehno Contribution Coordinator/Developer - Gareth Davidson - Bitplane; Developer/ Forum admin - Thomas Alten wrote the apfelbaum software rasterizer + Christian Stehno (hybrid) Contribution Coordinator/Developer + Gareth Davidson (bitplane) Developer/ Forum admin + Thomas Alten (burningwater) Wrote the burningsvideo software rasterizer + Luke P. Hoschke (luke) Wrote the b3d loader, the new animation system, VBOs and other things + Colin MacDonald (rogerborg) + Dean Wadsworth (varmint) OSX port maintainer and game developer + Alvaro F. Celis (afecelis) Lots of work in the community, for example video tutorials about Irrlicht, forum admin + John Goewert (Saigumi) Wrote some tutorials for the Irrlicht Engine and doing admin stuff + Jam Takes care of moderating the forums and keeps them clean from those evil spammers. + Etienne Petitjean wrote the MacPort of the engine - Greg Roelofs Created the zlib and libpng - The Independent JPEG Group Created JPEG lib - Guy Eric Schalnat, Andreas Dilger, Glenn Randers-Pehrson and others Created libPng - Chad Austin, Jacky Chong, Theo Reed, Ben Scott Made Audiere - Mark Jeacocke Wrote lots of helpful comments and ideas in the forums and per email. - Julio Gorgé Created the 'Unofficial DirectX 9.0 Driver for the Irrlicht Engine' - Andy Spurgeon Wrote the Dev-Cpp tutorial. - André Simon Wrote the Codewarrior tutorial. - KnightToFlight Created the unoffical terrain renderer addon for the Irrlicht Engine. - Jon Pry Wrote the code to load compressed TGA files. - Saigumi Wrote some tutorials for the Irrlicht Engine and doing admin stuff - Matthew Couch Wrote the tokamak integration tutorial. - Max Winkel Wrote the splitscreen tutorial. - Gorgon Zola Wrote the ODE integration tutorial. - Dean P. Macri Sent in code for curved surfaces and PCX Loading. - Sirshane Made several bug fixes, sent in code for making the mouse cursor invisible in Linux. - Matthias Gall Sent in code for a spline scene node animator and reported lots of bugs. - Mario Gruber Suggested triangle fan drawing and sent in code for this. - Ariaci Spotted out a bug in the ATI driver. - Dr Andros C Bragianos Improved texture mapping in test scene node. - Philipp Dortmann Sent in code for stencil buffer support for OpenGL. - Jerome Nichols Created the Irrlicht/Ruby interface located at irr.rubyforge.org - Vash TheStampede Sent code for missing Draw2DLine() implementation s - MattyBoy XBOX support suggestions - Oliver Klems createImageFromData() method suggestion/implementation - Jox really, really a lot of bug fixes, and the LMTS file loader - Zola Quaternion method additions - Tomasz Nowakowski various bug fixes - Nicholas Bray stencil shadow bug fixes with OpenGL - REAPER mouswheel events for scrollbar - Calimero various bug fixes like vector2d operators - Haddock bugfix in the linked list - G.o.D XML parser fix - Alvaro F. Celis Lots of work in the community, for example video tutorials about Irrlicht, forum admin - Erik Zilli Translated some of the tutorials from my stuttering english into real english. :) - Martin Piskernig Linux bugfixing and testing - Soconne Wrote the original terrain renderer were Irrlichts terrain renderer of Irrlicht is based on it. - Spintz GeoMipMap scene node, terrain renderer of Irrlicht is based on it. - Murphy McCauley OCT file loader, MIM tools - Saurav Mohapatra IrrCSM, and lots of addons, suggestions and bug reports - Zhuck Dimitry My3D Tools - Terry Welsh Allowed me to use the textures of his 'Parallax Mapping with Offset Limiting' paper for the parallax demo of Irrlicht - rt Wrote the original .png loader for Irrlicht - Salvatore Russo Wrote the original .dmf loader for Irrlicht - Vox Various bug reports and fixes - atomice Contributed code for a ms3d loader enhancement - William Finlayson OpenGL RTT, GLSL support and the reflection 2 layer material for OpenGL. - Delight Various code contributions for Irrlicht.NET (particle system, basic shader support and more) + Mark Jeacocke Wrote lots of helpful comments and ideas in the forums and per email. + Julio Gorgé Created the 'Unofficial DirectX 9.0 Driver for the Irrlicht Engine' + Andy Spurgeon Wrote the Dev-Cpp tutorial. + André Simon Wrote the Codewarrior tutorial. + KnightToFlight Created the unoffical terrain renderer addon for the Irrlicht Engine. + Jon Pry Wrote the code to load compressed TGA files. + Matthew Couch Wrote the tokamak integration tutorial. + Max Winkel Wrote the splitscreen tutorial. + Gorgon Zola Wrote the ODE integration tutorial. + Dean P. Macri Sent in code for curved surfaces and PCX Loading. + Sirshane Made several bug fixes, sent in code for making the mouse cursor invisible in Linux. + Matthias Gall Sent in code for a spline scene node animator and reported lots of bugs. + Mario Gruber Suggested triangle fan drawing and sent in code for this. + Ariaci Spotted out a bug in the ATI driver. + Dr Andros C Bragianos Improved texture mapping in cube scene node. + Philipp Dortmann Sent in code for stencil buffer support for OpenGL. + Jerome Nichols Created the Irrlicht/Ruby interface located at irr.rubyforge.org + Vash TheStampede Sent code for missing Draw2DLine() implementations + MattyBoy XBOX support suggestions + Oliver Klems createImageFromData() method suggestion/implementation + Jox really, really a lot of bug fixes, and the LMTS file loader + Zola Quaternion method additions + Tomasz Nowakowski various bug fixes + Nicholas Bray stencil shadow bug fixes with OpenGL + REAPER mouswheel events for scrollbar + Calimero various bug fixes like vector2d operators + Haddock bugfix in the linked list + G.o.D XML parser fix + Erik Zilli Translated some of the tutorials from my stuttering english into real english. :) + Martin Piskernig Linux bugfixing and testing + Soconne Wrote the original terrain renderer were Irrlichts terrain renderer of Irrlicht is based on it. + Spintz GeoMipMap scene node, terrain renderer of Irrlicht is based on it. + Murphy McCauley OCT file loader, MIM tools + Saurav Mohapatra IrrCSM, and lots of addons, suggestions and bug reports + Zhuck Dimitry My3D Tools + Terry Welsh Allowed me to use the textures of his 'Parallax Mapping with Offset Limiting' paper for the parallax demo of Irrlicht + rt Wrote the original .png loader for Irrlicht + Salvatore Russo Wrote the original .dmf loader for Irrlicht + Vox Various bug reports and fixes + atomice Contributed code for a ms3d loader enhancement + William Finlayson OpenGL RTT, GLSL support and the reflection 2 layer material for OpenGL. + Delight Various code contributions for Irrlicht.NET (particle system, basic shader support and more) Michael Zoech Improved GLSL support + Greg Roelofs Created the zlib and libpng + Guy Eric Schalnat, Andreas Dilger, Glenn Randers-Pehrson and others Created libpng + The Independent JPEG Group Created JPEG lib diff --git a/source/Irrlicht/CAnimatedMeshSceneNode.cpp b/source/Irrlicht/CAnimatedMeshSceneNode.cpp index 4cf52f1c..a818a554 100644 --- a/source/Irrlicht/CAnimatedMeshSceneNode.cpp +++ b/source/Irrlicht/CAnimatedMeshSceneNode.cpp @@ -201,29 +201,24 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode() } } -IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(bool forceRecalcOfControlJoints) +IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(void) { if(Mesh->getMeshType() != EAMT_SKINNED) { - if(!MeshForCurrentFrame || core::equals(CurrentFrameNr, FrameWhenCurrentMeshWasGenerated)) + if(!MeshForCurrentFrame || !core::equals(CurrentFrameNr, FrameWhenCurrentMeshWasGenerated)) MeshForCurrentFrame = Mesh->getMesh((s32)getFrameNr(), 255, StartFrame, EndFrame); } else { + // As multiple scene nodes may be sharing the same skinned mesh, we have to + // re-animated it every frame to ensure that this node gets the mesh that it needs. + CSkinnedMesh* skinnedMesh = reinterpret_cast(Mesh); - if (JointMode == EJUOR_CONTROL && forceRecalcOfControlJoints)//write to mesh - { + if (JointMode == EJUOR_CONTROL)//write to mesh skinnedMesh->transferJointsToMesh(JointChildSceneNodes); - } else - { - // Return the mesh for the current frame if it hasn't changed, otherwise update it. - if(MeshForCurrentFrame && core::equals(CurrentFrameNr, FrameWhenCurrentMeshWasGenerated)) - return MeshForCurrentFrame; - else - skinnedMesh->animateMesh(getFrameNr(), 1.0f); - } + skinnedMesh->animateMesh(getFrameNr(), 1.0f); // Update the skinned mesh for the current joint transforms. skinnedMesh->skinMesh(); @@ -239,9 +234,10 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(bool forceRecalcOfControl JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option } } - else + + if(JointMode == EJUOR_CONTROL) { - // For EJUOR_READ meshes, this is done by calling animateMesh() + // For meshes other than EJUOR_CONTROL, this is done by calling animateMesh() skinnedMesh->updateBoundingBox(); } @@ -256,15 +252,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(bool forceRecalcOfControl //! OnAnimate() is called just before rendering the whole scene. void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs) { - CurrentFrameNr = buildFrameNr ( timeMs ); - - if ( Mesh ) - { - scene::IMesh * mesh = getMeshForCurrentFrame(true); - - if ( mesh ) - Box = mesh->getBoundingBox(); - } + CurrentFrameNr = buildFrameNr ( timeMs ); IAnimatedMeshSceneNode::OnAnimate ( timeMs ); } @@ -284,9 +272,13 @@ void CAnimatedMeshSceneNode::render() ++PassCount; - scene::IMesh* m = getMeshForCurrentFrame(false); + scene::IMesh* m = getMeshForCurrentFrame(); - if ( 0 == m ) + if(m) + { + Box = m->getBoundingBox(); + } + else { #ifdef _DEBUG os::Printer::log("Animated Mesh returned no mesh to render.", Mesh->getDebugName(), ELL_WARNING); @@ -830,6 +822,9 @@ void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh) Mesh = mesh; + // Forget about the stored frame of any existing mesh. + MeshForCurrentFrame = 0; + // get materials and bounding box Box = Mesh->getBoundingBox(); diff --git a/source/Irrlicht/CAnimatedMeshSceneNode.h b/source/Irrlicht/CAnimatedMeshSceneNode.h index f2cbefcf..efb67f7e 100644 --- a/source/Irrlicht/CAnimatedMeshSceneNode.h +++ b/source/Irrlicht/CAnimatedMeshSceneNode.h @@ -162,10 +162,7 @@ namespace scene private: //! Get a static mesh for the current frame of this animated mesh - /** \param forceRecalcOfControlJoints If the mesh is a skinned mesh with controlled joints, force - a recalculation even if the frame number hasn't changed. Otherwise return the cached mesh for the - current frame if it exists. */ - IMesh* getMeshForCurrentFrame(bool forceRecalcOfControlJoints); + IMesh* getMeshForCurrentFrame(void); f32 buildFrameNr( u32 timeMs); void checkJoints(); diff --git a/source/Irrlicht/CCameraSceneNode.cpp b/source/Irrlicht/CCameraSceneNode.cpp index 6f9abeeb..93545b8f 100644 --- a/source/Irrlicht/CCameraSceneNode.cpp +++ b/source/Irrlicht/CCameraSceneNode.cpp @@ -230,13 +230,13 @@ void CCameraSceneNode::OnRegisterSceneNode() f32 dp = tgtv.dotProduct(up); - if ( core::equals ( fabs ( dp ), 1.f ) ) + if ( core::equals(fabsf(dp), 1.f) ) { up.X += 0.5f; } - ViewArea.Matrices [ video::ETS_VIEW ].buildCameraLookAtMatrixLH(pos, Target, up); - ViewArea.setTransformState ( video::ETS_VIEW ); + ViewArea.Matrices[video::ETS_VIEW].buildCameraLookAtMatrixLH(pos, Target, up); + ViewArea.setTransformState(video::ETS_VIEW); recalculateViewArea(); if ( SceneManager->getActiveCamera () == this ) @@ -275,7 +275,7 @@ const SViewFrustum* CCameraSceneNode::getViewFrustum() const void CCameraSceneNode::recalculateViewArea() { ViewArea.cameraPosition = getAbsolutePosition(); - ViewArea.setFrom ( ViewArea.Matrices [ SViewFrustum::ETS_VIEW_PROJECTION_3 ] ); + ViewArea.setFrom(ViewArea.Matrices[SViewFrustum::ETS_VIEW_PROJECTION_3]); } @@ -318,6 +318,7 @@ void CCameraSceneNode::bindTargetAndRotation(bool bound) TargetAndRotationAreBound = bound; } + //! Gets the binding between the camera's rotation and target. bool CCameraSceneNode::getTargetAndRotationBinding(void) const { diff --git a/source/Irrlicht/CD3D9Texture.cpp b/source/Irrlicht/CD3D9Texture.cpp index 8aba2ea5..dea1753d 100644 --- a/source/Irrlicht/CD3D9Texture.cpp +++ b/source/Irrlicht/CD3D9Texture.cpp @@ -365,7 +365,7 @@ bool CD3D9Texture::copyTexture(IImage * image) HRESULT hr = Texture->LockRect(0, &rect, 0, 0); if (FAILED(hr)) { - os::Printer::log("Could not lock D3D9 Texture.", ELL_ERROR); + os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR); return false; } @@ -375,7 +375,7 @@ bool CD3D9Texture::copyTexture(IImage * image) hr = Texture->UnlockRect(0); if (FAILED(hr)) { - os::Printer::log("Could not unlock D3D9 Texture.", ELL_ERROR); + os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR); return false; } } @@ -395,6 +395,13 @@ void* CD3D9Texture::lock(bool readOnly) if(!IsRenderTarget) { hr = Texture->LockRect(0, &rect, 0, readOnly?D3DLOCK_READONLY:0); + if (FAILED(hr)) + { + os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); + return 0; + } + + return rect.pBits; } else { @@ -405,7 +412,7 @@ void* CD3D9Texture::lock(bool readOnly) hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0); if (FAILED(hr)) { - os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D9 Texture", "Offscreen surface creation failed.", ELL_ERROR); return 0; } } @@ -414,31 +421,24 @@ void* CD3D9Texture::lock(bool readOnly) hr = Texture->GetSurfaceLevel(0, &surface); if (FAILED(hr)) { - os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR); return 0; } hr = Device->GetRenderTargetData(surface, RTTSurface); surface->Release(); if(FAILED(hr)) { - os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR); return 0; } hr = RTTSurface->LockRect(&rect, 0, readOnly?D3DLOCK_READONLY:0); if(FAILED(hr)) { - os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR); return 0; } return rect.pBits; } - if (FAILED(hr)) - { - os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); - return 0; - } - - return rect.pBits; } diff --git a/source/Irrlicht/CGUIContextMenu.cpp b/source/Irrlicht/CGUIContextMenu.cpp index 238bf005..fc7e59cc 100644 --- a/source/Irrlicht/CGUIContextMenu.cpp +++ b/source/Irrlicht/CGUIContextMenu.cpp @@ -378,7 +378,7 @@ bool CGUIContextMenu::highlight(const core::position2d& p, bool canOpenSubM for (s32 j=0; j<(s32)Items.size(); ++j) if (Items[j].SubMenu) { - if ( j == i && canOpenSubMenu ) + if ( j == i && canOpenSubMenu && Items[j].Enabled ) Items[j].SubMenu->setVisible(true); else if ( j != i ) Items[j].SubMenu->setVisible(false); diff --git a/source/Irrlicht/CGUIFont.cpp b/source/Irrlicht/CGUIFont.cpp index 347172e5..d07da50d 100644 --- a/source/Irrlicht/CGUIFont.cpp +++ b/source/Irrlicht/CGUIFont.cpp @@ -582,7 +582,6 @@ void CGUIFont::draw(const wchar_t* text, const core::rect& position, video: core::dimension2d textDimension; core::position2d offset = position.UpperLeftCorner; - core::rect pos; if (hcenter || vcenter || clip) textDimension = getDimension(text); diff --git a/source/Irrlicht/CImage.cpp b/source/Irrlicht/CImage.cpp index cdcd0efc..13233e55 100644 --- a/source/Irrlicht/CImage.cpp +++ b/source/Irrlicht/CImage.cpp @@ -517,6 +517,28 @@ static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job ) } } +static void executeBlit_TextureCopy_16_to_24( const SBlitJob * job ) +{ + const u16 *src = (u16*) job->src; + u8 *dst = (u8*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + u32 colour = video::A1R5G5B5toA8R8G8B8( src[dx] ); + u8 * writeTo = &dst[dx * 3]; + *writeTo++ = (colour >> 16)& 0xFF; + *writeTo++ = (colour >> 8) & 0xFF; + *writeTo++ = colour & 0xFF; + } + + src = (u16*) ( (u8*) (src) + job->srcPitch ); + dst += job->dstPitch; + } +} + + /*! */ static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job ) @@ -539,6 +561,27 @@ static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job ) } } +static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job ) +{ + const u32 * src = (u32*) job->src; + u8 * dst = (u8*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + u8 * writeTo = &dst[dx * 3]; + *writeTo++ = (src[dx] >> 16)& 0xFF; + *writeTo++ = (src[dx] >> 8) & 0xFF; + *writeTo++ = src[dx] & 0xFF; + } + + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst += job->dstPitch ; + } + +} + /*! */ @@ -754,9 +797,15 @@ static tExecuteBlit getBlitter( eBlitter operation,const video::IImage * dest,co if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_A1R5G5B5 ) return executeBlit_TextureCopy_16_to_32; + if ( destFormat == video::ECF_R8G8B8 && sourceFormat == video::ECF_A1R5G5B5 ) + return executeBlit_TextureCopy_16_to_24; + if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_R8G8B8 ) return executeBlit_TextureCopy_24_to_32; + if ( destFormat == video::ECF_R8G8B8 && sourceFormat == video::ECF_A8R8G8B8 ) + return executeBlit_TextureCopy_32_to_24; + } break; case BLITTER_TEXTURE_ALPHA_BLEND: diff --git a/source/Irrlicht/CIrrDeviceSDL.cpp b/source/Irrlicht/CIrrDeviceSDL.cpp index 0c5d9005..d5eb71d5 100644 --- a/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/source/Irrlicht/CIrrDeviceSDL.cpp @@ -83,6 +83,8 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) // enable key to character translation SDL_EnableUNICODE(1); + (void)SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + if ( CreationParams.Fullscreen ) SDL_Flags |= SDL_FULLSCREEN; if (CreationParams.DriverType == video::EDT_OPENGL) diff --git a/source/Irrlicht/CMS3DMeshFileLoader.cpp b/source/Irrlicht/CMS3DMeshFileLoader.cpp index 6f35d20d..768767cf 100644 --- a/source/Irrlicht/CMS3DMeshFileLoader.cpp +++ b/source/Irrlicht/CMS3DMeshFileLoader.cpp @@ -16,6 +16,10 @@ namespace irr namespace scene { +#ifdef _DEBUG +#define _IRR_DEBUG_MS3D_LOADER_ +#endif + // byte-align structures #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) @@ -195,6 +199,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) os::Printer::log("Only Milkshape3D version 3 and 4 (1.3 to 1.8) is supported. Loading failed", file->getFileName(), ELL_ERROR); return false; } +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Loaded header version", core::stringc(pHeader->Version).c_str()); +#endif // get pointers to data @@ -202,6 +209,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) u16 numVertices = *(u16*)pPtr; #ifdef __BIG_ENDIAN__ numVertices = os::Byteswap::byteswap(numVertices); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Load vertices", core::stringc(numVertices).c_str()); #endif pPtr += sizeof(u16); MS3DVertex *vertices = (MS3DVertex*)pPtr; @@ -227,6 +237,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) u16 numTriangles = *(u16*)pPtr; #ifdef __BIG_ENDIAN__ numTriangles = os::Byteswap::byteswap(numTriangles); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Load Triangles", core::stringc(numTriangles).c_str()); #endif pPtr += sizeof(u16); MS3DTriangle *triangles = (MS3DTriangle*)pPtr; @@ -261,6 +274,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) u16 numGroups = *(u16*)pPtr; #ifdef __BIG_ENDIAN__ numGroups = os::Byteswap::byteswap(numGroups); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Load Groups", core::stringc(numGroups).c_str()); #endif pPtr += sizeof(u16); @@ -313,6 +329,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) u16 numMaterials = *(u16*)pPtr; #ifdef __BIG_ENDIAN__ numMaterials = os::Byteswap::byteswap(numMaterials); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Load Materials", core::stringc(numMaterials).c_str()); #endif pPtr += sizeof(u16); @@ -378,6 +397,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) f32 framesPerSecond = *(float*)pPtr; #ifdef __BIG_ENDIAN__ framesPerSecond = os::Byteswap::byteswap(framesPerSecond); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("FPS", core::stringc(framesPerSecond).c_str()); #endif pPtr += sizeof(float) * 2; // fps and current time @@ -394,6 +416,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) u16 jointCount = *(u16*)pPtr; #ifdef __BIG_ENDIAN__ jointCount = os::Byteswap::byteswap(jointCount); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Joints", core::stringc(jointCount).c_str()); #endif pPtr += sizeof(u16); if (pPtr > buffer+fileSize) @@ -430,6 +455,11 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) ISkinnedMesh::SJoint *jnt = AnimatedMesh->createJoint(); jnt->Name = pJoint->Name; +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Joint", jnt->Name.c_str()); + os::Printer::log("Rotation keyframes", core::stringc(pJoint->NumRotationKeyframes).c_str()); + os::Printer::log("Translation keyframes", core::stringc(pJoint->NumTranslationKeyframes).c_str()); +#endif jnt->LocalMatrix.makeIdentity(); jnt->LocalMatrix.setRotationRadians( core::vector3df(pJoint->Rotation[0], pJoint->Rotation[1], pJoint->Rotation[2]) ); @@ -525,6 +555,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) for (u32 j=0; j<4; ++j) // four comment groups { +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Skipping comment group", core::stringc(j+1).c_str()); +#endif u32 numComments = *(u32*)pPtr; #ifdef __BIG_ENDIAN__ numComments = os::Byteswap::byteswap(numComments); @@ -557,6 +590,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) #endif pPtr += sizeof(s32); +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Reading vertex weights"); +#endif // read vertex weights, ignoring data 'extra' from 1.8.2 vertexWeights.reallocate(numVertices); const char offset = (subVersion==1)?6:10; @@ -582,6 +618,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) #endif pPtr += sizeof(s32); // skip joint colors +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Skip joint color"); +#endif pPtr += 3*sizeof(float)*jointCount; if (pPtr > buffer+fileSize) @@ -599,6 +638,9 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) subVersion = os::Byteswap::byteswap(subVersion); #endif pPtr += sizeof(s32); +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Skip model extra information"); +#endif // now the model extra information would follow // we also skip this for now } diff --git a/source/Irrlicht/COBJMeshFileLoader.cpp b/source/Irrlicht/COBJMeshFileLoader.cpp index 68a89eb0..2c363479 100644 --- a/source/Irrlicht/COBJMeshFileLoader.cpp +++ b/source/Irrlicht/COBJMeshFileLoader.cpp @@ -22,7 +22,9 @@ namespace irr namespace scene { -//#define _IRR_DEBUG_OBJ_LOADER_ +#ifdef _DEBUG +#define _IRR_DEBUG_OBJ_LOADER_ +#endif static const u32 WORD_BUFFER_LENGTH = 512; @@ -81,7 +83,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) // Process obj information const c8* bufPtr = buf; - core::stringc grpName; + core::stringc grpName, mtlName; + bool mtlChanged=false; bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS); while(bufPtr != bufEnd) { @@ -120,7 +123,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) case 't': // texcoord { core::vector2df vec; - bufPtr = readVec2(bufPtr, vec, bufEnd); + bufPtr = readUV(bufPtr, vec, bufEnd); textureCoordBuffer.push_back(vec); } break; @@ -141,6 +144,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) else grpName = "default"; } + mtlChanged=true; } break; @@ -166,11 +170,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) #ifdef _IRR_DEBUG_OBJ_LOADER_ os::Printer::log("Loaded material start",matName); #endif - // retrieve the material - SObjMtl *useMtl = findMtl(matName, grpName); - // only change material if we found it - if (useMtl) - currMtl = useMtl; + mtlName=matName; + mtlChanged=true; } break; @@ -179,6 +180,15 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) c8 vertexWord[WORD_BUFFER_LENGTH]; // for retrieving vertex data video::S3DVertex v; // Assign vertex color from currently active material's diffuse colour + if (mtlChanged) + { + // retrieve the material + SObjMtl *useMtl = findMtl(mtlName, grpName); + // only change material if we found it + if (useMtl) + currMtl = useMtl; + mtlChanged=false; + } if (currMtl) v.Color = currMtl->Meshbuffer->Material.DiffuseColor; @@ -642,7 +652,7 @@ const c8* COBJMeshFileLoader::readVec3(const c8* bufPtr, core::vector3df& vec, c //! Read 2d vector of floats -const c8* COBJMeshFileLoader::readVec2(const c8* bufPtr, core::vector2df& vec, const c8* const bufEnd) +const c8* COBJMeshFileLoader::readUV(const c8* bufPtr, core::vector2df& vec, const c8* const bufEnd) { const u32 WORD_BUFFER_LENGTH = 256; c8 wordBuffer[WORD_BUFFER_LENGTH]; @@ -650,7 +660,7 @@ const c8* COBJMeshFileLoader::readVec2(const c8* bufPtr, core::vector2df& vec, c bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); vec.X=core::fast_atof(wordBuffer); bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); - vec.Y=-core::fast_atof(wordBuffer); // change handedness + vec.Y=1-core::fast_atof(wordBuffer); // change handedness return bufPtr; } @@ -670,6 +680,8 @@ const c8* COBJMeshFileLoader::readBool(const c8* bufPtr, bool& tf, const c8* con COBJMeshFileLoader::SObjMtl* COBJMeshFileLoader::findMtl(const core::stringc& mtlName, const core::stringc& grpName) { COBJMeshFileLoader::SObjMtl* defMaterial = 0; + // search existing Materials for best match + // exact match does return immediately, only name match means a new group for (u32 i = 0; i < Materials.size(); ++i) { if ( Materials[i]->Name == mtlName ) @@ -677,16 +689,23 @@ COBJMeshFileLoader::SObjMtl* COBJMeshFileLoader::findMtl(const core::stringc& mt if ( Materials[i]->Group == grpName ) return Materials[i]; else - if ( Materials[i]->Group == "" ) defMaterial = Materials[i]; } } + // we found a partial match if (defMaterial) { Materials.push_back(new SObjMtl(*defMaterial)); Materials.getLast()->Group = grpName; return Materials.getLast(); } + // we found a new group for a non-existant material + else if (grpName.size()) + { + Materials.push_back(new SObjMtl(*Materials[0])); + Materials.getLast()->Group = grpName; + return Materials.getLast(); + } return 0; } diff --git a/source/Irrlicht/COBJMeshFileLoader.h b/source/Irrlicht/COBJMeshFileLoader.h index 602d370d..6d3a5bd8 100644 --- a/source/Irrlicht/COBJMeshFileLoader.h +++ b/source/Irrlicht/COBJMeshFileLoader.h @@ -96,7 +96,7 @@ private: //! Read 3d vector of floats const c8* readVec3(const c8* bufPtr, core::vector3df& vec, const c8* const pBufEnd); //! Read 2d vector of floats - const c8* readVec2(const c8* bufPtr, core::vector2df& vec, const c8* const pBufEnd); + const c8* readUV(const c8* bufPtr, core::vector2df& vec, const c8* const pBufEnd); //! Read boolean value represented as 'on' or 'off' const c8* readBool(const c8* bufPtr, bool& tf, const c8* const bufEnd); diff --git a/source/Irrlicht/COgreMeshFileLoader.cpp b/source/Irrlicht/COgreMeshFileLoader.cpp index e5f30ded..d7eeea3a 100644 --- a/source/Irrlicht/COgreMeshFileLoader.cpp +++ b/source/Irrlicht/COgreMeshFileLoader.cpp @@ -619,6 +619,9 @@ void COgreMeshFileLoader::getMaterialToken(io::IReadFile* file, core::stringc& t c8 c=0; token = ""; + if (file->getPos() >= file->getSize()) + return; + file->read(&c, sizeof(c8)); // search for word beginning while ( core::isspace(c) && (file->getPos() < file->getSize())) @@ -835,6 +838,9 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique } else if (token=="texture_unit") { +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Read Texture unit"); +#endif getMaterialToken(file, token); //open brace getMaterialToken(file, token); while(token != "}") @@ -842,6 +848,9 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique if (token=="texture") { getMaterialToken(file, pass.Texture.Filename); +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Read Texture", pass.Texture.Filename.c_str()); +#endif getMaterialToken(file, pass.Texture.CoordsType, true); getMaterialToken(file, pass.Texture.MipMaps, true); getMaterialToken(file, pass.Texture.Alpha, true); diff --git a/source/Irrlicht/COpenGLDriver.cpp b/source/Irrlicht/COpenGLDriver.cpp index 032239b2..3078cb4e 100644 --- a/source/Irrlicht/COpenGLDriver.cpp +++ b/source/Irrlicht/COpenGLDriver.cpp @@ -1931,9 +1931,7 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater if (resetAllRenderStates || lastmaterial.AmbientColor != material.AmbientColor || lastmaterial.DiffuseColor != material.DiffuseColor || - lastmaterial.SpecularColor != material.SpecularColor || - lastmaterial.EmissiveColor != material.EmissiveColor || - lastmaterial.Shininess != material.Shininess) + lastmaterial.EmissiveColor != material.EmissiveColor) { GLfloat color[4]; @@ -1951,6 +1949,21 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater color[3] = material.DiffuseColor.getAlpha() * inv; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); + color[0] = material.EmissiveColor.getRed() * inv; + color[1] = material.EmissiveColor.getGreen() * inv; + color[2] = material.EmissiveColor.getBlue() * inv; + color[3] = material.EmissiveColor.getAlpha() * inv; + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color); + } + + if (resetAllRenderStates || + lastmaterial.SpecularColor != material.SpecularColor || + lastmaterial.Shininess != material.Shininess) + { + GLfloat color[4]={0.f,0.f,0.f,1.f}; + const f32 inv = 1.0f / 255.0f; + + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material.Shininess); // disable Specular colors if no shininess is set if (material.Shininess != 0.0f) { @@ -1958,24 +1971,16 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater if (FeatureAvailable[IRR_EXT_separate_specular_color]) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); #endif - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material.Shininess); color[0] = material.SpecularColor.getRed() * inv; color[1] = material.SpecularColor.getGreen() * inv; color[2] = material.SpecularColor.getBlue() * inv; color[3] = material.SpecularColor.getAlpha() * inv; - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); } #ifdef GL_EXT_separate_specular_color - else - if (FeatureAvailable[IRR_EXT_separate_specular_color]) - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); + else if (FeatureAvailable[IRR_EXT_separate_specular_color]) + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); #endif - - color[0] = material.EmissiveColor.getRed() * inv; - color[1] = material.EmissiveColor.getGreen() * inv; - color[2] = material.EmissiveColor.getBlue() * inv; - color[3] = material.EmissiveColor.getAlpha() * inv; - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); } // Texture filter @@ -2776,7 +2781,7 @@ ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d& si //! call. u32 COpenGLDriver::getMaximalPrimitiveCount() const { - return 65535;// TODO: Fix all loaders to auto-split and then return the correct value: MaxIndices; + return 0x7fffffff; } diff --git a/source/Irrlicht/COpenGLExtensionHandler.cpp b/source/Irrlicht/COpenGLExtensionHandler.cpp index f4ef2e53..82afe254 100644 --- a/source/Irrlicht/COpenGLExtensionHandler.cpp +++ b/source/Irrlicht/COpenGLExtensionHandler.cpp @@ -85,9 +85,9 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) if (str[i] == ' ') { str[i] = 0; - for (u32 j=0; jaddAnimator(anm); + setActiveCamera(node); + anm->drop(); node->drop(); - setActiveCamera(node); - return node; } @@ -667,18 +667,18 @@ ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent, parent = this; ICameraSceneNode* node = new CCameraSceneNode(parent, this, id); - ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl, rotateSpeed, - moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement); + ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl, + rotateSpeed, moveSpeed, jumpSpeed, + keyMapArray, keyMapSize, noVerticalMovement); // Bind the node's rotation to its target. This is consistent with 1.4.2 and below. node->bindTargetAndRotation(true); node->addAnimator(anm); - anm->drop(); - node->drop(); - setActiveCamera(node); + anm->drop(); + node->drop(); return node; } diff --git a/source/Irrlicht/CSceneManager.h b/source/Irrlicht/CSceneManager.h index 276eb397..d6b90d3b 100644 --- a/source/Irrlicht/CSceneManager.h +++ b/source/Irrlicht/CSceneManager.h @@ -127,18 +127,18 @@ namespace scene //! \return Pointer to interface to camera virtual ICameraSceneNode* addCameraSceneNode(ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& lookat = core::vector3df(0,0,0), s32 id=-1); + const core::vector3df& lookat = core::vector3df(0,0,100), s32 id=-1); //! Adds a camera scene node which is able to be controlle with the mouse similar //! like in the 3D Software Maya by Alias Wavefront. //! The returned pointer must not be dropped. virtual ICameraSceneNode* addCameraSceneNodeMaya(ISceneNode* parent = 0, - f32 rotateSpeed = -1500.0f, f32 zoomSpeed = 200.0f, f32 translationSpeed = 100.0f, s32 id=-1); + f32 rotateSpeed = -1500.0f, f32 zoomSpeed = 200.0f, f32 translationSpeed = 1500.0f, s32 id=-1); //! Adds a camera scene node which is able to be controled with the mouse and keys //! like in most first person shooters (FPS): virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, - f32 rotateSpeed = 1500.0f, f32 moveSpeed = 200.0f, s32 id=-1, + f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, f32 jumpSpeed = 0.f); @@ -167,8 +167,9 @@ namespace scene //! Adds a skydome scene node. A skydome is a large (half-) sphere with a //! panoramic texture on it and is drawn around the camera position. virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, - u32 horiRes, u32 vertRes, f64 texturePercentage, - f64 spherePercentage, ISceneNode* parent=0, s32 id=-1); + u32 horiRes=16, u32 vertRes=8, + f64 texturePercentage=0.9, f64 spherePercentage=2.0, + ISceneNode* parent=0, s32 id=-1); //! Adds a text scene node, which is able to display //! 2d text at a position in three dimensional space diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp index 59dc2ee7..2e665f31 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp @@ -20,9 +20,8 @@ CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cu f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed, SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement) : CursorControl(cursorControl), MaxVerticalAngle(88.0f), - MoveSpeed(moveSpeed/1000.0f), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed), - LastAnimationTime(0), firstUpdate(true), NoVerticalMovement(noVerticalMovement), - KeyMapArray(keyMapArray), KeyMapSize(keyMapSize) + MoveSpeed(moveSpeed), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed), + LastAnimationTime(0), firstUpdate(true), NoVerticalMovement(noVerticalMovement) { #ifdef _DEBUG setDebugName("CCameraSceneNodeAnimatorFPS"); @@ -34,7 +33,7 @@ CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cu allKeysUp(); // create key map - if (!KeyMapArray || !KeyMapSize) + if (!keyMapArray || !keyMapSize) { // create default key map KeyMap.push_back(SCamKeyMap(EKA_MOVE_FORWARD, irr::KEY_UP)); @@ -46,7 +45,7 @@ CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cu else { // create custom key map - setKeyMap(KeyMapArray, KeyMapSize); + setKeyMap(keyMapArray, keyMapSize); } } @@ -97,7 +96,7 @@ bool CSceneNodeAnimatorCameraFPS::OnEvent(const SEvent& evt) void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) { - if (node->getType() != ESNT_CAMERA) + if (!node || node->getType() != ESNT_CAMERA) return; ICameraSceneNode* camera = static_cast(node); @@ -116,6 +115,14 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) firstUpdate = false; } + // If the camera isn't the active camera, and receiving input, then don't process it. + if(!camera->isInputReceiverEnabled()) + return; + + scene::ISceneManager * smgr = camera->getSceneManager(); + if(smgr && smgr->getActiveCamera() != camera) + return; + // get time f32 timeDiff = (f32) ( timeMs - LastAnimationTime ); LastAnimationTime = timeMs; @@ -147,14 +154,15 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) { relativeRotation.X = MaxVerticalAngle; } - - // reset cursor position - CursorControl->setPosition(0.5f, 0.5f); - CenterCursor = CursorControl->getRelativePosition(); - // needed to avoid problems when the ecent receiver is - // disabled - CursorPos = CenterCursor; } + + // reset cursor position to the centre of the window. Do this unconditionally + // to cope with the case where the mouse has escaped our window in a single + // tick, so we don't get messages for it. + CursorControl->setPosition(0.5f, 0.5f); + CenterCursor = CursorControl->getRelativePosition(); + // needed to avoid problems when the event receiver is disabled + CursorPos = CenterCursor; } // set target @@ -294,20 +302,30 @@ void CSceneNodeAnimatorCameraFPS::setKeyMap(SKeyMap *map, u32 count) } } + //! Sets whether vertical movement should be allowed. void CSceneNodeAnimatorCameraFPS::setVerticalMovement(bool allow) { NoVerticalMovement = !allow; } + ISceneNodeAnimator* CSceneNodeAnimatorCameraFPS::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorCameraFPS * newAnimator = - new CSceneNodeAnimatorCameraFPS(CursorControl, RotateSpeed, (MoveSpeed * 1000.0f), JumpSpeed, - KeyMapArray, KeyMapSize, NoVerticalMovement); + new CSceneNodeAnimatorCameraFPS(CursorControl, RotateSpeed, MoveSpeed, JumpSpeed, + 0, 0, NoVerticalMovement); + newAnimator->setKeyMap(KeyMap); return newAnimator; } + +void CSceneNodeAnimatorCameraFPS::setKeyMap(const core::array& keymap) +{ + KeyMap=keymap; +} + + } // namespace scene } // namespace irr diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h index c0dd7bf6..c4bc8e7c 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h +++ b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h @@ -27,7 +27,7 @@ namespace scene //! Constructor CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cursorControl, - f32 rotateSpeed = 100.0f, f32 moveSpeed = 500.0f, f32 jumpSpeed=0.f, + f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, f32 jumpSpeed=0.f, SKeyMap* keyMapArray=0, u32 keyMapSize=0, bool noVerticalMovement=false); //! Destructor @@ -39,10 +39,10 @@ namespace scene //! Event receiver virtual bool OnEvent(const SEvent& event); - //! Returns the speed of movement in units per millisecond + //! Returns the speed of movement in units per second virtual f32 getMoveSpeed() const; - //! Sets the speed of movement in units per millisecond + //! Sets the speed of movement in units per second virtual void setMoveSpeed(f32 moveSpeed); //! Returns the rotation speed @@ -77,8 +77,6 @@ namespace scene this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); - private: - struct SCamKeyMap { SCamKeyMap() {}; @@ -88,6 +86,12 @@ namespace scene EKEY_CODE keycode; }; + //! Sets the keyboard mapping for this animator + /** Helper function for the clone method. + \param keymap the new keymap array */ + void setKeyMap(const core::array& keymap); + + private: void allKeysUp(); gui::ICursorControl *CursorControl; @@ -108,12 +112,10 @@ namespace scene bool firstUpdate; bool NoVerticalMovement; - - SKeyMap* KeyMapArray; - u32 KeyMapSize; }; } // end namespace scene } // end namespace irr #endif // __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ + diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp b/source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp index 1304056c..89b16f53 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp @@ -6,6 +6,7 @@ #include "ICursorControl.h" #include "ICameraSceneNode.h" #include "SViewFrustum.h" +#include "ISceneManager.h" namespace irr { @@ -14,11 +15,9 @@ namespace scene //! constructor CSceneNodeAnimatorCameraMaya::CSceneNodeAnimatorCameraMaya(gui::ICursorControl* cursor, f32 rotate, f32 zoom, f32 translate) - : CursorControl(cursor), Zooming(false), Rotating(false), Moving(false), Translating(false), - ZoomSpeed(zoom), RotateSpeed(rotate), TranslateSpeed(translate), - RotateStartX(0.0f), RotateStartY(0.0f), ZoomStartX(0.0f), ZoomStartY(0.0f), - TranslateStartX(0.0f), TranslateStartY(0.0f), CurrentZoom(70.0f), RotX(0.0f), RotY(0.0f), - Target(0,0,0), OldTarget(0,0,0), OldCamera(0), MousePos(0.5f, 0.5f) + : CursorControl(cursor), Zooming(false), Rotating(false), Moving(false), + Translating(false), ZoomSpeed(zoom), RotateSpeed(rotate), TranslateSpeed(translate), + CurrentZoom(70.0f), RotX(0.0f), RotY(0.0f), OldCamera(0), MousePos(0.5f, 0.5f) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorCameraMaya"); @@ -43,7 +42,7 @@ CSceneNodeAnimatorCameraMaya::~CSceneNodeAnimatorCameraMaya() //! It is possible to send mouse and key events to the camera. Most cameras -//! may ignore this input, but camera scene nodes which are created for +//! may ignore this input, but camera scene nodes which are created for //! example with scene::ISceneManager::addMayaCameraSceneNode or //! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input //! for changing their position, look at target or whatever. @@ -92,20 +91,26 @@ void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) //Alt + LM + MM = Dolly forth/back in view direction (speed % distance camera pivot - max distance to pivot) //Alt + MM = Move on camera plane (Screen center is about the mouse pointer, depending on move speed) - if (node->getType() != ESNT_CAMERA) + if (!node || node->getType() != ESNT_CAMERA) return; ICameraSceneNode* camera = static_cast(node); + // If the camera isn't the active camera, and receiving input, then don't process it. + if(!camera->isInputReceiverEnabled()) + return; + + scene::ISceneManager * smgr = camera->getSceneManager(); + if(smgr && smgr->getActiveCamera() != camera) + return; + if (OldCamera != camera) { OldTarget = camera->getTarget(); OldCamera = camera; } - Target = camera->getTarget(); - - const SViewFrustum* va = camera->getViewFrustum(); + core::vector3df target = camera->getTarget(); f32 nRotX = RotX; f32 nRotY = RotY; @@ -115,75 +120,61 @@ void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) { if (!Zooming) { - ZoomStartX = MousePos.X; - ZoomStartY = MousePos.Y; + ZoomStart = MousePos; Zooming = true; nZoom = CurrentZoom; } else { - f32 old = nZoom; - nZoom += (ZoomStartX - MousePos.X) * ZoomSpeed; + const f32 targetMinDistance = 0.1f; + nZoom += (ZoomStart.X - MousePos.X) * ZoomSpeed; - f32 targetMinDistance = 0.1f; if (nZoom < targetMinDistance) // jox: fixed bug: bounce back when zooming to close nZoom = targetMinDistance; - - if (nZoom < 0) - nZoom = old; } } - else + else if (Zooming) { - if (Zooming) - { - f32 old = CurrentZoom; - CurrentZoom = CurrentZoom + (ZoomStartX - MousePos.X ) * ZoomSpeed; - nZoom = CurrentZoom; - - if (nZoom < 0) - nZoom = CurrentZoom = old; - } + const f32 old = CurrentZoom; + CurrentZoom = CurrentZoom + (ZoomStart.X - MousePos.X ) * ZoomSpeed; + nZoom = CurrentZoom; + if (nZoom < 0) + nZoom = CurrentZoom = old; Zooming = false; } // Translation --------------------------------- - core::vector3df translate(OldTarget), UpVector(camera->getUpVector()); + core::vector3df translate(OldTarget), upVector(camera->getUpVector()); - core::vector3df tvectX = Pos - Target; - tvectX = tvectX.crossProduct(UpVector); + core::vector3df tvectX = Pos - target; + tvectX = tvectX.crossProduct(upVector); tvectX.normalize(); + const SViewFrustum* const va = camera->getViewFrustum(); core::vector3df tvectY = (va->getFarLeftDown() - va->getFarRightDown()); - tvectY = tvectY.crossProduct(UpVector.Y > 0 ? Pos - Target : Target - Pos); + tvectY = tvectY.crossProduct(upVector.Y > 0 ? Pos - target : target - Pos); tvectY.normalize(); - if (isMouseKeyDown(2) && !Zooming) { if (!Translating) { - TranslateStartX = MousePos.X; - TranslateStartY = MousePos.Y; + TranslateStart = MousePos; Translating = true; } else { - translate += tvectX * (TranslateStartX - MousePos.X)*TranslateSpeed + - tvectY * (TranslateStartY - MousePos.Y)*TranslateSpeed; + translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + + tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; } } - else + else if (Translating) { - if (Translating) - { - translate += tvectX * (TranslateStartX - MousePos.X)*TranslateSpeed + - tvectY * (TranslateStartY - MousePos.Y)*TranslateSpeed; - OldTarget = translate; - } - + translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + + tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; + OldTarget = translate; Translating = false; } @@ -193,52 +184,47 @@ void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) { if (!Rotating) { - RotateStartX = MousePos.X; - RotateStartY = MousePos.Y; + RotateStart = MousePos; Rotating = true; nRotX = RotX; nRotY = RotY; } else { - nRotX += (RotateStartX - MousePos.X) * RotateSpeed; - nRotY += (RotateStartY - MousePos.Y) * RotateSpeed; + nRotX += (RotateStart.X - MousePos.X) * RotateSpeed; + nRotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; } } - else + else if (Rotating) { - if (Rotating) - { - RotX = RotX + (RotateStartX - MousePos.X) * RotateSpeed; - RotY = RotY + (RotateStartY - MousePos.Y) * RotateSpeed; - nRotX = RotX; - nRotY = RotY; - } - + RotX += (RotateStart.X - MousePos.X) * RotateSpeed; + RotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; + nRotX = RotX; + nRotY = RotY; Rotating = false; } // Set Pos ------------------------------------ - Target = translate; + target = translate; - Pos.X = nZoom + Target.X; - Pos.Y = Target.Y; - Pos.Z = Target.Z; + Pos.X = nZoom + target.X; + Pos.Y = target.Y; + Pos.Z = target.Z; - Pos.rotateXYBy(nRotY, Target); - Pos.rotateXZBy(-nRotX, Target); + Pos.rotateXYBy(nRotY, target); + Pos.rotateXZBy(-nRotX, target); // Rotation Error ---------------------------- // jox: fixed bug: jitter when rotating to the top and bottom of y - UpVector.set(0,1,0); - UpVector.rotateXYBy(-nRotY); - UpVector.rotateXZBy(-nRotX+180.f); + upVector.set(0,1,0); + upVector.rotateXYBy(-nRotY); + upVector.rotateXZBy(-nRotX+180.f); camera->setPosition(Pos); - camera->setTarget(Target); - camera->setUpVector(UpVector); + camera->setTarget(target); + camera->setUpVector(upVector); } @@ -255,29 +241,10 @@ void CSceneNodeAnimatorCameraMaya::allKeysUp() } -// function added by jox -void CSceneNodeAnimatorCameraMaya::updateAnimationState() -{ - core::vector3df pos(Pos - Target); - - // X rotation - core::vector2df vec2d(pos.X, pos.Z); - RotX = (f32)vec2d.getAngle(); - - // Y rotation - pos.rotateXZBy(RotX); - vec2d.set(pos.X, pos.Y); - RotY = -(f32)vec2d.getAngle(); - - // Zoom - CurrentZoom = (f32)Pos.getDistanceFrom(Target); -} - - //! Sets the rotation speed void CSceneNodeAnimatorCameraMaya::setRotateSpeed(f32 speed) { - RotateSpeed = speed; + RotateSpeed = speed; } @@ -317,7 +284,7 @@ f32 CSceneNodeAnimatorCameraMaya::getZoomSpeed() const ISceneNodeAnimator* CSceneNodeAnimatorCameraMaya::createClone(ISceneNode* node, ISceneManager* newManager) { - CSceneNodeAnimatorCameraMaya * newAnimator = + CSceneNodeAnimatorCameraMaya * newAnimator = new CSceneNodeAnimatorCameraMaya(CursorControl, RotateSpeed, ZoomSpeed, TranslateSpeed); return newAnimator; } diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraMaya.h b/source/Irrlicht/CSceneNodeAnimatorCameraMaya.h index 0acfbaae..39010f32 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraMaya.h +++ b/source/Irrlicht/CSceneNodeAnimatorCameraMaya.h @@ -21,8 +21,8 @@ namespace scene { //! Special scene node animator for FPS cameras - /** This scene node animator can be attached to a camera to make it act like a first - person shooter + /** This scene node animator can be attached to a camera to make it act + like a 3d modelling tool camera */ class CSceneNodeAnimatorCameraMaya : public ISceneNodeAnimatorCameraMaya { @@ -81,7 +81,6 @@ namespace scene void allKeysUp(); void animate(); bool isMouseKeyDown(s32 key); - void updateAnimationState(); bool MouseKeys[3]; @@ -94,19 +93,19 @@ namespace scene f32 ZoomSpeed; f32 RotateSpeed; f32 TranslateSpeed; - f32 RotateStartX, RotateStartY; - f32 ZoomStartX, ZoomStartY; - f32 TranslateStartX, TranslateStartY; + core::position2df RotateStart; + core::position2df ZoomStart; + core::position2df TranslateStart; f32 CurrentZoom; f32 RotX, RotY; - core::vector3df Target; core::vector3df OldTarget; scene::ICameraSceneNode* OldCamera; - core::position2d MousePos; + core::position2df MousePos; }; } // end namespace scene } // end namespace irr #endif + diff --git a/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp b/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp index 76032520..8fe6fc6a 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp @@ -137,12 +137,9 @@ ITriangleSelector* CSceneNodeAnimatorCollisionResponse::getWorld() const void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 timeMs) { if (node != Object) - { setNode(node); - return; - } - if (!World) + if(!Object || !World) return; u32 diff = timeMs - LastTime; @@ -164,9 +161,10 @@ void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 time // TODO: divide SlidingSpeed by frame time bool f = false; + core::vector3df collisionPosition; // Not used. pos = SceneManager->getSceneCollisionManager()->getCollisionResultPosition( World, LastPosition-Translation, - Radius, vel, triangle, f, SlidingSpeed, FallingVelocity); + Radius, vel, triangle, collisionPosition, f, SlidingSpeed, FallingVelocity); pos += Translation; diff --git a/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h b/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h index 6058be1c..13eb1972 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h +++ b/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h @@ -15,7 +15,7 @@ namespace scene //! Special scene node animator for doing automatic collision detection and response. /** This scene node animator can be attached to any scene node modifying it in that way, that it cannot move through walls of the world, is influenced by gravity and - acceleration. This animator is useful for example for first person shooter + acceleration. This animator is useful for example for first person shooter games. Attach it for example to a first person shooter camera, and the camera will behave as the player control in a first person shooter game: The camera stops and slides at walls, walks up stairs, falls down if there is no floor under it, and so on. @@ -26,7 +26,7 @@ namespace scene //! constructor CSceneNodeAnimatorCollisionResponse(ISceneManager* scenemanager, - ITriangleSelector* world, ISceneNode* object, + ITriangleSelector* world, ISceneNode* object, const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), const core::vector3df& gravityPerSecond = core::vector3df(0,-100.0f,0), const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0), @@ -41,7 +41,7 @@ namespace scene virtual bool isFalling() const; //! Sets the radius of the ellipsoid with which collision detection and - //! response is done. + //! response is done. virtual void setEllipsoidRadius(const core::vector3df& radius); //! Returns the radius of the ellipsoid with which the collision detection and @@ -82,13 +82,19 @@ namespace scene //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_COLLISION_RESPONSE; } - + //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); + //! Set the single node that this animator will act on. + virtual void setTargetNode(ISceneNode * node) { setNode(node); } + + //! Gets the single node that this animator is acting on. + virtual ISceneNode* getTargetNode(void) const { return Object; } + private: void setNode(ISceneNode* node); @@ -100,7 +106,7 @@ namespace scene core::vector3df LastPosition; core::triangle3df RefTriangle; - + ITriangleSelector* World; ISceneNode* Object; ISceneManager* SceneManager; diff --git a/source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp b/source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp index b13c743f..dab93f38 100644 --- a/source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp @@ -30,6 +30,9 @@ inline s32 CSceneNodeAnimatorFollowSpline::clamp(s32 idx, s32 size) //! animates a scene node void CSceneNodeAnimatorFollowSpline::animateNode(ISceneNode* node, u32 timeMs) { + if(!node) + return; + const u32 pSize = Points.size(); if (pSize==0) return; diff --git a/source/Irrlicht/CSceneNodeAnimatorTexture.cpp b/source/Irrlicht/CSceneNodeAnimatorTexture.cpp index c569e6b5..44d32497 100644 --- a/source/Irrlicht/CSceneNodeAnimatorTexture.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorTexture.cpp @@ -53,6 +53,9 @@ void CSceneNodeAnimatorTexture::clearTextures() //! animates a scene node void CSceneNodeAnimatorTexture::animateNode(ISceneNode* node, u32 timeMs) { + if(!node) + return; + if (Textures.size()) { const u32 t = (timeMs-StartTime); diff --git a/source/Irrlicht/CTerrainSceneNode.cpp b/source/Irrlicht/CTerrainSceneNode.cpp index df37081f..301b195f 100644 --- a/source/Irrlicht/CTerrainSceneNode.cpp +++ b/source/Irrlicht/CTerrainSceneNode.cpp @@ -69,7 +69,8 @@ namespace scene //! Initializes the terrain data. Loads the vertices from the heightMapFile - bool CTerrainSceneNode::loadHeightMap( io::IReadFile* file, video::SColor vertexColor, s32 smoothFactor ) + bool CTerrainSceneNode::loadHeightMap(io::IReadFile* file, video::SColor vertexColor, + s32 smoothFactor) { if( !file ) return false; @@ -130,7 +131,7 @@ namespace scene scene::CDynamicMeshBuffer *mb=0; const u32 numVertices = TerrainData.Size * TerrainData.Size; - if (numVertices <65535) + if (numVertices <= 65536) { //small enough for 16bit buffers mb=new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); @@ -231,22 +232,33 @@ namespace scene //! Initializes the terrain data. Loads the vertices from the heightMapFile - bool CTerrainSceneNode::loadHeightMapRAW( io::IReadFile* file, s32 bitsPerPixel, video::SColor vertexColor, s32 smoothFactor ) + bool CTerrainSceneNode::loadHeightMapRAW( io::IReadFile* file, s32 bitsPerPixel, bool signedData, bool floatVals, s32 width, video::SColor vertexColor, s32 smoothFactor ) { - if( !file ) + if (!file) + return false; + if (floatVals && bitsPerPixel != 32) return false; - Mesh.MeshBuffers.clear(); // start reading const u32 startTime = os::Timer::getTime(); - // get file size - const long fileSize = file->getSize(); - // TODO: Currently no floats are supported + Mesh.MeshBuffers.clear(); + const s32 bytesPerPixel = bitsPerPixel / 8; // Get the dimension of the heightmap data - TerrainData.Size = core::floor32(sqrtf( (f32)( fileSize / bytesPerPixel ) )); + const s32 filesize = file->getSize(); + if (!width) + TerrainData.Size = core::floor32(sqrtf( (f32)( filesize / bytesPerPixel ) )); + else + { + if ((filesize-file->getPos())/bytesPerPixel>width*width) + { + os::Printer::log("Error reading heightmap RAW file", "File is too small."); + return false; + } + TerrainData.Size = width; + } switch( TerrainData.PatchSize ) { @@ -286,7 +298,7 @@ namespace scene // resize the vertex array for the mesh buffer one time (makes loading faster) scene::CDynamicMeshBuffer *mb=0; const u32 numVertices = TerrainData.Size * TerrainData.Size; - if (numVertices <65535) + if (numVertices <= 65536) { //small enough for 16bit buffers mb=new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); @@ -316,42 +328,78 @@ namespace scene float fz2=0.f; for( s32 z = 0; z < TerrainData.Size; ++z ) { + bool failure=false; vertex.Pos.X = fx; - switch (bytesPerPixel) + if (floatVals) { - case 1: + if( file->read( &vertex.Pos.Y, bytesPerPixel ) != bytesPerPixel ) + failure=true; + } + else if (signedData) + { + switch (bytesPerPixel) { - u8 val; - if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + case 1: { - os::Printer::log("Error reading heightmap RAW file."); - mb->drop(); - return false; + s8 val; + if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + failure=true; + vertex.Pos.Y=val; } + break; + case 2: + { + s16 val; + if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + failure=true; + vertex.Pos.Y=val/256.f; + } + break; + case 4: + { + s32 val; + if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + failure=true; + vertex.Pos.Y=val/16777216.f; + } + break; } - break; - case 2: + } + else + { + switch (bytesPerPixel) { - u16 val; - if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + case 1: { - os::Printer::log("Error reading heightmap RAW file."); - mb->drop(); - return false; + u8 val; + if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + failure=true; + vertex.Pos.Y=val; } - } - break; - case 4: - { - u32 val; - if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + break; + case 2: { - os::Printer::log("Error reading heightmap RAW file."); - mb->drop(); - return false; + u16 val; + if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + failure=true; + vertex.Pos.Y=val/256.f; } + break; + case 4: + { + u32 val; + if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + failure=true; + vertex.Pos.Y=val/16777216.f; + } + break; } - break; + } + if (failure) + { + os::Printer::log("Error reading heightmap RAW file."); + mb->drop(); + return false; } vertex.Pos.Z = fz; @@ -378,7 +426,6 @@ namespace scene // We copy the data to the renderBuffer, after the normals have been calculated. RenderBuffer->getVertexBuffer().set_used( vertexCount ); - for( u32 i = 0; i < vertexCount; i++ ) { RenderBuffer->getVertexBuffer()[i] = mb->getVertexBuffer()[i]; @@ -406,7 +453,7 @@ namespace scene RenderBuffer->getIndexBuffer().set_used( TerrainData.PatchCount * TerrainData.PatchCount * TerrainData.CalcPatchSize * TerrainData.CalcPatchSize * 6 ); - u32 endTime = os::Timer::getTime(); + const u32 endTime = os::Timer::getTime(); c8 tmp[255]; snprintf(tmp, 255, "Generated terrain data (%dx%d) in %.4f seconds", @@ -426,6 +473,7 @@ namespace scene ForceRecalculation = true; } + //! Sets the rotation of the node. This only modifies //! the relative rotation of the node. //! \param rotation: New rotation of the node in degrees. @@ -436,6 +484,7 @@ namespace scene ForceRecalculation = true; } + //! Sets the pivot point for rotation of this node. This is useful for the TiledTerrainManager to //! rotate all terrain tiles around a global world point. //! NOTE: The default for the RotationPivot will be the center of the individual tile. @@ -445,6 +494,7 @@ namespace scene TerrainData.RotationPivot = pivot; } + //! Sets the position of the node. //! \param newpos: New postition of the scene node. void CTerrainSceneNode::setPosition(const core::vector3df& newpos) @@ -454,6 +504,7 @@ namespace scene ForceRecalculation = true; } + //! Apply transformation changes( scale, position, rotation ) void CTerrainSceneNode::applyTransformation() { @@ -479,9 +530,9 @@ namespace scene calculatePatchData(); RenderBuffer->setDirty(EBT_VERTEX); - } + //! Updates the scene nodes indices if the camera has moved or rotated by a certain //! threshold, which can be changed using the SetCameraMovementDeltaThreshold and //! SetCameraRotationDeltaThreshold functions. This also determines if a given patch @@ -498,9 +549,10 @@ namespace scene ForceRecalculation = false; } + void CTerrainSceneNode::preRenderLODCalculations() { - SceneManager->registerNodeForRendering( this ); + SceneManager->registerNodeForRendering(this); // Do Not call ISceneNode::OnRegisterSceneNode(), this node should have no children // Determine the camera rotation, based on the camera direction. @@ -508,7 +560,6 @@ namespace scene const core::vector3df cameraRotation = core::line3d(cameraPosition, SceneManager->getActiveCamera()->getTarget()).getVector().getHorizontalAngle(); const f32 CameraFOV = SceneManager->getActiveCamera()->getFOV(); - // Only check on the Camera's Y Rotation if (!ForceRecalculation) { @@ -572,18 +623,15 @@ namespace scene switch (RenderBuffer->getIndexBuffer().getType()) { case video::EIT_16BIT: - { preRenderIndicesCalculationsDirect((u16*)RenderBuffer->getIndexBuffer().pointer()); break; - } case video::EIT_32BIT: - { preRenderIndicesCalculationsDirect((u32*)RenderBuffer->getIndexBuffer().pointer()); break; - } } } + template void CTerrainSceneNode::preRenderIndicesCalculationsDirect(INDEX_TYPE* IndexBuffer) { @@ -642,10 +690,6 @@ namespace scene } - - - - //! Render the scene node void CTerrainSceneNode::render() { @@ -744,18 +788,21 @@ namespace scene } } + //! Return the bounding box of the entire terrain. const core::aabbox3d& CTerrainSceneNode::getBoundingBox() const { return TerrainData.BoundingBox; } + //! Return the bounding box of a patch const core::aabbox3d& CTerrainSceneNode::getBoundingBox( s32 patchX, s32 patchZ ) const { return TerrainData.Patches[patchX * TerrainData.PatchCount + patchZ].BoundingBox; } + //! Gets the meshbuffer data based on a specified Level of Detail. //! \param mb: A reference to an SMeshBuffer object //! \param LOD: The Level Of Detail you want the indices from. @@ -816,6 +863,7 @@ namespace scene } } + //! Gets the indices for a specified patch at a specified Level of Detail. //! \param mb: A reference to an array of u32 indices. //! \param patchX: Patch x coordinate. @@ -893,6 +941,7 @@ namespace scene return rv; } + //! Populates an array with the CurrentLOD of each patch. //! \param LODs: A reference to a core::array to hold the values //! \return Returns the number of elements in the array @@ -933,6 +982,7 @@ namespace scene return true; } + //! Creates a planar texture mapping on the terrain //! \param resolution: resolution of the planar mapping. This is the value //! specifying the relation between world space and texture coordinate space. @@ -979,6 +1029,7 @@ namespace scene RenderBuffer->setDirty(EBT_VERTEX); } + //! used to get the indices when generating index data for patches at varying levels of detail. u32 CTerrainSceneNode::getIndex(const s32 PatchX, const s32 PatchZ, const s32 PatchIndex, u32 vX, u32 vZ) const @@ -1035,6 +1086,7 @@ namespace scene (vX + ((TerrainData.CalcPatchSize) * PatchX)); } + //! smooth the terrain void CTerrainSceneNode::smoothTerrain(CDynamicMeshBuffer* mb, s32 smoothFactor) { @@ -1056,6 +1108,7 @@ namespace scene } } + //! calculate smooth normals void CTerrainSceneNode::calculateNormals( CDynamicMeshBuffer* mb ) { @@ -1179,6 +1232,7 @@ namespace scene } } + //! create patches, stuff that needs to be done only once for patches goes here. void CTerrainSceneNode::createPatches() { @@ -1190,6 +1244,7 @@ namespace scene TerrainData.Patches = new SPatch[TerrainData.PatchCount * TerrainData.PatchCount]; } + //! used to calculate the internal STerrainData structure both at creation and after scaling/position calls. void CTerrainSceneNode::calculatePatchData() { @@ -1275,6 +1330,7 @@ namespace scene } } + void CTerrainSceneNode::setCurrentLODOfPatches(s32 lod) { const s32 count = TerrainData.PatchCount * TerrainData.PatchCount; @@ -1282,6 +1338,7 @@ namespace scene TerrainData.Patches[i].CurrentLOD = lod; } + void CTerrainSceneNode::setCurrentLODOfPatches(const core::array& lodarray) { const s32 count = TerrainData.PatchCount * TerrainData.PatchCount; @@ -1291,7 +1348,7 @@ namespace scene //! Gets the height - f32 CTerrainSceneNode::getHeight( f32 x, f32 z ) const + f32 CTerrainSceneNode::getHeight(f32 x, f32 z) const { if (!Mesh.getMeshBufferCount()) return 0; diff --git a/source/Irrlicht/CTerrainSceneNode.h b/source/Irrlicht/CTerrainSceneNode.h index dcaf8174..0c262cea 100644 --- a/source/Irrlicht/CTerrainSceneNode.h +++ b/source/Irrlicht/CTerrainSceneNode.h @@ -55,7 +55,7 @@ namespace scene //! Initializes the terrain data. Loads the vertices from the heightMapFile. virtual bool loadHeightMapRAW(io::IReadFile* file, s32 bitsPerPixel = 16, - video::SColor vertexColor = video::SColor ( 255, 255, 255, 255 ), s32 smoothFactor = 0 ); + bool signedData=true, bool floatVals=false, s32 width=0, video::SColor vertexColor = video::SColor ( 255, 255, 255, 255 ), s32 smoothFactor = 0 ); //! Returns the material based on the zero based index i. This scene node only uses //! 1 material. @@ -141,9 +141,9 @@ namespace scene virtual IMeshBuffer* getRenderBuffer() { return RenderBuffer; } //! Gets the meshbuffer data based on a specified Level of Detail. - //! \param mb: A reference to an SMeshBufferLightMap object + //! \param mb: A reference to an IDynamicMeshBuffer object //! \param LOD: The Level Of Detail you want the indices from. - virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD ) const; + virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD=0) const; //! Gets the indices for a specified patch at a specified Level of Detail. //! \param indices: A reference to an array of u32 indices. @@ -151,10 +151,10 @@ namespace scene //! \param patchZ: Patch z coordinate. //! \param LOD: The level of detail to get for that patch. If -1, then get //! the CurrentLOD. If the CurrentLOD is set to -1, meaning it's not shown, - //! then it will retrieve the triangles at the highest LOD ( 0 ). + //! then it will retrieve the triangles at the highest LOD (0). //! \return: Number of indices put into the buffer. virtual s32 getIndicesForPatch(core::array& indices, - s32 patchX, s32 patchZ, s32 LOD = 0 ); + s32 patchX, s32 patchZ, s32 LOD=0); //! Populates an array with the CurrentLOD of each patch. //! \param LODs: A reference to a core::array to hold the values @@ -165,7 +165,7 @@ namespace scene //! \param patchX: Patch x coordinate. //! \param patchZ: Patch z coordinate. //! \param LOD: The level of detail to set the patch to. - virtual void setLODOfPatch( s32 patchX, s32 patchZ, s32 LOD ); + virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0); //! Returns center of terrain. virtual const core::vector3df& getTerrainCenter() const diff --git a/source/Irrlicht/CTerrainTriangleSelector.h b/source/Irrlicht/CTerrainTriangleSelector.h index 3a03e027..013818b3 100644 --- a/source/Irrlicht/CTerrainTriangleSelector.h +++ b/source/Irrlicht/CTerrainTriangleSelector.h @@ -28,29 +28,29 @@ class CTerrainTriangleSelector : public ITriangleSelector public: //! Constructs a selector based on an IGeoMipMapSceneNode - CTerrainTriangleSelector(ITerrainSceneNode* node, s32 LOD ); + CTerrainTriangleSelector(ITerrainSceneNode* node, s32 LOD); //! Destructor virtual ~CTerrainTriangleSelector(); //! Clears and sets triangle data - virtual void setTriangleData ( ITerrainSceneNode* node, s32 LOD ); + virtual void setTriangleData (ITerrainSceneNode* node, s32 LOD); //! Gets all triangles. - void getTriangles ( core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, - const core::matrix4* transform = 0 ) const; + void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, + const core::matrix4* transform=0) const; //! Gets all triangles which lie within a specific bounding box. - void getTriangles ( core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, - const core::aabbox3d& box, const core::matrix4* transform = 0 ) const; + void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, + const core::aabbox3d& box, const core::matrix4* transform=0) const; //! Gets all triangles which have or may have contact with a 3d line. - virtual void getTriangles ( core::triangle3df* triangles, s32 arraySize, + virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, - const core::matrix4* transform = 0 ) const; + const core::matrix4* transform=0) const; //! Returns amount of all available triangles in this selector - virtual s32 getTriangleCount ( ) const; + virtual s32 getTriangleCount() const; private: @@ -65,10 +65,9 @@ private: struct SGeoMipMapTrianglePatches { - SGeoMipMapTrianglePatches ( ) + SGeoMipMapTrianglePatches() : + NumPatches(0), TotalTriangles(0) { - TotalTriangles = 0; - NumPatches = 0; } core::array TrianglePatchArray; diff --git a/source/Irrlicht/CXMeshFileLoader.cpp b/source/Irrlicht/CXMeshFileLoader.cpp index 62a098d7..55087d56 100644 --- a/source/Irrlicht/CXMeshFileLoader.cpp +++ b/source/Irrlicht/CXMeshFileLoader.cpp @@ -293,8 +293,19 @@ bool CXMeshFileLoader::load(io::IReadFile* file) // count vertices in each buffer and reallocate for (i=0; iVertices.size(); ++i) ++vCountArray[verticesLinkBuffer[i]]; - for (i=0; i!=mesh->Buffers.size(); ++i) - mesh->Buffers[i]->Vertices_Standard.reallocate(vCountArray[i]); + if (mesh->TCoords2.size()) + { + for (i=0; i!=mesh->Buffers.size(); ++i) + { + mesh->Buffers[i]->Vertices_2TCoords.reallocate(vCountArray[i]); + mesh->Buffers[i]->VertexType=video::EVT_2TCOORDS; + } + } + else + { + for (i=0; i!=mesh->Buffers.size(); ++i) + mesh->Buffers[i]->Vertices_Standard.reallocate(vCountArray[i]); + } verticesLinkIndex.set_used(mesh->Vertices.size()); // actually store vertices @@ -302,8 +313,17 @@ bool CXMeshFileLoader::load(io::IReadFile* file) { scene::SSkinMeshBuffer *buffer = mesh->Buffers[ verticesLinkBuffer[i] ]; - verticesLinkIndex[i] = buffer->Vertices_Standard.size(); - buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); + if (mesh->TCoords2.size()) + { + verticesLinkIndex[i] = buffer->Vertices_2TCoords.size(); + buffer->Vertices_2TCoords.push_back( mesh->Vertices[i] ); + buffer->Vertices_2TCoords.getLast().TCoords2=mesh->TCoords2[i]; + } + else + { + verticesLinkIndex[i] = buffer->Vertices_Standard.size(); + buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); + } } // count indices per buffer and reallocate @@ -531,8 +551,7 @@ bool CXMeshFileLoader::parseDataObjectTemplate() } - -bool CXMeshFileLoader::parseDataObjectFrame( CSkinnedMesh::SJoint *Parent ) +bool CXMeshFileLoader::parseDataObjectFrame(CSkinnedMesh::SJoint *Parent) { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: Reading frame"); @@ -787,10 +806,6 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) { core::stringc objectName = getNextToken(); -#ifdef _XREADER_DEBUG - os::Printer::log("debug DataObject in mesh:", objectName.c_str() ); -#endif - if (objectName.size() == 0) { os::Printer::log("Unexpected ending found in Mesh in x file.", ELL_WARNING); @@ -802,7 +817,11 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) { break; // mesh finished } - else + +#ifdef _XREADER_DEBUG + os::Printer::log("debug DataObject in mesh:", objectName.c_str() ); +#endif + if (objectName == "MeshNormals") { if (!parseDataObjectMeshNormals(mesh)) @@ -965,17 +984,57 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) return false; } u8* dataptr = (u8*) data; + if ((uv2pos != -1) && (uv2type == 1)) + mesh.TCoords2.reallocate(mesh.Vertices.size()); for (j=0; j>8)&0xf)*sizeof(core::vector2df); + for (u32 j=0; jexistFile(TextureFileName.c_str())) - material.setTexture(0, SceneManager->getVideoDriver()->getTexture (TextureFileName.c_str())); + material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture (TextureFileName.c_str())); // mesh path else { TextureFileName=FilePath + stripPathFromString(TextureFileName,false); if (FileSystem->existFile(TextureFileName.c_str())) - material.setTexture(0, SceneManager->getVideoDriver()->getTexture(TextureFileName.c_str())); + material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName.c_str())); // working directory else - material.setTexture(0, SceneManager->getVideoDriver()->getTexture(stripPathFromString(TextureFileName,false).c_str())); + material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(stripPathFromString(TextureFileName,false).c_str())); } + ++textureLayer; + if (textureLayer==2) + material.MaterialType=video::EMT_LIGHTMAP; } else if (objectName.equals_ignore_case("NormalmapFilename")) @@ -1487,6 +1550,8 @@ bool CXMeshFileLoader::parseDataObjectMaterial(video::SMaterial& material) else material.setTexture(1, SceneManager->getVideoDriver()->getTexture(stripPathFromString(TextureFileName,false).c_str())); } + if (textureLayer==1) + ++textureLayer; } else { diff --git a/source/Irrlicht/CXMeshFileLoader.h b/source/Irrlicht/CXMeshFileLoader.h index 8c298b9a..77af6177 100644 --- a/source/Irrlicht/CXMeshFileLoader.h +++ b/source/Irrlicht/CXMeshFileLoader.h @@ -67,6 +67,7 @@ public: core::array Buffers; core::array Vertices; + core::array TCoords2; core::array Indices; diff --git a/source/Irrlicht/Irrlicht_Linux-gcc.cbp b/source/Irrlicht/Irrlicht-gcc.cbp similarity index 55% rename from source/Irrlicht/Irrlicht_Linux-gcc.cbp rename to source/Irrlicht/Irrlicht-gcc.cbp index 24113b5e..e17e69d9 100644 --- a/source/Irrlicht/Irrlicht_Linux-gcc.cbp +++ b/source/Irrlicht/Irrlicht-gcc.cbp @@ -3,43 +3,95 @@ diff --git a/source/Irrlicht/Irrlicht8.0.vcproj b/source/Irrlicht/Irrlicht8.0.vcproj index 4cfe52b0..f770e2a3 100644 --- a/source/Irrlicht/Irrlicht8.0.vcproj +++ b/source/Irrlicht/Irrlicht8.0.vcproj @@ -260,10 +260,10 @@ EnableFunctionLevelLinking="true" FloatingPointModel="2" RuntimeTypeInfo="false" - PrecompiledHeaderFile=".\..\obj\IrrRelease/Irrlicht.pch" - AssemblerListingLocation=".\..\obj\IrrRelease/" - ObjectFile=".\..\obj\IrrRelease/" - ProgramDataBaseFileName=".\..\obj\IrrRelease/" + PrecompiledHeaderFile=".\..\obj\IrrReleaseFastFPU/Irrlicht.pch" + AssemblerListingLocation=".\..\obj\IrrReleaseFastFPU/" + ObjectFile=".\..\obj\IrrReleaseFastFPU/" + ProgramDataBaseFileName=".\..\obj\IrrReleaseFastFPU/" WarningLevel="3" SuppressStartupBanner="true" DebugInformationFormat="0" @@ -358,10 +358,10 @@ RuntimeLibrary="1" DisableLanguageExtensions="false" RuntimeTypeInfo="false" - PrecompiledHeaderFile=".\..\obj\IrrDebug/Irrlicht.pch" - AssemblerListingLocation=".\..\obj\IrrDebug/" - ObjectFile=".\..\obj\IrrDebug/" - ProgramDataBaseFileName=".\..\obj\IrrDebug/" + PrecompiledHeaderFile=".\..\obj\IrrDebugStatic/Irrlicht.pch" + AssemblerListingLocation=".\..\obj\IrrDebugStatic/" + ObjectFile=".\..\obj\IrrDebugStatic/" + ProgramDataBaseFileName=".\..\obj\IrrDebugStatic/" WarningLevel="3" SuppressStartupBanner="true" DebugInformationFormat="3" @@ -442,10 +442,10 @@ RuntimeLibrary="0" BufferSecurityCheck="false" EnableFunctionLevelLinking="true" - PrecompiledHeaderFile=".\..\obj\IrrRelease/Irrlicht.pch" - AssemblerListingLocation=".\..\obj\IrrRelease/" - ObjectFile=".\..\obj\IrrRelease/" - ProgramDataBaseFileName=".\..\obj\IrrRelease/" + PrecompiledHeaderFile=".\..\obj\IrrReleaseStatic/Irrlicht.pch" + AssemblerListingLocation=".\..\obj\IrrReleaseStatic/" + ObjectFile=".\..\obj\IrrReleaseStatic/" + ProgramDataBaseFileName=".\..\obj\IrrReleaseStatic/" WarningLevel="3" SuppressStartupBanner="true" DebugInformationFormat="0" @@ -530,10 +530,10 @@ EnableFunctionLevelLinking="true" FloatingPointModel="2" RuntimeTypeInfo="false" - PrecompiledHeaderFile=".\..\obj\IrrRelease/Irrlicht.pch" - AssemblerListingLocation=".\..\obj\IrrRelease/" - ObjectFile=".\..\obj\IrrRelease/" - ProgramDataBaseFileName=".\..\obj\IrrRelease/" + PrecompiledHeaderFile=".\..\obj\IrrReleaseFastFPUStatic/Irrlicht.pch" + AssemblerListingLocation=".\..\obj\IrrReleaseFastFPUStatic/" + ObjectFile=".\..\obj\IrrReleaseFastFPUStatic/" + ProgramDataBaseFileName=".\..\obj\IrrReleaseFastFPUStatic/" WarningLevel="3" SuppressStartupBanner="true" DebugInformationFormat="0" diff --git a/source/Irrlicht/Irrlicht9.0.vcproj b/source/Irrlicht/Irrlicht9.0.vcproj index 125efd56..d1dbca74 100644 --- a/source/Irrlicht/Irrlicht9.0.vcproj +++ b/source/Irrlicht/Irrlicht9.0.vcproj @@ -261,9 +261,9 @@ FloatingPointModel="2" RuntimeTypeInfo="false" PrecompiledHeaderFile=".\..\obj\IrrRelease/Irrlicht.pch" - AssemblerListingLocation=".\..\obj\IrrRelease/" - ObjectFile=".\..\obj\IrrRelease/" - ProgramDataBaseFileName=".\..\obj\IrrRelease/" + AssemblerListingLocation=".\..\obj\IrrReleaseFastFPU/" + ObjectFile=".\..\obj\IrrReleaseFastFPU/" + ProgramDataBaseFileName=".\..\obj\IrrReleaseFastFPU/" WarningLevel="3" WarnAsError="false" SuppressStartupBanner="true" @@ -362,9 +362,9 @@ DisableLanguageExtensions="false" RuntimeTypeInfo="false" PrecompiledHeaderFile=".\..\obj\IrrDebug/Irrlicht.pch" - AssemblerListingLocation=".\..\obj\IrrDebug/" - ObjectFile=".\..\obj\IrrDebug/" - ProgramDataBaseFileName=".\..\obj\IrrDebug/" + AssemblerListingLocation=".\..\obj\IrrDebugStatic/" + ObjectFile=".\..\obj\IrrDebugStatic/" + ProgramDataBaseFileName=".\..\obj\IrrDebugStatic/" WarningLevel="3" SuppressStartupBanner="true" DebugInformationFormat="3" @@ -446,9 +446,9 @@ BufferSecurityCheck="false" EnableFunctionLevelLinking="true" PrecompiledHeaderFile=".\..\obj\IrrRelease/Irrlicht.pch" - AssemblerListingLocation=".\..\obj\IrrRelease/" - ObjectFile=".\..\obj\IrrRelease/" - ProgramDataBaseFileName=".\..\obj\IrrRelease/" + AssemblerListingLocation=".\..\obj\IrrReleaseStatic/" + ObjectFile=".\..\obj\IrrReleaseStatic/" + ProgramDataBaseFileName=".\..\obj\IrrReleaseStatic/" WarningLevel="3" SuppressStartupBanner="true" DebugInformationFormat="0" @@ -534,9 +534,9 @@ FloatingPointModel="2" RuntimeTypeInfo="false" PrecompiledHeaderFile=".\..\obj\IrrRelease/Irrlicht.pch" - AssemblerListingLocation=".\..\obj\IrrRelease/" - ObjectFile=".\..\obj\IrrRelease/" - ProgramDataBaseFileName=".\..\obj\IrrRelease/" + AssemblerListingLocation=".\..\obj\IrrReleaseFastFPUStatic/" + ObjectFile=".\..\obj\IrrReleaseFastFPUStatic/" + ProgramDataBaseFileName=".\..\obj\IrrReleaseFastFPUStatic/" WarningLevel="3" SuppressStartupBanner="true" DebugInformationFormat="0" diff --git a/source/Irrlicht/Irrlicht_Win32-gcc.cbp b/source/Irrlicht/Irrlicht_Win32-gcc.cbp deleted file mode 100644 index af72fc65..00000000 --- a/source/Irrlicht/Irrlicht_Win32-gcc.cbp +++ /dev/null @@ -1,2629 +0,0 @@ - - - - - - - diff --git a/source/Irrlicht/Makefile b/source/Irrlicht/Makefile index 3aed4e05..eb49ff83 100644 --- a/source/Irrlicht/Makefile +++ b/source/Irrlicht/Makefile @@ -1,5 +1,5 @@ -VERSION = 1.5.beta -# Irrlicht Engine 1.5.beta +VERSION = 1.5 +# Irrlicht Engine 1.5 # Makefile for Linux # # To use, just run: @@ -91,7 +91,7 @@ sharedlib_osx: LDFLAGS += -L/usr/X11R6/lib$(LIBSELECT) -lGL -lXxf86vm #Windows specific options sharedlib_win32 staticlib_win32: SYSTEM = Win32-gcc -sharedlib_win32: LDFLAGS = -lgdi32 -lopengl32 -ld3dx9d +sharedlib_win32: LDFLAGS = -lgdi32 -lopengl32 -ld3dx9d -lwinmm sharedlib_win32 staticlib_win32: CPPFLAGS += -DIRR_COMPILE_WITH_DX9_DEV_PACK -D__GNUWIN32__ -D_WIN32 -DWIN32 -D_WINDOWS -D_MBCS -D_USRDLL staticlib_win32: CPPFLAGS += -D_IRR_STATIC_LIB_ @@ -146,7 +146,7 @@ TAGS: # Create object files from objective-c code %.o:%.mm - $(CXX) $(CPPFLAGS) $(CXXFLAGS) $@ $< + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< ifneq ($(MAKECMDGOALS),clean) -include $(LINKOBJ:.o=.d) diff --git a/source/Irrlicht/SConstruct b/source/Irrlicht/SConstruct index c8bdcfd1..457a1b19 100644 --- a/source/Irrlicht/SConstruct +++ b/source/Irrlicht/SConstruct @@ -6,7 +6,7 @@ NDEBUG = 1; PROFILE = 1; APPLICATION_NAME = 'Irrlicht'; -LIBRARIES = ['gdi32', 'opengl32', 'd3dx9d']; +LIBRARIES = ['gdi32', 'opengl32', 'd3dx9d', 'winmm']; if USE_GCC==1 and PROFILE==1: LIBRARIES += ['gmon']; @@ -81,7 +81,10 @@ else: if PROFILE: CXXFLAGS += ['-pg']; -CXXFLAGS += ['-DPNG_NO_MMX_CODE', '-DPNG_NO_MNG_FEATURES', '-DIRRLICHT_EXPORTS=1']; +CXXFLAGS += ['-DPNG_NO_MMX_CODE', '-DPNG_NO_MNG_FEATURES', '-DIRRLICHT_EXPORTS=1', '-D_IRR_STATIC_LIB_']; +if USE_GCC: + CXXFLAGS += ['-D__GNUWIN32__=1']; + env.Append(CCFLAGS = CXXFLAGS); IrrlichtLibrary = env.SharedLibrary("Irrlicht.dll", LINKOBJ); diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 00000000..722a6f87 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,39 @@ +# Irrlicht Engine Regression Tests Makefile +Target = tests +Sources = $(wildcard *.cpp) + +CPPFLAGS = -I../include -I/usr/X11R6/include -pipe +# CXXFLAGS += -Wall -O3 +CXXFLAGS += -g -D_DEBUG + +ifeq ($(HOSTTYPE), x86_64) +LIBSELECT=64 +endif + +all: all_linux + +# target specific settings +all_linux: SYSTEM=Linux +all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../lib/$(SYSTEM) -lIrrlicht -lGL -lXxf86vm -lXext -lX11 + +all_win32 clean_win32: SYSTEM=Win32-gcc +all_win32: LDFLAGS = -L../lib/$(SYSTEM) -lIrrlicht -lopengl32 -lm + +all_win32 clean_win32: SUF=.exe +# name of the binary - only valid for targets which set SYSTEM +DESTPATH = ../bin/$(SYSTEM)/$(Target)$(SUF) + +OBJ = $(Sources:.cpp=.o) + +all_linux all_win32: $(OBJ) + $(warning Building...) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $(DESTPATH) $(LDFLAGS) + +clean: clean_linux clean_win32 + $(warning Cleaning...) + @$(RM) $(OBJ) + +clean_linux clean_win32: + @$(RM) $(DESTPATH) + +.PHONY: all all_win32 clean clean_linux clean_win32 diff --git a/tests/b3dAnimation.cpp b/tests/b3dAnimation.cpp new file mode 100644 index 00000000..d11fff28 --- /dev/null +++ b/tests/b3dAnimation.cpp @@ -0,0 +1,71 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "irrlicht.h" +#include "testUtils.h" +#include + +using namespace irr; +using namespace core; +using namespace scene; +using namespace video; +using namespace io; +using namespace gui; + +// Tests B3D animations. +/** Verify that two skinned animated mesh scene nodes can use different frames of the skinned mesh */ +bool b3dAnimation(void) +{ + // Use EDT_BURNINGSVIDEO since it is not dependent on (e.g.) OpenGL driver versions. + IrrlichtDevice *device = createDevice( EDT_BURNINGSVIDEO, dimension2d(160, 120), 32); + assert(device); + if (!device) + return false; + + IVideoDriver* driver = device->getVideoDriver(); + ISceneManager * smgr = device->getSceneManager(); + + IAnimatedMesh* mesh = smgr->getMesh("../media/ninja.b3d"); + IAnimatedMeshSceneNode* node1; + IAnimatedMeshSceneNode* node2; + assert(mesh); + + bool result = false; + if(mesh) + { + node1 = smgr->addAnimatedMeshSceneNode(mesh); + assert(node1); + + if(node1) + { + node1->setPosition(vector3df(-3, -3, 10)); + node1->setMaterialFlag(EMF_LIGHTING, false); + node1->setAnimationSpeed(0.f); + } + + node2 = smgr->addAnimatedMeshSceneNode(mesh); + assert(node2); + if(node2) + { + node2->setPosition(vector3df(3, -3, 10)); + node2->setMaterialFlag(EMF_LIGHTING, false); + node2->setAnimationSpeed(0.f); + node2->setCurrentFrame(62.f); + } + + (void)smgr->addCameraSceneNode(); + + // Just jump to the last frame since that's all we're interested in. + device->run(); + driver->beginScene(true, true, SColor(255, 255, 255, 0)); + smgr->drawAll(); + driver->endScene(); + + result = takeScreenshotAndCompareAgainstReference(driver, "-b3dAnimation.png"); + } + + device->drop(); + + return result; +} + diff --git a/tests/collisionResponseAnimator.cpp b/tests/collisionResponseAnimator.cpp new file mode 100644 index 00000000..a1ccaa13 --- /dev/null +++ b/tests/collisionResponseAnimator.cpp @@ -0,0 +1,106 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "testUtils.h" +#include "irrlicht.h" +#include + +using namespace irr; +using namespace core; +using namespace scene; +using namespace video; + + +/** Test that collision response animator will reset itself when removed from a + scene node, so that the scene node can then be moved without the animator + jumping it back again. */ +bool collisionResponseAnimator(void) +{ + IrrlichtDevice * device = irr::createDevice(video::EDT_NULL); + assert(device); + if(!device) + return false; + + ISceneManager * smgr = device->getSceneManager(); + + // Create 2 nodes to the left of a "wall" + ISceneNode * testNode1 = smgr->addEmptySceneNode(); + ISceneNode * testNode2 = smgr->addEmptySceneNode(); + testNode1->setPosition(vector3df(-50, 0,0)); + testNode2->setPosition(vector3df(-50, 0,0)); + + // Create a "wall" node, and collision response animators for each test node. + IMeshSceneNode * wallNode = smgr->addCubeSceneNode(10.f); + + ITriangleSelector * wallSelector = smgr->createTriangleSelectorFromBoundingBox(wallNode); + ISceneNodeAnimatorCollisionResponse * collisionAnimator1 = + smgr->createCollisionResponseAnimator(wallSelector, + testNode1, + vector3df(10,10,10), + vector3df(0, 0, 0)); + testNode1->addAnimator(collisionAnimator1); + collisionAnimator1->drop(); + collisionAnimator1 = 0; + + ISceneNodeAnimatorCollisionResponse * collisionAnimator2 = + smgr->createCollisionResponseAnimator(wallSelector, + testNode2, + vector3df(10,10,10), + vector3df(0, 0, 0)); + testNode2->addAnimator(collisionAnimator2); + + wallSelector->drop(); + // Don't drop() collisionAnimator2 since we're going to use it. + + // Get the system in a good state + device->run(); + smgr->drawAll(); + + // Try to move both nodes to the right of the wall. + // This one should be stopped by its animator. + testNode1->setPosition(vector3df(50, 0,0)); + + // Whereas this one, by forcing the animator to update its target node, should be + // able to pass through the wall. (In <=1.6 it was stopped by the wall even if + // the animator was removed and later re-added); + testNode2->setPosition(vector3df(50, 0,0)); + collisionAnimator2->setTargetNode(testNode2); + collisionAnimator2->drop(); // We're done using this now. + + device->run(); + smgr->drawAll(); + + bool result = true; + + if(testNode1->getAbsolutePosition().X > -15.f) + { + logTestString("collisionResponseAnimator test node 1 wasn't stopped from moving.\n"); + assert(false); + result = false; + } + + if(testNode2->getAbsolutePosition().X < 50.f) + { + logTestString("collisionResponseAnimator test node 2 was stopped from moving.\n"); + assert(false); + result = false; + } + + // Now try to move the second node back through the wall again. Now it should be + // stopped by the wall. + testNode2->setPosition(vector3df(-50, 0, 0)); + device->run(); + smgr->drawAll(); + + if(testNode2->getAbsolutePosition().X < 15.f) + { + logTestString("collisionResponseAnimator test node 2 wasn't stopped from moving.\n"); + assert(false); + result = false; + } + + device->drop(); + return result; +} + + diff --git a/tests/disambiguateTextures.cpp b/tests/disambiguateTextures.cpp new file mode 100644 index 00000000..cca8b9a1 --- /dev/null +++ b/tests/disambiguateTextures.cpp @@ -0,0 +1,82 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "testUtils.h" +#include +#include + +using namespace irr; +using namespace core; +using namespace scene; +using namespace video; +using namespace io; +using namespace gui; + +/** This tests verifies that textures opened from different places in the filesystem + can be distinguished, even if they have the same filename. */ +bool disambiguateTextures(void) +{ + IrrlichtDevice *device = + createDevice( video::EDT_NULL, dimension2d(640, 480)); + + if (!device) + { + logTestString("Unable to create EDT_NULL device\n"); + return false; + } + + // Expects an empty tmp/tmp directory under this app's wd and + // a media directory under this apps' directory with tools.png in it. + stringc wd = device->getFileSystem()->getWorkingDirectory(); + + if(-1 == wd.find("/tests") && -1 == wd.find("\\tests")) + { + logTestString("The tests must be run from the /tests directory, regardless of where\n"\ + "the test executable was built.\n"); + device->drop(); + return false; + } + + IVideoDriver * driver = device->getVideoDriver(); + + ITexture * tex1 = driver->getTexture("../media/tools.png"); + assert(tex1); + if(!tex1) + logTestString("Unable to open ../media/tools.png\n"); + + ITexture * tex2 = driver->getTexture("../media/tools.png"); + assert(tex2); + if(!tex2) + logTestString("Unable to open ../media/tools.png\n"); + + IReadFile * readFile = device->getFileSystem()->createAndOpenFile("../media/tools.png"); + assert(readFile); + if(!readFile) + logTestString("Unable to open ../media/tools.png\n"); + + ITexture * tex3 = driver->getTexture(readFile); + assert(tex3); + if(!readFile) + logTestString("Unable to create texture from ../media/tools.png\n"); + + readFile->drop(); + + // All 3 of the above textures should be identical. + assert(tex1 == tex2 && tex1 == tex3); + + stringc newWd = wd + "/empty/empty"; + bool changed = device->getFileSystem()->changeWorkingDirectoryTo(newWd.c_str()); + assert(changed); + ITexture * tex4 = driver->getTexture("../../media/tools.png"); + assert(tex4); + if(!tex4) + logTestString("Unable to open ../../media/tools.png\n"); + assert(tex1 != tex4); + + // The working directory must be restored for the other tests to work. + changed &= device->getFileSystem()->changeWorkingDirectoryTo(wd.c_str()); + + device->drop(); + return (changed && tex1 == tex2 && tex1 == tex3 && tex1 != tex4) ? true : false; +} + diff --git a/tests/drawPixel.cpp b/tests/drawPixel.cpp new file mode 100644 index 00000000..7565bf27 --- /dev/null +++ b/tests/drawPixel.cpp @@ -0,0 +1,68 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "irrlicht.h" +#include "testUtils.h" + +using namespace irr; +using namespace core; +using namespace scene; +using namespace video; +using namespace io; +using namespace gui; + +//! Tests IVideoDriver::drawPixel(). +/** Expect to see two diagonal lines overlaying a wall texture cube. + One line should run from green at the top left to red at the bottom right. + The other should run from cyan 100% transparent at the bottom left to + cyan 100% opaque at the top right. */ +static bool runTestWithDriver(E_DRIVER_TYPE driverType) +{ + IrrlichtDevice *device = createDevice( driverType, dimension2d(160, 120), 32); + if (!device) + return true; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs + + IVideoDriver* driver = device->getVideoDriver(); + ISceneManager * smgr = device->getSceneManager(); + + // Draw a cube background so that we can check that the pixels' alpha is working. + ISceneNode * cube = smgr->addCubeSceneNode(50.f, 0, -1, vector3df(0, 0, 60)); + cube->setMaterialTexture(0, driver->getTexture("../media/wall.bmp")); + cube->setMaterialFlag(video::EMF_LIGHTING, false); + (void)smgr->addCameraSceneNode(); + + driver->beginScene(true, true, SColor(255,100,101,140)); + smgr->drawAll(); + + // Test for benign handling of offscreen pixel values as well as onscreen ones. + for(s32 x = -10; x < 170; ++x) + { + s32 y = 120 * x / 160; + driver->drawPixel((u32)x, (u32)y, SColor(255, 255 * x / 640, 255 * (640 - x) / 640, 0)); + y = 120 - y; + driver->drawPixel((u32)x, (u32)y, SColor(255 * x / 640, 0, 255, 255)); + } + + driver->endScene(); + + bool result = takeScreenshotAndCompareAgainstReference(driver, "-drawPixel.png"); + + device->drop(); + + return result; +} + + +bool drawPixel(void) +{ + bool passed = true; + + passed &= runTestWithDriver(EDT_SOFTWARE); + passed &= runTestWithDriver(EDT_BURNINGSVIDEO); + passed &= runTestWithDriver(EDT_DIRECT3D9); + passed &= runTestWithDriver(EDT_DIRECT3D8); + passed &= runTestWithDriver(EDT_OPENGL); + + return passed; +} + diff --git a/tests/empty/empty/Direct3D 9.0.png b/tests/empty/empty/Direct3D 9.0.png new file mode 100644 index 00000000..66f160a8 Binary files /dev/null and b/tests/empty/empty/Direct3D 9.0.png differ diff --git a/tests/empty/empty/Irrlicht Software Device 1.0.png b/tests/empty/empty/Irrlicht Software Device 1.0.png new file mode 100644 index 00000000..b5389f1d Binary files /dev/null and b/tests/empty/empty/Irrlicht Software Device 1.0.png differ diff --git a/tests/empty/empty/OpenGL 2.1.2.png b/tests/empty/empty/OpenGL 2.1.2.png new file mode 100644 index 00000000..a88e0476 Binary files /dev/null and b/tests/empty/empty/OpenGL 2.1.2.png differ diff --git a/tests/empty/empty/burnings video 0.39b.png b/tests/empty/empty/burnings video 0.39b.png new file mode 100644 index 00000000..de345676 Binary files /dev/null and b/tests/empty/empty/burnings video 0.39b.png differ diff --git a/tests/exports.cpp b/tests/exports.cpp new file mode 100644 index 00000000..09d8b390 --- /dev/null +++ b/tests/exports.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "testUtils.h" +#include "irrlicht.h" + +//! Tests that symbols exported from Irrlicht can be used by the user app. +bool exports(void) +{ + irr::core::matrix4 identity = irr::core::IdentityMatrix; + (void)identity; // Satisfy the compiler that it's used. + + // If it built, we're done. + return true; +} diff --git a/tests/fast_atof.cpp b/tests/fast_atof.cpp new file mode 100644 index 00000000..20c5dd8b --- /dev/null +++ b/tests/fast_atof.cpp @@ -0,0 +1,179 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "testUtils.h" +#include "irrlicht.h" +#include +#include +#include + +using namespace irr; +using namespace core; + +//! This was an older Irrlicht implementation, tested against for reference. +static inline u32 old_strtol10(const char* in, const char** out=0) +{ + u32 value = 0; + + while ( ( *in >= '0') && ( *in <= '9' )) + { + value = ( value * 10 ) + ( *in - '0' ); + ++in; + } + if (out) + *out = in; + return value; +} + +//! This was an older Irrlicht implementation, tested against for reference. +static inline const char* old_fast_atof_move( const char* c, float& out) +{ + bool inv = false; + const char *t; + float f; + + if (*c=='-') + { + ++c; + inv = true; + } + + //f = (float)strtol(c, &t, 10); + f = (float) old_strtol10 ( c, &c ); + + if (*c == '.') + { + ++c; + + //float pl = (float)strtol(c, &t, 10); + float pl = (float) old_strtol10 ( c, &t ); + pl *= fast_atof_table[t-c]; + + f += pl; + + c = t; + + if (*c == 'e') + { + ++c; + //float exp = (float)strtol(c, &t, 10); + bool einv = (*c=='-'); + if (einv) + ++c; + + float exp = (float)old_strtol10(c, &c); + if (einv) + exp *= -1.0f; + + f *= (float)pow(10.0f, exp); + } + } + + if (inv) + f *= -1.0f; + + out = f; + return c; +} + +//! This was an older Irrlicht implementation, tested against for reference. +static inline float old_fast_atof(const char* c) +{ + float ret; + old_fast_atof_move(c, ret); + return ret; +} + + +static bool testCalculation(const char * valueString) +{ + const f32 newFastValue = fast_atof(valueString); + const f32 oldFastValue = old_fast_atof(valueString); + const f32 atofValue = (f32)atof(valueString); + + logTestString("\n String '%s'\n New fast %.40f\n Old fast %.40f\n atof %.40f\n", + valueString, newFastValue, oldFastValue, atofValue); + + bool accurate = fabs(newFastValue - atofValue) <= fabs(oldFastValue - atofValue); + + if(!accurate) + logTestString("*** ERROR - less accurate than old method ***\n\n"); + + return accurate; +} + +//! Test both the accuracy and speed of Irrlicht's fast_atof() implementation. +bool fast_atof(void) +{ + bool accurate = true; + + accurate &= testCalculation("340282346638528859811704183484516925440.000000"); + accurate &= testCalculation("3.402823466e+38F"); + accurate &= testCalculation("3402823466e+29F"); + accurate &= testCalculation("-340282346638528859811704183484516925440.000000"); + accurate &= testCalculation("-3.402823466e+38F"); + accurate &= testCalculation("-3402823466e+29F"); + accurate &= testCalculation("34028234663852885981170418348451692544.000000"); + accurate &= testCalculation("3.402823466e+37F"); + accurate &= testCalculation("3402823466e+28F"); + accurate &= testCalculation("-34028234663852885981170418348451692544.000000"); + accurate &= testCalculation("-3.402823466e+37F"); + accurate &= testCalculation("-3402823466e+28F"); + accurate &= testCalculation(".00234567"); + accurate &= testCalculation("-.00234567"); + accurate &= testCalculation("0.00234567"); + accurate &= testCalculation("-0.00234567"); + accurate &= testCalculation("1.175494351e-38F"); + accurate &= testCalculation("1175494351e-47F"); + accurate &= testCalculation("1.175494351e-37F"); + accurate &= testCalculation("1.175494351e-36F"); + accurate &= testCalculation("-1.175494351e-36F"); + accurate &= testCalculation("123456.789"); + accurate &= testCalculation("-123456.789"); + accurate &= testCalculation("0000123456.789"); + accurate &= testCalculation("-0000123456.789"); + + if(!accurate) + { + logTestString("Calculation is not accurate, so the speed is irrelevant\n"); + return false; + } + + IrrlichtDevice* device = createDevice(video::EDT_NULL); + if (!device) + return false; + ITimer* timer = device->getTimer(); + + enum { ITERATIONS = 100000 }; + int i; + + f32 value; + u32 then = timer->getRealTime(); + for(i = 0; i < ITERATIONS; ++i) + value = (f32)atof("-340282346638528859811704183484516925440.000000"); + + const u32 atofTime = timer->getRealTime() - then; + + then += atofTime; + for(i = 0; i < ITERATIONS; ++i) + value = fast_atof("-340282346638528859811704183484516925440.000000"); + const u32 fastAtofTime = timer->getRealTime() - then; + + then += fastAtofTime; + for(i = 0; i < ITERATIONS; ++i) + value = old_fast_atof("-340282346638528859811704183484516925440.000000"); + const u32 oldFastAtofTime = timer->getRealTime() - then; + + logTestString(" atof time = %d\n fast_atof Time = %d\nold fast_atof time = %d\n", + atofTime, fastAtofTime, oldFastAtofTime); + + device->drop(); + if(fastAtofTime > atofTime) + { + logTestString("The fast method is slower than atof()\n"); + return false; + } + + return true; +} + diff --git a/tests/guiDisabledMenu.cpp b/tests/guiDisabledMenu.cpp new file mode 100644 index 00000000..a9dbb3d6 --- /dev/null +++ b/tests/guiDisabledMenu.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "irrlicht.h" +#include "testUtils.h" +#include + +using namespace irr; +using namespace core; +using namespace gui; + +// Tests that disabled GUI menu items don't cause their submenu to appear when hovered over. +/** + http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?p=178436#178436 + */ + +bool guiDisabledMenu(void) +{ + IrrlichtDevice *device = createDevice( video::EDT_OPENGL, + dimension2d(160, 40), 32); + assert(device); + if (!device) + return false; + + video::IVideoDriver* driver = device->getVideoDriver(); + gui::IGUIEnvironment* env = device->getGUIEnvironment(); + + gui::IGUIContextMenu* menu = env->addMenu(); + menu->addItem(L"Menu", -1, true, true); + gui::IGUIContextMenu* subMenu = menu->getSubMenu(0); + subMenu->addItem(L"Submenu 1", -1, false, true); + gui::IGUIContextMenu* subSubMenu = subMenu->getSubMenu(0); + subSubMenu->addItem(L"Final item"); + + SEvent event; + event.EventType = EET_MOUSE_INPUT_EVENT; + event.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN; + event.MouseInput.X = menu->getAbsolutePosition().UpperLeftCorner.X + 1; + event.MouseInput.Y = menu->getAbsolutePosition().UpperLeftCorner.Y + 1; + (void)menu->OnEvent(event); + + // Hovering over the disabled submenu shouldn't cause the "Final item" to appear. + event.MouseInput.Event = EMIE_MOUSE_MOVED; + event.MouseInput.X = subMenu->getAbsolutePosition().UpperLeftCorner.X + 40; + event.MouseInput.Y = subMenu->getAbsolutePosition().UpperLeftCorner.Y + 10; + (void)menu->OnEvent(event); + + device->run(); + driver->beginScene(true, true, video::SColor(150,50,50,50)); + env->drawAll(); + driver->endScene(); + + bool result = takeScreenshotAndCompareAgainstReference(driver, "-guiDisabledMenu.png"); + device->drop(); + + return result; +} + diff --git a/tests/line2dIntersectWith.cpp b/tests/line2dIntersectWith.cpp new file mode 100644 index 00000000..4946373b --- /dev/null +++ b/tests/line2dIntersectWith.cpp @@ -0,0 +1,228 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "testUtils.h" +#include +#include + +using namespace irr; +using namespace core; + +static bool testLines(line2df const & line1, + line2df const & line2, + bool expectedHit, + const vector2df & expectedIntersection) +{ + bool gotExpectedResult = true; + + logTestString("\nLine 1 = %.1f %.1f to %.1f %.1f \n", + line1.start.X, line1.start.Y, + line1.end.X, line1.end.Y); + logTestString("Line 2 = %.1f %.1f to %.1f %.1f\n", + line2.start.X, line2.start.Y, + line2.end.X, line2.end.Y); + + vector2df intersection; + logTestString("line1 with line2 = "); + if(line1.intersectWith(line2, intersection)) + { + logTestString("hit at %.1f %.1f - ", + intersection.X, intersection.Y); + + if(!line1.isPointOnLine(intersection) || !line2.isPointOnLine(intersection)) + { + logTestString("ERROR! point is not on both lines - "); + gotExpectedResult = false; + } + + if(expectedHit) + { + if(intersection == expectedIntersection) + { + logTestString("expected\n"); + } + else + { + logTestString("unexpected intersection (expected %.1f %.1f)\n", + expectedIntersection.X, expectedIntersection.Y); + gotExpectedResult = false; + } + } + else + { + logTestString("UNEXPECTED\n"); + gotExpectedResult = false; + } + } + else + { + logTestString("miss - "); + if(!expectedHit) + { + logTestString("expected\n"); + } + else + { + logTestString("UNEXPECTED\n"); + gotExpectedResult = false; + } + } + + logTestString("line2 with line1 = "); + if(line2.intersectWith(line1, intersection)) + { + logTestString("hit at %.1f %.1f - ", + intersection.X, intersection.Y); + if(!line1.isPointOnLine(intersection) || !line2.isPointOnLine(intersection)) + { + logTestString("ERROR! point is not on both lines - "); + gotExpectedResult = false; + } + + if(expectedHit) + { + if(intersection == expectedIntersection) + { + logTestString("expected\n"); + } + else + { + logTestString("unexpected intersection (expected %.1f %.1f)\n", + expectedIntersection.X, expectedIntersection.Y); + gotExpectedResult = false; + } + } + else + { + logTestString("UNEXPECTED\n"); + gotExpectedResult = false; + } + } + else + { + logTestString("miss - "); + if(!expectedHit) + { + logTestString("expected\n"); + } + else + { + logTestString("UNEXPECTED\n"); + gotExpectedResult = false; + } + } + + return gotExpectedResult; +} + +// Test the functionality of line2d>T>::intersectWith(). +/** Validation is done with asserts() against expected results. */ +bool line2dIntersectWith(void) +{ + bool allExpected = true; + + // Crossing lines, horizontal and vertical + allExpected &= testLines(line2df(vector2df(1,1),vector2df(1,3)), + line2df(vector2df(0,2),vector2df(2,2)), + true, vector2df(1,2)); + + // Crossing lines, both diagonal + allExpected &= testLines(line2df(vector2df(0,0),vector2df(2,2)), + line2df(vector2df(0,2),vector2df(2,0)), + true, vector2df(1,1)); + + // Non-crossing lines, horizontal and vertical + allExpected &= testLines(line2df(vector2df(1,1),vector2df(1,3)), + line2df(vector2df(0,4),vector2df(2,4)), + false, vector2df()); + + // Non-crossing lines, both diagonal + allExpected &= testLines(line2df(vector2df(0,0),vector2df(2,2)), + line2df(vector2df(3,4),vector2df(4,3)), + false, vector2df()); + + // Meeting at a common point + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,0)), + line2df(vector2df(1,0),vector2df(2,0)), + true, vector2df(1,0)); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,0)), + line2df(vector2df(1,0),vector2df(0,1)), + true, vector2df(1,0)); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,0)), + line2df(vector2df(1,0),vector2df(0,-1)), + true, vector2df(1,0)); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(0,1)), + line2df(vector2df(0,1),vector2df(1,1)), + true, vector2df(0,1)); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(0,1)), + line2df(vector2df(0,1),vector2df(1,-1)), + true, vector2df(0,1)); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(0,1)), + line2df(vector2df(0,1),vector2df(0,2)), + true, vector2df(0,1)); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,0)), + line2df(vector2df(1,0),vector2df(2,0)), + true, vector2df(1,0)); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,1)), + line2df(vector2df(1,1),vector2df(0,2)), + true, vector2df(1,1)); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,1)), + line2df(vector2df(1,1),vector2df(2,0)), + true, vector2df(1,1)); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,1)), + line2df(vector2df(1,1),vector2df(2,2)), + true, vector2df(1,1)); + + + // Parallel lines, no intersection + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,0)), + line2df(vector2df(0,1),vector2df(1,1)), + false, vector2df()); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(0,1)), + line2df(vector2df(1,0),vector2df(1,1)), + false, vector2df()); + + // Non parallel lines, no intersection + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,0)), + line2df(vector2df(0,1),vector2df(0,2)), + false, vector2df()); + allExpected &= testLines(line2df(vector2df(0,0),vector2df(0,1)), + line2df(vector2df(1,0),vector2df(2,0)), + false, vector2df()); + + // Coincident (and thus parallel) lines + allExpected &= testLines(line2df(vector2df(0,0),vector2df(1,0)), + line2df(vector2df(0,0),vector2df(1,0)), + true, vector2df(0,0)); + allExpected &= testLines(line2df(vector2df(2,0),vector2df(0,2)), + line2df(vector2df(2,0),vector2df(0,2)), + true, vector2df(2,0)); + + // Overlapping parallel lines + allExpected &= testLines(line2df(vector2df(1,0),vector2df(2,0)), + line2df(vector2df(0,0),vector2df(3,0)), + true, vector2df(1.5f, 0)); + allExpected &= testLines(line2df(vector2df(0,1),vector2df(0,2)), + line2df(vector2df(0,0),vector2df(0,3)), + true, vector2df(0, 1.5f)); + allExpected &= testLines(line2df(vector2df(1,0),vector2df(2,0)), + line2df(vector2df(0,0),vector2df(3,0)), + true, vector2df(1.5f, 0)); + allExpected &= testLines(line2df(vector2df(0,1),vector2df(0,2)), + line2df(vector2df(0,0),vector2df(0,3)), + true, vector2df(0, 1.5f)); + allExpected &= testLines(line2df(vector2df(1,1),vector2df(2,2)), + line2df(vector2df(0,0),vector2df(3,3)), + true, vector2df(1.5f, 1.5f)); + allExpected &= testLines(line2df(vector2df(1,2),vector2df(2,1)), + line2df(vector2df(0,3),vector2df(3,0)), + true, vector2df(1.5f, 1.5f)); + + if(allExpected) + logTestString("\nAll tests passed\n"); + else + logTestString("\nFAIL!\n"); + + return allExpected; +} + diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 00000000..483c5809 --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,152 @@ +// This is the entry point for the Irrlicht test suite. +#define _CRT_SECURE_NO_WARNINGS + +#include "testUtils.h" +#include +#include +#include + +// This is an MSVC pragma to link against the Irrlicht library. +// Other builds must link against it in the project files. +#if defined(_MSC_VER) +#pragma comment(lib, "Irrlicht.lib") +#endif // _MSC_VER + +/* Each test must have the same signature. Test should (but are not + * required to) live in a .cpp file of the same name. There is no + * need to #include anything since the test entry points can be + * declared as extern before calling them. + */ +#define RUN_TEST(testEntryPoint)\ + extern bool testEntryPoint(void);\ + logTestString("\nStarting test '" #testEntryPoint "'\n");\ + if(!testEntryPoint()) \ + {\ + (void)printf("\n\n\n******** Test failure ********\nTest '" #testEntryPoint "' failed\n"\ + "******** Test failure ********\n\nPress return to continue\n");\ + (void)getc(stdin);\ + fails++;\ + } + +//! This is the main entry point for the Irrlicht test suite. +/** \return The number of test that failed, i.e. 0 is success. */ +int main(int argumentCount, char * arguments[]) +{ + bool logFileOpened = openTestLog(1 == argumentCount); + assert(logFileOpened); + + if(argumentCount > 3) + { + logTestString("\nUsage: %s [testNumber] [totalFails]\n"); + closeTestLog(); + return 9999; + } + + extern bool disambiguateTextures(void); + extern bool softwareDevice(void); + extern bool exports(void); + extern bool testVector3d(void); + extern bool testVector2d(void); + extern bool planeMatrix(void); + extern bool fast_atof(void); + extern bool line2dIntersectWith(void); + extern bool drawPixel(void); + extern bool md2Animation(void); + extern bool b3dAnimation(void); + extern bool guiDisabledMenu(void); + extern bool collisionResponseAnimator(void); + extern bool sceneCollisionManager(void); + + typedef struct _STest + { + bool(*testSignature)(void); + const char * testName; + } STest; + + #define TEST(x) { x, #x } + + static const STest tests[] = + { + // Note that to interactively debug a test, you will generally want to move it + // (temporarily) to the beginning of the list, since each test runs in its own + // process. + TEST(disambiguateTextures), // Normally you should run this first, since it validates the working directory. + TEST(sceneCollisionManager), + TEST(collisionResponseAnimator), + TEST(exports), + TEST(testVector3d), + TEST(testVector2d), + TEST(planeMatrix), + TEST(fast_atof), + TEST(line2dIntersectWith), + TEST(drawPixel), + TEST(md2Animation), + TEST(guiDisabledMenu), + TEST(softwareDevice), + TEST(b3dAnimation) + }; + static const unsigned int numberOfTests = sizeof tests / sizeof tests[0]; + + unsigned int testToRun = 0; + unsigned int fails = 0; + + if(argumentCount > 1) + { + testToRun = (unsigned int)atoi(arguments[1]); + if(testToRun >= numberOfTests) + { + logTestString("\nError: invalid test %d (maximum %d)\n", + testToRun, numberOfTests - 1); + closeTestLog(); + return 9999; + } + } + + if(argumentCount > 2) + fails = (unsigned int)atoi(arguments[2]); + + logTestString("\nStarting test %d, '%s'\n", + testToRun, tests[testToRun].testName); + + bool success = tests[testToRun].testSignature(); + + if(!success) + { + logTestString("\n\n\n******** Test failure ********\nTest %d '%s' failed\n"\ + "******** Test failure ********\n", + testToRun, tests[testToRun].testName); + fails++; + } + + testToRun++; + + if(testToRun == numberOfTests) + { + logTestString("\nTests finished. %d test%s failed.\n", fails, 1 == fails ? "" : "s"); + if(0 == fails) + { + time_t rawtime; + struct tm * timeinfo; + (void)time(&rawtime); + timeinfo = gmtime(&rawtime); + (void)printf("\nTest suite pass at GMT %s\n", asctime(timeinfo)); + FILE * testsLastPassedAtFile = fopen("tests-last-passed-at.txt", "w"); + if(testsLastPassedAtFile) + { + (void)fprintf(testsLastPassedAtFile, "Test suite pass at GMT %s\n", asctime(timeinfo)); + (void)fclose(testsLastPassedAtFile); + } + } + closeTestLog(); + } + else + { + closeTestLog(); + char runNextTest[256]; + (void)sprintf(runNextTest, "%s %d %d", arguments[0], testToRun, fails); + fails = system(runNextTest); + } + + return fails; +} + diff --git a/tests/md2Animation.cpp b/tests/md2Animation.cpp new file mode 100644 index 00000000..6717145b --- /dev/null +++ b/tests/md2Animation.cpp @@ -0,0 +1,61 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "irrlicht.h" +#include "testUtils.h" +#include + +using namespace irr; +using namespace core; +using namespace scene; +using namespace video; +using namespace io; +using namespace gui; + +// Tests MD2 animations. +/** At the moment, this just verifies that the last frame of the animation produces the expected bitmap. */ +bool md2Animation(void) +{ + // Use EDT_BURNINGSVIDEO since it is not dependent on (e.g.) OpenGL driver versions. + IrrlichtDevice *device = createDevice( EDT_BURNINGSVIDEO, dimension2d(160, 120), 32); + assert(device); + if (!device) + return false; + + IVideoDriver* driver = device->getVideoDriver(); + ISceneManager * smgr = device->getSceneManager(); + + IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2"); + IAnimatedMeshSceneNode* node; + assert(mesh); + + if(mesh) + { + node = smgr->addAnimatedMeshSceneNode(mesh); + assert(node); + + if(node) + { + node->setPosition(vector3df(20, 0, 30)); + node->setMaterialFlag(EMF_LIGHTING, false); + node->setMaterialTexture(0, driver->getTexture("../media/sydney.bmp")); + node->setLoopMode(false); + + (void)smgr->addCameraSceneNode(); + + // Just jump to the last frame since that's all we're interested in. + node->setMD2Animation(EMAT_DEATH_FALLBACK); + node->setCurrentFrame((f32)(node->getEndFrame())); + device->run(); + driver->beginScene(true, true, SColor(255, 255, 255, 0)); + smgr->drawAll(); + driver->endScene(); + } + } + + bool result = takeScreenshotAndCompareAgainstReference(driver, "-md2Animation.png"); + device->drop(); + + return result; +} + diff --git a/tests/media/Direct3D 8.1-drawPixel.png b/tests/media/Direct3D 8.1-drawPixel.png new file mode 100644 index 00000000..c045fafd Binary files /dev/null and b/tests/media/Direct3D 8.1-drawPixel.png differ diff --git a/tests/media/Direct3D 9.0-drawPixel.png b/tests/media/Direct3D 9.0-drawPixel.png new file mode 100644 index 00000000..3f39ed5c Binary files /dev/null and b/tests/media/Direct3D 9.0-drawPixel.png differ diff --git a/tests/media/Irrlicht Software Device 1.0-drawPixel.png b/tests/media/Irrlicht Software Device 1.0-drawPixel.png new file mode 100644 index 00000000..9002faf8 Binary files /dev/null and b/tests/media/Irrlicht Software Device 1.0-drawPixel.png differ diff --git a/tests/media/Irrlicht Software Device 1.0-softwareDevice-rotatedClip.png b/tests/media/Irrlicht Software Device 1.0-softwareDevice-rotatedClip.png new file mode 100644 index 00000000..9f753599 Binary files /dev/null and b/tests/media/Irrlicht Software Device 1.0-softwareDevice-rotatedClip.png differ diff --git a/tests/media/OpenGL-drawPixel.png b/tests/media/OpenGL-drawPixel.png new file mode 100644 index 00000000..2f9f5811 Binary files /dev/null and b/tests/media/OpenGL-drawPixel.png differ diff --git a/tests/media/OpenGL-guiDisabledMenu.png b/tests/media/OpenGL-guiDisabledMenu.png new file mode 100644 index 00000000..425a582e Binary files /dev/null and b/tests/media/OpenGL-guiDisabledMenu.png differ diff --git a/tests/media/burnings video 0.39b-b3dAnimation.png b/tests/media/burnings video 0.39b-b3dAnimation.png new file mode 100644 index 00000000..ef65d943 Binary files /dev/null and b/tests/media/burnings video 0.39b-b3dAnimation.png differ diff --git a/tests/media/burnings video 0.39b-drawPixel.png b/tests/media/burnings video 0.39b-drawPixel.png new file mode 100644 index 00000000..0c857e79 Binary files /dev/null and b/tests/media/burnings video 0.39b-drawPixel.png differ diff --git a/tests/media/burnings video 0.39b-md2Animation.png b/tests/media/burnings video 0.39b-md2Animation.png new file mode 100644 index 00000000..2f6a3fd5 Binary files /dev/null and b/tests/media/burnings video 0.39b-md2Animation.png differ diff --git a/tests/media/burnings video 0.39b-planeMatrix-scaledClip.png b/tests/media/burnings video 0.39b-planeMatrix-scaledClip.png new file mode 100644 index 00000000..68c1065e Binary files /dev/null and b/tests/media/burnings video 0.39b-planeMatrix-scaledClip.png differ diff --git a/tests/media/tools.png b/tests/media/tools.png new file mode 100644 index 00000000..b7e86c93 Binary files /dev/null and b/tests/media/tools.png differ diff --git a/tests/planeMatrix.cpp b/tests/planeMatrix.cpp new file mode 100644 index 00000000..0086aa71 --- /dev/null +++ b/tests/planeMatrix.cpp @@ -0,0 +1,237 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "testUtils.h" +#include "irrlicht.h" +#include + +using namespace irr; +using namespace core; +using namespace scene; +using namespace video; +using namespace io; +using namespace gui; + +// There's all sorts of minor and inevitable FP accuracy errors here, so use a sloppy comparison. +static bool sloppyComparePlanes(const plane3df plane1, const plane3df plane2) +{ + return(equals(plane1.D, plane2.D, 0.001f) && + equals(plane1.Normal.X, plane2.Normal.X, 0.001f) && + equals(plane1.Normal.Y, plane2.Normal.Y, 0.001f) && + equals(plane1.Normal.Z, plane2.Normal.Z, 0.001f)); +} + +static bool transformPlane(const vector3df & point, const vector3df & normal, + const matrix4 & matrix, const plane3df & expected) +{ + plane3df plane(point, vector3df(normal).normalize()); + + logTestString("\n Pre: (%.3ff,%.3ff,%.3ff), %.3ff\n", + plane.Normal.X, plane.Normal.Y, plane.Normal.Z, plane.D); + + matrix.transformPlane(plane); + + logTestString(" Post: (%.3ff,%.3ff,%.3ff), %.3ff\n", + plane.Normal.X, plane.Normal.Y, plane.Normal.Z, plane.D); + + logTestString("Expected: (%.3ff,%.3ff,%.3ff), %.3ff\n", + expected.Normal.X, expected.Normal.Y, expected.Normal.Z, expected.D); + + if(!sloppyComparePlanes(plane, expected)) + { + logTestString("Unexpected result\n"); + assert(false); + return false; + } + + return true; +} + + +static bool drawScaledOctTree(void) +{ + bool result = false; + IrrlichtDevice *device = createDevice(video::EDT_BURNINGSVIDEO, dimension2d(160, 120), 32); + if (!device) + return false; + + video::IVideoDriver* driver = device->getVideoDriver(); + ISceneManager * smgr = device->getSceneManager(); + + bool added = device->getFileSystem()->addZipFileArchive("../media/map-20kdm2.pk3"); + assert(added); + + if(added) + { + ISceneNode * node = smgr->addOctTreeSceneNode(smgr->getMesh("20kdm2.bsp")->getMesh(0), 0, -1, 1024); + assert(node); + + if (node) + { + node->setMaterialFlag(EMF_LIGHTING, false); + node->setPosition(core::vector3df(-1300,-820,-1249)); + node->setScale(core::vector3df(1, 5, 1)); + + (void)smgr->addCameraSceneNode(0, core::vector3df(0,0,0), core::vector3df(40,100,30)); + + driver->beginScene(true, true, video::SColor(255,255,255,0)); + smgr->drawAll(); + driver->endScene(); + + result = takeScreenshotAndCompareAgainstReference(driver, "-planeMatrix-scaledClip.png"); + } + } + + device->drop(); + + return result; +} + + +// Test the ability to transform a plane with a matrix. +bool planeMatrix(void) +{ + matrix4 rotationMatrix; + rotationMatrix.setRotationDegrees(vector3df(90, 0, 0)); + + matrix4 translationMatrix; + translationMatrix.setTranslation(vector3df(0, 3, 0)); + + matrix4 scaleMatrix; + scaleMatrix.setScale(vector3df(1, 2, 3)); + + bool success = true; + + matrix4 matrix = rotationMatrix; + logTestString("\nRotation matrix\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f\n", + matrix[0], matrix[1], matrix[2], matrix[3], + matrix[4], matrix[5], matrix[6], matrix[7], + matrix[8], matrix[9], matrix[10], matrix[11], + matrix[12], matrix[13], matrix[14], matrix[15]); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-.707f, 0.f, -.707f), 0.f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(.707f, 0.f, .707f), 0.f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-.707f, 0.f, .707f), 0.f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(.707f, 0.f, -.707f), 0.f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-.707f, 0.f, -.707f), .707f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(.707f, 0.f, .707f), -.707f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-.707f, 0.f, .707f), -.707f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(.707f, 0.f, -.707f), .707f)); + + + matrix = translationMatrix; + logTestString("\nTranslation matrix\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f\n", + matrix[0], matrix[1], matrix[2], matrix[3], + matrix[4], matrix[5], matrix[6], matrix[7], + matrix[8], matrix[9], matrix[10], matrix[11], + matrix[12], matrix[13], matrix[14], matrix[15]); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,-0.707f,0.000f), 2.121f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,0.707f,0.000f), -2.121f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,0.707f,0.000f), -2.121f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,-0.707f,0.000f), 2.121f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,-0.707f,0.000f), 2.828f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,0.707f,0.000f), -2.828f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,0.707f,0.000f), -2.828f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,-0.707f,0.000f), 2.828f)); + + + matrix = scaleMatrix; + logTestString("\nScale matrix\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f\n", + matrix[0], matrix[1], matrix[2], matrix[3], + matrix[4], matrix[5], matrix[6], matrix[7], + matrix[8], matrix[9], matrix[10], matrix[11], + matrix[12], matrix[13], matrix[14], matrix[15]); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,-0.354f,0.000f), -0.000f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,0.354f,0.000f), -0.000f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,0.354f,0.000f), -0.000f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,-0.354f,0.000f), -0.000f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,-0.354f,0.000f), 0.707f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,0.354f,0.000f), -0.707f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,0.354f,0.000f), -0.707f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,-0.354f,0.000f), 0.707f)); + + matrix = rotationMatrix * translationMatrix; + logTestString("\nRotation * translation matrix\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f\n", + matrix[0], matrix[1], matrix[2], matrix[3], + matrix[4], matrix[5], matrix[6], matrix[7], + matrix[8], matrix[9], matrix[10], matrix[11], + matrix[12], matrix[13], matrix[14], matrix[15]); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,0.000f,-0.707f), 2.121f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,-0.000f,0.707f), -2.121f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,-0.000f,0.707f), -2.121f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,0.000f,-0.707f), 2.121f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,0.000f,-0.707f), 2.828f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,-0.000f,0.707f), -2.828f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,-0.000f,0.707f), -2.828f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,0.000f,-0.707f), 2.828f)); + + matrix = rotationMatrix * scaleMatrix; + logTestString("\nRotation * scale matrix\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f\n", + matrix[0], matrix[1], matrix[2], matrix[3], + matrix[4], matrix[5], matrix[6], matrix[7], + matrix[8], matrix[9], matrix[10], matrix[11], + matrix[12], matrix[13], matrix[14], matrix[15]); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,0.000f,-0.354f), -0.000f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,-0.000f,0.354f), -0.000f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,-0.000f,0.354f), -0.000f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,0.000f,-0.354f), -0.000f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,0.000f,-0.354f), 0.707f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,-0.000f,0.354f), -0.707f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,-0.000f,0.354f), -0.707f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,0.000f,-0.354f), 0.707f)); + + matrix = translationMatrix * scaleMatrix; + logTestString("\nTranslation * scale matrix\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f\n", + matrix[0], matrix[1], matrix[2], matrix[3], + matrix[4], matrix[5], matrix[6], matrix[7], + matrix[8], matrix[9], matrix[10], matrix[11], + matrix[12], matrix[13], matrix[14], matrix[15]); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,-0.354f,0.000f), 1.061f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,0.354f,0.000f), -1.061f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,0.354f,0.000f), -1.061f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,-0.354f,0.000f), 1.061f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,-0.354f,0.000f), 1.768f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,0.354f,0.000f), -1.768f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,0.354f,0.000f), -1.768f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,-0.354f,0.000f), 1.768f)); + + matrix = rotationMatrix * translationMatrix * scaleMatrix; + logTestString("\nRotation * translation * scale matrix\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f" + "\n%02.02f %02.02f %02.02f %02.02f\n", + matrix[0], matrix[1], matrix[2], matrix[3], + matrix[4], matrix[5], matrix[6], matrix[7], + matrix[8], matrix[9], matrix[10], matrix[11], + matrix[12], matrix[13], matrix[14], matrix[15]); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,0.000f,-0.354f), 1.061f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,-0.000f,0.354f), -1.061f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,-0.000f,0.354f), -1.061f)); + success &= transformPlane(vector3df(0, 0, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,0.000f,-0.354f), 1.061f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, -1, 0), matrix, plane3df(vector3df(-0.707f,0.000f,-0.354f), 1.768f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, 1, 0), matrix, plane3df(vector3df(0.707f,-0.000f,0.354f), -1.768f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(-1, 1, 0), matrix, plane3df(vector3df(-0.707f,-0.000f,0.354f), -1.768f)); + success &= transformPlane(vector3df(0, 1, 0), vector3df(1, -1, 0), matrix, plane3df(vector3df(0.707f,0.000f,-0.354f), 1.768f)); + + success &= drawScaledOctTree(); + + return success; +} + diff --git a/tests/sceneCollisionManager.cpp b/tests/sceneCollisionManager.cpp new file mode 100644 index 00000000..7cef8372 --- /dev/null +++ b/tests/sceneCollisionManager.cpp @@ -0,0 +1,84 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "testUtils.h" +#include "irrlicht.h" +#include + +using namespace irr; +using namespace core; +using namespace scene; +using namespace video; + + +/** Test functionality of the sceneCollisionManager */ +bool sceneCollisionManager(void) +{ + IrrlichtDevice * device = irr::createDevice(video::EDT_NULL); + assert(device); + if(!device) + return false; + + ISceneManager * smgr = device->getSceneManager(); + ISceneCollisionManager * collMgr = smgr->getSceneCollisionManager(); + + IMeshSceneNode * cubeNode = smgr->addCubeSceneNode(10.f); + ITriangleSelector * cubeSelector = smgr->createTriangleSelectorFromBoundingBox(cubeNode); + + triangle3df triOut; + vector3df hitPosition; + bool falling; + + vector3df resultPosition = + collMgr->getCollisionResultPosition(cubeSelector, + vector3df(0, 50, 0), + vector3df(10, 20, 10), + vector3df(0, -100, 0), + triOut, + hitPosition, + falling); + + bool result = true; + if(!equals(resultPosition.Y, 25.f, 0.01f)) + { + logTestString("Unexpected collision response position\n"); + assert(false); + result = false; + } + + if(!equals(hitPosition.Y, 5.f, 0.01f)) + { + logTestString("Unexpected collision position\n"); + assert(false); + result = false; + } + + resultPosition = + collMgr->getCollisionResultPosition(cubeSelector, + vector3df(-20, 0, 0), + vector3df(10, 20, 10), + vector3df(100, 0, 0), + triOut, + hitPosition, + falling); + + if(!equals(resultPosition.X, -15.f, 0.01f)) + { + logTestString("Unexpected collision response position\n"); + assert(false); + result = false; + } + + if(!equals(hitPosition.X, -5.f, 0.01f)) + { + logTestString("Unexpected collision position\n"); + assert(false); + result = false; + } + + cubeSelector->drop(); + device->drop(); + return result; +} + + diff --git a/tests/softwareDevice.cpp b/tests/softwareDevice.cpp new file mode 100644 index 00000000..1da9d907 --- /dev/null +++ b/tests/softwareDevice.cpp @@ -0,0 +1,59 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "irrlicht.h" +#include "testUtils.h" + +using namespace irr; +using namespace core; +using namespace scene; + + + +//! Tests the basic functionality of the software device. +bool softwareDevice(void) +{ + IrrlichtDevice *device = createDevice(video::EDT_SOFTWARE, dimension2d(160, 120), 32); + if (!device) + return false; + + video::IVideoDriver* driver = device->getVideoDriver(); + ISceneManager * smgr = device->getSceneManager(); + + // Test a particular rotation that highlighted a clipping issue from matrix::transformPlane() + video::S3DVertex vertices[3]; + vertices[0] = video::S3DVertex(10,0,-10, 1,0,0, + video::SColor(255,255,0,255), 1, 1); + vertices[1] = video::S3DVertex(0,20,0, 0,1,1, + video::SColor(255,255,255,0), 1, 0); + vertices[2] = video::S3DVertex(-10,0,-10, 0,0,1, + video::SColor(255,0,255,0), 0, 0); + + video::SMaterial material; + material.Lighting = false; + material.Wireframe = false; + const u16 indices[] = { 1,0,2, }; + + matrix4 transform(matrix4::EM4CONST_IDENTITY); + vector3df rotations(290, 0, 290); // <-- This rotation used to clip the triangle incorrectly + transform.setRotationDegrees(rotations); + + (void)smgr->addCameraSceneNode(0, core::vector3df(0,0,-40), core::vector3df(0,0,0)); + + driver->beginScene(true, true, video::SColor(255,255,255,0)); + smgr->drawAll(); + + driver->setMaterial(material); + + driver->setTransform(video::ETS_WORLD, transform); + driver->drawIndexedTriangleList(&vertices[0], 3, &indices[0], 1); + driver->endScene(); + + bool result = takeScreenshotAndCompareAgainstReference(driver, "-softwareDevice-rotatedClip.png"); + + device->drop(); + + return result; +} + + diff --git a/tests/testUtils.cpp b/tests/testUtils.cpp new file mode 100644 index 00000000..2f1339be --- /dev/null +++ b/tests/testUtils.cpp @@ -0,0 +1,253 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#define _CRT_SECURE_NO_WARNINGS +#include "testUtils.h" +#include +#include +#include +#include + +#if defined(TESTING_ON_WINDOWS) +#include // For OutputDebugString() +#endif // #if defined(TESTING_ON_WINDOWS) + +using namespace irr; + +bool binaryCompareFiles(const char * fileName1, const char * fileName2) +{ + assert(fileName1); + assert(fileName2); + if(!fileName1 || !fileName2) + return false; + + FILE * file1 = fopen(fileName1, "rb"); + if(!file1) + { + logTestString("binaryCompareFiles: File '%s' cannot be opened\n", fileName1); + assert(file1); + return false; + } + + FILE * file2 = fopen(fileName2, "rb"); + if(!file2) + { + logTestString("binaryCompareFiles: File '%s' cannot be opened\n", fileName2); + (void)fclose(file1); + assert(file2); + return false; + } + + + (void)fseek(file1, 0, SEEK_END); + (void)fseek(file2, 0, SEEK_END); + if(ftell(file1) != ftell(file2)) + { + logTestString("binaryCompareFiles: Files are different sizes\n"); + (void)fclose(file1); + (void)fclose(file2); + return false; + } + + (void)fseek(file1, 0, SEEK_SET); + (void)fseek(file2, 0, SEEK_SET); + + char file1Buffer[8196]; + char file2Buffer[8196]; + + while(!feof(file1)) + { + if(feof(file2) + ||(fread(file1Buffer, sizeof(file1Buffer), 1, file1) != + fread(file2Buffer, sizeof(file2Buffer), 1, file2))) + { + logTestString("binaryCompareFiles: Error during file reading\n"); + break; + } + + if(memcmp(file1Buffer, file2Buffer, sizeof(file1Buffer))) + { + logTestString("binaryCompareFiles: files are different\n"); + break; + } + } + + bool filesAreIdentical = feof(file1) && feof(file2); + (void)fclose(file1); + (void)fclose(file2); + + return filesAreIdentical; +} + + +//! Compare two images, returning the degree to which they match. +/** \param image1 The first image to compare. + \param image2 The second image to compare. + \return The match, from 0.f to 100.f */ +static float fuzzyCompareImages(irr::video::IImage * image1, + irr::video::IImage * image2) +{ + assert(image1); + assert(image2); + if(!image1 || !image2) + return 0.f; + + if(image1->getDimension() != image2->getDimension()) + { + logTestString("fuzzyCompareImages: images are different sizes\n"); + return 0.f; + } + + video::ECOLOR_FORMAT format1 = image1->getColorFormat(); + if(video::ECF_R8G8B8 != format1) + { + logTestString("fuzzyCompareImages: image 1 must be ECF_R8G8B8\n"); + return 0.f; + } + + video::ECOLOR_FORMAT format2 = image2->getColorFormat(); + if(video::ECF_A8R8G8B8 != format2 && video::ECF_R8G8B8 != format2) + { + logTestString("fuzzyCompareImages: image 2 must be ECF_AR8G8B8 or ECF_R8G8B8\n"); + return 0.f; + } + + u8 * image1Data = (u8*)image1->lock(); + u8 * image2Data = (u8*)image2->lock(); + + const u32 pixels = (image1->getPitch() * image1->getDimension().Height) / 4; + u32 mismatchedColours = 0; + for(u32 pixel = 0; pixel < pixels; ++pixel) + { + const u8 r1 = *(image1Data++); + const u8 g1 = *(image1Data++); + const u8 b1 = *(image1Data++); + + if(video::ECF_A8R8G8B8 == format2) + image2Data++; + + const u8 r2 = *(image2Data++); + const u8 g2 = *(image2Data++); + const u8 b2 = *(image2Data++); + + mismatchedColours += abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2); + } + + image1->unlock(); + image2->unlock(); + + const u32 totalColours = pixels * 775; + return 100.f * (totalColours - mismatchedColours) / totalColours; +} + + +bool takeScreenshotAndCompareAgainstReference(irr::video::IVideoDriver * driver, + const char * fileName, + irr::f32 requiredMatch) +{ + irr::video::IImage * screenshot = driver->createScreenShot(); + if(!screenshot) + { + logTestString("Failed to take screenshot\n"); + assert(false); + return false; + } + + const video::ECOLOR_FORMAT format = screenshot->getColorFormat(); + if(format != video::ECF_R8G8B8) + { + irr::video::IImage * fixedScreenshot = driver->createImage(video::ECF_R8G8B8, screenshot); + screenshot->drop(); + + if(!fixedScreenshot) + { + logTestString("Failed to convert screenshot to ECF_A8R8G8B8\n"); + assert(false); + return false; + } + + screenshot = fixedScreenshot; + } + + irr::core::stringc driverName = driver->getName(); + // For OpenGL (only), chop the version number out. Other drivers have more stable version numbers. + if(driverName.find("OpenGL") > -1) + driverName = "OpenGL"; + + irr::core::stringc referenceFilename = "media/"; + referenceFilename += driverName; + referenceFilename += fileName; + irr::video::IImage * reference = driver->createImageFromFile(referenceFilename.c_str()); + if(!reference) + { + logTestString("\n*** Failed to load reference image '%s'\n*** Creating from screenshot - please check this image.\n\n", + referenceFilename.c_str()); + (void)driver->writeImageToFile(screenshot, referenceFilename.c_str()); + screenshot->drop(); + return false; + } + + float match = fuzzyCompareImages(screenshot, reference); + logTestString("Image match: %f%%\n", match); + + if(match < requiredMatch) + { + irr::core::stringc mismatchFilename = "results/"; + mismatchFilename += driverName; + mismatchFilename += fileName; + logTestString("Writing mismatched image to '%s\n", mismatchFilename.c_str()); + (void)driver->writeImageToFile(screenshot, mismatchFilename.c_str()); + } + + + screenshot->drop(); + reference->drop(); + + return (match >= requiredMatch); +} + +static FILE * logFile = 0; + +bool openTestLog(bool startNewLog, const char * filename) +{ + closeTestLog(); + + if(startNewLog) + logFile = fopen(filename, "w"); + else + logFile = fopen(filename, "a"); + + assert(logFile); + if(!logFile) + logTestString("\nWARNING: unable to open the test log file %s\n", filename); + + return (logFile != 0); +} + +void closeTestLog(void) +{ + if(logFile) + (void)fclose(logFile); +} + + +void logTestString(const char * format, ...) +{ + char logString[1024]; + + va_list arguments; + va_start(arguments, format); + vsprintf(logString, format, arguments); + va_end(arguments); + + (void)printf(logString); + if(logFile) + { + (void)fprintf(logFile, logString); + (void)fflush(logFile); + } + +#if defined(TESTING_ON_WINDOWS) + OutputDebugStringA(logString); +#endif // #if defined(TESTING_ON_WINDOWS) +} diff --git a/tests/testUtils.h b/tests/testUtils.h new file mode 100644 index 00000000..a103cc23 --- /dev/null +++ b/tests/testUtils.h @@ -0,0 +1,44 @@ + +#ifndef _TEST_UTILS_H_ +#define _TEST_UTILS_H_ 1 + +#include "irrlicht.h" + +#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) || defined(_WIN32_WCE) +#define TESTING_ON_WINDOWS +#endif + +//! Compare two files +/** \param fileName1 The first file for comparison. + \param fileName1 The second file for comparison. + \return true if the files are identical, false on any error or difference. */ +extern bool binaryCompareFiles(const char * fileName1, const char * fileName2); + +//! Take a screenshot and compare it against a reference screenshot in the tests/media subdirectory +/** \param driver The Irrlicht video driver. + \param fileName The unique filename suffix that will be appended to the name of the video driver. + \param requiredMatch The degree to which the screenshot needs to match the reference image + in order to be considered a match. + \return true if the screenshot was taken and is identical to the reference image of the same name + in the tests/media directory, false on any error or difference. */ +extern bool takeScreenshotAndCompareAgainstReference(irr::video::IVideoDriver * driver, + const char * fileName, + irr::f32 requiredMatch = 99.f); + + +//! Opens a test log file, deleting any existing contents. +/** \param startNewLog true to create a new log file, false to append to an + existing one. + \param filename The filename to open + \return true if the test log file was opened, false on error. */ +extern bool openTestLog(bool startNewLog, const char * filename = "tests.log"); + +//! Close the test log file opened with openTestLog() +extern void closeTestLog(); + +//! Log a string to the console and the test log file created by openTestLog(). +/** \param format The format string + \... optional parameters */ +extern void logTestString(const char * format, ...); + +#endif // _TEST_UTILS_H_ diff --git a/tests/testVector2d.cpp b/tests/testVector2d.cpp new file mode 100644 index 00000000..9450b3d9 --- /dev/null +++ b/tests/testVector2d.cpp @@ -0,0 +1,134 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "testUtils.h" +#include "irrlicht.h" +#include + +using namespace irr; +using namespace core; + +template +static bool compareVectors(const core::vector2d & compare, + const core::vector2d & with) +{ + if(compare != with) + { + logTestString("\nERROR: vector2d %.16f, %.16f != vector2d %.16f, %.16f\n", + (f64)compare.X, (f64)compare.Y, (f64)with.X, (f64)with.Y); + assert(compare == with); + return false; + } + + return true; +} + +template +static bool doTests() +{ + #define COMPARE_VECTORS(compare, with)\ + if(!compareVectors(compare, with)) return false; + + vector2d vec(5, 5); + vector2d otherVec(10, 20); + if(!equals(vec.getDistanceFrom(otherVec), (T)15.8113883)) + { + logTestString("vector2d::getDistanceFrom() failed\n"); + assert(0); + return false; + } + + + vec.rotateBy(45); // Test implicit (0, 0) center + COMPARE_VECTORS(vec, vector2d(0, (T)7.0710678118654755)); + + vec.normalize(); + COMPARE_VECTORS(vec, vector2d(0, (T)1.0000000461060017)); + + vec.set(10, 10); + vector2d center(5, 5); + vec.rotateBy(-5, center); + // -5 means rotate clockwise slightly, so expect the X to increase + // slightly and the Y to decrease slightly. + COMPARE_VECTORS(vec, vector2d((T)10.416752204197017, (T)9.5451947767204359)); + + vec.set(5, 5); + vec.normalize(); + compareVectors(vec, vector2d((T)0.70710681378841400, (T)0.70710681378841400)); + + vec.set(5, 5); + otherVec.set(10, 20); + + vector2d interpolated; + (void)interpolated.interpolate(vec, otherVec, 0.f); + COMPARE_VECTORS(interpolated, otherVec); // 0.f means all the second vector + + (void)interpolated.interpolate(vec, otherVec, 0.25f); + COMPARE_VECTORS(interpolated, vector2d((T)8.75, (T)16.25)); + + (void)interpolated.interpolate(vec, otherVec, 0.75f); + COMPARE_VECTORS(interpolated, vector2d((T)6.25, (T)8.75)); + + (void)interpolated.interpolate(vec, otherVec, 1.f); + COMPARE_VECTORS(interpolated, vec); // 1.f means all the first vector + + + interpolated = vec.getInterpolated(otherVec, 0.f); + COMPARE_VECTORS(interpolated, otherVec); // 0.f means all the second vector + + interpolated = vec.getInterpolated(otherVec, 0.25f); + COMPARE_VECTORS(interpolated, vector2d((T)8.75, (T)16.25)); + + interpolated = vec.getInterpolated(otherVec, 0.75f); + COMPARE_VECTORS(interpolated, vector2d((T)6.25, (T)8.75)); + + interpolated = vec.getInterpolated(otherVec, 1.f); + COMPARE_VECTORS(interpolated, vec); // 1.f means all the first vector + + + vector2d thirdVec(20, 10); + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 0.f); + COMPARE_VECTORS(interpolated, vec); // 0.f means all the 1st vector + + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 0.25f); + COMPARE_VECTORS(interpolated, vector2d((T)7.8125, (T)10.9375)); + + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 0.5f); + COMPARE_VECTORS(interpolated, vector2d((T)11.25, (T)13.75)); + + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 0.75f); + COMPARE_VECTORS(interpolated, vector2d((T)15.3125, (T)13.4375)); + + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 1.f); + COMPARE_VECTORS(interpolated, thirdVec); // 1.f means all the 3rd vector + + return true; +} + +/** Test the functionality of vector2d, particularly methods that + involve calculations done using different precision than . + Note that all reference vector2ds are creating using double precision + values cast to (T), as we need to test . */ +bool testVector2d(void) +{ + bool f32Success = doTests(); + if(f32Success) + logTestString("vector2df tests passed\n\n"); + else + logTestString("\n*** vector2df tests failed ***\n\n"); + + bool f64Success = doTests(); + if(f64Success) + logTestString("vector2d tests passed\n\n"); + else + logTestString("\n*** vector2d tests failed ***\n\n"); + + bool s32Success = doTests(); + if(s32Success) + logTestString("vector2di tests passed\n\n"); + else + logTestString("\n*** vector2di tests failed ***\n\n"); + + return f32Success && f64Success && s32Success; +} + diff --git a/tests/testVector3d.cpp b/tests/testVector3d.cpp new file mode 100644 index 00000000..259d72d7 --- /dev/null +++ b/tests/testVector3d.cpp @@ -0,0 +1,147 @@ +// Copyright (C) 2008 Colin MacDonald +// No rights reserved: this software is in the public domain. + +#include "testUtils.h" +#include "irrlicht.h" +#include + +using namespace irr; +using namespace core; + +template +static bool compareVectors(const core::vector3d & compare, + const core::vector3d & with) +{ + if(compare != with) + { + logTestString("\nERROR: vector3d %.16f, %.16f, %.16f != vector3d %.16f, %.16f, %.16f\n", + (f64)compare.X, (f64)compare.Y, (f64)compare.Z, + (f64)with.X, (f64)with.Y, (f64)with.Z); + assert(compare == with); + return false; + } + + return true; +} + +template +static bool doTests() +{ + #define COMPARE_VECTORS(compare, with)\ + if(!compareVectors(compare, with)) return false; + + vector3d vec(5, 5, 0); + vector3d otherVec(10, 20, 0); + if(!equals(vec.getDistanceFrom(otherVec), (T)15.8113883)) + { + logTestString("vector3d::getDistanceFrom() failed\n"); + assert(0); + return false; + } + + vector3d center(0, 0, 0); + + vec.rotateXYBy(45, center); + COMPARE_VECTORS(vec, vector3d(0, (T)7.0710678118654755, 0)); + + vec.normalize(); + COMPARE_VECTORS(vec, vector3d(0, (T)1.0000000461060017, 0)); + + vec.set(10, 10, 10); + center.set(5, 5, 10); + vec.rotateXYBy(-5, center); + // -5 means rotate clockwise slightly, so expect the X to increase + // slightly and the Y to decrease slightly. + COMPARE_VECTORS(vec, vector3d((T)10.416752204197017, (T)9.5451947767204359, 10)); + + vec.set(10, 10, 10); + center.set(5, 10, 5); + vec.rotateXZBy(-5, center); + COMPARE_VECTORS(vec, vector3d((T)10.416752204197017, 10, (T)9.5451947767204359)); + + vec.set(10, 10, 10); + center.set(10, 5, 5); + vec.rotateYZBy(-5, center); + COMPARE_VECTORS(vec, vector3d(10, (T)10.416752204197017, (T)9.5451947767204359)); + + vec.set(5, 5, 0); + vec.normalize(); + compareVectors(vec, vector3d((T)0.70710681378841400, (T)0.70710681378841400, 0)); + + vec.set(5, 5, 0); + otherVec.set(10, 20, 40); + + vector3d interpolated; + (void)interpolated.interpolate(vec, otherVec, 0.f); + COMPARE_VECTORS(interpolated, otherVec); // 0.f means all the second vector + + (void)interpolated.interpolate(vec, otherVec, 0.25f); + COMPARE_VECTORS(interpolated, vector3d((T)8.75, (T)16.25, 30)); + + (void)interpolated.interpolate(vec, otherVec, 0.75f); + COMPARE_VECTORS(interpolated, vector3d((T)6.25, (T)8.75, 10)); + + (void)interpolated.interpolate(vec, otherVec, 1.f); + COMPARE_VECTORS(interpolated, vec); // 1.f means all the first vector + + + interpolated = vec.getInterpolated(otherVec, 0.f); + COMPARE_VECTORS(interpolated, otherVec); // 0.f means all the second vector + + interpolated = vec.getInterpolated(otherVec, 0.25f); + COMPARE_VECTORS(interpolated, vector3d((T)8.75, (T)16.25, 30)); + + interpolated = vec.getInterpolated(otherVec, 0.75f); + COMPARE_VECTORS(interpolated, vector3d((T)6.25, (T)8.75, 10)); + + interpolated = vec.getInterpolated(otherVec, 1.f); + COMPARE_VECTORS(interpolated, vec); // 1.f means all the first vector + + + vector3d thirdVec(20, 10, -30); + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 0.f); + COMPARE_VECTORS(interpolated, vec); // 0.f means all the 1st vector + + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 0.25f); + COMPARE_VECTORS(interpolated, vector3d((T)7.8125, (T)10.9375, (T)13.125)); + + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 0.5f); + COMPARE_VECTORS(interpolated, vector3d((T)11.25, (T)13.75, (T)12.5)); + + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 0.75f); + COMPARE_VECTORS(interpolated, vector3d((T)15.3125, (T)13.4375, (T)-1.875)); + + interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 1.f); + COMPARE_VECTORS(interpolated, thirdVec); // 1.f means all the 3rd vector + + return true; +} + + +/** Test the functionality of vector3d, particularly methods that + involve calculations done using different precision than . + Note that all reference vector3ds are creating using double precision + values cast to (T), as we need to test . */ +bool testVector3d(void) +{ + bool f32Success = doTests(); + if(f32Success) + logTestString("vector3df tests passed\n\n"); + else + logTestString("\n*** vector3df tests failed ***\n\n"); + + bool f64Success = doTests(); + if(f64Success) + logTestString("vector3d tests passed\n\n"); + else + logTestString("\n*** vector3d tests failed ***\n\n"); + + bool s32Success = doTests(); + if(s32Success) + logTestString("vector3di tests passed\n\n"); + else + logTestString("\n*** vector3di tests failed ***\n\n"); + + return f32Success && f64Success && s32Success; +} + diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt new file mode 100644 index 00000000..cd372a9c --- /dev/null +++ b/tests/tests-last-passed-at.txt @@ -0,0 +1,2 @@ +Test suite pass at GMT Thu Dec 18 15:24:34 2008 + diff --git a/tests/tests-readme.txt b/tests/tests-readme.txt new file mode 100644 index 00000000..2f7c996d --- /dev/null +++ b/tests/tests-readme.txt @@ -0,0 +1,21 @@ + +Welcome to the Irrlicht test suite. + +This is composed of a series of tests which exercise basic Irrlicht functionality. These are not +strictly unit tests, since there is no stub framework that isolates each method under test. They +do however test small units of functionality and should help to isolate problems or spot regressions. + +Each test resides in its own source file, and must have an entry point with the signature +bool testName(void); where testName should be the same as the source file name (without the suffix). + +Each test runs independently, and is responsible for cleaning up after itself and restoring the +working directory to /tests. + +testUtils.cpp provides some functions for creating screenshots and comparing files (including images). + +Validation images should go im the /media subdirectory. Since the tests rely on the presence of /media +and /empty/empty subdirectories, the working directory must be the /tests directory, not /bin/$PLATFORM. +This means that you cannot run /bin/$PLATFORM/texts.exe from there. You can however cd to /tests and +run ../bin/$PLATFORM/tests.exe + +The overall test application will return a count of the number of test that failed, i.e. 0 is success. \ No newline at end of file diff --git a/tests/tests.cbp b/tests/tests.cbp new file mode 100644 index 00000000..a03b1615 --- /dev/null +++ b/tests/tests.cbp @@ -0,0 +1,62 @@ + + + + + + diff --git a/tests/tests.workspace b/tests/tests.workspace new file mode 100644 index 00000000..47714f00 --- /dev/null +++ b/tests/tests.workspace @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/tests_vc8.sln b/tests/tests_vc8.sln new file mode 100644 index 00000000..7e54cbcd --- /dev/null +++ b/tests/tests_vc8.sln @@ -0,0 +1,46 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests_vc8.vcproj", "{2A1DE18B-F678-4A94-A996-E848E20B2983}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "..\source\Irrlicht\Irrlicht8.0.vcproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release - Fast FPU|Win32 = Release - Fast FPU|Win32 + Release|Win32 = Release|Win32 + Static lib - Debug|Win32 = Static lib - Debug|Win32 + Static lib - Release - Fast FPU|Win32 = Static lib - Release - Fast FPU|Win32 + Static lib - Release|Win32 = Static lib - Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Debug|Win32.ActiveCfg = Debug|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Debug|Win32.Build.0 = Debug|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Release - Fast FPU|Win32.ActiveCfg = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Release - Fast FPU|Win32.Build.0 = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Release|Win32.ActiveCfg = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Release|Win32.Build.0 = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Debug|Win32.ActiveCfg = Debug|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Debug|Win32.Build.0 = Debug|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Release - Fast FPU|Win32.ActiveCfg = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Release - Fast FPU|Win32.Build.0 = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Release|Win32.ActiveCfg = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Release|Win32.Build.0 = Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.ActiveCfg = Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.Build.0 = Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.ActiveCfg = Static lib - Debug|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.Build.0 = Static lib - Debug|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.ActiveCfg = Static lib - Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.Build.0 = Static lib - Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.ActiveCfg = Static lib - Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.Build.0 = Static lib - Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tests/tests_vc8.vcproj b/tests/tests_vc8.vcproj new file mode 100644 index 00000000..4afd1517 --- /dev/null +++ b/tests/tests_vc8.vcproj @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/tests_vc9.sln b/tests/tests_vc9.sln new file mode 100644 index 00000000..b2dd8438 --- /dev/null +++ b/tests/tests_vc9.sln @@ -0,0 +1,46 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests_vc9.vcproj", "{2A1DE18B-F678-4A94-A996-E848E20B2983}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "..\source\Irrlicht\Irrlicht9.0.vcproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release - Fast FPU|Win32 = Release - Fast FPU|Win32 + Release|Win32 = Release|Win32 + Static lib - Debug|Win32 = Static lib - Debug|Win32 + Static lib - Release - Fast FPU|Win32 = Static lib - Release - Fast FPU|Win32 + Static lib - Release|Win32 = Static lib - Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Debug|Win32.ActiveCfg = Debug|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Debug|Win32.Build.0 = Debug|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Release - Fast FPU|Win32.ActiveCfg = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Release - Fast FPU|Win32.Build.0 = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Release|Win32.ActiveCfg = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Release|Win32.Build.0 = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Debug|Win32.ActiveCfg = Debug|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Debug|Win32.Build.0 = Debug|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Release - Fast FPU|Win32.ActiveCfg = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Release - Fast FPU|Win32.Build.0 = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Release|Win32.ActiveCfg = Release|Win32 + {2A1DE18B-F678-4A94-A996-E848E20B2983}.Static lib - Release|Win32.Build.0 = Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.ActiveCfg = Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.Build.0 = Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.ActiveCfg = Static lib - Debug|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.Build.0 = Static lib - Debug|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.ActiveCfg = Static lib - Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.Build.0 = Static lib - Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.ActiveCfg = Static lib - Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.Build.0 = Static lib - Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tests/tests_vc9.vcproj b/tests/tests_vc9.vcproj new file mode 100644 index 00000000..1306939d --- /dev/null +++ b/tests/tests_vc9.vcproj @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/GUIEditor/CGUIAttribute.h b/tools/GUIEditor/CGUIAttribute.h index 6b0350f1..0bea8371 100644 --- a/tools/GUIEditor/CGUIAttribute.h +++ b/tools/GUIEditor/CGUIAttribute.h @@ -30,7 +30,7 @@ namespace gui //! constructor CGUIAttribute(IGUIEnvironment* environment, IGUIElement *parent, s32 myParentID) : IGUIElement(EGUIET_ELEMENT, environment, parent, -1, core::rect(0, 0, 100, 100) ), - Attribs(0), Index(0), AttribName(0), MyParentID(myParentID) + AttribName(0), Attribs(0), Index(0), MyParentID(myParentID) { #ifdef _DEBUG @@ -79,6 +79,8 @@ namespace gui break; case EET_KEY_INPUT_EVENT: return true; + default: + break; } } @@ -157,8 +159,8 @@ namespace gui protected: IGUIStaticText* AttribName; io::IAttributes* Attribs; - u32 Index; - s32 MyParentID; + u32 Index; + s32 MyParentID; }; } // namespace gui diff --git a/tools/GUIEditor/CGUIAttributeEditor.cpp b/tools/GUIEditor/CGUIAttributeEditor.cpp index f45b4e0d..f34b8b47 100644 --- a/tools/GUIEditor/CGUIAttributeEditor.cpp +++ b/tools/GUIEditor/CGUIAttributeEditor.cpp @@ -20,7 +20,7 @@ using namespace io; CGUIAttributeEditor::CGUIAttributeEditor(IGUIEnvironment* environment, s32 id, IGUIElement *parent) : CGUIPanel(environment, parent, id, rect(0, 0, 100, 100)), - Attribs(0) + Attribs(0), Panel(0) { #ifdef _DEBUG setDebugName("CGUIAttributeEditor"); @@ -39,13 +39,11 @@ CGUIAttributeEditor::CGUIAttributeEditor(IGUIEnvironment* environment, s32 id, I core::rect r = sb->getRelativePosition(); r.LowerRightCorner.Y -= 16; sb->setRelativePosition(r); - } CGUIAttributeEditor::~CGUIAttributeEditor() { - u32 i; - for (i=0; iremove(); AttribList[i]->drop(); @@ -73,10 +71,9 @@ void CGUIAttributeEditor::refreshAttribs() AttribList.clear(); position2di top(10, 5); - rect r(top.X, - top.Y, - getClientArea().getWidth() - 10, - 5 + Environment->getSkin()->getFont()->getDimension(L"A").Height); + rect r(top.X, top.Y, + getClientArea().getWidth() - 10, + 5 + Environment->getSkin()->getFont()->getDimension(L"A").Height); // add attribute elements u32 c = Attribs->getAttributeCount(); @@ -107,7 +104,6 @@ void CGUIAttributeEditor::refreshAttribs() AttribList[i]->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); AttribList[i]->setAttrib(Attribs, i); r += position2di(0, AttribList[i]->getRelativePosition().getHeight() + 5); - } } @@ -119,3 +115,4 @@ void CGUIAttributeEditor::updateAttribs() } // namespace gui } // namespace irr + diff --git a/tools/GUIEditor/CGUIAttributeEditor.h b/tools/GUIEditor/CGUIAttributeEditor.h index 8fbeeb62..31950b96 100644 --- a/tools/GUIEditor/CGUIAttributeEditor.h +++ b/tools/GUIEditor/CGUIAttributeEditor.h @@ -39,9 +39,8 @@ namespace gui private: core::array AttribList; // attributes editing controls - io::IAttributes* Attribs; // current attributes - CGUIPanel* Panel; - + io::IAttributes* Attribs; // current attributes + CGUIPanel* Panel; }; } // end namespace gui diff --git a/tools/GUIEditor/CGUIColorAttribute.h b/tools/GUIEditor/CGUIColorAttribute.h index 465755b2..6321f705 100644 --- a/tools/GUIEditor/CGUIColorAttribute.h +++ b/tools/GUIEditor/CGUIColorAttribute.h @@ -16,15 +16,15 @@ namespace gui // CGUIColorAttribute(IGUIEnvironment* environment, IGUIElement *parent, s32 myParentID) : CGUIAttribute(environment, parent, myParentID), - AttribEditBox(0), AttribSliderA(0), AttribSliderR(0), AttribSliderG(0), AttribSliderB(0), - AttribColor(0) + AttribSliderA(0), AttribSliderR(0), AttribSliderG(0), AttribSliderB(0), + AttribEditBox(0), AttribColor(0) { s32 fh = Environment->getSkin()->getFont()->getDimension(L"A").Height; core::rect r0(getAbsolutePosition()), - r2(0, fh + 5, r0.getWidth() - 5, fh*2 + 10 ), - r3(r2), - r4(r2.getWidth() - 20, 3, r2.getWidth() - 3, r2.getHeight()-3); + r2(0, fh + 5, r0.getWidth() - 5, fh*2 + 10 ), + r3(r2), + r4(r2.getWidth() - 20, 3, r2.getWidth() - 3, r2.getHeight()-3); AttribColor = Environment->addTab(r4, this, 0); AttribColor->grab(); @@ -164,7 +164,7 @@ namespace gui IGUIScrollBar* AttribSliderG; IGUIScrollBar* AttribSliderB; IGUIEditBox* AttribEditBox; - IGUITab* AttribColor; + IGUITab* AttribColor; }; } // namespace gui diff --git a/tools/GUIEditor/CGUIEditWindow.cpp b/tools/GUIEditor/CGUIEditWindow.cpp index b15cc48d..c1b9536f 100644 --- a/tools/GUIEditor/CGUIEditWindow.cpp +++ b/tools/GUIEditor/CGUIEditWindow.cpp @@ -13,12 +13,10 @@ using namespace gui; //! constructor CGUIEditWindow::CGUIEditWindow(IGUIEnvironment* environment, core::rect rectangle, IGUIElement *parent) - : IGUIWindow(environment, parent, -1, rectangle), - Dragging(false), Resizing(false), SelectedElement(0), - AttribEditor(0), OptionEditor(0), EnvEditor(0) - + : IGUIWindow(environment, parent, -1, rectangle), + Dragging(false), Resizing(false), SelectedElement(0), + AttribEditor(0), OptionEditor(0), EnvEditor(0) { - #ifdef _DEBUG setDebugName("CGUIEditWindow"); #endif @@ -41,7 +39,7 @@ CGUIEditWindow::CGUIEditWindow(IGUIEnvironment* environment, core::rect rec s32 th = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); setRelativePosition(core::rect(50,50,250,500)); - setMinSize( core::dimension2di(200,200)); + setMinSize(core::dimension2di(200,200)); IGUITabControl *TabControl = environment->addTabControl(core::rect(1,th+5,199,449), this, false, true); TabControl->setSubElement(true); @@ -58,7 +56,7 @@ CGUIEditWindow::CGUIEditWindow(IGUIEnvironment* environment, core::rect rec OptionEditor = (CGUIAttributeEditor*) environment->addGUIElement("attributeEditor", EditorTab); OptionEditor->grab(); OptionEditor->setID(EGUIEDCE_OPTION_EDITOR); - OptionEditor->setRelativePosition(core::rect(0.0f, 0.0f, 1.0f, 1.0f)); + OptionEditor->setRelativePositionProportional(core::rect(0.0f, 0.0f, 1.0f, 1.0f)); OptionEditor->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); if (Parent && Parent->getParent() == Environment->getRootGUIElement()) @@ -67,7 +65,7 @@ CGUIEditWindow::CGUIEditWindow(IGUIEnvironment* environment, core::rect rec EnvEditor = (CGUIAttributeEditor*) environment->addGUIElement("attributeEditor", EnvTab); EnvEditor->grab(); EnvEditor->setID(EGUIEDCE_ENV_EDITOR); - EnvEditor->setRelativePosition(core::rect(0.0f, 0.0f, 1.0f, 1.0f)); + EnvEditor->setRelativePositionProportional(core::rect(0.0f, 0.0f, 1.0f, 1.0f)); EnvEditor->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); } IGUITab* ElementTab = TabControl->addTab(L"Element"); @@ -75,9 +73,9 @@ CGUIEditWindow::CGUIEditWindow(IGUIEnvironment* environment, core::rect rec AttribEditor = (CGUIAttributeEditor*) environment->addGUIElement("attributeEditor", ElementTab); AttribEditor->grab(); AttribEditor->setID(EGUIEDCE_ATTRIB_EDITOR); - AttribEditor->setRelativePosition( core::rect(0.0f, 0.0f, 1.0f, 1.0f)); + AttribEditor->setRelativePositionProportional(core::rect(0.0f, 0.0f, 1.0f, 1.0f)); AttribEditor->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); - + ResizeButton = environment->addButton(core::rect(199-th,449-th,199,449), this); ResizeButton->setDrawBorder(false); ResizeButton->setEnabled(false); @@ -87,9 +85,9 @@ CGUIEditWindow::CGUIEditWindow(IGUIEnvironment* environment, core::rect rec ResizeButton->grab(); ResizeButton->setSubElement(true); ResizeButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); - } + //! destructor CGUIEditWindow::~CGUIEditWindow() { @@ -140,7 +138,6 @@ void CGUIEditWindow::setSelectedElement(IGUIElement *sel) SelectedElement->serializeAttributes(Attribs); AttribEditor->refreshAttribs(); - } //! draws the element and its children. @@ -197,7 +194,7 @@ bool CGUIEditWindow::OnEvent(const SEvent &event) { case EMIE_LMOUSE_PRESSED_DOWN: { - + DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; @@ -250,7 +247,7 @@ bool CGUIEditWindow::OnEvent(const SEvent &event) else if (Resizing) { core::position2di dp = RelativeRect.LowerRightCorner + diff; - setRelativePosition( core::rect(RelativeRect.UpperLeftCorner, dp)); + setRelativePosition(core::rect(RelativeRect.UpperLeftCorner, dp)); DragStart += dp - RelativeRect.LowerRightCorner + diff; } @@ -264,10 +261,6 @@ bool CGUIEditWindow::OnEvent(const SEvent &event) } - - - - // we're supposed to supply these if we're creating an IGUIWindow // but we don't need them so we'll just return null IGUIButton* CGUIEditWindow::getCloseButton() const {return 0;} diff --git a/tools/GUIEditor/CGUIEditWorkspace.cpp b/tools/GUIEditor/CGUIEditWorkspace.cpp index 5fc4ec91..ede497b4 100644 --- a/tools/GUIEditor/CGUIEditWorkspace.cpp +++ b/tools/GUIEditor/CGUIEditWorkspace.cpp @@ -27,8 +27,8 @@ namespace gui //! constructor CGUIEditWorkspace::CGUIEditWorkspace(IGUIEnvironment* environment, s32 id, IGUIElement *parent) : IGUIElement(EGUIET_ELEMENT, environment, parent ? parent : environment->getRootGUIElement(), id, environment->getRootGUIElement()->getAbsolutePosition()), - DrawGrid(false), UseGrid(true), GridSize(10,10), MenuCommandStart(0x3D17), CurrentMode(EGUIEDM_SELECT), MouseOverMode(EGUIEDM_SELECT), + GridSize(10,10), MenuCommandStart(0x3D17), DrawGrid(false), UseGrid(true), MouseOverElement(0), SelectedElement(0), EditorWindow(0) { #ifdef _DEBUG @@ -224,7 +224,7 @@ bool CGUIEditWorkspace::OnEvent(const SEvent &e) IGUIFileOpenDialog* dialog=0; switch(e.EventType) { - case (EEVENT_TYPE)ATTRIBEDIT_ATTRIB_CHANGED: + case ATTRIBEDIT_ATTRIB_CHANGED: { switch (e.UserEvent.UserData1) { diff --git a/tools/GUIEditor/CGUIEditWorkspace.h b/tools/GUIEditor/CGUIEditWorkspace.h index e77e11a4..21ce5279 100644 --- a/tools/GUIEditor/CGUIEditWorkspace.h +++ b/tools/GUIEditor/CGUIEditWorkspace.h @@ -139,12 +139,12 @@ namespace gui core::position2di StartMovePos; core::rect SelectedArea; - bool DrawGrid, UseGrid; core::dimension2di GridSize; - s32 MenuCommandStart; + s32 MenuCommandStart; + bool DrawGrid, UseGrid; - IGUIElement *MouseOverElement, - *SelectedElement; + IGUIElement *MouseOverElement, + *SelectedElement; CGUIEditWindow *EditorWindow; core::rect TLRect; @@ -155,8 +155,6 @@ namespace gui core::rect RRect; core::rect BRRect; core::rect BRect; - - }; @@ -165,4 +163,3 @@ namespace gui #endif - diff --git a/tools/GUIEditor/CGUIPanel.cpp b/tools/GUIEditor/CGUIPanel.cpp index 0db39c52..17a7ceab 100644 --- a/tools/GUIEditor/CGUIPanel.cpp +++ b/tools/GUIEditor/CGUIPanel.cpp @@ -21,49 +21,48 @@ namespace gui { CGUIPanel::CGUIPanel( IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle, - bool border, E_SCROLL_BAR_MODE vMode, E_SCROLL_BAR_MODE hMode) - : IGUIElement(EGUIET_ELEMENT, environment, parent, id, rectangle), - VScrollBar(0), HScrollBar(0), ClipPane(0), InnerPane(0), - Border(border), VScrollBarMode(vMode), HScrollBarMode(hMode), NeedsUpdate(true) -{ - + bool border, E_SCROLL_BAR_MODE vMode, E_SCROLL_BAR_MODE hMode) + : IGUIElement(EGUIET_ELEMENT, environment, parent, id, rectangle), + VScrollBar(0), HScrollBar(0), ClipPane(0), InnerPane(0), + VScrollBarMode(vMode), HScrollBarMode(hMode), NeedsUpdate(true), Border(border) +{ #ifdef _DEBUG setDebugName("CGUIPanel"); #endif - s32 width = rectangle.getWidth(); - s32 height = rectangle.getHeight(); - - core::rect rct = core::rect(width - SCROLL_BAR_SIZE,0, width, height); - - VScrollBar = environment->addScrollBar( false, rct, 0, id ); + s32 width = rectangle.getWidth(); + s32 height = rectangle.getHeight(); + + core::rect rct = core::rect(width - SCROLL_BAR_SIZE,0, width, height); + + VScrollBar = environment->addScrollBar( false, rct, 0, id ); VScrollBar->setSubElement(true); VScrollBar->setTabStop(false); VScrollBar->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); - VScrollBar->grab(); + VScrollBar->grab(); IGUIElement::addChild(VScrollBar); - - rct = core::rect(0,height - SCROLL_BAR_SIZE, width - SCROLL_BAR_SIZE,height ); - - HScrollBar = environment->addScrollBar( true, rct, 0, id ); + + rct = core::rect(0,height - SCROLL_BAR_SIZE, width - SCROLL_BAR_SIZE,height ); + + HScrollBar = environment->addScrollBar( true, rct, 0, id ); HScrollBar->setSubElement(true); HScrollBar->setTabStop(false); HScrollBar->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); - HScrollBar->grab(); + HScrollBar->grab(); IGUIElement::addChild(HScrollBar); - rct = core::rect(0,0, width - SCROLL_BAR_SIZE, height - SCROLL_BAR_SIZE); + rct = core::rect(0,0, width - SCROLL_BAR_SIZE, height - SCROLL_BAR_SIZE); ClipPane = environment->addTab( rct, 0, -1); ClipPane->setSubElement(true); ClipPane->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); - ClipPane->grab(); + ClipPane->grab(); IGUIElement::addChild(ClipPane); InnerPane = environment->addTab( rct, ClipPane, -1); InnerPane->setSubElement(true); - InnerPane->grab(); - + InnerPane->grab(); + calculateClientArea(); resizeInnerPane(); } @@ -76,8 +75,8 @@ CGUIPanel::~CGUIPanel() IGUIElement::removeChild(ClipPane); // now we can drop the others - VScrollBar->drop(); - HScrollBar->drop(); + VScrollBar->drop(); + HScrollBar->drop(); ClipPane->drop(); InnerPane->drop(); } @@ -92,12 +91,11 @@ void CGUIPanel::draw() NeedsUpdate = false; } - video::IVideoDriver* driver = Environment->getVideoDriver(); - IGUISkin* skin = Environment->getSkin(); - if (Border && skin) - { - skin->draw3DSunkenPane( this, skin->getColor( EGDC_APP_WORKSPACE), false, true, AbsoluteRect, &AbsoluteClippingRect ); - } + IGUISkin* skin = Environment->getSkin(); + if (Border && skin) + { + skin->draw3DSunkenPane( this, skin->getColor( EGDC_APP_WORKSPACE), false, true, AbsoluteRect, &AbsoluteClippingRect ); + } IGUIElement::draw(); } @@ -125,51 +123,51 @@ const core::list& CGUIPanel::getChildren() bool CGUIPanel::hasBorder() const { - return Border; + return Border; } void CGUIPanel::setBorder( bool enabled ) { - Border = enabled; + Border = enabled; } IGUIScrollBar* CGUIPanel::getVScrollBar() const { - return VScrollBar; + return VScrollBar; } IGUIScrollBar* CGUIPanel::getHScrollBar() const { - return HScrollBar; + return HScrollBar; } E_SCROLL_BAR_MODE CGUIPanel::getVScrollBarMode() const { - return VScrollBarMode; + return VScrollBarMode; } void CGUIPanel::setVScrollBarMode( E_SCROLL_BAR_MODE mode ) { - VScrollBarMode = mode; + VScrollBarMode = mode; NeedsUpdate = true; } E_SCROLL_BAR_MODE CGUIPanel::getHScrollBarMode() const { - return HScrollBarMode; + return HScrollBarMode; } void CGUIPanel::setHScrollBarMode( E_SCROLL_BAR_MODE mode ) { - HScrollBarMode = mode; + HScrollBarMode = mode; NeedsUpdate = true; } bool CGUIPanel::OnEvent(const SEvent &event) { - // Redirect mouse wheel to scrollbar - if ( event.EventType == EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_MOUSE_WHEEL ) - { + // Redirect mouse wheel to scrollbar + if ( event.EventType == EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_MOUSE_WHEEL ) + { if (VScrollBar->isVisible()) { Environment->setFocus(VScrollBar); @@ -182,9 +180,9 @@ bool CGUIPanel::OnEvent(const SEvent &event) HScrollBar->OnEvent(event); return true; } - } - else - { + } + else + { if ( event.EventType == EET_GUI_EVENT && event.GUIEvent.EventType == EGET_SCROLL_BAR_CHANGED && ( event.GUIEvent.Caller == HScrollBar || event.GUIEvent.Caller == VScrollBar) ) { @@ -192,7 +190,7 @@ bool CGUIPanel::OnEvent(const SEvent &event) return true; } - } + } return IGUIElement::OnEvent(event); } @@ -213,25 +211,23 @@ void CGUIPanel::updateAbsolutePosition() resizeInnerPane(); } + void CGUIPanel::resizeInnerPane() { if (!HScrollBar || !VScrollBar || !InnerPane || !ClipPane) return; - s32 newHPos = HScrollBar->getPos(); - s32 newVPos = VScrollBar->getPos(); - // get outer pane size core::rect outerRect = ClipPane->getRelativePosition(); // resize flexible children depending on outer pane InnerPane->setRelativePosition(outerRect); - + // get desired size (total size of all children) core::rect totalRect(0,0,0,0); core::list::ConstIterator it; - + for ( it = InnerPane->getChildren().begin(); it != InnerPane->getChildren().end(); ++it ) { @@ -272,9 +268,9 @@ void CGUIPanel::resizeInnerPane() } InnerPane->setRelativePosition(totalRect); - + // scrollbars - if ( HScrollBarMode != ESBM_ALWAYS_INVISIBLE && + if ( HScrollBarMode != ESBM_ALWAYS_INVISIBLE && (totalRect.getWidth() > outerRect.getWidth() || HScrollBarMode == ESBM_ALWAYS_VISIBLE) ) { HScrollBar->setVisible(true); @@ -282,7 +278,7 @@ void CGUIPanel::resizeInnerPane() } else HScrollBar->setVisible(false); - + if ( VScrollBarMode != ESBM_ALWAYS_INVISIBLE && (totalRect.getHeight() > outerRect.getHeight() || VScrollBarMode == ESBM_ALWAYS_VISIBLE) ) { @@ -299,32 +295,32 @@ void CGUIPanel::resizeInnerPane() void CGUIPanel::calculateClientArea() { core::rect ClientArea(0,0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight()); - - if (VScrollBar->isVisible()) - ClientArea.LowerRightCorner.X -= VScrollBar->getRelativePosition().getWidth(); - - if (HScrollBar->isVisible()) - ClientArea.LowerRightCorner.Y -= HScrollBar->getRelativePosition().getHeight(); - - if (Border) - { - ClientArea.UpperLeftCorner += core::position2d( BORDER_WIDTH, BORDER_WIDTH ); - ClientArea.LowerRightCorner -= core::position2d( BORDER_WIDTH, BORDER_WIDTH ); - } + + if (VScrollBar->isVisible()) + ClientArea.LowerRightCorner.X -= VScrollBar->getRelativePosition().getWidth(); + + if (HScrollBar->isVisible()) + ClientArea.LowerRightCorner.Y -= HScrollBar->getRelativePosition().getHeight(); + + if (Border) + { + ClientArea.UpperLeftCorner += core::position2d( BORDER_WIDTH, BORDER_WIDTH ); + ClientArea.LowerRightCorner -= core::position2d( BORDER_WIDTH, BORDER_WIDTH ); + } ClipPane->setRelativePosition(ClientArea); } core::rect CGUIPanel::getClientArea() const -{ - return ClipPane->getRelativePosition(); +{ + return ClipPane->getRelativePosition(); } void CGUIPanel::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) { IGUIElement::serializeAttributes(out, options); - out->addBool("border", Border); + out->addBool("border", Border); out->addEnum("horizontalScrollBar", HScrollBarMode, GUIScrollBarModeNames ); out->addEnum("verticalScrollBar", VScrollBarMode, GUIScrollBarModeNames ); } diff --git a/tools/GUIEditor/CGUIPanel.h b/tools/GUIEditor/CGUIPanel.h index 3890cfa0..ba5c2071 100644 --- a/tools/GUIEditor/CGUIPanel.h +++ b/tools/GUIEditor/CGUIPanel.h @@ -11,20 +11,20 @@ namespace irr { namespace gui { - + class IGUIScrollBar; class IGUITab; enum E_SCROLL_BAR_MODE { - //! The scrollbar will only show up when needed. - ESBM_AUTOMATIC = 0, - - //! The scrollbar will never be visible. - ESBM_ALWAYS_INVISIBLE, - - //! The scrollbar will always the visible. - ESBM_ALWAYS_VISIBLE, + //! The scrollbar will only show up when needed. + ESBM_AUTOMATIC = 0, + + //! The scrollbar will never be visible. + ESBM_ALWAYS_INVISIBLE, + + //! The scrollbar will always the visible. + ESBM_ALWAYS_VISIBLE, //! just a count of how many are in this enum ESBM_COUNT @@ -41,45 +41,45 @@ const c8* const GUIScrollBarModeNames[] = class CGUIPanel : public IGUIElement { public: - CGUIPanel( IGUIEnvironment* environment, IGUIElement* parent, s32 id=-1, + CGUIPanel( IGUIEnvironment* environment, IGUIElement* parent, s32 id=-1, const core::rect& rectangle = core::rect(0,0,100,100), - bool border=false, + bool border=false, E_SCROLL_BAR_MODE vMode=ESBM_AUTOMATIC, - E_SCROLL_BAR_MODE hMode=ESBM_ALWAYS_INVISIBLE ); - - virtual ~CGUIPanel(); - + E_SCROLL_BAR_MODE hMode=ESBM_ALWAYS_INVISIBLE ); + + virtual ~CGUIPanel(); + //! draws the panel and its children - virtual void draw(); - + virtual void draw(); + //! returns true if it has a border, false if not - bool hasBorder() const; + bool hasBorder() const; //! sets whether the element draws a border - void setBorder(bool enabled); - + void setBorder(bool enabled); + //! returns a pointer to the vertical scrollbar - IGUIScrollBar* getVScrollBar() const; + IGUIScrollBar* getVScrollBar() const; //! returns a pointer to the horizontal scrollbar - IGUIScrollBar* getHScrollBar() const; - + IGUIScrollBar* getHScrollBar() const; + //! returns the vertical scrollbar visibility rule - E_SCROLL_BAR_MODE getVScrollBarMode() const; + E_SCROLL_BAR_MODE getVScrollBarMode() const; //! sets the vertical scrollbar visibility rule - void setVScrollBarMode(E_SCROLL_BAR_MODE mode); - + void setVScrollBarMode(E_SCROLL_BAR_MODE mode); + //! returns the horizontal scrollbar visibility rule - E_SCROLL_BAR_MODE getHScrollBarMode() const; + E_SCROLL_BAR_MODE getHScrollBarMode() const; //! sets the horizontal scrollbar visibility rule - void setHScrollBarMode(E_SCROLL_BAR_MODE mode); + void setHScrollBarMode(E_SCROLL_BAR_MODE mode); //! returns the visible area inside the panel, excluding scrollbar and border core::rect getClientArea() const; - - virtual bool OnEvent(const SEvent &event); + + virtual bool OnEvent(const SEvent &event); //! adds a child to the panel virtual void addChild(IGUIElement* child); @@ -87,7 +87,7 @@ public: //! removes a child from the panel virtual void removeChild(IGUIElement* child); - //! updates the absolute position + //! updates the absolute position virtual void updateAbsolutePosition(); //! returns children of the inner pane @@ -95,24 +95,24 @@ public: virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0); virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); - -protected: + +protected: void moveInnerPane(); void resizeInnerPane(); - void calculateClientArea(); + void calculateClientArea(); private: - - IGUIScrollBar* VScrollBar; - IGUIScrollBar* HScrollBar; - IGUITab* ClipPane; - IGUITab* InnerPane; - bool NeedsUpdate; - - E_SCROLL_BAR_MODE VScrollBarMode; - E_SCROLL_BAR_MODE HScrollBarMode; - - bool Border; + + IGUIScrollBar* VScrollBar; + IGUIScrollBar* HScrollBar; + IGUITab* ClipPane; + IGUITab* InnerPane; + + E_SCROLL_BAR_MODE VScrollBarMode; + E_SCROLL_BAR_MODE HScrollBarMode; + + bool NeedsUpdate; + bool Border; }; } // namespace gui diff --git a/tools/GUIEditor/CGUITextureCacheBrowser.cpp b/tools/GUIEditor/CGUITextureCacheBrowser.cpp index cb68a233..ba46eff8 100644 --- a/tools/GUIEditor/CGUITextureCacheBrowser.cpp +++ b/tools/GUIEditor/CGUITextureCacheBrowser.cpp @@ -16,7 +16,7 @@ namespace gui CGUITextureCacheBrowser::CGUITextureCacheBrowser(IGUIEnvironment* environment, s32 id, IGUIElement *parent) : IGUIWindow(environment, parent, id, core::rect(0,0,300,200)), - Dragging(false), DragStart(0,0), CloseButton(0), Images(), SelectedTexture(-1) + CloseButton(0), Panel(0), SelectedTexture(-1), Dragging(false) { #ifdef _DEBUG setDebugName("CGUIWindow"); @@ -170,7 +170,7 @@ void CGUITextureCacheBrowser::updateImageList() img->setRelativePosition(pos); img->setToolTipText(details.c_str()); img->setScaleImage(true); - img->setColor( SelectedTexture == i ? video::SColor(255,255,255,255) : video::SColor(128,128,128,128) ); + img->setColor( SelectedTexture == (s32)i ? video::SColor(255,255,255,255) : video::SColor(128,128,128,128) ); pos = pos + moveDist; } diff --git a/tools/GUIEditor/CGUITextureCacheBrowser.h b/tools/GUIEditor/CGUITextureCacheBrowser.h index 3cefe9c7..530ff988 100644 --- a/tools/GUIEditor/CGUITextureCacheBrowser.h +++ b/tools/GUIEditor/CGUITextureCacheBrowser.h @@ -54,15 +54,14 @@ namespace gui private: void updateImageList(); - core::array Images; - bool Dragging; + core::array Images; core::position2d DragStart; IGUIButton* CloseButton; CGUIPanel* Panel; s32 SelectedTexture; - + bool Dragging; }; @@ -71,4 +70,3 @@ namespace gui #endif - diff --git a/tools/GUIEditor/CMemoryReadWriteFile.cpp b/tools/GUIEditor/CMemoryReadWriteFile.cpp index e5adbbb8..b13d699e 100644 --- a/tools/GUIEditor/CMemoryReadWriteFile.cpp +++ b/tools/GUIEditor/CMemoryReadWriteFile.cpp @@ -8,21 +8,19 @@ using namespace irr; using namespace io; CMemoryReadWriteFile::CMemoryReadWriteFile(const c8* filename) -: Pos(0), Data(), FileName(filename) +: Data(), FileName(filename), Pos(0) { - } s32 CMemoryReadWriteFile::write(const void* buffer, u32 sizeToWrite) { - // no point in writing 0 bytes if (sizeToWrite < 1) return 0; // expand size - if (Pos + sizeToWrite > (s32)Data.size()) + if (Pos + sizeToWrite > Data.size()) Data.set_used(Pos+sizeToWrite); // copy data @@ -80,7 +78,7 @@ long CMemoryReadWriteFile::getSize() const s32 CMemoryReadWriteFile::read(void* buffer, u32 sizeToRead) { // cant read past the end - if (Pos + sizeToRead >= (s32)Data.size()) + if (Pos + sizeToRead >= Data.size()) sizeToRead = Data.size() - Pos; // cant read 0 bytes diff --git a/tools/GUIEditor/CMemoryReadWriteFile.h b/tools/GUIEditor/CMemoryReadWriteFile.h index 192ab7f8..1fa51b4b 100644 --- a/tools/GUIEditor/CMemoryReadWriteFile.h +++ b/tools/GUIEditor/CMemoryReadWriteFile.h @@ -61,8 +61,8 @@ namespace io private: core::array Data; - s32 Pos; core::stringc FileName; + long Pos; }; diff --git a/tools/GUIEditor/Makefile b/tools/GUIEditor/Makefile index 23ee0150..02f8189f 100644 --- a/tools/GUIEditor/Makefile +++ b/tools/GUIEditor/Makefile @@ -1,14 +1,43 @@ -CPPFLAGS = -I../../include -I/usr/X11R6/include -LDFLAGS = -L/usr/X11R6/lib -L../../lib/Linux -lIrrlicht -lGL -lGLU -lXxf86vm -lXext -lX11 +# Irrlicht Engine GUIEditor Makefile +Target = GUIEditor +Sources = CGUIAttributeEditor.cpp CGUIEditFactory.cpp CGUIEditWindow.cpp CGUIEditWorkspace.cpp CGUIPanel.cpp CGUITextureCacheBrowser.cpp CMemoryReadWriteFile.cpp main.cpp -SRCS = CGUIAttributeEditor.cpp CGUIEditFactory.cpp CGUIEditWindow.cpp CGUIEditWorkspace.cpp CGUIPanel.cpp CGUITextureCacheBrowser.cpp CMemoryReadWriteFile.cpp main.cpp -OBJS = $(SRCS:%.cpp=%.o) -DEST = GUIEditor +CPPFLAGS = -I../../include -I/usr/X11R6/include +CXXFLAGS = -Wall -O3 -ffast-math -all: $(DEST) +ifeq ($(HOSTTYPE), x86_64) +LIBSELECT=64 +endif -GUIEditor: $(OBJS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@ $(LDFLAGS) +all: all_linux -clean: - $(RM) $(OBJS) $(DEST) +# target specific settings +all_linux: SYSTEM=Linux +all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/$(SYSTEM) -lIrrlicht -lGL -lXxf86vm -lXext -lX11 + +all_win32 clean_win32: SYSTEM=Win32-gcc +all_win32: LDFLAGS = -L../../lib/$(SYSTEM) -lIrrlicht -lopengl32 -lm + +# if you enable sound add the proper library for linking +#LDFLAGS += -lIrrKlang +#LDFLAGS += -laudiere +#LDFLAGS += -lSDL_mixer -lSDL + +all_win32 clean_win32: SUF=.exe +# name of the binary - only valid for targets which set SYSTEM +DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) + +OBJ = $(Sources:.cpp=.o) + +all_linux all_win32: $(OBJ) + $(warning Building...) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $(DESTPATH) $(LDFLAGS) + +clean: clean_linux clean_win32 + $(warning Cleaning...) + @$(RM) $(OBJ) + +clean_linux clean_win32: + @$(RM) $(DESTPATH) + +.PHONY: all all_win32 clean clean_linux clean_win32 diff --git a/tools/GUIEditor/main.cpp b/tools/GUIEditor/main.cpp index cf7f0852..aa2f6e9f 100644 --- a/tools/GUIEditor/main.cpp +++ b/tools/GUIEditor/main.cpp @@ -7,7 +7,9 @@ using namespace irr; using namespace gui; +#ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") +#endif int main() {