diff --git a/src/Client/GUI/CCursorController.cpp b/src/Client/GUI/CCursorController.cpp index 07c87c2..36fddb0 100644 --- a/src/Client/GUI/CCursorController.cpp +++ b/src/Client/GUI/CCursorController.cpp @@ -66,11 +66,11 @@ void CCursorController::render() void CCursorController::addMouseCursorTexture(c8* Cursor_file, bool top_left) { m_pMouseCursor = videoDriver->getTexture(Cursor_file); - + bool isAlreadyLoaded = false; for(u32 i = 0; i < m_aMouseCursors.size() && !isAlreadyLoaded; i++) { - if(m_aMouseCursors[i].tex->getName() == m_pMouseCursor->getName()) + if(m_aMouseCursors[i].tex->getName().getInternalName() == m_pMouseCursor->getName().getInternalName()) { isAlreadyLoaded = !isAlreadyLoaded; break; diff --git a/src/Client/GUI/CImageLoaderBLP.cpp b/src/Client/GUI/CImageLoaderBLP.cpp index 9ef6826..981d528 100644 --- a/src/Client/GUI/CImageLoaderBLP.cpp +++ b/src/Client/GUI/CImageLoaderBLP.cpp @@ -1,5 +1,3 @@ -#include -#include #include "common.h" #include "irrlicht/irrlicht.h" #include "SImage.h" @@ -12,10 +10,10 @@ namespace video //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderBLP::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderBLP::isALoadableFileExtension(const io::path& fileName) const { // Checking for file extension - return strstr(fileName, ".blp")!=0; + return core::hasFileExtension ( fileName, "blp" ); } @@ -57,20 +55,14 @@ IImage* CImageLoaderBLP::loadImage(io::IReadFile* file) const return 0; BLPHeader header; -// std::cout<<"Trying to load the image\n"; -// std::cout<<"Checking Header\n"; file->read(&header,sizeof(BLPHeader)); -// std::cout<<"Header data: "< palette; PaletteColor tempColor; palette.reallocate(256); @@ -81,11 +73,10 @@ IImage* CImageLoaderBLP::loadImage(io::IReadFile* file) const } -// std::cout<<"Loading Mip 0 Length is "<seek(header.mip_ofs[0]); video::IImage* image = 0; - image = new SImage(ECF_A8R8G8B8, core::dimension2d(header.x_res, header.y_res)); + image = new SImage(ECF_A8R8G8B8, core::dimension2d(header.x_res, header.y_res)); if(header.compression==2) { @@ -117,7 +108,6 @@ IImage* CImageLoaderBLP::loadImage(io::IReadFile* file) const imagedata1.push_back(tempChunk1); } -// std::cout << "Data read\n"; u32 i=0; u32 alpha=255; u32 a[8]; @@ -142,15 +132,7 @@ IImage* CImageLoaderBLP::loadImage(io::IReadFile* file) const } else { - /* std::cout << imagedata1[i].color1 <<","<>11; - g1 = (u32)rgb*(imagedata1[i].color1 & 0x07C0) >>6; - b1 = (u32)rgb*(imagedata1[i].color1 & 0x003E) >>1; - r2 = (u32)rgb*(imagedata1[i].color2 & 0xF800) >>11; - g2 = (u32)rgb*(imagedata1[i].color2 & 0x07C0) >>6; - b2 = (u32)rgb*(imagedata1[i].color2 & 0x003E) >>1; - */ transparency_bit=true; + transparency_bit=true; } u32 tempbitmap=imagedata1[i].bitmap; @@ -225,7 +207,6 @@ IImage* CImageLoaderBLP::loadImage(io::IReadFile* file) const if(transparency_bit==false) image->setPixel(x+tx,y+ty,video::SColor(alpha,(u32)(0.667f*r1+0.333f*r2),(u32)(0.667f*g1+0.333f*g2),(u32)(0.667f*b1+0.333f*b2))); else - //image->setPixel(x+tx,y+ty,video::SColor(255,255,0,0)); image->setPixel(x+tx,y+ty,video::SColor(255,(u32)(0.5f*r1+0.5f*r2),(u32)(0.5f*g1+0.5f*g2),(u32)(0.5f*b1+0.5f*b2))); break; } diff --git a/src/Client/GUI/CImageLoaderBLP.h b/src/Client/GUI/CImageLoaderBLP.h index d8f449d..315779d 100644 --- a/src/Client/GUI/CImageLoaderBLP.h +++ b/src/Client/GUI/CImageLoaderBLP.h @@ -14,7 +14,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".blp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& fileName) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/src/Client/GUI/CM2Mesh.cpp b/src/Client/GUI/CM2Mesh.cpp index 3885bfe..c1895f1 100755 --- a/src/Client/GUI/CM2Mesh.cpp +++ b/src/Client/GUI/CM2Mesh.cpp @@ -73,7 +73,7 @@ void CM2Mesh::animateMesh(f32 frame, f32 blend) LastAnimatedFrame=frame; SkinnedLastFrame=false; - + if (blend<=0.f) return; //No need to animate @@ -118,7 +118,7 @@ void CM2Mesh::animateMesh(f32 frame, f32 blend) void CM2Mesh::buildAllAnimatedMatrices(SJoint *joint, SJoint *parentJoint) { - + if (!joint) { for (u32 i=0; iGlobalAnimatedMatrix= core::matrix4(); joint->GlobalAnimatedMatrix.setTranslation(joint->LocalMatrix.getTranslation()); - + core::matrix4 tm; tm.setTranslation(joint->Animatedposition); joint->GlobalAnimatedMatrix*=tm; - + joint->GlobalAnimatedMatrix*=joint->Animatedrotation.getMatrix(); - + core::matrix4 ts; ts.setScale(joint->Animatedscale); joint->GlobalAnimatedMatrix*=ts; @@ -369,7 +369,7 @@ void CM2Mesh::skinMesh() { if ( !HasAnimation || SkinnedLastFrame ) return; - + SkinnedLastFrame=true; if (!HardwareSkinning) { @@ -544,8 +544,8 @@ void CM2Mesh::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, for (u32 i=0; isetHardwareMappingHint(newMappingHint, buffer); } - - + + //! flags the meshbuffer as changed, reloads hardware buffers void CM2Mesh::setDirty(E_BUFFER_TYPE buffer) { @@ -1008,7 +1008,7 @@ if (HasAnimation) Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix; } } - + //calculate bounding box if (LocalBuffers.empty()) BoundingBox.reset(0,0,0); @@ -1050,7 +1050,7 @@ void CM2Mesh::updateBoundingBox(void) -scene::SSkinMeshBuffer *CM2Mesh::createBuffer() +scene::SSkinMeshBuffer *CM2Mesh::addMeshBuffer() { scene::SSkinMeshBuffer *buffer=new scene::SSkinMeshBuffer(); LocalBuffers.push_back(buffer); @@ -1058,7 +1058,7 @@ scene::SSkinMeshBuffer *CM2Mesh::createBuffer() } -CM2Mesh::SJoint *CM2Mesh::createJoint(SJoint *parent) +CM2Mesh::SJoint *CM2Mesh::addJoint(SJoint *parent) { SJoint *joint=new SJoint; @@ -1077,7 +1077,7 @@ CM2Mesh::SJoint *CM2Mesh::createJoint(SJoint *parent) } -CM2Mesh::SPositionKey *CM2Mesh::createPositionKey(SJoint *joint) +CM2Mesh::SPositionKey *CM2Mesh::addPositionKey(SJoint *joint) { if (!joint) return 0; @@ -1087,7 +1087,7 @@ CM2Mesh::SPositionKey *CM2Mesh::createPositionKey(SJoint *joint) } -CM2Mesh::SScaleKey *CM2Mesh::createScaleKey(SJoint *joint) +CM2Mesh::SScaleKey *CM2Mesh::addScaleKey(SJoint *joint) { if (!joint) return 0; @@ -1097,7 +1097,7 @@ CM2Mesh::SScaleKey *CM2Mesh::createScaleKey(SJoint *joint) } -CM2Mesh::SRotationKey *CM2Mesh::createRotationKey(SJoint *joint) +CM2Mesh::SRotationKey *CM2Mesh::addRotationKey(SJoint *joint) { if (!joint) return 0; @@ -1107,7 +1107,7 @@ CM2Mesh::SRotationKey *CM2Mesh::createRotationKey(SJoint *joint) } -CM2Mesh::SWeight *CM2Mesh::createWeight(SJoint *joint) +CM2Mesh::SWeight *CM2Mesh::addWeight(SJoint *joint) { if (!joint) return 0; @@ -1289,7 +1289,7 @@ void CM2Mesh::convertMeshToTangents() { if (LocalBuffers[b]) { - LocalBuffers[b]->MoveTo_Tangents(); + LocalBuffers[b]->convertToTangents(); const s32 idxCnt = LocalBuffers[b]->getIndexCount(); @@ -1392,11 +1392,11 @@ void CM2Mesh::getFrameLoop(u32 id, s32 &start, s32 &end) found=true; } start = a.begin; - end = a.end; + end = a.end; } else return; - + } void CM2Mesh::newAnimation(u32 id, s32 start, s32 end, f32 probability) @@ -1441,7 +1441,7 @@ bool CM2Mesh::getGeoSetRender(u32 meshbufferNumber)//This gets the render status { return GeoSetRender[meshbufferNumber]; } - else + else return false; }; diff --git a/src/Client/GUI/CM2Mesh.h b/src/Client/GUI/CM2Mesh.h index b7101d2..90630ff 100755 --- a/src/Client/GUI/CM2Mesh.h +++ b/src/Client/GUI/CM2Mesh.h @@ -69,7 +69,7 @@ namespace scene //! updates the bounding box virtual void updateBoundingBox(void); - + //! Returns the type of the animated mesh. virtual E_ANIMATED_MESH_TYPE getMeshType() const; @@ -132,22 +132,22 @@ namespace scene //! loaders should call this after populating the mesh virtual void finalize(); - SSkinMeshBuffer *createBuffer(u32 id) + SSkinMeshBuffer *addMeshBuffer(u32 id) { GeoSetID.push_back(id); GeoSetRender.push_back((id==0?true:false));//This may be changed later on when we know more about the submesh switching business - return createBuffer(); + return addMeshBuffer(); }; - virtual SSkinMeshBuffer *createBuffer(); + virtual SSkinMeshBuffer *addMeshBuffer(); - virtual SJoint *createJoint(SJoint *parent=0); + virtual SJoint *addJoint(SJoint *parent=0); - virtual SPositionKey *createPositionKey(SJoint *joint); - virtual SRotationKey *createRotationKey(SJoint *joint); - virtual SScaleKey *createScaleKey(SJoint *joint); + virtual SPositionKey *addPositionKey(SJoint *joint); + virtual SRotationKey *addRotationKey(SJoint *joint); + virtual SScaleKey *addScaleKey(SJoint *joint); + + virtual SWeight *addWeight(SJoint *joint); - virtual SWeight *createWeight(SJoint *joint); - //Retrieve animation information void getFrameLoop(u32 animId, s32 &start, s32 &end); void newAnimation(u32 id, s32 start, s32 end, f32 probability); @@ -205,7 +205,7 @@ private: core::aabbox3d BoundingBox; core::array< core::array > Vertices_Moved; - + core::array< M2Animation > Animations; core::map > AnimationLookup; }; diff --git a/src/Client/GUI/CM2MeshFileLoader.cpp b/src/Client/GUI/CM2MeshFileLoader.cpp index 1d234a2..3f8f37a 100644 --- a/src/Client/GUI/CM2MeshFileLoader.cpp +++ b/src/Client/GUI/CM2MeshFileLoader.cpp @@ -30,9 +30,9 @@ core::quaternion fixQuaternion(core::quaternion q) { return core::quaternion(q.X, q.Z, q.Y, q.W); } -bool CM2MeshFileLoader::isALoadableFileExtension(const c8* filename)const +bool CM2MeshFileLoader::isALoadableFileExtension(const io::path& filename)const { - return strstr(filename, ".m2")!=0; + return core::hasFileExtension ( filename, "m2" ); } @@ -282,7 +282,7 @@ for(u32 i=0; igetFileName(); + std::string AnimName = MeshFile->getFileName().c_str(); c8 ext[13]; sprintf(ext,"%04d-%02d.anim",M2MAnimations[i].animationID,M2MAnimations[i].subanimationID); AnimName = AnimName.substr(0, AnimName.length()-3) + ext; @@ -596,7 +596,7 @@ switch(header.version) MeshFile->read((u8*)&header+0x54,24);//nColors - nTransparency MeshFile->read((u8*)&header+0x74,sizeof(ModelHeader)-0x74);//nTexAnims - END - std::string SkinName = MeshFile->getFileName(); + std::string SkinName = MeshFile->getFileName().c_str(); SkinName = SkinName.substr(0, SkinName.length()-3) + "00.skin"; // FIX ME if we need more skins io::IReadFile* SkinFile = io::IrrCreateIReadFileBasic(Device, SkinName.c_str()); if (!SkinFile) @@ -619,7 +619,7 @@ switch(header.version) } default: { - logerror("M2: [%s] Wrong header %0X! File version doesn't match or file is not a M2 file.",MeshFile->getFileName(),header.version); + logerror("M2: [%s] Wrong header %0X! File version doesn't match or file is not a M2 file.",MeshFile->getFileName().c_str(),header.version); return 0; } } @@ -649,13 +649,13 @@ for(u32 i=0;igetAllJoints()[M2MBones[i].parentBone]; } - Joint=AnimatedMesh->createJoint(ParentJoint); + Joint=AnimatedMesh->addJoint(ParentJoint); if(M2MBones[i].translation.timestamps.size()>0) { for(u32 j=0;jcreatePositionKey(Joint); + scene::CM2Mesh::SPositionKey* pos=AnimatedMesh->addPositionKey(Joint); pos->frame=M2MBones[i].translation.timestamps[j]; pos->position=fixCoordSystem(core::vector3df(M2MBones[i].translation.values[j*3],M2MBones[i].translation.values[j*3+1],M2MBones[i].translation.values[j*3+2])); } @@ -664,7 +664,7 @@ for(u32 i=0;icreateRotationKey(Joint); + scene::CM2Mesh::SRotationKey* rot=AnimatedMesh->addRotationKey(Joint); rot->frame=M2MBones[i].rotation.timestamps[j]; core::quaternion tempQ=core::quaternion(M2MBones[i].rotation.values[j*4+0],M2MBones[i].rotation.values[j*4+1],M2MBones[i].rotation.values[j*4+2],M2MBones[i].rotation.values[j*4+3]); tempQ = fixQuaternion(tempQ); @@ -677,7 +677,7 @@ for(u32 i=0;icreateScaleKey(Joint); + scene::CM2Mesh::SScaleKey* scale=AnimatedMesh->addScaleKey(Joint); scale->frame=M2MBones[i].scaling.timestamps[j]; scale->scale=core::vector3df(M2MBones[i].scaling.values[j*3],M2MBones[i].scaling.values[j*3+1],M2MBones[i].scaling.values[j*3+2]); } @@ -715,7 +715,7 @@ for(u32 i=0;icreateBuffer(M2MSubmeshes[i].meshpartId); + scene::SSkinMeshBuffer *MeshBuffer = AnimatedMesh->addMeshBuffer(M2MSubmeshes[i].meshpartId); //Put the Indices and Vertices of the Submesh into a mesh buffer //Each Submesh contains only the Indices and Vertices that belong to it. @@ -735,7 +735,7 @@ for(u32 i=0; i < currentView.Submesh.num;i++)// if((M2MVertices[j].weights[k])>0) { u32 boneIndex = M2MVertices[j].bones[k]; - scene::CM2Mesh::SWeight* weight = AnimatedMesh->createWeight(AnimatedMesh->getAllJoints()[boneIndex]); + scene::CM2Mesh::SWeight* weight = AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneIndex]); weight->strength=M2MVertices[j].weights[k]; weight->vertex_id=MeshBuffer->Vertices_Standard.size()-1; weight->buffer_id=i; diff --git a/src/Client/GUI/CM2MeshFileLoader.h b/src/Client/GUI/CM2MeshFileLoader.h index 71276f7..098867c 100644 --- a/src/Client/GUI/CM2MeshFileLoader.h +++ b/src/Client/GUI/CM2MeshFileLoader.h @@ -195,7 +195,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName)const; + virtual bool isALoadableFileExtension(const io::path& fileName)const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/src/Client/GUI/CMDHMemoryReadFile.cpp b/src/Client/GUI/CMDHMemoryReadFile.cpp index 9492755..131c81d 100644 --- a/src/Client/GUI/CMDHMemoryReadFile.cpp +++ b/src/Client/GUI/CMDHMemoryReadFile.cpp @@ -27,7 +27,7 @@ CMDHReadFile::CMDHReadFile(void* memory, long len, const c8* fileName) CMDHReadFile::~CMDHReadFile() { // Drop the Memory, Irrlicht keeps a Model Cache of loaded models - MemoryDataHolder::Delete(getFileName()); + MemoryDataHolder::Delete(Filename.c_str()); } @@ -44,7 +44,7 @@ irr::s32 CMDHReadFile::read(void* buffer, irr::u32 sizeToRead) irr::c8* p = (irr::c8*)Buffer; memcpy(buffer, p + Pos, amount); - + Pos += amount; return amount; @@ -67,7 +67,7 @@ bool CMDHReadFile::seek(long finalPos, bool relativeMovement) { if (finalPos > Len) return false; - + Pos = finalPos; } @@ -93,9 +93,9 @@ long CMDHReadFile::getPos() const //! returns name of file -const irr::c8* CMDHReadFile::getFileName() const +const irr::io::path& CMDHReadFile::getFileName() const { - return Filename.c_str(); + return Filename; } diff --git a/src/Client/GUI/CMDHMemoryReadFile.h b/src/Client/GUI/CMDHMemoryReadFile.h index 872fb0f..ccefa4c 100644 --- a/src/Client/GUI/CMDHMemoryReadFile.h +++ b/src/Client/GUI/CMDHMemoryReadFile.h @@ -39,7 +39,7 @@ public: virtual long getPos() const; //! returns name of file - virtual const c8* getFileName() const; + virtual const path& getFileName() const; private: diff --git a/src/Client/GUI/CWMOMeshFileLoader.cpp b/src/Client/GUI/CWMOMeshFileLoader.cpp index efd81e9..b19061d 100644 --- a/src/Client/GUI/CWMOMeshFileLoader.cpp +++ b/src/Client/GUI/CWMOMeshFileLoader.cpp @@ -34,10 +34,9 @@ CWMOMeshFileLoader::~CWMOMeshFileLoader() } - -bool CWMOMeshFileLoader::isALoadableFileExtension(const c8* filename)const +bool CWMOMeshFileLoader::isALoadableFileExtension(const io::path& filename)const { - return strstr(filename, ".wmo")!=0; + return core::hasFileExtension ( filename, "wmo" ); } @@ -50,7 +49,7 @@ IAnimatedMesh* CWMOMeshFileLoader::createMesh(io::IReadFile* file) if(!file) return 0; MeshFile = file; - std::string filename=MeshFile->getFileName(); + std::string filename=MeshFile->getFileName().c_str(); Mesh = new scene::CM2Mesh(); if ( load(true) )//We try loading a root file first! @@ -274,7 +273,7 @@ for(u32 i=0;icreateBuffer(0); + scene::SSkinMeshBuffer *MeshBuffer = Mesh->addMeshBuffer(0); //Put the Indices and Vertices of the Submesh into a mesh buffer for(u32 j=lastindex;j(_xres,_yres),_colordepth,!_windowed,_shadows,_vsync); + _device = createDevice(_driverType,dimension2d(_xres,_yres),_colordepth,!_windowed,_shadows,_vsync); if(!_device) { logerror("PseuGUI: Can't use specified video driver, trying software mode..."); - _device = createDevice(video::EDT_SOFTWARE,dimension2d(_xres,_yres),_colordepth,!_windowed,false,false); + _device = createDevice(video::EDT_SOFTWARE,dimension2d(_xres,_yres),_colordepth,!_windowed,false,false); if(!_device) { logerror("ERROR: PseuGUI::_Init() failed, no video driver available!"); @@ -117,7 +117,7 @@ void PseuGUI::_Init(void) } DEBUG(logdebug("PseuGUI::Init() _device=%X",_device)); _device->setWindowCaption(L"PseuWoW - Initializing"); - _device->setResizeAble(true); + _device->setResizable(true); _driver = _device->getVideoDriver(); _smgr = _device->getSceneManager(); _guienv = _device->getGUIEnvironment(); diff --git a/src/Client/GUI/PseuGUI.h b/src/Client/GUI/PseuGUI.h index 6ba3d3e..ace5798 100644 --- a/src/Client/GUI/PseuGUI.h +++ b/src/Client/GUI/PseuGUI.h @@ -128,7 +128,7 @@ private: Scene *_scene; irr::ITimer *_timer; uint32 _passtime, _lastpasstime, _passtimediff; - irr::core::dimension2d _screendimension; + irr::core::dimension2d _screendimension; uint32 _throttle;//used for frameratelimiting bool _updateScene; // manually update scene? diff --git a/src/Client/GUI/SImage.cpp b/src/Client/GUI/SImage.cpp index 64bcbb5..96f2c15 100644 --- a/src/Client/GUI/SImage.cpp +++ b/src/Client/GUI/SImage.cpp @@ -1,343 +1,499 @@ -#include "SImage.h" -namespace irr -{ -namespace video -{ - - - //! constructor for empty image -//! constructor -SImage::SImage(ECOLOR_FORMAT format, const core::dimension2d& size): Size(size), Format(format), Data(0) -{ - initData(); -} - -void SImage::initData() -{ - setBitMasks(); - BitsPerPixel = getBitsPerPixelFromFormat(Format); - BytesPerPixel = BitsPerPixel / 8; - - // Pitch should be aligned... - Pitch = BytesPerPixel * Size.Width; - - if (!Data) - Data = new s8[Size.Height * Pitch]; -} - -u32 SImage::getBitsPerPixelFromFormat(ECOLOR_FORMAT format) -{ - switch(format) - { - case ECF_A1R5G5B5: - return 16; - case ECF_R5G6B5: - return 16; - case ECF_R8G8B8: - return 24; - case ECF_A8R8G8B8: - return 32; - } - - return 0; -} -SImage::~SImage() -{ - if (Data) - delete Data; -} - - -//! Returns width and height of image data. -const core::dimension2d& SImage::getDimension() const -{ - return Size; -} - - - -//! Returns bits per pixel. -u32 SImage::getBitsPerPixel() const -{ - return BitsPerPixel; -} - - -//! Returns bytes per pixel -u32 SImage::getBytesPerPixel() const -{ - return BytesPerPixel; -} - - - -//! Returns image data size in bytes -u32 SImage::getImageDataSizeInBytes() const -{ - return Pitch * Size.Height; -} - - - -//! Returns image data size in pixels -u32 SImage::getImageDataSizeInPixels() const -{ - return Size.Width * Size.Height; -} - - - -//! returns mask for red value of a pixel -u32 SImage::getRedMask() const -{ - return RedMask; -} - - - -//! returns mask for green value of a pixel -u32 SImage::getGreenMask() const -{ - return GreenMask; -} - - - -//! returns mask for blue value of a pixel -u32 SImage::getBlueMask() const -{ - return BlueMask; -} - - - -//! returns mask for alpha value of a pixel -u32 SImage::getAlphaMask() const -{ - return AlphaMask; -} - -void SImage::setBitMasks() -{ - switch(Format) - { - case ECF_A1R5G5B5: - AlphaMask = 0x1<<15; - RedMask = 0x1F<<10; - GreenMask = 0x1F<<5; - BlueMask = 0x1F; - break; - case ECF_R5G6B5: - AlphaMask = 0x0; - RedMask = 0x1F<<11; - GreenMask = 0x3F<<5; - BlueMask = 0x1F; - break; - case ECF_R8G8B8: - AlphaMask = 0x0; - RedMask = 0x00FF0000; - GreenMask = 0x0000FF00; - BlueMask = 0x000000FF; - break; - case ECF_A8R8G8B8: - AlphaMask = 0xFF000000; - RedMask = 0x00FF0000; - GreenMask = 0x0000FF00; - BlueMask = 0x000000FF; - break; - } -} - -//! sets a pixel -void SImage::setPixel(u32 x, u32 y, const SColor &color ) -{ - if (x >= (u32)Size.Width || y >= (u32)Size.Height) - return; - - switch(Format) - { - case ECF_A1R5G5B5: - { - u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 )); - *dest = video::A8R8G8B8toA1R5G5B5 ( color.color ); - } break; - - case ECF_R5G6B5: - { - u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 )); - *dest = video::A8R8G8B8toR5G6B5 ( color.color ); - } break; - - case ECF_R8G8B8: - { - u8* dest = (u8*) Data + ( y * Pitch ) + ( x * 3 ); - dest[0] = color.getRed(); - dest[1] = color.getGreen(); - dest[2] = color.getBlue(); - } break; - - case ECF_A8R8G8B8: - { - u32 * dest = (u32*) ((u8*) Data + ( y * Pitch ) + ( x << 2 )); - *dest = color.color; - } break; - } -} - - - -//! returns a pixel -SColor SImage::getPixel(u32 x, u32 y) const -{ - if (x >= (u32)Size.Width || y >= (u32)Size.Height) - return SColor(0); - - switch(Format) - { - case ECF_A1R5G5B5: - return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); - case ECF_R5G6B5: - return R5G6B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); - case ECF_A8R8G8B8: - return ((u32*)Data)[y*Size.Width + x]; - case ECF_R8G8B8: - { - u8* p = &((u8*)Data)[(y*3)*Size.Width + (x*3)]; - return SColor(255,p[0],p[1],p[2]); - } - } - - return SColor(0); -} - - -//! returns the color format -ECOLOR_FORMAT SImage::getColorFormat() const -{ - return Format; -} - -//! copies this surface into another, scaling it to the target image size -// note: this is very very slow. (i didn't want to write a fast version. -// but hopefully, nobody wants to scale surfaces every frame. -void SImage::copyToScaling(void* target, s32 width, s32 height, ECOLOR_FORMAT format, u32 pitch) -{ - if (!target || !width || !height) - return; - - const u32 bpp=getBitsPerPixelFromFormat(format)/8; - if (0==pitch) - pitch = width*bpp; - - if (Format==format && Size.Width==width && Size.Height==height) - { - if (pitch==Pitch) - { - memcpy(target, Data, height*pitch); - return; - } - else - { - u8* tgtpos = (u8*) target; - u8* dstpos = (u8*) Data; - const u32 bwidth = width*bpp; - for (s32 y=0; y& pos, const core::rect& sourceRect, const SColor &color, const core::rect* clipRect) -{ - // color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF -// Blit(color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND: BLITTER_TEXTURE_ALPHA_COLOR_BLEND, target, clipRect, &pos, this, &sourceRect, color.color); -} - -//! fills the surface with given color -void SImage::fill(const SColor &color) -{ - u32 c; - - switch ( Format ) - { - case ECF_A1R5G5B5: - c = video::A8R8G8B8toA1R5G5B5( color.color ); - c |= c << 16; - break; - case ECF_R5G6B5: - c = video::A8R8G8B8toR5G6B5( color.color ); - c |= c << 16; - break; - case ECF_A8R8G8B8: - c = color.color; - break; - default: -// os::Printer::log("CImage::Format not supported", ELL_ERROR); - return; - } - - //memset32( Data, c, getImageDataSizeInBytes() ); -} - -//! copies this surface into another, scaling it to the target image size -// note: this is very very slow. (i didn't want to write a fast version. -// but hopefully, nobody wants to scale surfaces every frame. -void SImage::copyToScaling(IImage* target) -{ - if (!target) - return; - - const core::dimension2d& targetSize = target->getDimension(); - - if (targetSize==Size) - { - copyTo(target); - return; - } - - copyToScaling(target->lock(), targetSize.Width, targetSize.Height, target->getColorFormat()); - target->unlock(); -} - -//! copies this surface into another -void SImage::copyTo(IImage* target, const core::position2d& pos) -{ -// Blit ( BLITTER_TEXTURE, target, 0, &pos, this, 0, 0 ); -} - - -//! copies this surface into another -void SImage::copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect) -{ -// Blit ( BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0 ); -} - - -}//video -}//irr - +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "SImage.h" + +namespace irr +{ +namespace video +{ + +//! Constructor of empty image +SImage::SImage(ECOLOR_FORMAT format, const core::dimension2d& size) +:Data(0), Size(size), Format(format), DeleteMemory(true) +{ + initData(); +} + + +//! Constructor from raw data +SImage::SImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* data, + bool ownForeignMemory, bool deleteForeignMemory) +: Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory) +{ + if (ownForeignMemory) + { + Data = (u8*)0xbadf00d; + initData(); + Data = (u8*)data; + } + else + { + Data = 0; + initData(); + memcpy(Data, data, Size.Height * Pitch); + } +} + + +//! assumes format and size has been set and creates the rest +void SImage::initData() +{ +#ifdef _DEBUG + setDebugName("SImage"); +#endif + BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8; + + // Pitch should be aligned... + Pitch = BytesPerPixel * Size.Width; + + if (!Data) + Data = new u8[Size.Height * Pitch]; +} + + +//! destructor +SImage::~SImage() +{ + if ( DeleteMemory ) + delete [] Data; +} + + +//! Returns width and height of image data. +const core::dimension2d& SImage::getDimension() const +{ + return Size; +} + + +//! Returns bits per pixel. +u32 SImage::getBitsPerPixel() const +{ + return getBitsPerPixelFromFormat(Format); +} + + +//! Returns bytes per pixel +u32 SImage::getBytesPerPixel() const +{ + return BytesPerPixel; +} + + +//! Returns image data size in bytes +u32 SImage::getImageDataSizeInBytes() const +{ + return Pitch * Size.Height; +} + + +//! Returns image data size in pixels +u32 SImage::getImageDataSizeInPixels() const +{ + return Size.Width * Size.Height; +} + + +//! returns mask for red value of a pixel +u32 SImage::getRedMask() const +{ + switch(Format) + { + case ECF_A1R5G5B5: + return 0x1F<<10; + case ECF_R5G6B5: + return 0x1F<<11; + case ECF_R8G8B8: + return 0x00FF0000; + case ECF_A8R8G8B8: + return 0x00FF0000; + default: + return 0x0; + } +} + + +//! returns mask for green value of a pixel +u32 SImage::getGreenMask() const +{ + switch(Format) + { + case ECF_A1R5G5B5: + return 0x1F<<5; + case ECF_R5G6B5: + return 0x3F<<5; + case ECF_R8G8B8: + return 0x0000FF00; + case ECF_A8R8G8B8: + return 0x0000FF00; + default: + return 0x0; + } +} + + +//! returns mask for blue value of a pixel +u32 SImage::getBlueMask() const +{ + switch(Format) + { + case ECF_A1R5G5B5: + return 0x1F; + case ECF_R5G6B5: + return 0x1F; + case ECF_R8G8B8: + return 0x000000FF; + case ECF_A8R8G8B8: + return 0x000000FF; + default: + return 0x0; + } +} + + +//! returns mask for alpha value of a pixel +u32 SImage::getAlphaMask() const +{ + switch(Format) + { + case ECF_A1R5G5B5: + return 0x1<<15; + case ECF_R5G6B5: + return 0x0; + case ECF_R8G8B8: + return 0x0; + case ECF_A8R8G8B8: + return 0xFF000000; + default: + return 0x0; + } +} + + +//! sets a pixel +void SImage::setPixel(u32 x, u32 y, const SColor &color, bool blend) +{ + if (x >= Size.Width || y >= Size.Height) + return; + + switch(Format) + { + case ECF_A1R5G5B5: + { + u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 )); + *dest = video::A8R8G8B8toA1R5G5B5( color.color ); + } break; + + case ECF_R5G6B5: + { + u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 )); + *dest = video::A8R8G8B8toR5G6B5( color.color ); + } break; + + case ECF_R8G8B8: + { + u8* dest = Data + ( y * Pitch ) + ( x * 3 ); + dest[0] = (u8)color.getRed(); + dest[1] = (u8)color.getGreen(); + dest[2] = (u8)color.getBlue(); + } break; + + case ECF_A8R8G8B8: + { + u32 * dest = (u32*) (Data + ( y * Pitch ) + ( x << 2 )); + *dest = color.color; + } break; + } +} + + +//! returns a pixel +SColor SImage::getPixel(u32 x, u32 y) const +{ + if (x >= Size.Width || y >= Size.Height) + return SColor(0); + + switch(Format) + { + case ECF_A1R5G5B5: + return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); + case ECF_R5G6B5: + return R5G6B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); + case ECF_A8R8G8B8: + return ((u32*)Data)[y*Size.Width + x]; + case ECF_R8G8B8: + { + u8* p = Data+(y*3)*Size.Width + (x*3); + return SColor(255,p[0],p[1],p[2]); + } + } + + return SColor(0); +} + + +//! returns the color format +ECOLOR_FORMAT SImage::getColorFormat() const +{ + return Format; +} + + +//! copies this surface into another at given position +void SImage::copyTo(IImage* target, const core::position2d& pos) +{ +// Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0); +} + + +//! copies this surface partially into another at given position +void SImage::copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect) +{ +// Blit(BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0); +} + + +//! copies this surface into another, using the alpha mask, a cliprect and a color to add with +void SImage::copyToWithAlpha(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const SColor &color, const core::rect* clipRect) +{ + // color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF +// Blit(color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND: BLITTER_TEXTURE_ALPHA_COLOR_BLEND, +// target, clipRect, &pos, this, &sourceRect, color.color); +} + + +//! copies this surface into another, scaling it to the target image size +// note: this is very very slow. +void SImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch) +{ + if (!target || !width || !height) + return; + + const u32 bpp=getBitsPerPixelFromFormat(format)/8; + if (0==pitch) + pitch = width*bpp; + + if (Format==format && Size.Width==width && Size.Height==height) + { + if (pitch==Pitch) + { + memcpy(target, Data, height*pitch); + return; + } + else + { + u8* tgtpos = (u8*) target; + u8* srcpos = Data; + const u32 bwidth = width*bpp; + const u32 rest = pitch-bwidth; + for (u32 y=0; y& targetSize = target->getDimension(); + + if (targetSize==Size) + { + copyTo(target); + return; + } + + copyToScaling(target->lock(), targetSize.Width, targetSize.Height, target->getColorFormat()); + target->unlock(); +} + + +//! copies this surface into another, scaling it to fit it. +void SImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend) +{ + const core::dimension2d destSize = target->getDimension(); + + const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width; + const f32 sourceYStep = (f32) Size.Height / (f32) destSize.Height; + + target->lock(); + + s32 fx = core::ceil32( sourceXStep ); + s32 fy = core::ceil32( sourceYStep ); + f32 sx; + f32 sy; + + sy = 0.f; + for ( u32 y = 0; y != destSize.Height; ++y ) + { + sx = 0.f; + for ( u32 x = 0; x != destSize.Width; ++x ) + { + target->setPixel( x, y, + getPixelBox( core::floor32(sx), core::floor32(sy), fx, fy, bias ), blend ); + sx += sourceXStep; + } + sy += sourceYStep; + } + + target->unlock(); +} + + +//! fills the surface with given color +void SImage::fill(const SColor &color) +{ + u32 c; + + switch ( Format ) + { + case ECF_A1R5G5B5: + c = color.toA1R5G5B5(); + c |= c << 16; + break; + case ECF_R5G6B5: + c = video::A8R8G8B8toR5G6B5( color.color ); + c |= c << 16; + break; + case ECF_A8R8G8B8: + c = color.color; + break; + case ECF_R8G8B8: + { + u8 rgb[3]; +// CColorConverter::convert_A8R8G8B8toR8G8B8(&color, 1, rgb); + const u32 size = getImageDataSizeInBytes(); + for (u32 i=0; i> sdiv ) + bias, 0, 255 ); +// r = core::s32_clamp( ( r >> sdiv ) + bias, 0, 255 ); +// g = core::s32_clamp( ( g >> sdiv ) + bias, 0, 255 ); +// b = core::s32_clamp( ( b >> sdiv ) + bias, 0, 255 ); + + c.set( a, r, g, b ); + return c; +} + + +// Methods for Software drivers, non-virtual and not necessary to copy into other image classes +//! draws a rectangle +void SImage::drawRectangle(const core::rect& rect, const SColor &color) +{ +// Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA, +// this, 0, &rect.UpperLeftCorner, 0, &rect, color.color); +} + + +//! draws a line from to with color +void SImage::drawLine(const core::position2d& from, const core::position2d& to, const SColor &color) +{ +// AbsRectangle clip; +// GetClip( clip, this ); + +// core::position2d p[2]; +// +// if ( ClipLine( clip, p[0], p[1], from, to ) ) +// { +// u32 alpha = extractAlpha( color.color ); +// +// switch ( Format ) +// { +// case ECF_A1R5G5B5: +// if ( alpha == 256 ) +// { +// RenderLine16_Decal( this, p[0], p[1], video::A8R8G8B8toA1R5G5B5( color.color ) ); +// } +// else +// { +// RenderLine16_Blend( this, p[0], p[1], video::A8R8G8B8toA1R5G5B5( color.color ), alpha >> 3 ); +// } +// break; +// case ECF_A8R8G8B8: +// if ( alpha == 256 ) +// { +// RenderLine32_Decal( this, p[0], p[1], color.color ); +// } +// else +// { +// RenderLine32_Blend( this, p[0], p[1], color.color, alpha ); +// } +// break; +// default: +// break; +// } +// } +} + + +} // end namespace video +} // end namespace irr diff --git a/src/Client/GUI/SImage.h b/src/Client/GUI/SImage.h index ba7a093..403fbc0 100644 --- a/src/Client/GUI/SImage.h +++ b/src/Client/GUI/SImage.h @@ -1,109 +1,130 @@ -//most simplistic IImage Implementation, copypasted form irrlichts CImage -#include "irrlicht/irrlicht.h" -namespace irr -{ -namespace video -{ - -class SImage : public IImage -{ -public: - //! constructor for empty image - SImage(ECOLOR_FORMAT format, const core::dimension2d& size); - //! destructor - virtual ~SImage(); - - //! returns a pixel - virtual SColor getPixel(u32 x, u32 y) const; - - //! sets a pixel - virtual void setPixel(u32 x, u32 y, const SColor &color ); - - //! Lock function. - virtual void* lock() - { - return Data; - }; - - //! Unlock function. - virtual void unlock() {}; - - //! Returns width and height of image data. - virtual const core::dimension2d& getDimension() const; - - //! Returns bits per pixel. - virtual u32 getBitsPerPixel() const; - - //! Returns bytes per pixel - virtual u32 getBytesPerPixel() const; - - //! Returns image data size in bytes - virtual u32 getImageDataSizeInBytes() const; - - //! Returns image data size in pixels - virtual u32 getImageDataSizeInPixels() const; - - //! returns mask for red value of a pixel - virtual u32 getRedMask() const; - - //! returns mask for green value of a pixel - virtual u32 getGreenMask() const; - - //! returns mask for blue value of a pixel - virtual u32 getBlueMask() const; - - //! returns mask for alpha value of a pixel - virtual u32 getAlphaMask() const; - - //! returns the color format - virtual ECOLOR_FORMAT getColorFormat() const; - - //! copies this surface into another - void copyTo(IImage* target, const core::position2d& pos=core::position2d(0,0)); - - //! copies this surface into another - void copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect=0); - - //! copies this surface into another, using the alpha mask, an cliprect and a color to add with - virtual void copyToWithAlpha(IImage* target, const core::position2d& pos, - const core::rect& sourceRect, const SColor &color, - const core::rect* clipRect = 0); - - //! fills the surface with black or white - virtual void fill(const SColor &color); - - //! copies this surface into another, scaling it to fit. - void copyToScaling(void* target, s32 width, s32 height, ECOLOR_FORMAT format, u32 pitch=0); - - //! copies this surface into another, scaling it to fit. - void copyToScaling(IImage* target); - - //! returns pitch of image - virtual u32 getPitch() const - { - return Pitch; - } - - static u32 getBitsPerPixelFromFormat(ECOLOR_FORMAT format); -private: - - //! assumes format and size has been set and creates the rest - void initData(); - - void setBitMasks(); - inline SColor getPixelBox ( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const; - void* Data; - core::dimension2d Size; - u32 BitsPerPixel; - u32 BytesPerPixel; - u32 Pitch; - ECOLOR_FORMAT Format; - - u32 RedMask; - u32 GreenMask; - u32 BlueMask; - u32 AlphaMask; -}; - -}//video -}//irr +//most simplistic IImage Implementation, copypasted form irrlichts CImage + +#ifndef __S_IMAGE_H_INCLUDED__ +#define __S_IMAGE_H_INCLUDED__ + +#include "irrlicht/irrlicht.h" + +namespace irr +{ +namespace video +{ + +//! IImage implementation with a lot of special image operations for +//! 16 bit A1R5G5B5/32 Bit A8R8G8B8 images, which are used by the SoftwareDevice. +class SImage : public IImage +{ +public: + + //! constructor from raw image data + /** \param useForeignMemory: If true, the image will use the data pointer + directly and own it from now on, which means it will also try to delete [] the + data when the image will be destructed. If false, the memory will by copied. */ + SImage(ECOLOR_FORMAT format, const core::dimension2d& size, + void* data, bool ownForeignMemory=true, bool deleteMemory = true); + + //! constructor for empty image + SImage(ECOLOR_FORMAT format, const core::dimension2d& size); + + //! destructor + virtual ~SImage(); + + //! Lock function. + virtual void* lock() + { + return Data; + } + + //! Unlock function. + virtual void unlock() {} + + //! Returns width and height of image data. + virtual const core::dimension2d& getDimension() const; + + //! Returns bits per pixel. + virtual u32 getBitsPerPixel() const; + + //! Returns bytes per pixel + virtual u32 getBytesPerPixel() const; + + //! Returns image data size in bytes + virtual u32 getImageDataSizeInBytes() const; + + //! Returns image data size in pixels + virtual u32 getImageDataSizeInPixels() const; + + //! returns mask for red value of a pixel + virtual u32 getRedMask() const; + + //! returns mask for green value of a pixel + virtual u32 getGreenMask() const; + + //! returns mask for blue value of a pixel + virtual u32 getBlueMask() const; + + //! returns mask for alpha value of a pixel + virtual u32 getAlphaMask() const; + + //! returns a pixel + virtual SColor getPixel(u32 x, u32 y) const; + + //! sets a pixel + virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ); + + //! returns the color format + virtual ECOLOR_FORMAT getColorFormat() const; + + //! returns pitch of image + virtual u32 getPitch() const { return Pitch; } + + //! copies this surface into another, scaling it to fit. + virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch=0); + + //! copies this surface into another, scaling it to fit. + virtual void copyToScaling(IImage* target); + + //! copies this surface into another + virtual void copyTo(IImage* target, const core::position2d& pos=core::position2d(0,0)); + + //! copies this surface into another + virtual void copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect=0); + + //! copies this surface into another, using the alpha mask, an cliprect and a color to add with + virtual void copyToWithAlpha(IImage* target, const core::position2d& pos, + const core::rect& sourceRect, const SColor &color, + const core::rect* clipRect = 0); + + //! copies this surface into another, scaling it to fit, appyling a box filter + virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false); + + //! fills the surface with black or white + virtual void fill(const SColor &color); + + //! draws a rectangle + void drawRectangle(const core::rect& rect, const SColor &color); + + //! draws a line from to + void drawLine(const core::position2d& from, const core::position2d& to, const SColor &color); + +private: + + //! assumes format and size has been set and creates the rest + void initData(); + + inline SColor getPixelBox ( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const; + + u8* Data; + core::dimension2d Size; + u32 BytesPerPixel; + u32 Pitch; + ECOLOR_FORMAT Format; + + bool DeleteMemory; +}; + +} // end namespace video +} // end namespace irr + + +#endif + diff --git a/src/Client/GUI/Scene.h b/src/Client/GUI/Scene.h index 48d08b5..3ff9a3a 100644 --- a/src/Client/GUI/Scene.h +++ b/src/Client/GUI/Scene.h @@ -13,7 +13,7 @@ using namespace gui; using namespace irrklang; -inline core::rect CalcRelativeScreenPos(core::dimension2d dim, f32 x, f32 y, f32 w, f32 h) +inline core::rect CalcRelativeScreenPos(core::dimension2d dim, f32 x, f32 y, f32 w, f32 h) { core::rect r; r.UpperLeftCorner.X = dim.Width * x; @@ -22,7 +22,7 @@ inline core::rect CalcRelativeScreenPos(core::dimension2d dim, f32 x, r.LowerRightCorner.Y = r.UpperLeftCorner.Y + (dim.Height * h); return r; } - +//Pure and applied stupidity: the driver returns u32, but guiend->addbutton insists on getting s32 inline core::rect CalcRelativeScreenPos(video::IVideoDriver* drv, f32 x, f32 y, f32 w, f32 h) { return CalcRelativeScreenPos(drv->getScreenSize(),x,y,w,h); diff --git a/src/Client/GUI/SceneCharselection.cpp b/src/Client/GUI/SceneCharselection.cpp index d5cf957..fdfe171 100644 --- a/src/Client/GUI/SceneCharselection.cpp +++ b/src/Client/GUI/SceneCharselection.cpp @@ -24,7 +24,7 @@ SceneCharSelection::SceneCharSelection(PseuGUI *gui) : Scene(gui) { realmwin = NULL; newcharwin = NULL; - + textdb = instance->dbmgr.GetDB("gui_charselect_text"); racedb = instance->dbmgr.GetDB("race"); classdb = instance->dbmgr.GetDB("class"); @@ -35,8 +35,8 @@ SceneCharSelection::SceneCharSelection(PseuGUI *gui) : Scene(gui) eventrecv->customHandledEvents.insert(EGET_LISTBOX_SELECTED_AGAIN); eventrecv->store_mouse = false; // do not queue mouse input - dimension2d scrn = driver->getScreenSize(); - + dimension2d scrn = driver->getScreenSize(); + guienv->addButton(CalcRelativeScreenPos(driver, 0.45f ,0.9f, 0.15f, 0.05f), NULL, BUTTON_ENTER_WORLD, GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_ENTERWORLD).c_str()); guienv->addButton(CalcRelativeScreenPos(driver, 0.9f, 0.92f, 0.08f, 0.03f), NULL, BUTTON_BACK, @@ -150,7 +150,7 @@ void SceneCharSelection::OnUpdate(s32 timepassed) } } - + } } } @@ -189,7 +189,7 @@ void SceneCharSelection::OnUpdate(s32 timepassed) } if(eventrecv->buttons & BUTTON_NEW_CHARACTER && !newcharwin) { - dimension2d dim; + dimension2d dim; rect pos; msgbox_textid = 0; newcharwin = guienv->addWindow(CalcRelativeScreenPos(driver, 0.2f, 0.2f, 0.6f, 0.6f), true, @@ -227,7 +227,7 @@ void SceneCharSelection::OnUpdate(s32 timepassed) scenedata[ISCENE_CHARSEL_REALMFIRST] = 0; if(instance->GetRSession()) { - dimension2d dim; + dimension2d dim; rect pos; realmwin = guienv->addWindow(CalcRelativeScreenPos(driver, 0.2f, 0.2f, 0.6f, 0.6f), true, GetStringFromDB(ISCENE_CHARSEL_LABELS, DSCENE_CHARSEL_LABEL_REALMWIN).c_str()); @@ -286,7 +286,7 @@ void SceneCharSelection::OnUpdate(s32 timepassed) { guienv->addMessageBox(L"Not yet implemented!", L"This action is not yet supported.\nYou can change the realm only while still connected to the realm server."); } - } + } if(eventrecv->buttons & BUTTON_REALMWIN_OK && realmwin) { RealmSession *rs = instance->GetRSession(); @@ -341,7 +341,7 @@ void SceneCharSelection::OnUpdate(s32 timepassed) newcharwin->remove(); newcharwin = NULL; } - + if(newcharwin && msgbox_textid != scenedata[ISCENE_CHARSEL_ERRMSG]) { msgbox_textid = scenedata[ISCENE_CHARSEL_ERRMSG]; diff --git a/src/Client/GUI/SceneLogin.cpp b/src/Client/GUI/SceneLogin.cpp index 1bb87d7..9d2262a 100644 --- a/src/Client/GUI/SceneLogin.cpp +++ b/src/Client/GUI/SceneLogin.cpp @@ -27,7 +27,7 @@ SceneLogin::SceneLogin(PseuGUI *gui) : Scene(gui) eventrecv->keyToButtonMap[KEY_ESCAPE] = BUTTON_QUIT; device->setEventReceiver(eventrecv); - dimension2d scrn = driver->getScreenSize(); + dimension2d scrn = driver->getScreenSize(); irrlogo = guienv->addImage(driver->getTexture("data/misc/irrlichtlogo.png"), core::position2d(5,5),true,rootgui); background = guienv->addImage(driver->getTexture("data/misc/sky.jpg"), core::position2d(5,5),true,rootgui); diff --git a/src/Client/GUI/SceneWorld.cpp b/src/Client/GUI/SceneWorld.cpp index 92637ae..0200359 100644 --- a/src/Client/GUI/SceneWorld.cpp +++ b/src/Client/GUI/SceneWorld.cpp @@ -94,7 +94,7 @@ SceneWorld::SceneWorld(PseuGUI *g) : Scene(g) logdetail("GUI: Using farclip=%.2f fogfar=%.2f fognear=%.2f", farclip, fogfar, fognear); - driver->setFog(envBasicColor, true, fognear, fogfar, 0.02f); + driver->setFog(envBasicColor, video::EFT_FOG_LINEAR, fognear, fogfar, 0.02f); // setup cursor // shlainn: The cursor contrpller is a horrible hack. diff --git a/src/Client/GUI/ShTlTerrainSceneNode.cpp b/src/Client/GUI/ShTlTerrainSceneNode.cpp index 76314af..596f2a5 100644 --- a/src/Client/GUI/ShTlTerrainSceneNode.cpp +++ b/src/Client/GUI/ShTlTerrainSceneNode.cpp @@ -195,12 +195,13 @@ ShTlTerrainSceneNode::ShTlTerrainSceneNode(scene::ISceneManager* smgr, bool mmflag = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); - CTexture = driver->addTexture(core::dimension2d(tw, th), "colortexture", video::ECF_A8R8G8B8); + CTexture = driver->addTexture(core::dimension2d(tw, th), "colortexture", video::ECF_A8R8G8B8); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mmflag); Material[0].TextureLayer[0].Texture = CTexture; - Material[0].TextureLayer[0].TextureWrap = video::ETC_CLAMP_TO_EDGE; + Material[0].TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; + Material[0].TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; // setup UV coordinates of vertices on 2nd texture layer f32 ax = (f32)MeshSize.Width / CTexture->getSize().Width / MeshSize.Width; diff --git a/src/dep/include/irrlicht/CDynamicMeshBuffer.h b/src/dep/include/irrlicht/CDynamicMeshBuffer.h index 587a164..2e63648 100644 --- a/src/dep/include/irrlicht/CDynamicMeshBuffer.h +++ b/src/dep/include/irrlicht/CDynamicMeshBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2008 Nikolaus Gebhardt +// Copyright (C) 2008-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/CIndexBuffer.h b/src/dep/include/irrlicht/CIndexBuffer.h index 61002f4..14d83ae 100644 --- a/src/dep/include/irrlicht/CIndexBuffer.h +++ b/src/dep/include/irrlicht/CIndexBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2008 Nikolaus Gebhardt +// Copyright (C) 2008-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/CMeshBuffer.h b/src/dep/include/irrlicht/CMeshBuffer.h index 52f9d4e..b7c9e43 100644 --- a/src/dep/include/irrlicht/CMeshBuffer.h +++ b/src/dep/include/irrlicht/CMeshBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/CVertexBuffer.h b/src/dep/include/irrlicht/CVertexBuffer.h index 2bcab45..cc4d24e 100644 --- a/src/dep/include/irrlicht/CVertexBuffer.h +++ b/src/dep/include/irrlicht/CVertexBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2008 Nikolaus Gebhardt +// Copyright (C) 2008-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/EAttributes.h b/src/dep/include/irrlicht/EAttributes.h new file mode 100644 index 0000000..c9fb925 --- /dev/null +++ b/src/dep/include/irrlicht/EAttributes.h @@ -0,0 +1,98 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_ATTRIBUTES_H_INCLUDED__ +#define __E_ATTRIBUTES_H_INCLUDED__ + +namespace irr +{ +namespace io +{ + +//! Types of attributes available for IAttributes +enum E_ATTRIBUTE_TYPE +{ + // integer attribute + EAT_INT = 0, + + // float attribute + EAT_FLOAT, + + // string attribute + EAT_STRING, + + // boolean attribute + EAT_BOOL, + + // enumeration attribute + EAT_ENUM, + + // color attribute + EAT_COLOR, + + // floating point color attribute + EAT_COLORF, + + // 3d vector attribute + EAT_VECTOR3D, + + // 2d position attribute + EAT_POSITION2D, + + // vector 2d + EAT_VECTOR2D, + + // rectangle attribute + EAT_RECT, + + // matrix attribute + EAT_MATRIX, + + // quaternion attribute + EAT_QUATERNION, + + // 3d bounding box + EAT_BBOX, + + // plane + EAT_PLANE, + + // 3d triangle + EAT_TRIANGLE3D, + + // line 2d + EAT_LINE2D, + + // line 3d + EAT_LINE3D, + + // array of stringws attribute + EAT_STRINGWARRAY, + + // array of float + EAT_FLOATARRAY, + + // array of int + EAT_INTARRAY, + + // binary data attribute + EAT_BINARY, + + // texture reference attribute + EAT_TEXTURE, + + // user pointer void* + EAT_USER_POINTER, + + // known attribute type count + EAT_COUNT, + + // unknown attribute + EAT_UNKNOWN +}; + +} // end namespace io +} // end namespace irr + +#endif diff --git a/src/dep/include/irrlicht/ECullingTypes.h b/src/dep/include/irrlicht/ECullingTypes.h index 61ae0ee..f9fb77e 100644 --- a/src/dep/include/irrlicht/ECullingTypes.h +++ b/src/dep/include/irrlicht/ECullingTypes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/EDebugSceneTypes.h b/src/dep/include/irrlicht/EDebugSceneTypes.h index f4fe2ce..230d87c 100644 --- a/src/dep/include/irrlicht/EDebugSceneTypes.h +++ b/src/dep/include/irrlicht/EDebugSceneTypes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/EDeviceTypes.h b/src/dep/include/irrlicht/EDeviceTypes.h new file mode 100644 index 0000000..fdbc619 --- /dev/null +++ b/src/dep/include/irrlicht/EDeviceTypes.h @@ -0,0 +1,56 @@ +#ifndef __E_DEVICE_TYPES_H_INCLUDED__ +#define __E_DEVICE_TYPES_H_INCLUDED__ + +namespace irr +{ + + //! An enum for the different device types supported by the Irrlicht Engine. + enum E_DEVICE_TYPE + { + + //! A device native to Microsoft Windows + /** This device uses the Win32 API and works in all versions of Windows. */ + EIDT_WIN32, + + //! A device native to Windows CE devices + /** This device works on Windows Mobile, Pocket PC and Microsoft SmartPhone devices */ + EIDT_WINCE, + + //! A device native to Unix style operating systems. + /** This device uses the X11 windowing system and works in Linux, Solaris, FreeBSD, OSX and + other operating systems which support X11. */ + EIDT_X11, + + //! A device native to Mac OSX + /** This device uses Apple's Cocoa API and works in Mac OSX 10.2 and above. */ + EIDT_OSX, + + //! A device which uses Simple DirectMedia Layer + /** The SDL device works under all platforms supported by SDL but first must be compiled + in by defining the IRR_USE_SDL_DEVICE macro in IrrCompileConfig.h */ + EIDT_SDL, + + //! A device for raw framebuffer access + /** Best used with embedded devices and mobile systems. + Does not need X11 or other graphical subsystems. + May support hw-acceleration via OpenGL-ES for FBDirect */ + EIDT_FRAMEBUFFER, + + //! A simple text only device supported by all platforms. + /** This device allows applications to run from the command line without opening a window. + It can render the output of the software drivers to the console as ASCII. It only supports + mouse and keyboard in Windows operating systems. */ + EIDT_CONSOLE, + + //! This selection allows Irrlicht to choose the best device from the ones available. + /** If this selection is chosen then Irrlicht will try to use the IrrlichtDevice native + to your operating system. If this is unavailable then the X11, SDL and then console device + will be tried. This ensures that Irrlicht will run even if your platform is unsupported, + although it may not be able to render anything. */ + EIDT_BEST + }; + +} // end namespace irr + +#endif // __E_DEVICE_TYPES_H_INCLUDED__ + diff --git a/src/dep/include/irrlicht/EDriverFeatures.h b/src/dep/include/irrlicht/EDriverFeatures.h index 20498d3..65f28f4 100644 --- a/src/dep/include/irrlicht/EDriverFeatures.h +++ b/src/dep/include/irrlicht/EDriverFeatures.h @@ -1,97 +1,118 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __E_DRIVER_FEATURES_H_INCLUDED__ -#define __E_DRIVER_FEATURES_H_INCLUDED__ - -namespace irr -{ -namespace video -{ - - //! enumeration for querying features of the video driver. - enum E_VIDEO_DRIVER_FEATURE - { - //! Is driver able to render to a surface? - EVDF_RENDER_TO_TARGET = 0, - - //! Is hardeware transform and lighting supported? - EVDF_HARDWARE_TL, - - //! Are multiple textures per material possible? - EVDF_MULTITEXTURE, - - //! Is driver able to render with a bilinear filter applied? - EVDF_BILINEAR_FILTER, - - //! Can the driver handle mip maps? - EVDF_MIP_MAP, - - //! Can the driver update mip maps automatically? - EVDF_MIP_MAP_AUTO_UPDATE, - - //! Are stencilbuffers switched on and does the device support stencil buffers? - EVDF_STENCIL_BUFFER, - - //! Is Vertex Shader 1.1 supported? - EVDF_VERTEX_SHADER_1_1, - - //! Is Vertex Shader 2.0 supported? - EVDF_VERTEX_SHADER_2_0, - - //! Is Vertex Shader 3.0 supported? - EVDF_VERTEX_SHADER_3_0, - - //! Is Pixel Shader 1.1 supported? - EVDF_PIXEL_SHADER_1_1, - - //! Is Pixel Shader 1.2 supported? - EVDF_PIXEL_SHADER_1_2, - - //! Is Pixel Shader 1.3 supported? - EVDF_PIXEL_SHADER_1_3, - - //! Is Pixel Shader 1.4 supported? - EVDF_PIXEL_SHADER_1_4, - - //! Is Pixel Shader 2.0 supported? - EVDF_PIXEL_SHADER_2_0, - - //! Is Pixel Shader 3.0 supported? - EVDF_PIXEL_SHADER_3_0, - - //! Are ARB vertex programs v1.0 supported? - EVDF_ARB_VERTEX_PROGRAM_1, - - //! Are ARB fragment programs v1.0 supported? - EVDF_ARB_FRAGMENT_PROGRAM_1, - - //! Is GLSL supported? - EVDF_ARB_GLSL, - - //! Is HLSL supported? - EVDF_HLSL, - - //! Are non-square textures supported? - EVDF_TEXTURE_NSQUARE, - - //! Are non-power-of-two textures supported? - EVDF_TEXTURE_NPOT, - - //! Are framebuffer objects supported? - EVDF_FRAMEBUFFER_OBJECT, - - //! Are vertex buffer objects supported? - EVDF_VERTEX_BUFFER_OBJECT, - - //! Only used for counting the elements of this enum - EVDF_COUNT - }; - -} // end namespace video -} // end namespace irr - - -#endif - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_DRIVER_FEATURES_H_INCLUDED__ +#define __E_DRIVER_FEATURES_H_INCLUDED__ + +namespace irr +{ +namespace video +{ + + //! enumeration for querying features of the video driver. + enum E_VIDEO_DRIVER_FEATURE + { + //! Is driver able to render to a surface? + EVDF_RENDER_TO_TARGET = 0, + + //! Is hardeware transform and lighting supported? + EVDF_HARDWARE_TL, + + //! Are multiple textures per material possible? + EVDF_MULTITEXTURE, + + //! Is driver able to render with a bilinear filter applied? + EVDF_BILINEAR_FILTER, + + //! Can the driver handle mip maps? + EVDF_MIP_MAP, + + //! Can the driver update mip maps automatically? + EVDF_MIP_MAP_AUTO_UPDATE, + + //! Are stencilbuffers switched on and does the device support stencil buffers? + EVDF_STENCIL_BUFFER, + + //! Is Vertex Shader 1.1 supported? + EVDF_VERTEX_SHADER_1_1, + + //! Is Vertex Shader 2.0 supported? + EVDF_VERTEX_SHADER_2_0, + + //! Is Vertex Shader 3.0 supported? + EVDF_VERTEX_SHADER_3_0, + + //! Is Pixel Shader 1.1 supported? + EVDF_PIXEL_SHADER_1_1, + + //! Is Pixel Shader 1.2 supported? + EVDF_PIXEL_SHADER_1_2, + + //! Is Pixel Shader 1.3 supported? + EVDF_PIXEL_SHADER_1_3, + + //! Is Pixel Shader 1.4 supported? + EVDF_PIXEL_SHADER_1_4, + + //! Is Pixel Shader 2.0 supported? + EVDF_PIXEL_SHADER_2_0, + + //! Is Pixel Shader 3.0 supported? + EVDF_PIXEL_SHADER_3_0, + + //! Are ARB vertex programs v1.0 supported? + EVDF_ARB_VERTEX_PROGRAM_1, + + //! Are ARB fragment programs v1.0 supported? + EVDF_ARB_FRAGMENT_PROGRAM_1, + + //! Is GLSL supported? + EVDF_ARB_GLSL, + + //! Is HLSL supported? + EVDF_HLSL, + + //! Are non-square textures supported? + EVDF_TEXTURE_NSQUARE, + + //! Are non-power-of-two textures supported? + EVDF_TEXTURE_NPOT, + + //! Are framebuffer objects supported? + EVDF_FRAMEBUFFER_OBJECT, + + //! Are vertex buffer objects supported? + EVDF_VERTEX_BUFFER_OBJECT, + + //! Supports Alpha To Coverage + EVDF_ALPHA_TO_COVERAGE, + + //! Supports Color masks (disabling color planes in output) + EVDF_COLOR_MASK, + + //! Supports multiple render targets at once + EVDF_MULTIPLE_RENDER_TARGETS, + + //! Supports separate blend settings for multiple render targets + EVDF_MRT_BLEND, + + //! Supports separate color masks for multiple render targets + EVDF_MRT_COLOR_MASK, + + //! Supports separate blend functions for multiple render targets + EVDF_MRT_BLEND_FUNC, + + //! Supports geometry shaders + EVDF_GEOMETRY_SHADER, + + //! Only used for counting the elements of this enum + EVDF_COUNT + }; + +} // end namespace video +} // end namespace irr + + +#endif + diff --git a/src/dep/include/irrlicht/EDriverTypes.h b/src/dep/include/irrlicht/EDriverTypes.h index 322c6a9..4ca1d6e 100644 --- a/src/dep/include/irrlicht/EDriverTypes.h +++ b/src/dep/include/irrlicht/EDriverTypes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -13,45 +13,47 @@ namespace video //! An enum for all types of drivers the Irrlicht Engine supports. enum E_DRIVER_TYPE { - //! Null driver, useful for applications to run the engine - //! without visualisation. The null device is able to load - //! textures, but does not render and display any graphics. + //! Null driver, useful for applications to run the engine without visualisation. + /** The null device is able to load textures, but does not + render and display any graphics. */ EDT_NULL, - //! The Irrlicht Engine Software renderer, runs on all - //! platforms, with every hardware. It should only be used for - //! 2d graphics, but it can also perform some primitive 3d - //! functions. These 3d drawing functions are quite fast, but - //! very inaccurate, and don't even support clipping in 3D mode. + //! The Irrlicht Engine Software renderer. + /** Runs on all platforms, with every hardware. It should only + be used for 2d graphics, but it can also perform some primitive + 3d functions. These 3d drawing functions are quite fast, but + very inaccurate, and don't even support clipping in 3D mode. */ EDT_SOFTWARE, - //! The Burning's Software Renderer, an alternative software - //! renderer for Irrlicht. Basically it can be described as the - //! Irrlicht Software renderer on steroids. It rasterizes 3D - //! geometry perfectly: It is able to perform correct 3d - //! clipping, perspective correct texture mapping, perspective - //! correct color mapping, and renders sub pixel correct, sub - //! texel correct primitives. In addition, it does bilinear - //! texel filtering and supports more materials than the - //! EDT_SOFTWARE driver. This renderer has been written - //! entirely by Thomas Alten, thanks a lot for this huge - //! contribution. + //! The Burning's Software Renderer, an alternative software renderer + /** Basically it can be described as the Irrlicht Software + renderer on steroids. It rasterizes 3D geometry perfectly: It + is able to perform correct 3d clipping, perspective correct + texture mapping, perspective correct color mapping, and renders + sub pixel correct, sub texel correct primitives. In addition, + it does bilinear texel filtering and supports more materials + than the EDT_SOFTWARE driver. This renderer has been written + entirely by Thomas Alten, thanks a lot for this huge + contribution. */ EDT_BURNINGSVIDEO, //! Direct3D8 device, only available on Win32 platforms. - //! Performs hardware accelerated rendering of 3D and 2D - //! primitives. + /** Performs hardware accelerated rendering of 3D and 2D + primitives. */ EDT_DIRECT3D8, //! Direct3D 9 device, only available on Win32 platforms. - //! Performs hardware accelerated rendering of 3D and 2D - //! primitives. + /** Performs hardware accelerated rendering of 3D and 2D + primitives. */ EDT_DIRECT3D9, //! OpenGL device, available on most platforms. - //! Performs hardware accelerated rendering of 3D and 2D - //! primitives. - EDT_OPENGL + /** Performs hardware accelerated rendering of 3D and 2D + primitives. */ + EDT_OPENGL, + + //! No driver, just for counting the elements + EDT_COUNT }; } // end namespace video diff --git a/src/dep/include/irrlicht/EGUIAlignment.h b/src/dep/include/irrlicht/EGUIAlignment.h index 837043a..b22fcd3 100644 --- a/src/dep/include/irrlicht/EGUIAlignment.h +++ b/src/dep/include/irrlicht/EGUIAlignment.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -35,3 +35,4 @@ const c8* const GUIAlignmentNames[] = } // namespace irr #endif // __E_GUI_ALIGNMENT_H_INCLUDED__ + diff --git a/src/dep/include/irrlicht/EGUIElementTypes.h b/src/dep/include/irrlicht/EGUIElementTypes.h index 660fb8c..3e361cf 100644 --- a/src/dep/include/irrlicht/EGUIElementTypes.h +++ b/src/dep/include/irrlicht/EGUIElementTypes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -79,17 +79,19 @@ enum EGUI_ELEMENT_TYPE //! A tool bar (IGUIToolBar) EGUIET_TOOL_BAR, + //! A Tree View + EGUIET_TREE_VIEW, + //! A window EGUIET_WINDOW, - //! Not an element, amount of elements in there - EGUIET_COUNT, - //! Unknown type. EGUIET_ELEMENT, - //! This enum is never used, it only forces the compiler to - //! compile these enumeration values to 32 bit. + //! Not an element, amount of elements in there + EGUIET_COUNT, + + //! This enum is never used, it only forces the compiler to compile this enumeration to 32 bit. EGUIET_FORCE_32_BIT = 0x7fffffff }; @@ -118,7 +120,9 @@ const c8* const GUIElementTypeNames[] = "tabControl", "table", "toolBar", + "treeview", "window", + "element", 0 }; diff --git a/src/dep/include/irrlicht/EHardwareBufferFlags.h b/src/dep/include/irrlicht/EHardwareBufferFlags.h index c665008..c65419a 100644 --- a/src/dep/include/irrlicht/EHardwareBufferFlags.h +++ b/src/dep/include/irrlicht/EHardwareBufferFlags.h @@ -1,40 +1,44 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __E_HARDWARE_BUFFER_FLAGS_INCLUDED__ -#define __E_HARDWARE_BUFFER_FLAGS_INCLUDED__ - -namespace irr -{ -namespace scene -{ - - enum E_HARDWARE_MAPPING - { - //! Don't load in hardware - EHM_NEVER=0, - - //! Rarely changed - EHM_STATIC, - - //! Sometimes changed - EHM_DYNAMIC, - - //! Always changed - EHM_STREAM - }; - - enum E_BUFFER_TYPE - { - EBT_NONE=0, - EBT_VERTEX, - EBT_INDEX, - EBT_VERTEX_AND_INDEX - }; - -} // end namespace scene -} // end namespace irr - -#endif - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_HARDWARE_BUFFER_FLAGS_INCLUDED__ +#define __E_HARDWARE_BUFFER_FLAGS_INCLUDED__ + +namespace irr +{ +namespace scene +{ + + enum E_HARDWARE_MAPPING + { + //! Don't store on the hardware + EHM_NEVER=0, + + //! Rarely changed, usually stored completely on the hardware + EHM_STATIC, + + //! Sometimes changed, driver optimized placement + EHM_DYNAMIC, + + //! Always changed, cache optimizing on the GPU + EHM_STREAM + }; + + enum E_BUFFER_TYPE + { + //! Does not change anything + EBT_NONE=0, + //! Change the vertex mapping + EBT_VERTEX, + //! Change the index mapping + EBT_INDEX, + //! Change both vertex and index mapping to the same value + EBT_VERTEX_AND_INDEX + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/src/dep/include/irrlicht/EMaterialFlags.h b/src/dep/include/irrlicht/EMaterialFlags.h index eec4aee..1e49c75 100644 --- a/src/dep/include/irrlicht/EMaterialFlags.h +++ b/src/dep/include/irrlicht/EMaterialFlags.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -14,48 +14,48 @@ namespace video enum E_MATERIAL_FLAG { //! Draw as wireframe or filled triangles? Default: false - EMF_WIREFRAME = 0, + EMF_WIREFRAME = 0x1, //! Draw as point cloud or filled triangles? Default: false - EMF_POINTCLOUD, + EMF_POINTCLOUD = 0x2, //! Flat or Gouraud shading? Default: true - EMF_GOURAUD_SHADING, + EMF_GOURAUD_SHADING = 0x4, //! Will this material be lighted? Default: true - EMF_LIGHTING, + EMF_LIGHTING = 0x8, //! Is the ZBuffer enabled? Default: true - EMF_ZBUFFER, + EMF_ZBUFFER = 0x10, //! May be written to the zbuffer or is it readonly. Default: true /** This flag is ignored, if the material type is a transparent type. */ - EMF_ZWRITE_ENABLE, + EMF_ZWRITE_ENABLE = 0x20, //! Is backface culling enabled? Default: true - EMF_BACK_FACE_CULLING, + EMF_BACK_FACE_CULLING = 0x40, //! Is frontface culling enabled? Default: false /** Overrides EMF_BACK_FACE_CULLING if both are enabled. */ - EMF_FRONT_FACE_CULLING, + EMF_FRONT_FACE_CULLING = 0x80, //! Is bilinear filtering enabled? Default: true - EMF_BILINEAR_FILTER, + EMF_BILINEAR_FILTER = 0x100, //! Is trilinear filtering enabled? Default: false /** If the trilinear filter flag is enabled, the bilinear filtering flag is ignored. */ - EMF_TRILINEAR_FILTER, + EMF_TRILINEAR_FILTER = 0x200, //! Is anisotropic filtering? Default: false /** In Irrlicht you can use anisotropic texture filtering in conjunction with bilinear or trilinear texture filtering to improve rendering results. Primitives will look less blurry with this flag switched on. */ - EMF_ANISOTROPIC_FILTER, + EMF_ANISOTROPIC_FILTER = 0x400, //! Is fog enabled? Default: false - EMF_FOG_ENABLE, + EMF_FOG_ENABLE = 0x800, //! Normalizes normals. Default: false /** You can enable this if you need to scale a dynamic lighted @@ -63,13 +63,19 @@ namespace video will get darker. If you enable the EMF_NORMALIZE_NORMALS flag, the normals will be normalized again, and the model will look as bright as it should. */ - EMF_NORMALIZE_NORMALS, + EMF_NORMALIZE_NORMALS = 0x1000, //! Access to all layers texture wrap settings. Overwrites separate layer settings. - EMF_TEXTURE_WRAP, + EMF_TEXTURE_WRAP = 0x2000, - //! This is not a flag, but a value indicating how much flags there are. - EMF_MATERIAL_FLAG_COUNT + //! AntiAliasing mode + EMF_ANTI_ALIASING = 0x4000, + + //! ColorMask bits, for enabling the color planes + EMF_COLOR_MASK = 0x8000, + + //! ColorMaterial enum for vertex color interpretation + EMF_COLOR_MATERIAL = 0x10000 }; } // end namespace video diff --git a/src/dep/include/irrlicht/EMaterialTypes.h b/src/dep/include/irrlicht/EMaterialTypes.h index e496c54..4958ccf 100644 --- a/src/dep/include/irrlicht/EMaterialTypes.h +++ b/src/dep/include/irrlicht/EMaterialTypes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -13,37 +13,39 @@ namespace video //! Abstracted and easy to use fixed function/programmable pipeline material modes. enum E_MATERIAL_TYPE { - //! Standard solid material. Only first texture is used, which - //! is supposed to be the diffuse material. + //! Standard solid material. + /** Only first texture is used, which is supposed to be the + diffuse material. */ EMT_SOLID = 0, - //! Solid material with 2 texture layers. The second is blended - //! onto the first using the alpha value of the vertex colors. - //! This material is currently not implemented in OpenGL. + //! Solid material with 2 texture layers. + /** The second is blended onto the first using the alpha value + of the vertex colors. This material is currently not implemented in OpenGL. + */ EMT_SOLID_2_LAYER, - //! Material type with standard lightmap technique: - //! There should be 2 textures: The first texture layer is a - //! diffuse map, the second is a light map. Dynamic light is - //! ignored. + //! Material type with standard lightmap technique + /** There should be 2 textures: The first texture layer is a + diffuse map, the second is a light map. Dynamic light is + ignored. */ EMT_LIGHTMAP, - //! Material type with lightmap technique like EMT_LIGHTMAP. But - //! lightmap and diffuse texture are added instead of modulated. + //! Material type with lightmap technique like EMT_LIGHTMAP. + /** But lightmap and diffuse texture are added instead of modulated. */ EMT_LIGHTMAP_ADD, - //! Material type with standard lightmap technique: - //! There should be 2 textures: The first texture layer is a - //! diffuse map, the second is a light map. Dynamic light is - //! ignored. The texture colors are effectively multiplied by 2 - //! for brightening. Like known in DirectX as D3DTOP_MODULATE2X. + //! Material type with standard lightmap technique + /** There should be 2 textures: The first texture layer is a + diffuse map, the second is a light map. Dynamic light is + ignored. The texture colors are effectively multiplied by 2 + for brightening. Like known in DirectX as D3DTOP_MODULATE2X. */ EMT_LIGHTMAP_M2, - //! Material type with standard lightmap technique: - //! There should be 2 textures: The first texture layer is a - //! diffuse map, the second is a light map. Dynamic light is - //! ignored. The texture colors are effectively multiplyied by 4 - //! for brightening. Like known in DirectX as D3DTOP_MODULATE4X. + //! Material type with standard lightmap technique + /** There should be 2 textures: The first texture layer is a + diffuse map, the second is a light map. Dynamic light is + ignored. The texture colors are effectively multiplyied by 4 + for brightening. Like known in DirectX as D3DTOP_MODULATE4X. */ EMT_LIGHTMAP_M4, //! Like EMT_LIGHTMAP, but also supports dynamic lighting. @@ -55,153 +57,142 @@ namespace video //! Like EMT_LIGHTMAP_4, but also supports dynamic lighting. EMT_LIGHTMAP_LIGHTING_M4, - //! Detail mapped material. The first texture is diffuse color - //! map, the second is added to this and usually displayed with - //! a bigger scale value so that it adds more detail. The - //! detail map is added to the diffuse map using ADD_SIGNED, so - //! that it is possible to add and substract color from the - //! diffuse map. For example a value of (127,127,127) will not - //! change the appearance of the diffuse map at all. Often used - //! for terrain rendering. + //! Detail mapped material. + /** The first texture is diffuse color map, the second is added + to this and usually displayed with a bigger scale value so that + it adds more detail. The detail map is added to the diffuse map + using ADD_SIGNED, so that it is possible to add and substract + color from the diffuse map. For example a value of + (127,127,127) will not change the appearance of the diffuse map + at all. Often used for terrain rendering. */ EMT_DETAIL_MAP, - //! Makes the material look like it was reflection the - //! environment around it. To make this possible, a texture - //! called 'sphere map' is used, which must be set as the first - //! texture. + //! Look like a reflection of the environment around it. + /** To make this possible, a texture called 'sphere map' is + used, which must be set as the first texture. */ EMT_SPHERE_MAP, - //! A reflecting material with an optional additional non - //! reflecting texture layer. The reflection map should be set - //! as first texture. + //! A reflecting material with an optional non reflecting texture layer. + /** The reflection map should be set as first texture. */ EMT_REFLECTION_2_LAYER, - //! A transparent material. Only the first texture is used. - //! The new color is calculated by simply adding the source - //! color and the dest color. This means if for example a - //! billboard using a texture with black background and a red - //! circle on it is drawn with this material, the result is - //! that only the red circle will be drawn a little bit - //! transparent, and everything which was black is 100% - //! transparent and not visible. This material type is useful - //! for particle effects. + //! A transparent material. + /** Only the first texture is used. The new color is calculated + by simply adding the source color and the dest color. This + means if for example a billboard using a texture with black + background and a red circle on it is drawn with this material, + the result is that only the red circle will be drawn a little + bit transparent, and everything which was black is 100% + transparent and not visible. This material type is useful for + particle effects. */ EMT_TRANSPARENT_ADD_COLOR, - //! Makes the material transparent based on the texture alpha - //! channel. The final color is blended together from the - //! destination color and the texture color, using the alpha - //! channel value as blend factor. Only first texture is used. - //! If you are using this material with small textures, it is a - //! good idea to load the texture in 32 bit mode - //! (video::IVideoDriver::setTextureCreationFlag()). Also, an - //! alpha ref is used, which can be manipulated using - //! SMaterial::MaterialTypeParam. If set to 0, the alpha ref - //! gets its default value which is 0.5f and means that - //! pixels with an alpha value >127 will be written, others not. - //! In other, simple words: this value controls how sharp the - //! edges become when going from a transparent to a solid spot - //! on the texture. + //! Makes the material transparent based on the texture alpha channel. + /** The final color is blended together from the destination + color and the texture color, using the alpha channel value as + blend factor. Only first texture is used. If you are using + this material with small textures, it is a good idea to load + the texture in 32 bit mode + (video::IVideoDriver::setTextureCreationFlag()). Also, an alpha + ref is used, which can be manipulated using + SMaterial::MaterialTypeParam. This value controls how sharp the + edges become when going from a transparent to a solid spot on + the texture. */ EMT_TRANSPARENT_ALPHA_CHANNEL, - //! Makes the material transparent based on the texture alpha - //! channel. If the alpha channel value is greater than 127, a - //! pixel is written to the target, otherwise not. This - //! material does not use alpha blending and is a lot faster - //! than EMT_TRANSPARENT_ALPHA_CHANNEL. It is ideal for drawing - //! stuff like leafes of plants, because the borders are not - //! blurry but sharp. Only first texture is used. If you are - //! using this material with small textures and 3d object, it - //! is a good idea to load the texture in 32 bit mode - //! (video::IVideoDriver::setTextureCreationFlag()). + //! Makes the material transparent based on the texture alpha channel. + /** If the alpha channel value is greater than 127, a + pixel is written to the target, otherwise not. This + material does not use alpha blending and is a lot faster + than EMT_TRANSPARENT_ALPHA_CHANNEL. It is ideal for drawing + stuff like leafes of plants, because the borders are not + blurry but sharp. Only first texture is used. If you are + using this material with small textures and 3d object, it + is a good idea to load the texture in 32 bit mode + (video::IVideoDriver::setTextureCreationFlag()). */ EMT_TRANSPARENT_ALPHA_CHANNEL_REF, - //! Makes the material transparent based on the vertex alpha - //! value. + //! Makes the material transparent based on the vertex alpha value. EMT_TRANSPARENT_VERTEX_ALPHA, - //! A transparent reflecting material with an optional - //! additional non reflecting texture layer. The reflection map - //! should be set as first texture. The transparency depends on - //! the alpha value in the vertex colors. A texture which will - //! not reflect can be set as second texture. Please note that - //! this material type is currently not 100% implemented in - //! OpenGL. + //! A transparent reflecting material with an optional additional non reflecting texture layer. + /** The reflection map should be set as first texture. The + transparency depends on the alpha value in the vertex colors. A + texture which will not reflect can be set as second texture. + Please note that this material type is currently not 100% + implemented in OpenGL. */ EMT_TRANSPARENT_REFLECTION_2_LAYER, - //! A solid normal map renderer. First texture is the color - //! map, the second should be the normal map. Note that you - //! should use this material only when drawing geometry - //! consisting of vertices of type S3DVertexTangents - //! (EVT_TANGENTS). You can convert any mesh into this format - //! using IMeshManipulator::createMeshWithTangents() (See - //! SpecialFX2 Tutorial). This shader runs on vertex shader - //! 1.1 and pixel shader 1.1 capable hardware and falls back to - //! a fixed function lighted material if this hardware is not - //! available. Only two lights are supported by this shader, - //! if there are more, the nearest two are chosen. + //! A solid normal map renderer. + /** First texture is the color map, the second should be the + normal map. Note that you should use this material only when + drawing geometry consisting of vertices of type + S3DVertexTangents (EVT_TANGENTS). You can convert any mesh into + this format using IMeshManipulator::createMeshWithTangents() + (See SpecialFX2 Tutorial). This shader runs on vertex shader + 1.1 and pixel shader 1.1 capable hardware and falls back to a + fixed function lighted material if this hardware is not + available. Only two lights are supported by this shader, if + there are more, the nearest two are chosen. */ EMT_NORMAL_MAP_SOLID, - //! A transparent normal map renderer. First texture is the - //! color map, the second should be the normal map. Note that - //! you should use this material only when drawing geometry - //! consisting of vertices of type S3DVertexTangents - //! (EVT_TANGENTS). You can convert any mesh into this format - //! using IMeshManipulator::createMeshWithTangents() (See - //! SpecialFX2 Tutorial). This shader runs on vertex shader - //! 1.1 and pixel shader 1.1 capable hardware and falls back to - //! a fixed function lighted material if this hardware is not - //! available. Only two lights are supported by this shader, - //! if there are more, the nearest two are chosen. + //! A transparent normal map renderer. + /** First texture is the color map, the second should be the + normal map. Note that you should use this material only when + drawing geometry consisting of vertices of type + S3DVertexTangents (EVT_TANGENTS). You can convert any mesh into + this format using IMeshManipulator::createMeshWithTangents() + (See SpecialFX2 Tutorial). This shader runs on vertex shader + 1.1 and pixel shader 1.1 capable hardware and falls back to a + fixed function lighted material if this hardware is not + available. Only two lights are supported by this shader, if + there are more, the nearest two are chosen. */ EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, - //! A transparent (based on the vertex alpha value) normal map - //! renderer. First texture is the color map, the second - //! should be the normal map. Note that you should use this - //! material only when drawing geometry consisting of vertices - //! of type S3DVertexTangents (EVT_TANGENTS). You can convert - //! any mesh into this format using - //! IMeshManipulator::createMeshWithTangents() (See SpecialFX2 - //! Tutorial). This shader runs on vertex shader 1.1 and pixel - //! shader 1.1 capable hardware and falls back to a fixed - //! function lighted material if this hardware is not available. - //! Only two lights are supported by this shader, if there are - //! more, the nearest two are chosen. + //! A transparent (based on the vertex alpha value) normal map renderer. + /** First texture is the color map, the second should be the + normal map. Note that you should use this material only when + drawing geometry consisting of vertices of type + S3DVertexTangents (EVT_TANGENTS). You can convert any mesh into + this format using IMeshManipulator::createMeshWithTangents() + (See SpecialFX2 Tutorial). This shader runs on vertex shader + 1.1 and pixel shader 1.1 capable hardware and falls back to a + fixed function lighted material if this hardware is not + available. Only two lights are supported by this shader, if + there are more, the nearest two are chosen. */ EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, - //! Just like EMT_NORMAL_MAP_SOLID, but uses parallax mapping - //! too, which looks a lot more realistic. This only works when - //! the hardware supports at least vertex shader 1.1 and pixel - //! shader 1.4. First texture is the color map, the second - //! should be the normal map. The normal map texture should - //! contain the height value in the alpha component. The - //! IVideoDriver::makeNormalMapTexture() method writes this - //! value automatically when creating normal maps from a - //! heightmap when using a 32 bit texture. The height scale of - //! the material (affecting the bumpiness) is being controlled - //! by the SMaterial::MaterialTypeParam member. If set to - //! zero, the default value (0.02f) will be applied. Otherwise - //! the value set in SMaterial::MaterialTypeParam is taken. This - //! value depends on with which scale the texture is mapped on - //! the material. Too high or low values of MaterialTypeParam - //! can result in strange artifacts. + //! Just like EMT_NORMAL_MAP_SOLID, but uses parallax mapping. + /** Looks a lot more realistic. This only works when the + hardware supports at least vertex shader 1.1 and pixel shader + 1.4. First texture is the color map, the second should be the + normal map. The normal map texture should contain the height + value in the alpha component. The + IVideoDriver::makeNormalMapTexture() method writes this value + automatically when creating normal maps from a heightmap when + using a 32 bit texture. The height scale of the material + (affecting the bumpiness) is being controlled by the + SMaterial::MaterialTypeParam member. If set to zero, the + default value (0.02f) will be applied. Otherwise the value set + in SMaterial::MaterialTypeParam is taken. This value depends on + with which scale the texture is mapped on the material. Too + high or low values of MaterialTypeParam can result in strange + artifacts. */ EMT_PARALLAX_MAP_SOLID, - //! A material just like EMT_PARALLAX_MAP_SOLID, but it is - //! transparent, using EMT_TRANSPARENT_ADD_COLOR as base - //! material. + //! A material like EMT_PARALLAX_MAP_SOLID, but transparent. + /** Using EMT_TRANSPARENT_ADD_COLOR as base material. */ EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, - //! A material just like EMT_PARALLAX_MAP_SOLID, but it is - //! transparent, using EMT_TRANSPARENT_VERTEX_ALPHA as base - //! material. + //! A material like EMT_PARALLAX_MAP_SOLID, but transparent. + /** Using EMT_TRANSPARENT_VERTEX_ALPHA as base material. */ EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA, //! BlendFunc = source * sourceFactor + dest * destFactor ( E_BLEND_FUNC ) - //! Using only first texture. Generic blending method. + /** Using only first texture. Generic blending method. */ EMT_ONETEXTURE_BLEND, - //! This value is not used. It only forces this enumeration to - //! compile in 32 bit. + //! This value is not used. It only forces this enumeration to compile to 32 bit. EMT_FORCE_32BIT = 0x7fffffff }; diff --git a/src/dep/include/irrlicht/EMeshWriterEnums.h b/src/dep/include/irrlicht/EMeshWriterEnums.h index bc0f1d3..ab77478 100644 --- a/src/dep/include/irrlicht/EMeshWriterEnums.h +++ b/src/dep/include/irrlicht/EMeshWriterEnums.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,7 +18,7 @@ namespace scene name clashes with external mesh writers.*/ enum EMESH_WRITER_TYPE { - //! Irrlicht Native mesh writer, for static .irrmesh files. + //! Irrlicht native mesh writer, for static .irrmesh files. EMWT_IRR_MESH = MAKE_IRR_ID('i','r','r','m'), //! COLLADA mesh writer for .dae and .xml files @@ -28,7 +28,10 @@ namespace scene EMWT_STL = MAKE_IRR_ID('s','t','l',0), //! OBJ mesh writer for .obj files - EMWT_OBJ = MAKE_IRR_ID('o','b','j',0) + EMWT_OBJ = MAKE_IRR_ID('o','b','j',0), + + //! PLY mesh writer for .ply files + EMWT_PLY = MAKE_IRR_ID('p','l','y',0) }; @@ -41,8 +44,11 @@ namespace scene //! write lightmap textures out if possible EMWF_WRITE_LIGHTMAPS = 0x1, - //! write in a way that does consume less disk space - EMWF_WRITE_COMPRESSED = 0x2 + //! write in a way that consumes less disk space + EMWF_WRITE_COMPRESSED = 0x2, + + //! write in binary format rather than text + EMWF_WRITE_BINARY = 0x4 }; } // end namespace scene diff --git a/src/dep/include/irrlicht/EMessageBoxFlags.h b/src/dep/include/irrlicht/EMessageBoxFlags.h index e4d7dc6..a705b5a 100644 --- a/src/dep/include/irrlicht/EMessageBoxFlags.h +++ b/src/dep/include/irrlicht/EMessageBoxFlags.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -33,3 +33,4 @@ enum EMESSAGE_BOX_FLAG } // namespace irr #endif + diff --git a/src/dep/include/irrlicht/EPrimitiveTypes.h b/src/dep/include/irrlicht/EPrimitiveTypes.h new file mode 100644 index 0000000..ba8c71c --- /dev/null +++ b/src/dep/include/irrlicht/EPrimitiveTypes.h @@ -0,0 +1,56 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_PRIMITIVE_TYPES_H_INCLUDED__ +#define __E_PRIMITIVE_TYPES_H_INCLUDED__ + +namespace irr +{ +namespace scene +{ + + //! Enumeration for all primitive types there are. + enum E_PRIMITIVE_TYPE + { + //! All vertices are non-connected points. + EPT_POINTS=0, + + //! All vertices form a single connected line. + EPT_LINE_STRIP, + + //! Just as LINE_STRIP, but the last and the first vertex is also connected. + EPT_LINE_LOOP, + + //! Every two vertices are connected creating n/2 lines. + EPT_LINES, + + //! After the first two vertices each vertex defines a new triangle. + //! Always the two last and the new one form a new triangle. + EPT_TRIANGLE_STRIP, + + //! After the first two vertices each vertex defines a new triangle. + //! All around the common first vertex. + EPT_TRIANGLE_FAN, + + //! Explicitly set all vertices for each triangle. + EPT_TRIANGLES, + + //! After the first two vertices each further tw vetices create a quad with the preceding two. + EPT_QUAD_STRIP, + + //! Every four vertices create a quad. + EPT_QUADS, + + //! Just as LINE_LOOP, but filled. + EPT_POLYGON, + + //! The single vertices are expanded to quad billboards on the GPU. + EPT_POINT_SPRITES + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/src/dep/include/irrlicht/ESceneNodeAnimatorTypes.h b/src/dep/include/irrlicht/ESceneNodeAnimatorTypes.h index 99a4234..732172d 100644 --- a/src/dep/include/irrlicht/ESceneNodeAnimatorTypes.h +++ b/src/dep/include/irrlicht/ESceneNodeAnimatorTypes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -46,8 +46,7 @@ namespace scene //! Unknown scene node animator ESNAT_UNKNOWN, - //! This enum is never used, it only forces the compiler to - //! compile these enumeration values to 32 bit. + //! This enum is never used, it only forces the compiler to compile this enumeration to 32 bit. ESNAT_FORCE_32_BIT = 0x7fffffff }; diff --git a/src/dep/include/irrlicht/ESceneNodeTypes.h b/src/dep/include/irrlicht/ESceneNodeTypes.h index 833608a..37c5c12 100644 --- a/src/dep/include/irrlicht/ESceneNodeTypes.h +++ b/src/dep/include/irrlicht/ESceneNodeTypes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -36,11 +36,14 @@ namespace scene //! Sky Box Scene Node ESNT_SKY_BOX = MAKE_IRR_ID('s','k','y','_'), + //! Sky Dome Scene Node + ESNT_SKY_DOME = MAKE_IRR_ID('s','k','y','d'), + //! Shadow Volume Scene Node ESNT_SHADOW_VOLUME = MAKE_IRR_ID('s','h','d','w'), - //! OctTree Scene Node - ESNT_OCT_TREE = MAKE_IRR_ID('o','c','t','t'), + //! Octree Scene Node + ESNT_OCTREE = MAKE_IRR_ID('o','c','t','r'), //! Mesh Scene Node ESNT_MESH = MAKE_IRR_ID('m','e','s','h'), @@ -66,15 +69,21 @@ namespace scene //! Particle System Scene Node ESNT_PARTICLE_SYSTEM = MAKE_IRR_ID('p','t','c','l'), + //! Quake3 Shader Scene Node + ESNT_Q3SHADER_SCENE_NODE = MAKE_IRR_ID('q','3','s','h'), + //! Quake3 Model Scene Node ( has tag to link to ) ESNT_MD3_SCENE_NODE = MAKE_IRR_ID('m','d','3','_'), + //! Volume Light Scene Node + ESNT_VOLUME_LIGHT = MAKE_IRR_ID('v','o','l','l'), + //! Maya Camera Scene Node - //! Legacy, for loading version <= 1.4.x .irr files + /** Legacy, for loading version <= 1.4.x .irr files */ ESNT_CAMERA_MAYA = MAKE_IRR_ID('c','a','m','M'), //! First Person Shooter Camera - //! Legacy, for loading version <= 1.4.x .irr files + /** Legacy, for loading version <= 1.4.x .irr files */ ESNT_CAMERA_FPS = MAKE_IRR_ID('c','a','m','F'), //! Unknown scene node diff --git a/src/dep/include/irrlicht/EShaderTypes.h b/src/dep/include/irrlicht/EShaderTypes.h new file mode 100644 index 0000000..691930c --- /dev/null +++ b/src/dep/include/irrlicht/EShaderTypes.h @@ -0,0 +1,90 @@ +#ifndef __E_SHADER_TYPES_H_INCLUDED__ +#define __E_SHADER_TYPES_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace video +{ + +//! Compile target enumeration for the addHighLevelShaderMaterial() method. +enum E_VERTEX_SHADER_TYPE +{ + EVST_VS_1_1 = 0, + EVST_VS_2_0, + EVST_VS_2_a, + EVST_VS_3_0, + EVST_VS_4_0, + EVST_VS_4_1, + EVST_VS_5_0, + + //! This is not a type, but a value indicating how much types there are. + EVST_COUNT +}; + +//! Names for all vertex shader types, each entry corresponds to a E_VERTEX_SHADER_TYPE entry. +const c8* const VERTEX_SHADER_TYPE_NAMES[] = { + "vs_1_1", + "vs_2_0", + "vs_2_a", + "vs_3_0", + "vs_4_0", + "vs_4_1", + "vs_5_0", + 0 }; + +//! Compile target enumeration for the addHighLevelShaderMaterial() method. +enum E_PIXEL_SHADER_TYPE +{ + EPST_PS_1_1 = 0, + EPST_PS_1_2, + EPST_PS_1_3, + EPST_PS_1_4, + EPST_PS_2_0, + EPST_PS_2_a, + EPST_PS_2_b, + EPST_PS_3_0, + EPST_PS_4_0, + EPST_PS_4_1, + EPST_PS_5_0, + + //! This is not a type, but a value indicating how much types there are. + EPST_COUNT +}; + +//! Names for all pixel shader types, each entry corresponds to a E_PIXEL_SHADER_TYPE entry. +const c8* const PIXEL_SHADER_TYPE_NAMES[] = { + "ps_1_1", + "ps_1_2", + "ps_1_3", + "ps_1_4", + "ps_2_0", + "ps_2_a", + "ps_2_b", + "ps_3_0", + "ps_4_0", + "ps_4_1", + "ps_5_0", + 0 }; + +//! Enum for supported geometry shader types +enum E_GEOMETRY_SHADER_TYPE +{ + EGST_GS_4_0 = 0, + + //! This is not a type, but a value indicating how much types there are. + EGST_COUNT +}; + +//! String names for supported geometry shader types +const c8* const GEOMETRY_SHADER_TYPE_NAMES[] = { + "gs_4_0", + 0 }; + + +} // end namespace video +} // end namespace irr + +#endif // __E_SHADER_TYPES_H_INCLUDED__ + diff --git a/src/dep/include/irrlicht/ETerrainElements.h b/src/dep/include/irrlicht/ETerrainElements.h index a9b65ee..f4805ec 100644 --- a/src/dep/include/irrlicht/ETerrainElements.h +++ b/src/dep/include/irrlicht/ETerrainElements.h @@ -1,36 +1,36 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __E_TERRAIN_ELEMENTS_H__ -#define __E_TERRAIN_ELEMENTS_H__ - -namespace irr -{ -namespace scene -{ - - //! enumeration for patch sizes specifying the size of patches in the TerrainSceneNode - enum E_TERRAIN_PATCH_SIZE - { - //! patch size of 9, at most, use 4 levels of detail with this patch size. - ETPS_9 = 9, - - //! patch size of 17, at most, use 5 levels of detail with this patch size. - ETPS_17 = 17, - - //! patch size of 33, at most, use 6 levels of detail with this patch size. - ETPS_33 = 33, - - //! patch size of 65, at most, use 7 levels of detail with this patch size. - ETPS_65 = 65, - - //! patch size of 129, at most, use 8 levels of detail with this patch size. - ETPS_129 = 129 - }; - -} // end namespace scene -} // end namespace irr - -#endif - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_TERRAIN_ELEMENTS_H__ +#define __E_TERRAIN_ELEMENTS_H__ + +namespace irr +{ +namespace scene +{ + + //! enumeration for patch sizes specifying the size of patches in the TerrainSceneNode + enum E_TERRAIN_PATCH_SIZE + { + //! patch size of 9, at most, use 4 levels of detail with this patch size. + ETPS_9 = 9, + + //! patch size of 17, at most, use 5 levels of detail with this patch size. + ETPS_17 = 17, + + //! patch size of 33, at most, use 6 levels of detail with this patch size. + ETPS_33 = 33, + + //! patch size of 65, at most, use 7 levels of detail with this patch size. + ETPS_65 = 65, + + //! patch size of 129, at most, use 8 levels of detail with this patch size. + ETPS_129 = 129 + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/src/dep/include/irrlicht/IAnimatedMesh.h b/src/dep/include/irrlicht/IAnimatedMesh.h index 7b91a59..3f49f25 100644 --- a/src/dep/include/irrlicht/IAnimatedMesh.h +++ b/src/dep/include/irrlicht/IAnimatedMesh.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -47,8 +47,10 @@ namespace scene can be loaded directly by Irrlicht */ EAMT_OCT, + //PSEUWOW //! WoW M2 files EAMT_M2, + //PSEUWOW END //! generic skinned mesh EAMT_SKINNED diff --git a/src/dep/include/irrlicht/IAnimatedMeshMD2.h b/src/dep/include/irrlicht/IAnimatedMeshMD2.h index 43852a9..ba8d9e3 100644 --- a/src/dep/include/irrlicht/IAnimatedMeshMD2.h +++ b/src/dep/include/irrlicht/IAnimatedMeshMD2.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IAnimatedMeshMD3.h b/src/dep/include/irrlicht/IAnimatedMeshMD3.h index 53cb218..167af14 100644 --- a/src/dep/include/irrlicht/IAnimatedMeshMD3.h +++ b/src/dep/include/irrlicht/IAnimatedMeshMD3.h @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2007-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -89,15 +89,15 @@ namespace scene struct SMD3Header { c8 headerID[4]; //id of file, always "IDP3" - s32 Version; //this is a version number, always 15 + s32 Version; //this is a version number, always 15 s8 fileName[68]; //sometimes left Blank... 65 chars, 32bit aligned == 68 chars - s32 numFrames; //number of KeyFrames - s32 numTags; //number of 'tags' per frame - s32 numMeshes; //number of meshes/skins - s32 numMaxSkins; //maximum number of unique skins used in md3 file - s32 headerSize; //always equal to the length of this header - s32 tagStart; //starting position of tag-structures - s32 tagEnd; //ending position of tag-structures/starting position of mesh-structures + s32 numFrames; //number of KeyFrames + s32 numTags; //number of 'tags' per frame + s32 numMeshes; //number of meshes/skins + s32 numMaxSkins; //maximum number of unique skins used in md3 file. artefact md2 + s32 frameStart; //starting position of frame-structur + s32 tagStart; //starting position of tag-structures + s32 tagEnd; //ending position of tag-structures/starting position of mesh-structures s32 fileSize; }; @@ -153,7 +153,7 @@ namespace scene { SMD3MeshHeader MeshHeader; - core::array < core::stringc > Shader; + core::stringc Shader; core::array < s32 > Indices; core::array < SMD3Vertex > Vertices; core::array < SMD3TexCoord > Tex; @@ -161,44 +161,74 @@ namespace scene //! hold a tag info for connecting meshes /** Basically its an alternate way to describe a transformation. */ - struct SMD3QuaterionTag + struct SMD3QuaternionTag { - SMD3QuaterionTag() {} + virtual ~SMD3QuaternionTag() + { + position.X = 0.f; + } - SMD3QuaterionTag( const core::stringc& name ) + // construct copy constructor + SMD3QuaternionTag( const SMD3QuaternionTag & copyMe ) + { + *this = copyMe; + } + + // construct for searching + SMD3QuaternionTag( const core::stringc& name ) : Name ( name ) {} // construct from a matrix - SMD3QuaterionTag ( const core::stringc& name, const core::matrix4 &m ) : Name(name), position(m.getTranslation()), rotation(m) - { } + SMD3QuaternionTag ( const core::stringc& name, const core::matrix4 &m ) + : Name(name), position(m.getTranslation()), rotation(m) {} // construct from a position and euler angles in degrees - SMD3QuaterionTag ( const core::vector3df &pos, const core::vector3df &angle ) : position(pos), rotation(angle * core::DEGTORAD) - { } + SMD3QuaternionTag ( const core::vector3df &pos, const core::vector3df &angle ) + : position(pos), rotation(angle * core::DEGTORAD) {} // set to matrix void setto ( core::matrix4 &m ) { - rotation.getMatrix ( m ); - m.setTranslation ( position ); + rotation.getMatrix ( m, position ); } - bool operator == ( const SMD3QuaterionTag &other ) const + bool operator == ( const SMD3QuaternionTag &other ) const { return Name == other.Name; } + SMD3QuaternionTag & operator=( const SMD3QuaternionTag & copyMe ) + { + Name = copyMe.Name; + position = copyMe.position; + rotation = copyMe.rotation; + return *this; + } + core::stringc Name; core::vector3df position; core::quaternion rotation; }; //! holds a associative list of named quaternions - struct SMD3QuaterionTagList : public virtual IReferenceCounted + struct SMD3QuaternionTagList { - SMD3QuaterionTag* get ( const core::stringc& name ) + SMD3QuaternionTagList () { - SMD3QuaterionTag search ( name ); + Container.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); + } + + // construct copy constructor + SMD3QuaternionTagList( const SMD3QuaternionTagList & copyMe ) + { + *this = copyMe; + } + + virtual ~SMD3QuaternionTagList () {} + + SMD3QuaternionTag* get ( const core::stringc& name ) + { + SMD3QuaternionTag search ( name ); s32 index = Container.linear_search ( search ); if ( index >= 0 ) return &Container[index]; @@ -210,39 +240,61 @@ namespace scene return Container.size(); } - const SMD3QuaterionTag& operator[](u32 index) const + void set_used ( u32 new_size) + { + s32 diff = (s32) new_size - (s32) Container.allocated_size (); + if ( diff > 0 ) + { + SMD3QuaternionTag e ( "" ); + for ( s32 i = 0; i < diff; ++i ) + Container.push_back ( e ); + } + } + + const SMD3QuaternionTag& operator[](u32 index) const { return Container[index]; } - SMD3QuaterionTag& operator[](u32 index) + SMD3QuaternionTag& operator[](u32 index) { return Container[index]; } - SMD3QuaterionTagList & operator = (const SMD3QuaterionTagList & copyMe) + void push_back ( const SMD3QuaternionTag& other ) + { + Container.push_back ( other ); + } + + SMD3QuaternionTagList& operator = (const SMD3QuaternionTagList & copyMe) { Container = copyMe.Container; return *this; } - core::array < SMD3QuaterionTag > Container; + private: + core::array < SMD3QuaternionTag > Container; }; //! Holding Frames Buffers and Tag Infos struct SMD3Mesh: public IReferenceCounted { - ~SMD3Mesh() + SMD3Mesh () + { + MD3Header.numFrames = 0; + } + + virtual ~SMD3Mesh() { for (u32 i=0; idrop(); } - SMD3Header MD3Header; core::stringc Name; core::array < SMD3MeshBuffer * > Buffer; - SMD3QuaterionTagList TagList; + SMD3QuaternionTagList TagList; + SMD3Header MD3Header; }; @@ -255,7 +307,7 @@ namespace scene virtual void setInterpolationShift ( u32 shift, u32 loopMode ) = 0; //! get the tag list of the mesh. - virtual SMD3QuaterionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) = 0; + virtual SMD3QuaternionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) = 0; //! get the original md3 mesh. virtual SMD3Mesh * getOriginalMesh () = 0; diff --git a/src/dep/include/irrlicht/IAnimatedMeshSceneNode.h b/src/dep/include/irrlicht/IAnimatedMeshSceneNode.h index f8fbec0..d9a8aa6 100644 --- a/src/dep/include/irrlicht/IAnimatedMeshSceneNode.h +++ b/src/dep/include/irrlicht/IAnimatedMeshSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -25,10 +25,7 @@ namespace scene EJUOR_READ, //! control joint positions in the mesh (eg. ragdolls, or set the animation from animateJoints() ) - EJUOR_CONTROL, - - //! count of all available interpolation modes - EJUOR_COUNT + EJUOR_CONTROL }; @@ -81,10 +78,14 @@ namespace scene \return True if successful, false if not. */ virtual bool setFrameLoop(s32 begin, s32 end) = 0; - //! Sets the speed with witch the animation is played. + //! Sets the speed with which the animation is played. /** \param framesPerSecond: Frames per second played. */ virtual void setAnimationSpeed(f32 framesPerSecond) = 0; + //! Gets the speed with which the animation is played. + /** \return Frames per second played. */ + virtual f32 getAnimationSpeed() const =0; + //! Creates shadow volume scene node as child of this node. /** The shadow can be rendered using the ZPass or the zfail method. ZPass is a little bit faster because the shadow volume @@ -135,9 +136,11 @@ namespace scene //! Deprecated command, please use getJointNode virtual ISceneNode* getXJointNode(const c8* jointName) = 0; + //PSEUWOW //! Starts a M2 animation. virtual bool setM2Animation(u32 anim) = 0; - + //PSEUWOW END + //! Starts a default MD2 animation. /** With this method it is easily possible to start a Run, Attack, Die or whatever animation, if the mesh contained in @@ -196,7 +199,7 @@ namespace scene virtual IAnimatedMesh* getMesh(void) = 0; //! Get the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, or the absolutetransformation if it's a normal scenenode - virtual const SMD3QuaterionTag& getMD3TagTransformation( const core::stringc & tagname) = 0; + virtual const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname) = 0; //! Set how the joints should be updated on render virtual void setJointMode(E_JOINT_UPDATE_ON_RENDER mode)=0; diff --git a/src/dep/include/irrlicht/IAttributeExchangingObject.h b/src/dep/include/irrlicht/IAttributeExchangingObject.h index c430a7a..7bf25a2 100644 --- a/src/dep/include/irrlicht/IAttributeExchangingObject.h +++ b/src/dep/include/irrlicht/IAttributeExchangingObject.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IAttributes.h b/src/dep/include/irrlicht/IAttributes.h index 389357f..727f774 100644 --- a/src/dep/include/irrlicht/IAttributes.h +++ b/src/dep/include/irrlicht/IAttributes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,6 +23,7 @@ #include "irrString.h" #include "irrArray.h" #include "IXMLReader.h" +#include "EAttributes.h" namespace irr { @@ -34,88 +35,6 @@ namespace io { class IXMLWriter; -//! Types of attributes available for IAttributes -enum E_ATTRIBUTE_TYPE -{ - // integer attribute - EAT_INT = 0, - - // float attribute - EAT_FLOAT, - - // string attribute - EAT_STRING, - - // boolean attribute - EAT_BOOL, - - // enumeration attribute - EAT_ENUM, - - // color attribute - EAT_COLOR, - - // floating point color attribute - EAT_COLORF, - - // 3d vector attribute - EAT_VECTOR3D, - - // 2d position attribute - EAT_POSITION2D, - - // vector 2d - EAT_VECTOR2D, - - // rectangle attribute - EAT_RECT, - - // matrix attribute - EAT_MATRIX, - - // quaternion attribute - EAT_QUATERNION, - - // 3d bounding box - EAT_BBOX, - - // plane - EAT_PLANE, - - // 3d triangle - EAT_TRIANGLE3D, - - // line 2d - EAT_LINE2D, - - // line 3d - EAT_LINE3D, - - // array of stringws attribute - EAT_STRINGWARRAY, - - // array of float - EAT_FLOATARRAY, - - // array of int - EAT_INTARRAY, - - // binary data attribute - EAT_BINARY, - - // texture reference attribute - EAT_TEXTURE, - - // user pointer void* - EAT_USER_POINTER, - - // known attribute type count - EAT_COUNT, - - // unknown attribute - EAT_UNKNOWN -}; - //! Provides a generic interface for attributes and their values and the possiblity to serialize them class IAttributes : public virtual IReferenceCounted { @@ -315,12 +234,12 @@ public: */ //! Adds an attribute as wide string array - virtual void addArray(const c8* attributeName, core::array value) = 0; + virtual void addArray(const c8* attributeName, const core::array& value) = 0; //! Sets an attribute value as a wide string array. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute - virtual void setAttribute(const c8* attributeName, const core::array value) = 0; + virtual void setAttribute(const c8* attributeName, const core::array& value) = 0; //! Gets an attribute as an array of wide strings. //! \param attributeName: Name of the attribute to get. @@ -333,7 +252,7 @@ public: virtual core::array getAttributeAsArray(s32 index) = 0; //! Sets an attribute as an array of wide strings - virtual void setAttribute(s32 index, core::array value) = 0; + virtual void setAttribute(s32 index, const core::array& value) = 0; /* diff --git a/src/dep/include/irrlicht/IBillboardSceneNode.h b/src/dep/include/irrlicht/IBillboardSceneNode.h index 9930dca..53e587c 100644 --- a/src/dep/include/irrlicht/IBillboardSceneNode.h +++ b/src/dep/include/irrlicht/IBillboardSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IBillboardTextSceneNode.h b/src/dep/include/irrlicht/IBillboardTextSceneNode.h index 09c7166..363804a 100644 --- a/src/dep/include/irrlicht/IBillboardTextSceneNode.h +++ b/src/dep/include/irrlicht/IBillboardTextSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IBoneSceneNode.h b/src/dep/include/irrlicht/IBoneSceneNode.h index 97498a0..22db67a 100644 --- a/src/dep/include/irrlicht/IBoneSceneNode.h +++ b/src/dep/include/irrlicht/IBoneSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/ICameraSceneNode.h b/src/dep/include/irrlicht/ICameraSceneNode.h index 2bd21ac..c239749 100644 --- a/src/dep/include/irrlicht/ICameraSceneNode.h +++ b/src/dep/include/irrlicht/ICameraSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -42,15 +42,26 @@ namespace scene \param isOrthogonal Set this to true if the matrix is an orthogonal one (e.g. from matrix4::buildProjectionMatrixOrtho). */ - virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal = false) = 0; + virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal=false) =0; //! Gets the current projection matrix of the camera. /** \return The current projection matrix of the camera. */ - virtual const core::matrix4& getProjectionMatrix() const = 0; + virtual const core::matrix4& getProjectionMatrix() const =0; //! Gets the current view matrix of the camera. /** \return The current view matrix of the camera. */ - virtual const core::matrix4& getViewMatrix() const = 0; + virtual const core::matrix4& getViewMatrix() const =0; + + //! Sets a custom view matrix affector. + /** The matrix passed here, will be multiplied with the view + matrix when it gets updated. This allows for custom camera + setups like, for example, a reflection camera. + \param affector The affector matrix. */ + virtual void setViewMatrixAffector(const core::matrix4& affector) =0; + + //! Get the custom view matrix affector. + /** \return The affector matrix. */ + virtual const core::matrix4& getViewMatrixAffector() const =0; //! It is possible to send mouse and key events to the camera. /** Most cameras may ignore this input, but camera scene nodes @@ -59,14 +70,14 @@ namespace scene ISceneManager::addCameraSceneNodeFPS, may want to get this input for changing their position, look at target or whatever. */ - virtual bool OnEvent(const SEvent& event) = 0; + virtual bool OnEvent(const SEvent& event) =0; //! Sets the look at target of the camera /** 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, in world co-ordinates. */ - virtual void setTarget(const core::vector3df& pos) = 0; + virtual void setTarget(const core::vector3df& pos) =0; //! Sets the rotation of the node. /** This only modifies the relative rotation of the node. @@ -74,64 +85,64 @@ namespace scene 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; + 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, in world co-ordinates */ - virtual const core::vector3df& getTarget() const = 0; + virtual const core::vector3df& getTarget() const =0; //! Sets the up vector of the camera. /** \param pos: New upvector of the camera. */ - virtual void setUpVector(const core::vector3df& pos) = 0; + virtual void setUpVector(const core::vector3df& pos) =0; //! Gets the up vector of the camera. /** \return The up vector of the camera, in world space. */ - virtual const core::vector3df& getUpVector() const = 0; + virtual const core::vector3df& getUpVector() const =0; //! Gets the value of the near plane of the camera. /** \return The value of the near plane of the camera. */ - virtual f32 getNearValue() const = 0; + virtual f32 getNearValue() const =0; //! Gets the value of the far plane of the camera. /** \return The value of the far plane of the camera. */ - virtual f32 getFarValue() const = 0; + virtual f32 getFarValue() const =0; //! Gets the aspect ratio of the camera. /** \return The aspect ratio of the camera. */ - virtual f32 getAspectRatio() const = 0; + virtual f32 getAspectRatio() const =0; //! Gets the field of view of the camera. - /** \return The field of view of the camera in radiants. */ - virtual f32 getFOV() const = 0; + /** \return The field of view of the camera in radians. */ + virtual f32 getFOV() const =0; //! Sets the value of the near clipping plane. (default: 1.0f) /** \param zn: New z near value. */ - virtual void setNearValue(f32 zn) = 0; + virtual void setNearValue(f32 zn) =0; //! Sets the value of the far clipping plane (default: 2000.0f) /** \param zf: New z far value. */ - virtual void setFarValue(f32 zf) = 0; + virtual void setFarValue(f32 zf) =0; //! Sets the aspect ratio (default: 4.0f / 3.0f) /** \param aspect: New aspect ratio. */ - virtual void setAspectRatio(f32 aspect) = 0; + virtual void setAspectRatio(f32 aspect) =0; //! Sets the field of view (Default: PI / 2.5f) - /** \param fovy: New field of view in radiants. */ - virtual void setFOV(f32 fovy) = 0; + /** \param fovy: New field of view in radians. */ + virtual void setFOV(f32 fovy) =0; //! Get the view frustum. /** Needed sometimes by bspTree or LOD render nodes. \return The current view frustum. */ - virtual const SViewFrustum* getViewFrustum() const = 0; + 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. */ - virtual void setInputReceiverEnabled(bool enabled) = 0; + virtual void setInputReceiverEnabled(bool enabled) =0; //! Checks if the input receiver of the camera is currently enabled. - virtual bool isInputReceiverEnabled() const = 0; + virtual bool isInputReceiverEnabled() const =0; //! Checks if a camera is orthogonal. virtual bool isOrthogonal() const @@ -146,14 +157,14 @@ namespace scene 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 + \param bound True to bind the camera's scene node rotation and targetting, false to unbind them. @see getTargetAndRotationBinding() */ - virtual void bindTargetAndRotation(bool bound) = 0; + virtual void bindTargetAndRotation(bool bound) =0; //! Queries if the camera scene node's rotation and its target position are bound together. /** @see bindTargetAndRotation() */ - virtual bool getTargetAndRotationBinding(void) const = 0; + virtual bool getTargetAndRotationBinding(void) const =0; protected: diff --git a/src/dep/include/irrlicht/ICursorControl.h b/src/dep/include/irrlicht/ICursorControl.h index 915c89e..b2494ba 100644 --- a/src/dep/include/irrlicht/ICursorControl.h +++ b/src/dep/include/irrlicht/ICursorControl.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -57,7 +57,7 @@ namespace gui //! Returns the current position of the mouse cursor. /** \return Returns the current position of the cursor. The returned position is the position of the mouse cursor in pixel units. */ - virtual core::position2d getPosition() = 0; + virtual const core::position2d& getPosition() = 0; //! Returns the current position of the mouse cursor. /** \return Returns the current position of the cursor. The returned position diff --git a/src/dep/include/irrlicht/IDummyTransformationSceneNode.h b/src/dep/include/irrlicht/IDummyTransformationSceneNode.h index 0e4634a..9175143 100644 --- a/src/dep/include/irrlicht/IDummyTransformationSceneNode.h +++ b/src/dep/include/irrlicht/IDummyTransformationSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IDynamicMeshBuffer.h b/src/dep/include/irrlicht/IDynamicMeshBuffer.h index 1b6f62f..2efe7c2 100644 --- a/src/dep/include/irrlicht/IDynamicMeshBuffer.h +++ b/src/dep/include/irrlicht/IDynamicMeshBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2008 Nikolaus Gebhardt +// Copyright (C) 2008-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IEventReceiver.h b/src/dep/include/irrlicht/IEventReceiver.h index 33e5380..c67136d 100644 --- a/src/dep/include/irrlicht/IEventReceiver.h +++ b/src/dep/include/irrlicht/IEventReceiver.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,7 +6,6 @@ #define __I_EVENT_RECEIVER_H_INCLUDED__ #include "ILogger.h" -#include "position2d.h" #include "Keycodes.h" #include "irrString.h" @@ -31,7 +30,7 @@ namespace irr EET_MOUSE_INPUT_EVENT, //! A key input event. - /** Like mouse events, keyboard events are created by the device and passed to + /** Like mouse events, keyboard events are created by the device and passed to IrrlichtDevice::postEventFromUser. They take the same path as mouse events. */ EET_KEY_INPUT_EVENT, @@ -43,7 +42,7 @@ namespace irr Linux: Implemented, with POV hat issues. MacOS / Other: Not yet implemented. */ - EET_JOYSTICK_INPUT_EVENT, + EET_JOYSTICK_INPUT_EVENT, //! A log event /** Log events are only passed to the user receiver if there is one. If they are absorbed by the @@ -99,10 +98,50 @@ namespace irr //! in what direction and how fast. EMIE_MOUSE_WHEEL, + //! Left mouse button double click. + //! This event is generated after the second EMIE_LMOUSE_PRESSED_DOWN event. + EMIE_LMOUSE_DOUBLE_CLICK, + + //! Right mouse button double click. + //! This event is generated after the second EMIE_RMOUSE_PRESSED_DOWN event. + EMIE_RMOUSE_DOUBLE_CLICK, + + //! Middle mouse button double click. + //! This event is generated after the second EMIE_MMOUSE_PRESSED_DOWN event. + EMIE_MMOUSE_DOUBLE_CLICK, + + //! Left mouse button triple click. + //! This event is generated after the third EMIE_LMOUSE_PRESSED_DOWN event. + EMIE_LMOUSE_TRIPLE_CLICK, + + //! Right mouse button triple click. + //! This event is generated after the third EMIE_RMOUSE_PRESSED_DOWN event. + EMIE_RMOUSE_TRIPLE_CLICK, + + //! Middle mouse button triple click. + //! This event is generated after the third EMIE_MMOUSE_PRESSED_DOWN event. + EMIE_MMOUSE_TRIPLE_CLICK, + //! No real event. Just for convenience to get number of events EMIE_COUNT }; + //! Masks for mouse button states + enum E_MOUSE_BUTTON_STATE_MASK + { + EMBSM_LEFT = 0x01, + EMBSM_RIGHT = 0x02, + EMBSM_MIDDLE = 0x04, + + //! currently only on windows + EMBSM_EXTRA1 = 0x08, + + //! currently only on windows + EMBSM_EXTRA2 = 0x10, + + EMBSM_FORCE_32_BIT = 0x7fffffff + }; + namespace gui { @@ -121,9 +160,11 @@ namespace irr EGET_ELEMENT_FOCUSED, //! The mouse cursor hovered over a gui element. + /** If an element has sub-elements you also get this message for the subelements */ EGET_ELEMENT_HOVERED, //! The mouse cursor left the hovered element. + /** If an element has sub-elements you also get this message for the subelements */ EGET_ELEMENT_LEFT, //! An element would like to close. @@ -140,15 +181,20 @@ namespace irr //! A checkbox has changed its check state. EGET_CHECKBOX_CHANGED, - //! A new item in a listbox was seleted. + //! A new item in a listbox was selected. + /** NOTE: You also get this event currently when the same item was clicked again after more than 500 ms. */ EGET_LISTBOX_CHANGED, //! An item in the listbox was selected, which was already selected. + /** NOTE: You get the event currently only if the item was clicked again within 500 ms or selected by "enter" or "space". */ EGET_LISTBOX_SELECTED_AGAIN, //! A file has been selected in the file dialog EGET_FILE_SELECTED, + //! A directory has been selected in the file dialog + EGET_DIRECTORY_SELECTED, + //! A file open dialog has been closed without choosing a file EGET_FILE_CHOOSE_DIALOG_CANCELLED, @@ -164,9 +210,15 @@ namespace irr //! 'Cancel' was clicked on a messagebox EGET_MESSAGEBOX_CANCEL, - //! In an editbox was pressed 'ENTER' + //! In an editbox 'ENTER' was pressed EGET_EDITBOX_ENTER, + //! The text in an editbox was changed. This does not include automatic changes in text-breaking. + EGET_EDITBOX_CHANGED, + + //! The marked area in an editbox was changed. + EGET_EDITBOX_MARKING_CHANGED, + //! The tab was changed in an tab control EGET_TAB_CHANGED, @@ -178,11 +230,29 @@ namespace irr //! The value of a spin box has changed EGET_SPINBOX_CHANGED, + //! A table has changed EGET_TABLE_CHANGED, EGET_TABLE_HEADER_CHANGED, - EGET_TABLE_SELECTED_AGAIN + EGET_TABLE_SELECTED_AGAIN, + //! A tree view node lost selection. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_DESELECT, + + //! A tree view node was selected. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_SELECT, + + //! A tree view node was expanded. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_EXPAND, + + //! deprecated - use EGET_TREEVIEW_NODE_COLLAPSE instead + EGET_TREEVIEW_NODE_COLLAPS, + + //! A tree view node was collapsed. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_COLLAPSE = EGET_TREEVIEW_NODE_COLLAPS, + + //! No real event. Just for convenience to get number of events + EGET_COUNT }; } // end namespace gui @@ -217,6 +287,26 @@ struct SEvent /** Only valid if event was EMIE_MOUSE_WHEEL */ f32 Wheel; + //! True if shift was also pressed + bool Shift:1; + + //! True if ctrl was also pressed + bool Control:1; + + //! A bitmap of button states. You can use isButtonPressed() to determine + //! if a button is pressed or not. + //! Currently only valid if the event was EMIE_MOUSE_MOVED + u32 ButtonStates; + + //! Is the left button pressed down? + bool isLeftPressed() const { return 0 != ( ButtonStates & EMBSM_LEFT ); } + + //! Is the right button pressed down? + bool isRightPressed() const { return 0 != ( ButtonStates & EMBSM_RIGHT ); } + + //! Is the middle button pressed down? + bool isMiddlePressed() const { return 0 != ( ButtonStates & EMBSM_MIDDLE ); } + //! Type of mouse event EMOUSE_INPUT_EVENT Event; }; @@ -231,22 +321,22 @@ struct SEvent EKEY_CODE Key; //! If not true, then the key was left up - bool PressedDown; + bool PressedDown:1; //! True if shift was also pressed - bool Shift; + bool Shift:1; //! True if ctrl was also pressed - bool Control; + bool Control:1; }; //! A joystick event. - /** Unlike other events, joystick events represent the result of polling + /** Unlike other events, joystick events represent the result of polling * each connected joystick once per run() of the device. Joystick events will - * not be generated by default. If joystick support is available for the - * active device, _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ is defined, and - * @ref IrrlichtDevice::activateJoysticks() has been called, an event of - * this type will be generated once per joystick per @ref IrrlichtDevice::run() + * not be generated by default. If joystick support is available for the + * active device, _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ is defined, and + * @ref irr::IrrlichtDevice::activateJoysticks() has been called, an event of + * this type will be generated once per joystick per @ref IrrlichtDevice::run() * regardless of whether the state of the joystick has actually changed. */ struct SJoystickEvent { @@ -269,16 +359,16 @@ 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 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, + * 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]; - /** The POV represents the angle of the POV hat in degrees * 100, - * from 0 to 35,900. A value of 65535 indicates that the POV hat + /** The POV represents the angle of the POV hat in degrees * 100, + * from 0 to 35,900. A value of 65535 indicates that the POV hat * is centered (or not present). * This value is only supported on Windows. On Linux, the POV hat * will be sent as 2 axes instead. */ @@ -298,7 +388,7 @@ struct SEvent return (ButtonStates & (1 << button)) ? true : false; } }; - + //! Any kind of log event. struct SLogEvent @@ -347,18 +437,22 @@ public: virtual ~IEventReceiver() {} //! Called if an event happened. - /** \return True if the event was processed. */ + /** Please take care that you should only return 'true' when you want to _prevent_ Irrlicht + * from processing the event any further. So 'true' does mean that an event is completely done. + * Therefore your return value for all unprocessed events should be 'false'. + \return True if the event was processed. + */ virtual bool OnEvent(const SEvent& event) = 0; }; -//! Information on a joystick, returned from @ref IrrlichtDevice::activateJoysticks() +//! Information on a joystick, returned from @ref irr::IrrlichtDevice::activateJoysticks() struct SJoystickInfo { //! The ID of the joystick /** This is an internal Irrlicht index; it does not map directly - * to any particular hardware joystick. It corresponds to the - * @ref SJoystickEvent Joystick ID. */ + * to any particular hardware joystick. It corresponds to the + * irr::SJoystickEvent Joystick ID. */ u8 Joystick; //! The name that the joystick uses to identify itself. diff --git a/src/dep/include/irrlicht/IFileArchive.h b/src/dep/include/irrlicht/IFileArchive.h new file mode 100644 index 0000000..5147c1b --- /dev/null +++ b/src/dep/include/irrlicht/IFileArchive.h @@ -0,0 +1,129 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt/ Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_FILE_ARCHIVE_H_INCLUDED__ +#define __I_FILE_ARCHIVE_H_INCLUDED__ + +#include "IReadFile.h" +#include "IFileList.h" + +namespace irr +{ + +namespace io +{ + +//! FileSystemType: which Filesystem should be used for e.g. browsing +enum EFileSystemType +{ + FILESYSTEM_NATIVE = 0, // Native OS FileSystem + FILESYSTEM_VIRTUAL // Virtual FileSystem +}; + +//! Contains the different types of archives +enum E_FILE_ARCHIVE_TYPE +{ + //! A PKZIP archive + EFAT_ZIP = MAKE_IRR_ID('Z','I','P', 0), + + //! A gzip archive + EFAT_GZIP = MAKE_IRR_ID('g','z','i','p'), + + //! A virtual directory + EFAT_FOLDER = MAKE_IRR_ID('f','l','d','r'), + + //! An ID Software PAK archive + EFAT_PAK = MAKE_IRR_ID('P','A','K', 0), + + //! A Nebula Device archive + EFAT_NPK = MAKE_IRR_ID('N','P','K', 0), + + //! A Tape ARchive + EFAT_TAR = MAKE_IRR_ID('T','A','R', 0), + + //! The type of this archive is unknown + EFAT_UNKNOWN = MAKE_IRR_ID('u','n','k','n') +}; + +//! The FileArchive manages archives and provides access to files inside them. +class IFileArchive : public virtual IReferenceCounted +{ +public: + + //! Opens a file based on its name + /** Creates and returns a new IReadFile for a file in the archive. + \param filename The file to open + \return Returns A pointer to the created file on success, + or 0 on failure. */ + virtual IReadFile* createAndOpenFile(const path& filename) =0; + + //! Opens a file based on its position in the file list. + /** Creates and returns + \param index The zero based index of the file. + \return Returns a pointer to the created file on success, or 0 on failure. */ + virtual IReadFile* createAndOpenFile(u32 index) =0; + + //! Returns the complete file tree + /** \return Returns the complete directory tree for the archive, + including all files and folders */ + virtual const IFileList* getFileList() const =0; + + //! get the archive type + virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_UNKNOWN; } + + //! An optionally used password string + /** This variable is publicly accessible from the interface in order to + avoid single access patterns to this place, and hence allow some more + obscurity. + */ + core::stringc Password; +}; + +//! Class which is able to create an archive from a file. +/** If you want the Irrlicht Engine be able to load archives of +currently unsupported file formats (e.g .wad), then implement +this and add your new Archive loader with +IFileSystem::addArchiveLoader() to the engine. */ +class IArchiveLoader : public virtual IReferenceCounted +{ +public: + //! Check if the file might be loaded by this class + /** Check based on the file extension (e.g. ".zip") + \param filename Name of file to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(const path& filename) const =0; + + //! Check if the file might be loaded by this class + /** This check may look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const =0; + + //! Check to see if the loader can create archives of this type. + /** Check based on the archive type. + \param fileType The archive type to check. + \return True if the archile loader supports this type, false if not */ + virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const =0; + + //! Creates an archive from the filename + /** \param filename File to use. + \param ignoreCase Searching is performed without regarding the case + \param ignorePaths Files are searched for without checking for the directories + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(const path& filename, bool ignoreCase, bool ignorePaths) const =0; + + //! Creates an archive from the file + /** \param file File handle to use. + \param ignoreCase Searching is performed without regarding the case + \param ignorePaths Files are searched for without checking for the directories + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const =0; +}; + + +} // end namespace io +} // end namespace irr + +#endif + diff --git a/src/dep/include/irrlicht/IFileList.h b/src/dep/include/irrlicht/IFileList.h index dcdd85f..6e1ff10 100644 --- a/src/dep/include/irrlicht/IFileList.h +++ b/src/dep/include/irrlicht/IFileList.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,13 +6,16 @@ #define __I_FILE_LIST_H_INCLUDED__ #include "IReferenceCounted.h" +#include "path.h" namespace irr { namespace io { -//! The Filelist lists all files in a directory. +//! Provides a list of files and folders. +/** File lists usually contain a list of all files in a given folder, +but can also contain a complete directory structure. */ class IFileList : public virtual IReferenceCounted { public: @@ -23,21 +26,57 @@ public: //! Gets the name of a file in the list, based on an index. /** The path is not included in this name. Use getFullFileName for this. \param index is the zero based index of the file which name should - be returned. The index has to be smaller than the amount getFileCount() returns. + be returned. The index must be less than the amount getFileCount() returns. \return File name of the file. Returns 0, if an error occured. */ - virtual const c8* getFileName(u32 index) const = 0; + virtual const io::path& getFileName(u32 index) const = 0; - //! Gets the full name of a file in the list, path included, based on an index. + //! Gets the full name of a file in the list including the path, based on an index. /** \param index is the zero based index of the file which name should - be returned. The index has to be smaller than the amount getFileCount() returns. - \return File name of the file. Returns 0, if an error occured. */ - virtual const c8* getFullFileName(u32 index) = 0; + be returned. The index must be less than the amount getFileCount() returns. + \return File name of the file. Returns 0 if an error occured. */ + virtual const io::path& getFullFileName(u32 index) const = 0; + + //! Returns the size of a file in the file list, based on an index. + /** \param index is the zero based index of the file which should be returned. + The index must be less than the amount getFileCount() returns. + \return The size of the file in bytes. */ + virtual u32 getFileSize(u32 index) const = 0; + + //! Returns the ID of a file in the file list, based on an index. + /** This optional ID can be used to link the file list entry to information held + elsewhere. For example this could be an index in an IFileArchive, linking the entry + to its data offset, uncompressed size and CRC. + \param index is the zero based index of the file which should be returned. + The index must be less than the amount getFileCount() returns. + \return The ID of the file. */ + virtual u32 getID(u32 index) const = 0; //! Check if the file is a directory - /** \param index The zero based index of the file whose name shall - be returned. The index has to be smaller than the amount getFileCount() returns. + /** \param index The zero based index which will be checked. The index + must be less than the amount getFileCount() returns. \return True if the file is a directory, else false. */ virtual bool isDirectory(u32 index) const = 0; + + //! Searches for a file or folder in the list + /** Searches for a file by name + \param filename The name of the file to search for. + \param isFolder True if you are searching for a directory path, false if you are searching for a file + \return Returns the index of the file in the file list, or -1 if + no matching name name was found. */ + virtual s32 findFile(const io::path& filename, bool isFolder=false) const = 0; + + //! Returns the base path of the file list + virtual const io::path& getPath() const = 0; + + //! Add as a file or folder to the list + /** \param fullPath The file name including path, from the root of the file list. + \param isDirectory True if this is a directory rather than a file. + \param size The size of the file in bytes. + \param id The ID of the file in the archive which owns it */ + virtual u32 addItem(const io::path& fullPath, u32 size, bool isDirectory, u32 id=0) = 0; + + //! Sorts the file list. You should call this after adding any items to the file list + virtual void sort() = 0; }; } // end namespace irr diff --git a/src/dep/include/irrlicht/IFileSystem.h b/src/dep/include/irrlicht/IFileSystem.h index ae200ee..6ad7772 100644 --- a/src/dep/include/irrlicht/IFileSystem.h +++ b/src/dep/include/irrlicht/IFileSystem.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,7 +7,7 @@ #include "IReferenceCounted.h" #include "IXMLReader.h" -#include "irrString.h" +#include "IFileArchive.h" namespace irr { @@ -24,6 +24,7 @@ class IFileList; class IXMLWriter; class IAttributes; + //! The FileSystem manages files and archives and provides access to them. /** It manages where files are, so that modules which use the the IO do not need to know where every file is located. A file could be in a .zip-Archive or @@ -34,10 +35,10 @@ public: //! Opens a file for read access. /** \param filename: Name of file to open. - \return Returns a pointer to the created file interface. + \return Pointer to the created file interface. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ - virtual IReadFile* createAndOpenFile(const c8* filename) = 0; + virtual IReadFile* createAndOpenFile(const path& filename) =0; //! Creates an IReadFile interface for accessing memory like a file. /** This allows you to use a pointer to memory where an IReadFile is requested. @@ -46,46 +47,147 @@ public: \param fileName: The name given to this file \param deleteMemoryWhenDropped: True if the memory should be deleted along with the IReadFile when it is dropped. - \return Returns a pointer to the created file interface. + \return Pointer to the created file interface. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ - virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const c8* fileName, bool deleteMemoryWhenDropped=false) = 0; + virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; + + //! Creates an IReadFile interface for accessing files inside files. + /** This is useful e.g. for archives. + \param fileName: The name given to this file + \param alreadyOpenedFile: Pointer to the enclosing file + \param pos: Start of the file inside alreadyOpenedFile + \param areaSize: The length of the file + \return A pointer to the created file interface. + The returned pointer should be dropped when no longer needed. + See IReferenceCounted::drop() for more information. + */ + virtual IReadFile* createLimitReadFile(const path& fileName, + IReadFile* alreadyOpenedFile, long pos, long areaSize) =0; + + //! Creates an IWriteFile interface for accessing memory like a file. + /** This allows you to use a pointer to memory where an IWriteFile is requested. + You are responsible for allocating enough memory. + \param memory: A pointer to the start of the file in memory (allocated by you) + \param len: The length of the memory in bytes + \param fileName: The name given to this file + \param deleteMemoryWhenDropped: True if the memory should be deleted + along with the IWriteFile when it is dropped. + \return Pointer to the created file interface. + The returned pointer should be dropped when no longer needed. + See IReferenceCounted::drop() for more information. + */ + virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; + //! Opens a file for write access. /** \param filename: Name of file to open. \param append: If the file already exist, all write operations are appended to the file. - \return Returns a pointer to the created file interface. 0 is returned, if the + \return Pointer to the created file interface. 0 is returned, if the file could not created or opened for writing. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ - virtual IWriteFile* createAndWriteFile(const c8* filename, bool append=false) = 0; + virtual IWriteFile* createAndWriteFile(const path& filename, bool append=false) =0; - //! Adds an zip archive to the file system. - /** After calling this, the Irrlicht Engine will search and open files directly from this archive too. + //! Adds an archive to the file system. + /** After calling this, the Irrlicht Engine will also search and open + files directly from this archive. This is useful for hiding data from + the end user, speeding up file access and making it possible to access + for example Quake3 .pk3 files, which are just renamed .zip files. By + default Irrlicht supports ZIP, PAK, TAR, PNK, and directories as + archives. You can provide your own archive types by implementing + IArchiveLoader and passing an instance to addArchiveLoader. + Irrlicht supports AES-encrypted zip files, and the advanced compression + techniques lzma and bzip2. + \param filename: Filename of the archive to add to the file system. + \param ignoreCase: If set to true, files in the archive can be accessed without + writing all letters in the right case. + \param ignorePaths: If set to true, files in the added archive can be accessed + without its complete path. + \param archiveType: If no specific E_FILE_ARCHIVE_TYPE is selected then + the type of archive will depend on the extension of the file name. If + you use a different extension then you can use this parameter to force + a specific type of archive. + \param password An optional password, which is used in case of encrypted archives. + \return True if the archive was added successfully, false if not. */ + virtual bool addFileArchive(const path& filename, bool ignoreCase=true, + bool ignorePaths=true, + E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN, + const core::stringc& password="") =0; + + //! Adds an external archive loader to the engine. + /** Use this function to add support for new archive types to the + engine, for example proprietary or encrypted file storage. */ + virtual void addArchiveLoader(IArchiveLoader* loader) =0; + + //! Get the number of archives currently attached to the file system + virtual u32 getFileArchiveCount() const =0; + + //! Removes an archive from the file system. + /** This will close the archive and free any file handles, but will not close resources which have already + been loaded and are now cached, for example textures and meshes. + \param index: The index of the archive to remove + \return True on success, false on failure */ + virtual bool removeFileArchive(u32 index) =0; + + //! Removes an archive from the file system. + /** This will close the archive and free any file handles, but will not + close resources which have already been loaded and are now cached, for + example textures and meshes. + \param filename The archive of the given name will be removed + \return True on success, false on failure */ + virtual bool removeFileArchive(const path& filename) =0; + + //! Changes the search order of attached archives. + /** + \param sourceIndex: The index of the archive to change + \param relative: The relative change in position, archives with a lower index are searched first */ + virtual bool moveFileArchive(u32 sourceIndex, s32 relative) =0; + + //! Get the archive at a given index. + virtual IFileArchive* getFileArchive(u32 index) =0; + + //! Adds a zip archive to the file system. + /** \deprecated This function is provided for compatibility + with older versions of Irrlicht and may be removed in future versions, + you should use addFileArchive instead. + After calling this, the Irrlicht Engine will search and open files directly from this archive too. This is useful for hiding data from the end user, speeding up file access and making it possible to - access for example Quake3 .pk3 files, which are nothing different than .zip files. + access for example Quake3 .pk3 files, which are no different than .zip files. \param filename: Filename of the zip archive to add to the file system. \param ignoreCase: If set to true, files in the archive can be accessed without writing all letters in the right case. \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path. - \return Returns true if the archive was added successful, false if not. */ - virtual bool addZipFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) = 0; + \return True if the archive was added successfully, false if not. */ + virtual bool addZipFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) + { + return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_ZIP); + } - //! Adds an unzipped archive ( or basedirectory with subdirectories..) to the file system. - /** Useful for handling data which will be in a zip file + //! Adds an unzipped archive (or basedirectory with subdirectories..) to the file system. + /** \deprecated This function is provided for compatibility + with older versions of Irrlicht and may be removed in future versions, + you should use addFileArchive instead. + Useful for handling data which will be in a zip file \param filename: Filename of the unzipped zip archive base directory to add to the file system. \param ignoreCase: If set to true, files in the archive can be accessed without writing all letters in the right case. \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path. - \return Returns true if the archive was added successful, false if not. */ - virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) = 0; + \return True if the archive was added successful, false if not. */ + virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) + { + return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_FOLDER); + } - //! Adds an pak archive to the file system. - /** After calling this, the Irrlicht Engine will search and open files directly from this archive too. + //! Adds a pak archive to the file system. + /** \deprecated This function is provided for compatibility + with older versions of Irrlicht and may be removed in future versions, + you should use addFileArchive instead. + After calling this, the Irrlicht Engine will search and open files directly from this archive too. This is useful for hiding data from the end user, speeding up file access and making it possible to access for example Quake2/KingPin/Hexen2 .pak files \param filename: Filename of the pak archive to add to the file system. @@ -93,50 +195,62 @@ public: writing all letters in the right case. \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path.(should not use with Quake2 paks - \return Returns true if the archive was added successful, false if not. */ - virtual bool addPakFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) = 0; + \return True if the archive was added successful, false if not. */ + virtual bool addPakFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) + { + return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_PAK); + } //! Get the current working directory. /** \return Current working directory as a string. */ - virtual const c8* getWorkingDirectory() = 0; + virtual const path& getWorkingDirectory() =0; //! Changes the current working directory. /** \param newDirectory: A string specifying the new working directory. The string is operating system dependent. Under Windows it has the form ":\\\<..>". An example would be: "C:\Windows\" \return True if successful, otherwise false. */ - virtual bool changeWorkingDirectoryTo(const c8* newDirectory) = 0; + virtual bool changeWorkingDirectoryTo(const path& newDirectory) =0; //! Converts a relative path to an absolute (unique) path, resolving symbolic links if required - /** \param filename Possibly relative filename begin queried. + /** \param filename Possibly relative file or directory name to query. \result Absolute filename which points to the same file. */ - virtual core::stringc getAbsolutePath(const core::stringc& filename) const = 0; + virtual path getAbsolutePath(const path& filename) const =0; - //! Returns the directory a file is located in. + //! Get the directory a file is located in. /** \param filename: The file to get the directory from. \return String containing the directory of the file. */ - virtual core::stringc getFileDir(const core::stringc& filename) const = 0; + virtual path getFileDir(const path& filename) const =0; - //! Returns the base part of a filename, i.e. the name without the directory - //! part. If no directory is prefixed, the full name is returned. - /** \param filename: The file to get the basename from */ - virtual core::stringc getFileBasename(const core::stringc& filename, bool keepExtension=true) const = 0; + //! Get the base part of a filename, i.e. the name without the directory part. + /** If no directory is prefixed, the full name is returned. + \param filename: The file to get the basename from + \param keepExtension True if filename with extension is returned otherwise everything + after the final '.' is removed as well. */ + virtual path getFileBasename(const path& filename, bool keepExtension=true) const =0; + + //! flatten a path and file name for example: "/you/me/../." becomes "/you" + virtual path& flattenFilename(path& directory, const path& root="/") const =0; //! Creates a list of files and directories in the current working directory and returns it. /** \return a Pointer to the created IFileList is returned. After the list has been used it has to be deleted using its IFileList::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IFileList* createFileList() const = 0; + virtual IFileList* createFileList() =0; + + //! Creates an empty filelist + /** \return a Pointer to the created IFileList is returned. After the list has been used + it has to be deleted using its IFileList::drop() method. + See IReferenceCounted::drop() for more information. */ + virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) =0; + + //! Set the active type of file system. + virtual EFileSystemType setFileListSystem(EFileSystemType listType) =0; //! Determines if a file exists and could be opened. /** \param filename is the string identifying the file which should be tested for existence. - \return Returns true if file exists, and false if it does not exist or an error occured. */ - virtual bool existFile(const c8* filename) const = 0; - - //! Determines if a file exists and could be opened. - /** \param filename is the string identifying the file which should be tested for existence. - \return Returns true if file exists, and false if it does not exist or an error occured. */ - virtual bool existFile(const core::stringc& filename) const = 0; + \return True if file exists, and false if it does not exist or an error occured. */ + virtual bool existFile(const path& filename) const =0; //! Creates a XML Reader from a file which returns all parsed strings as wide characters (wchar_t*). /** Use createXMLReaderUTF8() if you prefer char* instead of wchar_t*. See IIrrXMLReader for @@ -145,7 +259,7 @@ public: IXMLReader is returned. After use, the reader has to be deleted using its IXMLReader::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IXMLReader* createXMLReader(const c8* filename) = 0; + virtual IXMLReader* createXMLReader(const path& filename) =0; //! Creates a XML Reader from a file which returns all parsed strings as wide characters (wchar_t*). /** Use createXMLReaderUTF8() if you prefer char* instead of wchar_t*. See IIrrXMLReader for @@ -154,7 +268,7 @@ public: IXMLReader is returned. After use, the reader has to be deleted using its IXMLReader::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IXMLReader* createXMLReader(IReadFile* file) = 0; + virtual IXMLReader* createXMLReader(IReadFile* file) =0; //! Creates a XML Reader from a file which returns all parsed strings as ASCII/UTF-8 characters (char*). /** Use createXMLReader() if you prefer wchar_t* instead of char*. See IIrrXMLReader for @@ -163,7 +277,7 @@ public: IXMLReader is returned. After use, the reader has to be deleted using its IXMLReaderUTF8::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IXMLReaderUTF8* createXMLReaderUTF8(const c8* filename) = 0; + virtual IXMLReaderUTF8* createXMLReaderUTF8(const path& filename) =0; //! Creates a XML Reader from a file which returns all parsed strings as ASCII/UTF-8 characters (char*). /** Use createXMLReader() if you prefer wchar_t* instead of char*. See IIrrXMLReader for @@ -172,21 +286,21 @@ public: IXMLReader is returned. After use, the reader has to be deleted using its IXMLReaderUTF8::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file) = 0; + virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file) =0; //! Creates a XML Writer from a file. /** \return 0, if file could not be opened, otherwise a pointer to the created IXMLWriter is returned. After use, the reader has to be deleted using its IXMLWriter::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IXMLWriter* createXMLWriter(const c8* filename) = 0; + virtual IXMLWriter* createXMLWriter(const path& filename) =0; //! Creates a XML Writer from a file. /** \return 0, if file could not be opened, otherwise a pointer to the created IXMLWriter is returned. After use, the reader has to be deleted using its IXMLWriter::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IXMLWriter* createXMLWriter(IWriteFile* file) = 0; + virtual IXMLWriter* createXMLWriter(IWriteFile* file) =0; //! Creates a new empty collection of attributes, usable for serialization and more. /** \param driver: Video driver to be used to load textures when specified as attribute values. @@ -194,12 +308,12 @@ public: \return Pointer to the created object. If you no longer need the object, you should call IAttributes::drop(). See IReferenceCounted::drop() for more information. */ - virtual IAttributes* createEmptyAttributes(video::IVideoDriver* driver=0) = 0; + virtual IAttributes* createEmptyAttributes(video::IVideoDriver* driver=0) =0; }; + } // end namespace io } // end namespace irr - #endif diff --git a/src/dep/include/irrlicht/IGPUProgrammingServices.h b/src/dep/include/irrlicht/IGPUProgrammingServices.h index 1ae0a74..e56eb96 100644 --- a/src/dep/include/irrlicht/IGPUProgrammingServices.h +++ b/src/dep/include/irrlicht/IGPUProgrammingServices.h @@ -1,12 +1,14 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GPU_PROGRAMMING_SERVICES_H_INCLUDED__ #define __I_GPU_PROGRAMMING_SERVICES_H_INCLUDED__ -#include "IReferenceCounted.h" -#include "SMaterial.h" +#include "EShaderTypes.h" +#include "EMaterialTypes.h" +#include "EPrimitiveTypes.h" +#include "path.h" namespace irr { @@ -22,54 +24,6 @@ namespace video class IVideoDriver; class IShaderConstantSetCallBack; -//! Compile target enumeration for the addHighLevelShaderMaterial() method. -enum E_VERTEX_SHADER_TYPE -{ - EVST_VS_1_1 = 0, - EVST_VS_2_0, - EVST_VS_2_a, - EVST_VS_3_0, - - //! This is not a type, but a value indicating how much types there are. - EVST_COUNT -}; - -//! Names for all vertex shader types, each entry corresponds to a E_VERTEX_SHADER_TYPE entry. -const c8* const VERTEX_SHADER_TYPE_NAMES[] = { - "vs_1_1", - "vs_2_0", - "vs_2_a", - "vs_3_0", - 0 }; - -//! Compile target enumeration for the addHighLevelShaderMaterial() method. -enum E_PIXEL_SHADER_TYPE -{ - EPST_PS_1_1 = 0, - EPST_PS_1_2, - EPST_PS_1_3, - EPST_PS_1_4, - EPST_PS_2_0, - EPST_PS_2_a, - EPST_PS_2_b, - EPST_PS_3_0, - - //! This is not a type, but a value indicating how much types there are. - EPST_COUNT -}; - -//! Names for all pixel shader types, each entry corresponds to a E_PIXEL_SHADER_TYPE entry. -const c8* const PIXEL_SHADER_TYPE_NAMES[] = { - "ps_1_1", - "ps_1_2", - "ps_1_3", - "ps_1_4", - "ps_2_0", - "ps_2_a", - "ps_2_b", - "ps_3_0", - 0 }; - //! Interface making it possible to create and use programs running on the GPU. class IGPUProgrammingServices { @@ -83,18 +37,30 @@ public: \param vertexShaderProgram: String containing the source of the vertex shader program. This can be 0 if no vertex program shall be used. \param vertexShaderEntryPointName: Name of the entry function of the - vertexShaderProgram - \param vsCompileTarget: Vertex shader version where the high level - shader shall be compiled to. + vertexShaderProgram (p.e. "main") + \param vsCompileTarget: Vertex shader version the high level shader + shall be compiled to. \param pixelShaderProgram: String containing the source of the pixel shader program. This can be 0 if no pixel shader shall be used. \param pixelShaderEntryPointName: Entry name of the function of the - pixelShaderEntryPointName - \param psCompileTarget: Pixel shader version where the high level - shader shall be compiled to. + pixelShaderProgram (p.e. "main") + \param psCompileTarget: Pixel shader version the high level shader + shall be compiled to. + \param geometryShaderProgram: String containing the source of the + geometry shader program. This can be 0 if no geometry shader shall be + used. + \param geometryShaderEntryPointName: Entry name of the function of the + geometryShaderProgram (p.e. "main") + \param gsCompileTarget: Geometry shader version the high level shader + shall be compiled to. + \param inType Type of vertices passed to geometry shader + \param outType Type of vertices created by geometry shader + \param verticesOut Maximal number of vertices created by geometry + shader. If 0, maximal number supported is assumed. \param callback: Pointer to an implementation of - IShaderConstantSetCallBack in which you can set the needed vertex and - pixel shader program constants. Set this to 0 if you don't need this. + IShaderConstantSetCallBack in which you can set the needed vertex, + pixel, and geometry shader program constants. Set this to 0 if you + don't need this. \param baseMaterial: Base material which renderstates will be used to shade the material. \param userData: a user data int. This int can be set to any value and @@ -102,60 +68,30 @@ public: OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. - \return Returns the number of the material type which can be set in - SMaterial::MaterialType to use the renderer. -1 is returned if an - error occured, e.g. if a vertex or pixel shader program could not be - compiled or a compile target is not reachable. The error strings are - then printed to the error log and can be catched with a custom event - receiver. */ + \return Number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an error + occured, e.g. if a shader program could not be compiled or a compile + target is not reachable. The error strings are then printed to the + error log and can be catched with a custom event receiver. */ virtual s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, - const c8* vertexShaderEntryPointName = "main", - E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, - const c8* pixelShaderProgram = 0, - const c8* pixelShaderEntryPointName = "main", - E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const c8* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0 ) = 0; - //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. - /** \param vertexShaderProgram: Text file containing the source of the - * vertex shader program. - Set to 0 if no shader shall be created. - \param vertexShaderEntryPointName: Name of the entry function of the - vertexShaderProgram - \param vsCompileTarget: Vertex shader version where the high level - shader shall be compiled to. - \param pixelShaderProgram: Text file containing the source of the pixel - shader program. Set to 0 if no shader shall be created. - \param vertexShaderEntryPointName: Name of the entry function of the - vertexShaderProgram - \param vsCompileTarget: Vertex shader version where the high level - shader shall be compiled to. - \param pixelShaderProgram: String containing the source of the pixel - shader program. This can be 0 if no pixel shader shall be used. - \param pixelShaderEntryPointName: Entry name of the function of the - pixelShaderEntryPointName - \param psCompileTarget: Pixel shader version where the high level - shader shall be compiled to. - \param callback: Pointer to an implementation of - IShaderConstantSetCallBack in which you can set the needed vertex and - pixel shader program constants. Set this to 0 if you don't need this. - \param baseMaterial: Base material which renderstates will be used to - shade the material. - \param userData: a user data int. This int can be set to any value and - will be set as parameter in the callback method when calling - OnSetConstants(). In this way it is easily possible to use the same - callback method for multiple materials and distinguish between them - during the call. - \return Returns the number of the material type which can be set in - SMaterial::MaterialType to use the renderer. -1 is returned if an - error occured, e.g. if a vertex or pixel shader program could not be - compiled or a compile target is not reachable. The error strings are - then printed to the error log and can be catched with a custom event - receiver. */ - virtual s32 addHighLevelShaderMaterialFromFiles( + //! convenience function for use without geometry shaders + s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, @@ -164,25 +100,122 @@ public: E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0 ) + { + return addHighLevelShaderMaterial( + vertexShaderProgram, vertexShaderEntryPointName, + vsCompileTarget, pixelShaderProgram, + pixelShaderEntryPointName, psCompileTarget, + 0, "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData); + } + + //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. + /** \param vertexShaderProgramFileName: Text file containing the source + of the vertex shader program. Set to empty string if no vertex shader + shall be created. + \param vertexShaderEntryPointName: Name of the entry function of the + vertexShaderProgram (p.e. "main") + \param vsCompileTarget: Vertex shader version the high level shader + shall be compiled to. + \param pixelShaderProgramFileName: Text file containing the source of + the pixel shader program. Set to empty string if no pixel shader shall + be created. + \param pixelShaderEntryPointName: Entry name of the function of the + pixelShaderProgram (p.e. "main") + \param psCompileTarget: Pixel shader version the high level shader + shall be compiled to. + \param geometryShaderProgramFileName: Name of the source of + the geometry shader program. Set to empty string if no geometry shader + shall be created. + \param geometryShaderEntryPointName: Entry name of the function of the + geometryShaderProgram (p.e. "main") + \param gsCompileTarget: Geometry shader version the high level shader + shall be compiled to. + \param inType Type of vertices passed to geometry shader + \param outType Type of vertices created by geometry shader + \param verticesOut Maximal number of vertices created by geometry + shader. If 0, maximal number supported is assumed. + \param callback: Pointer to an implementation of + IShaderConstantSetCallBack in which you can set the needed vertex, + pixel, and geometry shader program constants. Set this to 0 if you + don't need this. + \param baseMaterial: Base material which renderstates will be used to + shade the material. + \param userData: a user data int. This int can be set to any value and + will be set as parameter in the callback method when calling + OnSetConstants(). In this way it is easily possible to use the same + callback method for multiple materials and distinguish between them + during the call. + \return Number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an error + occured, e.g. if a shader program could not be compiled or a compile + target is not reachable. The error strings are then printed to the + error log and can be catched with a custom event receiver. */ + virtual s32 addHighLevelShaderMaterialFromFiles( + const io::path& vertexShaderProgramFileName, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const io::path& pixelShaderProgramFileName, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const io::path& geometryShaderProgramFileName, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0) = 0; + //! convenience function for use without geometry shaders + s32 addHighLevelShaderMaterialFromFiles( + const io::path& vertexShaderProgramFileName, + const c8* vertexShaderEntryPointName = "main", + E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, + const io::path& pixelShaderProgramFileName = "", + const c8* pixelShaderEntryPointName = "main", + E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0) + { + return addHighLevelShaderMaterialFromFiles( + vertexShaderProgramFileName, vertexShaderEntryPointName, + vsCompileTarget, pixelShaderProgramFileName, + pixelShaderEntryPointName, psCompileTarget, + "", "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData); + } //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. /** \param vertexShaderProgram: Text file handle containing the source - * of the vertex shader program. - Set to 0 if no shader shall be created. + of the vertex shader program. Set to 0 if no vertex shader shall be + created. \param vertexShaderEntryPointName: Name of the entry function of the vertexShaderProgram - \param vsCompileTarget: Vertex shader version where the high level - shader shall be compiled to. - \param pixelShaderProgram: Text file containing the source of the pixel - shader program. Set to + \param vsCompileTarget: Vertex shader version the high level shader + shall be compiled to. \param pixelShaderProgram: Text file handle containing the source of - the pixel shader program. Set to 0 if no shader shall be created. + the pixel shader program. Set to 0 if no pixel shader shall be created. \param pixelShaderEntryPointName: Entry name of the function of the - pixelShaderEntryPointName - \param psCompileTarget: Pixel shader version where the high level - shader shall be compiled to. + pixelShaderProgram (p.e. "main") + \param psCompileTarget: Pixel shader version the high level shader + shall be compiled to. + \param geometryShaderProgram: Text file handle containing the source of + the geometry shader program. Set to 0 if no geometry shader shall be + created. + \param geometryShaderEntryPointName: Entry name of the function of the + geometryShaderProgram (p.e. "main") + \param gsCompileTarget: Geometry shader version the high level shader + shall be compiled to. + \param inType Type of vertices passed to geometry shader + \param outType Type of vertices created by geometry shader + \param verticesOut Maximal number of vertices created by geometry + shader. If 0, maximal number supported is assumed. \param callback: Pointer to an implementation of IShaderConstantSetCallBack in which you can set the needed vertex and pixel shader program constants. Set this to 0 if you don't need this. @@ -193,13 +226,30 @@ public: OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. - \return Returns the number of the material type which can be set in + \return Number of the material type which can be set in SMaterial::MaterialType to use the renderer. -1 is returned if an - error occured, e.g. if a vertex or pixel shader program could not be - compiled or a compile target is not reachable. The error strings are - then printed to the error log and can be catched with a custom event - receiver. */ + error occured, e.g. if a shader program could not be compiled or a + compile target is not reachable. The error strings are then printed to + the error log and can be catched with a custom event receiver. */ virtual s32 addHighLevelShaderMaterialFromFiles( + io::IReadFile* vertexShaderProgram, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + io::IReadFile* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + io::IReadFile* geometryShaderProgram, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0) = 0; + + //! convenience function for use without geometry shaders + s32 addHighLevelShaderMaterialFromFiles( io::IReadFile* vertexShaderProgram, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, @@ -208,7 +258,16 @@ public: E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, - s32 userData = 0) = 0; + s32 userData = 0) + { + return addHighLevelShaderMaterialFromFiles( + vertexShaderProgram, vertexShaderEntryPointName, + vsCompileTarget, pixelShaderProgram, + pixelShaderEntryPointName, psCompileTarget, + 0, "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData); + } //! Adds a new ASM shader material renderer to the VideoDriver /** Note that it is a good idea to call IVideoDriver::queryFeature() in @@ -293,8 +352,8 @@ public: error occured. -1 is returned for example if a vertex or pixel shader program could not be compiled, the error strings are then printed out into the error log, and can be catched with a custom event receiver. */ - virtual s32 addShaderMaterialFromFiles(const c8* vertexShaderProgramFileName, - const c8* pixelShaderProgramFileName, + virtual s32 addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, + const io::path& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0) = 0; diff --git a/src/dep/include/irrlicht/IGUIButton.h b/src/dep/include/irrlicht/IGUIButton.h index 498f289..634f3c1 100644 --- a/src/dep/include/irrlicht/IGUIButton.h +++ b/src/dep/include/irrlicht/IGUIButton.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -67,7 +67,7 @@ namespace gui //! Sets an image which should be displayed on the button when it is in normal state. /** \param image: Image to be displayed */ - virtual void setImage(video::ITexture* image) = 0; + virtual void setImage(video::ITexture* image=0) = 0; //! Sets a background image for the button when it is in normal state. /** \param image: Texture containing the image to be displayed @@ -78,7 +78,7 @@ namespace gui /** If no images is specified for the pressed state via setPressedImage(), this image is also drawn in pressed state. \param image: Image to be displayed */ - virtual void setPressedImage(video::ITexture* image) = 0; + virtual void setPressedImage(video::ITexture* image=0) = 0; //! Sets an image which should be displayed on the button when it is in pressed state. /** \param image: Texture containing the image to be displayed @@ -86,7 +86,7 @@ namespace gui virtual void setPressedImage(video::ITexture* image, const core::rect& pos) = 0; //! Sets the sprite bank used by the button - virtual void setSpriteBank(IGUISpriteBank* bank) = 0; + virtual void setSpriteBank(IGUISpriteBank* bank=0) = 0; //! Sets the animated sprite for a specific button state /** \param index: Number of the sprite within the sprite bank, use -1 for no sprite @@ -101,16 +101,16 @@ namespace gui //! Sets if the button should behave like a push button. /** Which means it can be in two states: Normal or Pressed. With a click on the button, the user can change the state of the button. */ - virtual void setIsPushButton(bool isPushButton) = 0; + virtual void setIsPushButton(bool isPushButton=true) = 0; //! Sets the pressed state of the button if this is a pushbutton - virtual void setPressed(bool pressed) = 0; + virtual void setPressed(bool pressed=true) = 0; //! Returns if the button is currently pressed virtual bool isPressed() const = 0; //! Sets if the alpha channel should be used for drawing background images on the button (default is false) - virtual void setUseAlphaChannel(bool useAlphaChannel) = 0; + virtual void setUseAlphaChannel(bool useAlphaChannel=true) = 0; //! Returns if the alpha channel should be used for drawing background images on the button virtual bool isAlphaChannelUsed() const = 0; @@ -119,10 +119,16 @@ namespace gui virtual bool isPushButton() const = 0; //! Sets if the button should use the skin to draw its border and button face (default is true) - virtual void setDrawBorder(bool border) = 0; + virtual void setDrawBorder(bool border=true) = 0; //! Returns if the border and button face are being drawn using the skin virtual bool isDrawingBorder() const = 0; + + //! Sets if the button should scale the button images to fit + virtual void setScaleImage(bool scaleImage=true) = 0; + + //! Checks whether the button scales the used images + virtual bool isScalingImage() const = 0; }; diff --git a/src/dep/include/irrlicht/IGUICheckBox.h b/src/dep/include/irrlicht/IGUICheckBox.h index a5fc6cc..8e789bc 100644 --- a/src/dep/include/irrlicht/IGUICheckBox.h +++ b/src/dep/include/irrlicht/IGUICheckBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IGUIColorSelectDialog.h b/src/dep/include/irrlicht/IGUIColorSelectDialog.h index 662e340..ea45cbe 100644 --- a/src/dep/include/irrlicht/IGUIColorSelectDialog.h +++ b/src/dep/include/irrlicht/IGUIColorSelectDialog.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,7 +12,7 @@ namespace irr namespace gui { - //! Standard file chooser dialog. + //! Standard color chooser dialog. class IGUIColorSelectDialog : public IGUIElement { public: diff --git a/src/dep/include/irrlicht/IGUIComboBox.h b/src/dep/include/irrlicht/IGUIComboBox.h index fabcfa1..ab98e3a 100644 --- a/src/dep/include/irrlicht/IGUIComboBox.h +++ b/src/dep/include/irrlicht/IGUIComboBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -27,8 +27,14 @@ namespace gui //! Returns string of an item. the idx may be a value from 0 to itemCount-1 virtual const wchar_t* getItem(u32 idx) const = 0; + //! Returns item data of an item. the idx may be a value from 0 to itemCount-1 + virtual u32 getItemData(u32 idx) const = 0; + + //! Returns index based on item data + virtual s32 getIndexForItemData(u32 data ) const = 0; + //! Adds an item and returns the index of it - virtual u32 addItem(const wchar_t* text) = 0; + virtual u32 addItem(const wchar_t* text, u32 data = 0) = 0; //! Removes an item from the combo box. /** Warning. This will change the index of all following items */ @@ -44,10 +50,10 @@ namespace gui virtual void setSelected(s32 idx) = 0; //! Sets text justification of the text area - /** \param horizontal: EGUIA_UPPERLEFT for left justified (default), - EGUIA_LOWEERRIGHT for right justified, or EGUIA_CENTER for centered text. - \param vertical: EGUIA_UPPERLEFT to align with top edge, - EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ + /** \param horizontal: EGUIA_UPPERLEFT for left justified (default), + EGUIA_LOWEERRIGHT for right justified, or EGUIA_CENTER for centered text. + \param vertical: EGUIA_UPPERLEFT to align with top edge, + EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; }; diff --git a/src/dep/include/irrlicht/IGUIContextMenu.h b/src/dep/include/irrlicht/IGUIContextMenu.h index 1b714ba..4de6c1d 100644 --- a/src/dep/include/irrlicht/IGUIContextMenu.h +++ b/src/dep/include/irrlicht/IGUIContextMenu.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,6 +11,21 @@ namespace irr { namespace gui { + //! Close behaviour. + //! Default is ECMC_REMOVE + enum ECONTEXT_MENU_CLOSE + { + //! do nothing - menu stays open + ECMC_IGNORE = 0, + + //! remove the gui element + ECMC_REMOVE = 1, + + //! call setVisible(false) + ECMC_HIDE = 2 + + // note to implementors - this is planned as bitset, so continue with 4 if you need to add further flags. + }; //! GUI Context menu interface. class IGUIContextMenu : public IGUIElement @@ -21,6 +36,12 @@ namespace gui IGUIContextMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_CONTEXT_MENU, environment, parent, id, rectangle) {} + //! set behaviour when menus are closed + virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose) = 0; + + //! get current behaviour when the menu will be closed + virtual ECONTEXT_MENU_CLOSE getCloseHandling() const = 0; + //! Get amount of menu items virtual u32 getItemCount() const = 0; @@ -32,13 +53,36 @@ namespace gui set to whatever you want. \param enabled: Specifies if the menu item should be enabled. \param hasSubMenu: Set this to true if there should be a submenu - at this item. You can acess this submenu via getSubMenu(). + at this item. You can access this submenu via getSubMenu(). \param checked: Specifies if the menu item should be initially checked. + \param autoChecking: Specifies if the item should be checked by clicking \return Returns the index of the new item */ virtual u32 addItem(const wchar_t* text, s32 commandId=-1, bool enabled=true, - bool hasSubMenu=false, - bool checked=false - ) = 0; + bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; + + //! Insert a menu item at specified position. + /** \param idx: Position to insert the new element, + should be smaller than itemcount otherwise the item is added to the end. + \param text: Text of menu item. Set this to 0 to create + an separator instead of a real item, which is the same like + calling addSeparator(); + \param commandId: Command id of menu item, a simple id you may + set to whatever you want. + \param enabled: Specifies if the menu item should be enabled. + \param hasSubMenu: Set this to true if there should be a submenu + at this item. You can access this submenu via getSubMenu(). + \param checked: Specifies if the menu item should be initially checked. + \param autoChecking: Specifies if the item should be checked by clicking + \return Returns the index of the new item */ + virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId=-1, bool enabled=true, + bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; + + //! Find an item by it's CommandID + /** + \param commandId: We are looking for the first item which has this commandID + \param idxStartSearch: Start searching from this index. + \return Returns the index of the item when found or otherwise -1. */ + virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch=0) const = 0; //! Adds a separator item to the menu virtual void addSeparator() = 0; @@ -96,6 +140,15 @@ namespace gui \param idx: Zero based index of the menu item \return Returns a pointer to the submenu of an item. */ virtual IGUIContextMenu* getSubMenu(u32 idx) const = 0; + + //! should the element change the checked status on clicking + virtual void setItemAutoChecking(u32 idx, bool autoChecking) = 0; + + //! does the element change the checked status on clicking + virtual bool getItemAutoChecking(u32 idx) const = 0; + + //! When an eventparent is set it receives events instead of the usual parent element + virtual void setEventParent(IGUIElement *parent) = 0; }; } // end namespace gui diff --git a/src/dep/include/irrlicht/IGUIEditBox.h b/src/dep/include/irrlicht/IGUIEditBox.h index 37df5b5..2739866 100644 --- a/src/dep/include/irrlicht/IGUIEditBox.h +++ b/src/dep/include/irrlicht/IGUIEditBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -38,7 +38,7 @@ namespace gui \param color: New color of the text. */ virtual void setOverrideColor(video::SColor color) = 0; - //! Sets if the text should use the overide color or the color in the gui skin. + //! Sets if the text should use the override color or the color in the gui skin. /** \param enable: If set to true, the override color, which can be set with IGUIEditBox::setOverrideColor is used, otherwise the EGDC_BUTTON_TEXT color of the skin. */ @@ -61,7 +61,7 @@ namespace gui virtual void setWordWrap(bool enable) = 0; //! Checks if word wrap is enabled - //! \return true if word wrap is enabled, false otherwise + /** \return true if word wrap is enabled, false otherwise */ virtual bool isWordWrapEnabled() const = 0; //! Enables or disables newlines. @@ -70,15 +70,15 @@ namespace gui virtual void setMultiLine(bool enable) = 0; //! Checks if multi line editing is enabled - //! \return true if mult-line is enabled, false otherwise + /** \return true if multi-line is enabled, false otherwise */ virtual bool isMultiLineEnabled() const = 0; //! Enables or disables automatic scrolling with cursor position - //! \param enable: If set to true, the text will move around with the cursor position + /** \param enable: If set to true, the text will move around with the cursor position */ virtual void setAutoScroll(bool enable) = 0; //! Checks to see if automatic scrolling is enabled - //! \return true if automatic scrolling is enabled, false if not + /** \return true if automatic scrolling is enabled, false if not */ virtual bool isAutoScrollEnabled() const = 0; //! Sets whether the edit box is a password box. Setting this to true will @@ -91,8 +91,8 @@ namespace gui virtual bool isPasswordBox() const = 0; //! Gets the size area of the text in the edit box - //! \return Returns the size in pixels of the text - virtual core::dimension2di getTextDimension() = 0; + /** \return The size in pixels of the text */ + virtual core::dimension2du getTextDimension() = 0; //! Sets the maximum amount of characters which may be entered in the box. /** \param max: Maximum amount of characters. If 0, the character amount is diff --git a/src/dep/include/irrlicht/IGUIElement.h b/src/dep/include/irrlicht/IGUIElement.h index c896106..f951521 100644 --- a/src/dep/include/irrlicht/IGUIElement.h +++ b/src/dep/include/irrlicht/IGUIElement.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,7 +28,7 @@ public: //! Constructor IGUIElement(EGUI_ELEMENT_TYPE type, IGUIEnvironment* environment, IGUIElement* parent, - s32 id, core::rect rectangle) + s32 id, const core::rect& rectangle) : Parent(0), RelativeRect(rectangle), AbsoluteRect(rectangle), AbsoluteClippingRect(rectangle), DesiredRect(rectangle), MaxSize(0,0), MinSize(1,1), IsVisible(true), IsEnabled(true), @@ -42,15 +42,9 @@ public: // if we were given a parent to attach to if (parent) - parent->addChild(this); - - // if we succeeded in becoming a child - if (Parent) { - LastParentRect = Parent->getAbsolutePosition(); - AbsoluteRect += LastParentRect.UpperLeftCorner; - AbsoluteClippingRect = AbsoluteRect; - AbsoluteClippingRect.clipAgainst(Parent->AbsoluteClippingRect); + parent->addChildToEnd(this); + recalculateAbsolutePosition(true); } } @@ -83,7 +77,7 @@ public: //! Sets the relative rectangle of this element. - /** \param r The absolute position to set */ + /** \param r The absolute position to set */ void setRelativePosition(const core::rect& r) { if (Parent) @@ -107,22 +101,22 @@ public: } //! Sets the relative rectangle of this element, maintaining its current width and height - /** \param position The new relative position to set. Width and height will not be changed. */ + /** \param position The new relative position to set. Width and height will not be changed. */ void setRelativePosition(const core::position2di & position) { const core::dimension2di mySize = RelativeRect.getSize(); - const core::rect rectangle(position.X, position.Y, - position.X + mySize.Width, position.Y + mySize.Height); + const core::rect rectangle(position.X, position.Y, + position.X + mySize.Width, position.Y + mySize.Height); setRelativePosition(rectangle); } //! Sets the relative rectangle of this element as a proportion of its parent's area. /** \note This method used to be 'void setRelativePosition(const core::rect& r)' - \param r The rectangle to set, interpreted as a proportion of the parent's area. + \param r The rectangle to set, interpreted as a proportion of the parent's area. Meaningful values are in the range [0...1], unless you intend this element to spill outside its parent. */ - void setRelativePositionProportional(const core::rect& r) + void setRelativePositionProportional(const core::rect& r) { if (!Parent) return; @@ -156,10 +150,11 @@ public: //! Sets whether the element will ignore its parent's clipping rectangle - /** \param noClip If true, the element will not be clipped by its parent's clipping rectangle. */ + /** \param noClip If true, the element will not be clipped by its parent's clipping rectangle. */ void setNotClipped(bool noClip) { NoClip = noClip; + updateAbsolutePosition(); } @@ -173,7 +168,7 @@ public: //! Sets the maximum size allowed for this element /** If set to 0,0, there is no maximum size */ - void setMaxSize(core::dimension2di size) + void setMaxSize(core::dimension2du size) { MaxSize = size; updateAbsolutePosition(); @@ -181,7 +176,7 @@ public: //! Sets the minimum size allowed for this element - void setMinSize(core::dimension2di size) + void setMinSize(core::dimension2du size) { MinSize = size; if (MinSize.Width < 1) @@ -192,6 +187,7 @@ public: } + //! The alignment defines how the borders of this element will be positioned when the parent element is resized. void setAlignment(EGUI_ALIGNMENT left, EGUI_ALIGNMENT right, EGUI_ALIGNMENT top, EGUI_ALIGNMENT bottom) { AlignLeft = left; @@ -220,121 +216,7 @@ public: //! Updates the absolute position. virtual void updateAbsolutePosition() { - core::rect parentAbsolute(0,0,0,0); - core::rect parentAbsoluteClip; - s32 diffx, diffy; - f32 fw=0.f, fh=0.f; - - if (Parent) - { - parentAbsolute = Parent->AbsoluteRect; - - if (NoClip) - { - IGUIElement* p=this; - while (p && p->Parent) - p = p->Parent; - parentAbsoluteClip = p->AbsoluteClippingRect; - } - else - parentAbsoluteClip = Parent->AbsoluteClippingRect; - } - - diffx = parentAbsolute.getWidth() - LastParentRect.getWidth(); - diffy = parentAbsolute.getHeight() - LastParentRect.getHeight(); - - if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE) - fw = (f32)parentAbsolute.getWidth(); - - if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE) - fh = (f32)parentAbsolute.getHeight(); - - switch (AlignLeft) - { - case EGUIA_UPPERLEFT: - break; - case EGUIA_LOWERRIGHT: - DesiredRect.UpperLeftCorner.X += diffx; - break; - case EGUIA_CENTER: - DesiredRect.UpperLeftCorner.X += diffx/2; - break; - case EGUIA_SCALE: - DesiredRect.UpperLeftCorner.X = (s32)(ScaleRect.UpperLeftCorner.X * fw); - break; - } - - switch (AlignRight) - { - case EGUIA_UPPERLEFT: - break; - case EGUIA_LOWERRIGHT: - DesiredRect.LowerRightCorner.X += diffx; - break; - case EGUIA_CENTER: - DesiredRect.LowerRightCorner.X += diffx/2; - break; - case EGUIA_SCALE: - DesiredRect.LowerRightCorner.X = (s32)(ScaleRect.LowerRightCorner.X * fw); - break; - } - - switch (AlignTop) - { - case EGUIA_UPPERLEFT: - break; - case EGUIA_LOWERRIGHT: - DesiredRect.UpperLeftCorner.Y += diffy; - break; - case EGUIA_CENTER: - DesiredRect.UpperLeftCorner.Y += diffy/2; - break; - case EGUIA_SCALE: - DesiredRect.UpperLeftCorner.Y = (s32)(ScaleRect.UpperLeftCorner.Y * fh); - break; - } - - switch (AlignBottom) - { - case EGUIA_UPPERLEFT: - break; - case EGUIA_LOWERRIGHT: - DesiredRect.LowerRightCorner.Y += diffy; - break; - case EGUIA_CENTER: - DesiredRect.LowerRightCorner.Y += diffy/2; - break; - case EGUIA_SCALE: - DesiredRect.LowerRightCorner.Y = (s32)(ScaleRect.LowerRightCorner.Y * fh); - break; - } - - RelativeRect = DesiredRect; - - const s32 w = RelativeRect.getWidth(); - const s32 h = RelativeRect.getHeight(); - - // make sure the desired rectangle is allowed - if (w < MinSize.Width) - RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width; - if (h < MinSize.Height) - RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height; - if (MaxSize.Width && w > MaxSize.Width) - RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width; - if (MaxSize.Height && h > MaxSize.Height) - RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height; - - RelativeRect.repair(); - - AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner; - - if (!Parent) - parentAbsoluteClip = AbsoluteRect; - - AbsoluteClippingRect = AbsoluteRect; - AbsoluteClippingRect.clipAgainst(parentAbsoluteClip); - - LastParentRect = parentAbsolute; + recalculateAbsolutePosition(false); // update all children core::list::Iterator it = Children.begin(); @@ -345,7 +227,18 @@ public: } - //! Returns the child element, which is at the position of the point. + //! Returns the topmost GUI element at the specific position. + /** + This will check this GUI element and all of its descendants, so it + may return this GUI element. To check all GUI elements, call this + function on device->getGUIEnvironment()->getRootGUIElement(). Note + that the root element is the size of the screen, so doing so (with + an on-screen point) will always return the root element if no other + element is above it at that point. + \param point: The point at which to find a GUI element. + \return The topmost GUI element at that point, or 0 if there are + no candidate elements at this point. + */ IGUIElement* getElementFromPoint(const core::position2d& point) { IGUIElement* target = 0; @@ -355,7 +248,8 @@ public: core::list::Iterator it = Children.getLast(); - if (IsVisible) + if (isVisible()) + { while(it != Children.end()) { target = (*it)->getElementFromPoint(point); @@ -364,8 +258,9 @@ public: --it; } + } - if (IsVisible && isPointInside(point)) + if (isVisible() && isPointInside(point)) target = this; return target; @@ -373,26 +268,23 @@ public: //! Returns true if a point is within this element. - //! Elements with a shape other than a rectangle will override this method + /** Elements with a shape other than a rectangle should override this method */ virtual bool isPointInside(const core::position2d& point) const { return AbsoluteClippingRect.isPointInside(point); } + //! Adds a GUI element as new child of this element. virtual void addChild(IGUIElement* child) { + addChildToEnd(child); if (child) { - child->grab(); - child->remove(); // remove from old parent - child->LastParentRect = getAbsolutePosition(); - child->Parent = this; - Children.push_back(child); + child->updateAbsolutePosition(); } } - //! Removes a child. virtual void removeChild(IGUIElement* child) { @@ -419,24 +311,24 @@ public: //! Draws the element and its children. virtual void draw() { - if (!IsVisible) - return; - - core::list::Iterator it = Children.begin(); - for (; it != Children.end(); ++it) - (*it)->draw(); + if ( isVisible() ) + { + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->draw(); + } } //! animate the element and its children. virtual void OnPostRender(u32 timeMs) { - if (!IsVisible) - return; - - core::list::Iterator it = Children.begin(); - for (; it != Children.end(); ++it) - (*it)->OnPostRender( timeMs ); + if ( isVisible() ) + { + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->OnPostRender( timeMs ); + } } @@ -470,19 +362,18 @@ public: } - //! Sets whether this control was created as part of its parent, - //! for example when a scrollbar is part of a listbox. - //! SubElements are not saved to disk when calling guiEnvironment->saveGUI() + //! Sets whether this control was created as part of its parent. + /** For example, it is true when a scrollbar is part of a listbox. + SubElements are not saved to disk when calling guiEnvironment->saveGUI() */ virtual void setSubElement(bool subElement) { IsSubElement = subElement; } - //! If set to true, the focus will visit this element when using - //! the tab key to cycle through elements. - //! If this element is a tab group (see isTabGroup/setTabGroup) then - //! ctrl+tab will be used instead. + //! If set to true, the focus will visit this element when using the tab key to cycle through elements. + /** If this element is a tab group (see isTabGroup/setTabGroup) then + ctrl+tab will be used instead. */ void setTabStop(bool enable) { IsTabStop = enable; @@ -497,9 +388,9 @@ public: } - //! Sets the priority of focus when using the tab key to navigate between a group - //! of elements. See setTabGroup, isTabGroup and getTabGroup for information on tab groups. - //! Elements with a lower number are focused first + //! Sets the priority of focus when using the tab key to navigate between a group of elements. + /** See setTabGroup, isTabGroup and getTabGroup for information on tab groups. + Elements with a lower number are focused first */ void setTabOrder(s32 index) { // negative = autonumber @@ -534,9 +425,9 @@ public: } - //! Sets whether this element is a container for a group of elements which - //! can be navigated using the tab key. For example, windows are tab groups. - //! Groups can be navigated using ctrl+tab, providing isTabStop is true. + //! Sets whether this element is a container for a group of elements which can be navigated using the tab key. + /** For example, windows are tab groups. + Groups can be navigated using ctrl+tab, providing isTabStop is true. */ void setTabGroup(bool isGroup) { IsTabGroup = isGroup; @@ -551,8 +442,7 @@ public: } - //! Returns the container element which holds all elements in this element's - //! tab group. + //! Returns the container element which holds all elements in this element's tab group. IGUIElement* getTabGroup() { IGUIElement *ret=this; @@ -629,7 +519,7 @@ public: //! Brings a child to front - /** \return Returns true if successful, false if not. */ + /** \return True if successful, false if not. */ virtual bool bringToFront(IGUIElement* element) { core::list::Iterator it = Children.begin(); @@ -702,13 +592,13 @@ public: //! searches elements to find the closest next element to tab to - //! \param startOrder: The TabOrder of the current element, -1 if none - //! \param reverse: true if searching for a lower number - //! \param group: true if searching for a higher one - //! \param first: element with the highest/lowest known tab order depending on search direction - //! \param closest: the closest match, depending on tab order and direction - //! \param includeInvisible: includes invisible elements in the search (default=false) - //! \return true if successfully found an element, false to continue searching/fail + /** \param startOrder: The TabOrder of the current element, -1 if none + \param reverse: true if searching for a lower number + \param group: true if searching for a higher one + \param first: element with the highest/lowest known tab order depending on search direction + \param closest: the closest match, depending on tab order and direction + \param includeInvisible: includes invisible elements in the search (default=false) + \return true if successfully found an element, false to continue searching/fail */ bool getNextElement(s32 startOrder, bool reverse, bool group, IGUIElement*& first, IGUIElement*& closest, bool includeInvisible=false) const { @@ -794,6 +684,20 @@ public: return Type; } + //! Returns true if the gui element supports the given type. + /** This is mostly used to check if you can cast a gui element to the class that goes with the type. + Most gui elements will only support their own type, but if you derive your own classes from interfaces + you can overload this function and add a check for the type of the base-class additionally. + This allows for checks comparable to the dynamic_cast of c++ with enabled rtti. + Note that you can't do that by calling BaseClass::hasType(type), but you have to do an explicit + comparison check, because otherwise the base class usually just checks for the membervariable + Type which contains the type of your derived class. + */ + virtual bool hasType(EGUI_ELEMENT_TYPE type) const + { + return type == Type; + } + //! Returns the type name of the gui element. /** This is needed serializing elements. For serializing your own elements, override this function @@ -805,8 +709,8 @@ public: //! Writes attributes of the scene node. - //! Implement this to expose the attributes of your scene node for - //! scripting languages, editors, debuggers or xml serialization purposes. + /** Implement this to expose the attributes of your scene node for + scripting languages, editors, debuggers or xml serialization purposes. */ virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { out->addInt("Id", ID ); @@ -814,7 +718,6 @@ public: out->addRect("Rect", DesiredRect); out->addPosition2d("MinSize", core::position2di(MinSize.Width, MinSize.Height)); out->addPosition2d("MaxSize", core::position2di(MaxSize.Width, MaxSize.Height)); - out->addBool("NoClip", NoClip); out->addEnum("LeftAlign", AlignLeft, GUIAlignmentNames); out->addEnum("RightAlign", AlignRight, GUIAlignmentNames); out->addEnum("TopAlign", AlignTop, GUIAlignmentNames); @@ -824,12 +727,13 @@ public: out->addBool("TabStop", IsTabStop); out->addBool("TabGroup", IsTabGroup); out->addInt("TabOrder", TabOrder); + out->addBool("NoClip", NoClip); } //! Reads attributes of the scene node. - //! Implement this to set the attributes of your scene node for - //! scripting languages, editors, debuggers or xml deserialization purposes. + /** Implement this to set the attributes of your scene node for + scripting languages, editors, debuggers or xml deserialization purposes. */ virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { setID(in->getAttributeAsInt("Id")); @@ -841,18 +745,162 @@ public: TabOrder = in->getAttributeAsInt("TabOrder"); core::position2di p = in->getAttributeAsPosition2d("MaxSize"); - setMaxSize(core::dimension2di(p.X,p.Y)); + setMaxSize(core::dimension2du(p.X,p.Y)); p = in->getAttributeAsPosition2d("MinSize"); - setMinSize(core::dimension2di(p.X,p.Y)); + setMinSize(core::dimension2du(p.X,p.Y)); - setNotClipped(in->getAttributeAsBool("NoClip")); setAlignment((EGUI_ALIGNMENT) in->getAttributeAsEnumeration("LeftAlign", GUIAlignmentNames), (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("RightAlign", GUIAlignmentNames), (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("TopAlign", GUIAlignmentNames), (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("BottomAlign", GUIAlignmentNames)); setRelativePosition(in->getAttributeAsRect("Rect")); + + setNotClipped(in->getAttributeAsBool("NoClip")); + } + +protected: + // not virtual because needed in constructor + void addChildToEnd(IGUIElement* child) + { + if (child) + { + child->grab(); // prevent destruction when removed + child->remove(); // remove from old parent + child->LastParentRect = getAbsolutePosition(); + child->Parent = this; + Children.push_back(child); + } + } + + // not virtual because needed in constructor + void recalculateAbsolutePosition(bool recursive) + { + core::rect parentAbsolute(0,0,0,0); + core::rect parentAbsoluteClip; + f32 fw=0.f, fh=0.f; + + if (Parent) + { + parentAbsolute = Parent->AbsoluteRect; + + if (NoClip) + { + IGUIElement* p=this; + while (p && p->Parent) + p = p->Parent; + parentAbsoluteClip = p->AbsoluteClippingRect; + } + else + parentAbsoluteClip = Parent->AbsoluteClippingRect; + } + + const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth(); + const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight(); + + if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE) + fw = (f32)parentAbsolute.getWidth(); + + if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE) + fh = (f32)parentAbsolute.getHeight(); + + switch (AlignLeft) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.UpperLeftCorner.X += diffx; + break; + case EGUIA_CENTER: + DesiredRect.UpperLeftCorner.X += diffx/2; + break; + case EGUIA_SCALE: + DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw); + break; + } + + switch (AlignRight) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.LowerRightCorner.X += diffx; + break; + case EGUIA_CENTER: + DesiredRect.LowerRightCorner.X += diffx/2; + break; + case EGUIA_SCALE: + DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw); + break; + } + + switch (AlignTop) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.UpperLeftCorner.Y += diffy; + break; + case EGUIA_CENTER: + DesiredRect.UpperLeftCorner.Y += diffy/2; + break; + case EGUIA_SCALE: + DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh); + break; + } + + switch (AlignBottom) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.LowerRightCorner.Y += diffy; + break; + case EGUIA_CENTER: + DesiredRect.LowerRightCorner.Y += diffy/2; + break; + case EGUIA_SCALE: + DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh); + break; + } + + RelativeRect = DesiredRect; + + const s32 w = RelativeRect.getWidth(); + const s32 h = RelativeRect.getHeight(); + + // make sure the desired rectangle is allowed + if (w < (s32)MinSize.Width) + RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width; + if (h < (s32)MinSize.Height) + RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height; + if (MaxSize.Width && w > (s32)MaxSize.Width) + RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width; + if (MaxSize.Height && h > (s32)MaxSize.Height) + RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height; + + RelativeRect.repair(); + + AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner; + + if (!Parent) + parentAbsoluteClip = AbsoluteRect; + + AbsoluteClippingRect = AbsoluteRect; + AbsoluteClippingRect.clipAgainst(parentAbsoluteClip); + + LastParentRect = parentAbsolute; + + if ( recursive ) + { + // update all children + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + { + (*it)->recalculateAbsolutePosition(recursive); + } + } } protected: @@ -883,7 +931,7 @@ protected: core::rect ScaleRect; //! maximum and minimum size of the element - core::dimension2di MaxSize, MinSize; + core::dimension2du MaxSize, MinSize; //! is visible? bool IsVisible; diff --git a/src/dep/include/irrlicht/IGUIElementFactory.h b/src/dep/include/irrlicht/IGUIElementFactory.h index d4d7811..040f929 100644 --- a/src/dep/include/irrlicht/IGUIElementFactory.h +++ b/src/dep/include/irrlicht/IGUIElementFactory.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -15,7 +15,7 @@ namespace gui { class IGUIElement; - //! Interface making it possible to dynamicly create GUI elements + //! Interface making it possible to dynamically create GUI elements /** To be able to add custom elements to Irrlicht and to make it possible for the scene manager to save and load them, simply implement this interface and register it in your gui environment via IGUIEnvironment::registerGUIElementFactory. diff --git a/src/dep/include/irrlicht/IGUIEnvironment.h b/src/dep/include/irrlicht/IGUIEnvironment.h index 2c082f9..f7ecf6b 100644 --- a/src/dep/include/irrlicht/IGUIEnvironment.h +++ b/src/dep/include/irrlicht/IGUIEnvironment.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,6 +11,7 @@ #include "EMessageBoxFlags.h" #include "IEventReceiver.h" #include "IXMLReader.h" +#include "path.h" namespace irr { @@ -41,6 +42,8 @@ class IGUIImage; class IGUIMeshViewer; class IGUICheckBox; class IGUIListBox; +class IGUITreeView; +class IGUIImageList; class IGUIFileOpenDialog; class IGUIColorSelectDialog; class IGUIInOutFader; @@ -62,8 +65,7 @@ class IGUIEnvironment : public virtual IReferenceCounted { public: - //! Draws all gui elements by traversing the GUI environment starting - //! at the root node. + //! Draws all gui elements by traversing the GUI environment starting at the root node. virtual void drawAll() = 0; //! Sets the focus to an element. @@ -75,7 +77,7 @@ public: virtual bool setFocus(IGUIElement* element) = 0; //! Returns the element which holds the focus. - //! \return Pointer to the element with focus. + /** \return Pointer to the element with focus. */ virtual IGUIElement* getFocus() const = 0; //! Removes the focus from an element. @@ -91,15 +93,15 @@ public: virtual bool hasFocus(IGUIElement* element) const = 0; //! Returns the current video driver. - //! \return Pointer to the video driver. + /** \return Pointer to the video driver. */ virtual video::IVideoDriver* getVideoDriver() const = 0; //! Returns the file system. - //! \return Pointer to the file system. + /** \return Pointer to the file system. */ virtual io::IFileSystem* getFileSystem() const = 0; //! returns a pointer to the OS operator - //! \return Pointer to the OS operator. + /** \return Pointer to the OS operator. */ virtual IOSOperator* getOSOperator() const = 0; //! Removes all elements from the environment. @@ -119,7 +121,7 @@ public: virtual void setUserEventReceiver(IEventReceiver* evr) = 0; //! Returns pointer to the current gui skin. - //! \return Pointer to the GUI skin. + /** \return Pointer to the GUI skin. */ virtual IGUISkin* getSkin() const = 0; //! Sets a new GUI Skin @@ -145,13 +147,32 @@ public: See IReferenceCounted::drop() for more information. */ virtual IGUISkin* createSkin(EGUI_SKIN_TYPE type) = 0; + + //! Creates the image list from the given texture. + /** \param texture Texture to split into images + \param imageSize Dimension of each image + \param useAlphaChannel Flag whether alpha channel of the texture should be honored. + \return Pointer to the font. Returns 0 if the font could not be loaded. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIImageList* createImageList( video::ITexture* texture, + core::dimension2d imageSize, bool useAlphaChannel ) = 0; + //! Returns pointer to the font with the specified filename. /** Loads the font if it was not loaded before. \param filename Filename of the Font. \return Pointer to the font. Returns 0 if the font could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IGUIFont* getFont(const c8* filename) = 0; + virtual IGUIFont* getFont(const io::path& filename) = 0; + + //! Adds an externally loaded font to the font list. + /** This method allows to attach an already loaded font to the list of + existing fonts. The font is grabbed if non-null and adding was successful. + \param name Name the font should be stored as. + \param font Pointer to font to add. + \return Pointer to the font stored. This can differ from given parameter if the name previously existed. */ + virtual IGUIFont* addFont(const io::path& name, IGUIFont* font) = 0; //! Returns the default built-in font. /** \return Pointer to the default built-in font. @@ -164,55 +185,55 @@ public: \param filename Filename of the sprite bank's origin. \return Pointer to the sprite bank. Returns 0 if it could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IGUISpriteBank* getSpriteBank(const c8* filename) = 0; + virtual IGUISpriteBank* getSpriteBank(const io::path& filename) = 0; //! Adds an empty sprite bank to the manager /** \param name Name of the new sprite bank. \return Pointer to the sprite bank. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IGUISpriteBank* addEmptySpriteBank(const c8 *name) = 0; + virtual IGUISpriteBank* addEmptySpriteBank(const io::path& name) = 0; //! Returns the root gui element. - /** This is the first gui element, parent of all other - gui elements. You'll never need to use this method, unless you are - creating your own gui elements, trying to add them to the gui elements - without a parent. + /** This is the first gui element, the (direct or indirect) parent of all + other gui elements. It is a valid IGUIElement, with dimensions the same + size as the screen. You should not need to use this method directly, unless + you wish to reparent GUI elements to the top level. \return Pointer to the root element of the GUI. The returned pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIElement* getRootGUIElement() = 0; //! Adds a button element. - /** \param rectangle Position and dimension of the button. + /** \param rectangle Rectangle specifying the borders of the button. \param parent Parent gui element of the button. \param id Id with which the gui element can be identified. \param text Text displayed on the button. \param tooltiptext Text displayed in the tooltip. - \return Pointer to the created button. Returns 0 if an error occured. + \return Pointer to the created button. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIButton* addButton(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, const wchar_t* tooltiptext = 0) = 0; //! Adds an empty window element. - /** \param rectangle Position and dimension of the window. + /** \param rectangle Rectangle specifying the borders of the window. \param modal Defines if the dialog is modal. This means, that all other gui elements which were created before the window cannot be used until it is removed. \param text Text displayed as the window title. \param parent Parent gui element of the window. \param id Id with which the gui element can be identified. - \return Pointer to the created window. Returns 0 if an error occured. + \return Pointer to the created window. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIWindow* addWindow(const core::rect& rectangle, bool modal = false, const wchar_t* text=0, IGUIElement* parent=0, s32 id=-1) = 0; - //! Adds a modal screen. This control stops its parent's members from - //! being able to recieve input until its last child is removed, it - //! then deletes itself. - /** \param parent Parent gui element of the modal. - \return Pointer to the created modal. Returns 0 if an error occured. + //! Adds a modal screen. + /** This control stops its parent's members from being able to receive + input until its last child is removed, it then deletes itself. + \param parent Parent gui element of the modal. + \return Pointer to the created modal. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIElement* addModalScreen(IGUIElement* parent) = 0; @@ -228,20 +249,21 @@ public: to (EMBF_OK | EMBF_CANCEL). \param parent Parent gui element of the message box. \param id Id with which the gui element can be identified. + \param image Optional texture which will be displayed beside the text as an image \return Pointer to the created message box. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0, - bool modal = true, s32 flags = EMBF_OK, IGUIElement* parent=0, s32 id=-1) = 0; + bool modal = true, s32 flags = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0) = 0; //! Adds a scrollbar. /** \param horizontal Specifies if the scroll bar is drawn horizontal or vertical. - \param rectangle Position and dimension of the scroll bar. + \param rectangle Rectangle specifying the borders of the scrollbar. \param parent Parent gui element of the scroll bar. \param id Id to identify the gui element. \return Pointer to the created scrollbar. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; @@ -256,53 +278,67 @@ public: \param id Id to identify the gui element. \param text Title text of the image. \return Pointer to the created image element. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIImage* addImage(video::ITexture* image, core::position2d pos, bool useAlphaChannel=true, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; //! Adds an image element. /** Use IGUIImage::setImage later to set the image to be displayed. - \param rectangle Position and dimension of the image. + \param rectangle Rectangle specifying the borders of the image. \param parent Parent gui element of the image. \param id Id to identify the gui element. \param text Title text of the image. \return Pointer to the created image element. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIImage* addImage(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; //! Adds a checkbox element. /** \param checked Define the initial state of the check box. - \param rectangle Position and dimension of check box. + \param rectangle Rectangle specifying the borders of the check box. \param parent Parent gui element of the check box. \param id Id to identify the gui element. \param text Title text of the check box. \return Pointer to the created check box. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUICheckBox* addCheckBox(bool checked, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; //! Adds a list box element. - /** \param rectangle Position and dimension of list box. + /** \param rectangle Rectangle specifying the borders of the list box. \param parent Parent gui element of the list box. \param id Id to identify the gui element. \param drawBackground Flag whether the background should be drawn. - \return Pointer to the created list box. Returns 0 if an error occured. + \return Pointer to the created list box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIListBox* addListBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) = 0; + //! Adds a tree view element. + /** \param rectangle Position and dimension of list box. + \param parent Parent gui element of the list box. + \param id Id to identify the gui element. + \param drawBackground Flag whether the background should be drawn. + \param scrollBarVertical Flag whether a vertical scrollbar should be used + \param scrollBarHorizontal Flag whether a horizontal scrollbar should be used + \return Pointer to the created list box. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUITreeView* addTreeView(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, bool drawBackground=false, + bool scrollBarVertical = true, bool scrollBarHorizontal = false) = 0; + //! Adds a mesh viewer. Not 100% implemented yet. - /** \param rectangle Position and dimension of mesh viewer. + /** \param rectangle Rectangle specifying the borders of the mesh viewer. \param parent Parent gui element of the mesh viewer. \param id Id to identify the gui element. \param text Title text of the mesh viewer. \return Pointer to the created mesh viewer. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIMeshViewer* addMeshViewer(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; @@ -315,7 +351,7 @@ public: \param parent Parent gui element of the dialog. \param id Id to identify the gui element. \return Pointer to the created file open dialog. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIFileOpenDialog* addFileOpenDialog(const wchar_t* title = 0, bool modal=true, IGUIElement* parent=0, s32 id=-1) = 0; @@ -328,14 +364,14 @@ public: \param parent The parent of the dialog. \param id The ID of the dialog. \return Pointer to the created file open dialog. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIColorSelectDialog* addColorSelectDialog(const wchar_t* title = 0, bool modal=true, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a static text. /** \param text Text to be displayed. Can be altered after creation by SetText(). - \param rectangle Position and dimension of the static text. + \param rectangle Rectangle specifying the borders of the static text \param border Set to true if the static text should have a 3d border. \param wordWrap Enable if the text should wrap into multiple lines. \param parent Parent item of the element, e.g. a window. @@ -343,7 +379,7 @@ public: \param fillBackground Enable if the background shall be filled. Defaults to false. \return Pointer to the created static text. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIStaticText* addStaticText(const wchar_t* text, const core::rect& rectangle, bool border=false, bool wordWrap=true, IGUIElement* parent=0, s32 id=-1, @@ -356,12 +392,12 @@ public: ctrl+X, ctrl+V, ctrl+C, shift+Left, shift+Right, Home, End, and so on. \param text Text to be displayed. Can be altered after creation by setText(). - \param rectangle Position and dimension of the edit box. + \param rectangle Rectangle specifying the borders of the edit box. \param border Set to true if the edit box should have a 3d border. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the edit box directly in the environment. \param id The ID of the element. - \return Pointer to the created edit box. Returns 0 if an error occured. + \return Pointer to the created edit box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect& rectangle, @@ -370,28 +406,29 @@ public: //! Adds a spin box. /** An edit box with up and down buttons \param text Text to be displayed. Can be altered after creation by setText(). - \param rectangle Position and dimension of the spin box. + \param rectangle Rectangle specifying the borders of the spin box. + \param border Set to true if the spin box should have a 3d border. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the spin box directly in the environment. \param id The ID of the element. - \return Pointer to the created spin box. Returns 0 if an error occured. + \return Pointer to the created spin box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, - IGUIElement* parent=0, s32 id=-1) = 0; + bool border=true,IGUIElement* parent=0, s32 id=-1) = 0; //! Adds an element for fading in or out. - /* \param rectangle Rectangle specifying the borders of the element. + /** \param rectangle Rectangle specifying the borders of the fader. If the pointer is NULL, the whole screen is used. \param parent Parent item of the element, e.g. a window. \param id An identifier for the fader. \return Pointer to the created in-out-fader. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIInOutFader* addInOutFader(const core::rect* rectangle=0, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a tab control to the environment. - /** \param rectangle Position and dimension of the tab control. + /** \param rectangle Rectangle specifying the borders of the tab control. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the tab control directly in the environment. \param fillbackground Specifies if the background of the tab control @@ -401,7 +438,7 @@ public: the environment without a window as parent. \param id An identifier for the tab control. \return Pointer to the created tab control element. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITabControl* addTabControl(const core::rect& rectangle, IGUIElement* parent=0, bool fillbackground=false, @@ -411,36 +448,36 @@ public: /** You can use this element to group other elements. This is not used for creating tabs on tab controls, please use IGUITabControl::addTab() for this instead. - \param rectangle Position and dimension of the tab. + \param rectangle Rectangle specifying the borders of the tab. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the tab directly in the environment. \param id An identifier for the tab. \return Pointer to the created tab. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITab* addTab(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a context menu to the environment. - /** \param rectangle Position and dimension of the menu. Note that the - menu is resizing itself based on what items you add. + /** \param rectangle Rectangle specifying the borders of the menu. + Note that the menu is resizing itself based on what items you add. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the menu directly in the environment. \param id An identifier for the menu. \return Pointer to the created context menu. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIContextMenu* addContextMenu(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a menu to the environment. - /* This is like the menu you can find on top of most windows in modern + /** This is like the menu you can find on top of most windows in modern graphical user interfaces. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the menu directly in the environment. \param id An identifier for the menu. \return Pointer to the created menu. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIContextMenu* addMenu(IGUIElement* parent=0, s32 id=-1) = 0; @@ -451,26 +488,34 @@ public: Set it to 0 to place the tool bar directly in the environment. \param id An identifier for the tool bar. \return Pointer to the created tool bar. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIToolBar* addToolBar(IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a combo box to the environment. - /** \param rectangle Position and dimension of the combo box. + /** \param rectangle Rectangle specifying the borders of the combo box. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the combo box directly in the environment. \param id An identifier for the combo box. \return Pointer to the created combo box. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIComboBox* addComboBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a table to the environment - virtual IGUITable* addTable(const core::rect& rectangle, - IGUIElement* parent=0, s32 id=-1, bool drawBackground = false) = 0; + /** \param rectangle Rectangle specifying the borders of the table. + \param parent Parent item of the element, e.g. a window. Set it to 0 + to place the element directly in the environment. + \param id An identifier for the table. + \param drawBackground Flag whether the background should be drawn. + \return Pointer to the created table. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUITable* addTable(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) =0; - //! Returns the default element factory which can create all built in elements + //! Get the default element factory which can create all built-in elements /** \return Pointer to the factory. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ @@ -483,34 +528,45 @@ public: \param factoryToAdd Pointer to new factory. */ virtual void registerGUIElementFactory(IGUIElementFactory* factoryToAdd) = 0; - //! Returns amount of registered gui element factories. - //! \return Amount of registered gui element factories. + //! Get amount of registered gui element factories. + /** \return Amount of registered gui element factories. */ virtual u32 getRegisteredGUIElementFactoryCount() const = 0; - //! Returns a gui element factory by index + //! Get a gui element factory by index + /** \param index Index of the factory. + \return Factory at given index, or 0 if no such factory exists. */ virtual IGUIElementFactory* getGUIElementFactory(u32 index) const = 0; - //! Adds a GUI Element by its name + //! Adds a GUI element by its name + /** Each factory is checked if it can create an element of the given + name. The first match will be created. + \param elementName Name of the element to be created. + \param parent Parent of the new element, if not 0. + \return New GUI element, or 0 if no such element exists. */ virtual IGUIElement* addGUIElement(const c8* elementName, IGUIElement* parent=0) = 0; //! Saves the current gui into a file. - //! \param filename Name of the file. - //! \param start The GUIElement to start with. Root if 0. - virtual bool saveGUI(const c8* filename, IGUIElement* start=0) = 0; + /** \param filename Name of the file. + \param start The GUIElement to start with. Root if 0. + \return True if saving succeeded, else false. */ + virtual bool saveGUI(const io::path& filename, IGUIElement* start=0) = 0; //! Saves the current gui into a file. - //! \param file The file to write to. - //! \param start The GUIElement to start with. Root if 0. + /** \param file The file to write to. + \param start The GUIElement to start with. Root if 0. + \return True if saving succeeded, else false. */ virtual bool saveGUI(io::IWriteFile* file, IGUIElement* start=0) = 0; //! Loads the gui. Note that the current gui is not cleared before. - //! \param filename Name of the file . - //! \param parent Parent for the loaded GUI, root if 0. - virtual bool loadGUI(const c8* filename, IGUIElement* parent=0) = 0; + /** \param filename Name of the file. + \param parent Parent for the loaded GUI, root if 0. + \return True if loading succeeded, else false. */ + virtual bool loadGUI(const io::path& filename, IGUIElement* parent=0) = 0; //! Loads the gui. Note that the current gui is not cleared before. - //! \param file The file to load from. - //! \param parent Parent for the loaded GUI, root if 0. + /** \param file The file to load from. + \param parent Parent for the loaded GUI, root if 0. + \return True if loading succeeded, else false. */ virtual bool loadGUI(io::IReadFile* file, IGUIElement* parent=0) = 0; //! Writes attributes of the gui environment @@ -523,7 +579,7 @@ public: virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* node) =0; //! reads an element - virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* parent) =0; + virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node) =0; }; diff --git a/src/dep/include/irrlicht/IGUIFileOpenDialog.h b/src/dep/include/irrlicht/IGUIFileOpenDialog.h index 11e3025..64a7568 100644 --- a/src/dep/include/irrlicht/IGUIFileOpenDialog.h +++ b/src/dep/include/irrlicht/IGUIFileOpenDialog.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,7 @@ #define __I_GUI_FILE_OPEN_DIALOG_H_INCLUDED__ #include "IGUIElement.h" +#include "path.h" namespace irr { @@ -23,6 +24,9 @@ namespace gui //! Returns the filename of the selected file. Returns NULL, if no file was selected. virtual const wchar_t* getFileName() const = 0; + + //! Returns the directory of the selected file. Returns NULL, if no directory was selected. + virtual const io::path& getDirectoryName() = 0; }; diff --git a/src/dep/include/irrlicht/IGUIFont.h b/src/dep/include/irrlicht/IGUIFont.h index 25cf18b..5dc5323 100644 --- a/src/dep/include/irrlicht/IGUIFont.h +++ b/src/dep/include/irrlicht/IGUIFont.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -8,6 +8,7 @@ #include "IReferenceCounted.h" #include "SColor.h" #include "rect.h" +#include "irrString.h" namespace irr { @@ -21,13 +22,13 @@ enum EGUI_FONT_TYPE EGFT_BITMAP = 0, //! Scalable vector fonts loaded from an XML file. - //! These fonts reside in system memory and use no video memory - //! until they are displayed. These are slower than bitmap fonts - //! but can be easily scaled and rotated. + /** These fonts reside in system memory and use no video memory + until they are displayed. These are slower than bitmap fonts + but can be easily scaled and rotated. */ EGFT_VECTOR, //! A font which uses a the native API provided by the operating system. - //! Currently not used. + /** Currently not used. */ EGFT_OS, //! An external font type provided by the user. @@ -39,22 +40,22 @@ class IGUIFont : public virtual IReferenceCounted { public: - //! Draws an text and clips it to the specified rectangle if wanted. + //! Draws some text and clips it to the specified rectangle if wanted. /** \param text: Text to draw \param position: Rectangle specifying position where to draw the text. \param color: Color of the text - \param hcenter: Specifiies if the text should be centered horizontally into the rectangle. + \param hcenter: Specifies if the text should be centered horizontally into the rectangle. \param vcenter: Specifies if the text should be centered vertically into the rectangle. \param clip: Optional pointer to a rectangle against which the text will be clipped. If the pointer is null, no clipping will be done. */ - virtual void draw(const wchar_t* text, const core::rect& position, + virtual void draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0) = 0; - //! Calculates the dimension of a text. + //! Calculates the width and height of a given string of text. /** \return Returns width and height of the area covered by the text if it would be drawn. */ - virtual core::dimension2d getDimension(const wchar_t* text) const = 0; + virtual core::dimension2d getDimension(const wchar_t* text) const = 0; //! Calculates the index of the character in the text which is on a specific position. /** \param text: Text string. @@ -66,23 +67,34 @@ public: //! Returns the type of this font virtual EGUI_FONT_TYPE getType() const { return EGFT_CUSTOM; } - //! Sets global kerning for the font. + //! Sets global kerning width for the font. virtual void setKerningWidth (s32 kerning) = 0; + + //! Sets global kerning height for the font. virtual void setKerningHeight (s32 kerning) = 0; //! Gets kerning values (distance between letters) for the font. If no parameters are provided, /** the global kerning distance is returned. - \param thisLetter: If this parameter is provided, the left side kerning for this letter is added - to the global kerning value. For example, a space might only be one pixel wide, but it may - be displayed as several pixels. - \param previousLetter: If provided, kerning is calculated for both letters and added to the global - kerning value. For example, in a font which supports kerning pairs a string such as 'Wo' may have - the 'o' tucked neatly under the 'W'. + \param thisLetter: If this parameter is provided, the left side kerning + for this letter is added to the global kerning value. For example, a + space might only be one pixel wide, but it may be displayed as several + pixels. + \param previousLetter: If provided, kerning is calculated for both + letters and added to the global kerning value. For example, in a font + which supports kerning pairs a string such as 'Wo' may have the 'o' + tucked neatly under the 'W'. */ virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const = 0; //! Returns the distance between letters virtual s32 getKerningHeight() const = 0; + + //! Define which characters should not be drawn by the font. + /** For example " " would not draw any space which is usually blank in + most fonts. + \param s String of symbols which are not send down to the videodriver + */ + virtual void setInvisibleCharacters( const wchar_t *s ) = 0; }; } // end namespace gui diff --git a/src/dep/include/irrlicht/IGUIFontBitmap.h b/src/dep/include/irrlicht/IGUIFontBitmap.h index b348788..cd960ed 100644 --- a/src/dep/include/irrlicht/IGUIFontBitmap.h +++ b/src/dep/include/irrlicht/IGUIFontBitmap.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IGUIImage.h b/src/dep/include/irrlicht/IGUIImage.h index 566719e..a27598c 100644 --- a/src/dep/include/irrlicht/IGUIImage.h +++ b/src/dep/include/irrlicht/IGUIImage.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IGUIImageList.h b/src/dep/include/irrlicht/IGUIImageList.h new file mode 100644 index 0000000..f1f50c1 --- /dev/null +++ b/src/dep/include/irrlicht/IGUIImageList.h @@ -0,0 +1,45 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de + +#ifndef __I_GUI_IMAGE_LIST_H_INCLUDED__ +#define __I_GUI_IMAGE_LIST_H_INCLUDED__ + +#include "IGUIElement.h" +#include "rect.h" +#include "irrTypes.h" + +namespace irr +{ +namespace gui +{ + +//! Font interface. +class IGUIImageList : public virtual IReferenceCounted +{ +public: + + //! Destructor + virtual ~IGUIImageList() {}; + + //! Draws an image and clips it to the specified rectangle if wanted + //! \param index: Index of the image + //! \param destPos: Position of the image to draw + //! \param clip: Optional pointer to a rectalgle against which the text will be clipped. + //! If the pointer is null, no clipping will be done. + virtual void draw(s32 index, const core::position2d& destPos, + const core::rect* clip = 0) = 0; + + //! Returns the count of Images in the list. + //! \return Returns the count of Images in the list. + virtual s32 getImageCount() const = 0; + + //! Returns the size of the images in the list. + //! \return Returns the size of the images in the list. + virtual core::dimension2d getImageSize() const = 0; +}; + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/src/dep/include/irrlicht/IGUIInOutFader.h b/src/dep/include/irrlicht/IGUIInOutFader.h index 18357c1..d878f84 100644 --- a/src/dep/include/irrlicht/IGUIInOutFader.h +++ b/src/dep/include/irrlicht/IGUIInOutFader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -36,22 +36,23 @@ namespace gui virtual video::SColor getColor() const = 0; //! Sets the color to fade out to or to fade in from. - //! \param color: Color to where it is faded out od from it is faded in. + /** \param color: Color to where it is faded out od from it is faded in. */ virtual void setColor(video::SColor color) = 0; virtual void setColor(video::SColor source, video::SColor dest) = 0; - //! Starts the fade in process. In the beginning the whole rect is drawn by - //! the set color (black by default) and at the end of the overgiven - //! time the color has faded out. - //! \param time: Time specifing how long it should need to fade in, - //! in milliseconds. + //! Starts the fade in process. + /** In the beginning the whole rect is drawn by the set color + (black by default) and at the end of the overgiven time the + color has faded out. + \param time: Time specifying how long it should need to fade in, + in milliseconds. */ virtual void fadeIn(u32 time) = 0; - //! Starts the fade out process. In the beginning everything is visible, - //! and at the end of the time only the set color (black by the fault) - //! will be drawn. - //! \param time: Time specifing how long it should need to fade out, - //! in milliseconds. + //! Starts the fade out process. + /** In the beginning everything is visible, and at the end of + the time only the set color (black by the fault) will be drawn. + \param time: Time specifying how long it should need to fade out, + in milliseconds. */ virtual void fadeOut(u32 time) = 0; //! Returns if the fade in or out process is done. diff --git a/src/dep/include/irrlicht/IGUIListBox.h b/src/dep/include/irrlicht/IGUIListBox.h index 40adcc9..a003f28 100644 --- a/src/dep/include/irrlicht/IGUIListBox.h +++ b/src/dep/include/irrlicht/IGUIListBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,7 +12,6 @@ namespace irr { namespace gui { - class IGUIFont; class IGUISpriteBank; //! Enumeration for listbox colors @@ -49,10 +48,9 @@ namespace gui virtual u32 addItem(const wchar_t* text) = 0; //! adds an list item with an icon - //! \param text Text of list entry - //! \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon - //! \return - //! returns the id of the new created item + /** \param text Text of list entry + \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon + \return The id of the new created item */ virtual u32 addItem(const wchar_t* text, s32 icon) = 0; //! Removes an item from the list @@ -61,10 +59,11 @@ namespace gui //! Returns the icon of an item virtual s32 getIcon(u32 index) const = 0; - //! Sets the sprite bank which should be used to draw list icons. This font is set to the sprite bank of - //! the built-in-font by default. A sprite can be displayed in front of every list item. - //! An icon is an index within the icon sprite bank. Several default icons are available in the - //! skin through getIcon + //! Sets the sprite bank which should be used to draw list icons. + /** This font is set to the sprite bank of the built-in-font by + default. A sprite can be displayed in front of every list item. + An icon is an index within the icon sprite bank. Several + default icons are available in the skin through getIcon. */ virtual void setSpriteBank(IGUISpriteBank* bank) = 0; //! clears the list, deletes all items in the listbox @@ -76,8 +75,10 @@ namespace gui //! sets the selected item. Set this to -1 if no item should be selected virtual void setSelected(s32 index) = 0; - //! set whether the listbox should scroll to show a newly selected item - //! or a new item as it is added to the list. + //! sets the selected item. Set this to 0 if no item should be selected + virtual void setSelected(const wchar_t *item) = 0; + + //! set whether the listbox should scroll to newly selected items virtual void setAutoScrollEnabled(bool scroll) = 0; //! returns true if automatic scrolling is enabled, false if not. @@ -108,11 +109,17 @@ namespace gui virtual void setItem(u32 index, const wchar_t* text, s32 icon) = 0; //! Insert the item at the given index - //! Return the index on success or -1 on failure. + /** \return The index on success or -1 on failure. */ virtual s32 insertItem(u32 index, const wchar_t* text, s32 icon) = 0; //! Swap the items at the given indices virtual void swapItems(u32 index1, u32 index2) = 0; + + //! set global itemHeight + virtual void setItemHeight( s32 height ) = 0; + + //! Sets whether to draw the background + virtual void setDrawBackground(bool draw) = 0; }; diff --git a/src/dep/include/irrlicht/IGUIMeshViewer.h b/src/dep/include/irrlicht/IGUIMeshViewer.h index a1dd39b..fdff182 100644 --- a/src/dep/include/irrlicht/IGUIMeshViewer.h +++ b/src/dep/include/irrlicht/IGUIMeshViewer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IGUIScrollBar.h b/src/dep/include/irrlicht/IGUIScrollBar.h index cbcb35c..edbd58b 100644 --- a/src/dep/include/irrlicht/IGUIScrollBar.h +++ b/src/dep/include/irrlicht/IGUIScrollBar.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -21,24 +21,30 @@ namespace gui IGUIScrollBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_SCROLL_BAR, environment, parent, id, rectangle) {} + //! sets the maximum value of the scrollbar. + virtual void setMax(s32 max) = 0; //! gets the maximum value of the scrollbar. virtual s32 getMax() const = 0; - //! sets the maximum value of the scrollbar. - virtual void setMax(s32 max) = 0; + //! sets the minimum value of the scrollbar. + virtual void setMin(s32 min) = 0; + //! gets the minimum value of the scrollbar. + virtual s32 getMin() const = 0; //! gets the small step value virtual s32 getSmallStep() const = 0; - //! Sets the small step, the amount that the value changes by when clicking - //! on the buttons or using the cursor keys. + //! Sets the small step + /** That is the amount that the value changes by when clicking + on the buttons or using the cursor keys. */ virtual void setSmallStep(s32 step) = 0; //! gets the large step value virtual s32 getLargeStep() const = 0; - //! Sets the large step, the amount that the value changes by when clicking - //! in the tray, or using the page up and page down keys. + //! Sets the large step + /** That is the amount that the value changes by when clicking + in the tray, or using the page up and page down keys. */ virtual void setLargeStep(s32 step) = 0; //! gets the current position of the scrollbar diff --git a/src/dep/include/irrlicht/IGUISkin.h b/src/dep/include/irrlicht/IGUISkin.h index 3b86b4d..c49d326 100644 --- a/src/dep/include/irrlicht/IGUISkin.h +++ b/src/dep/include/irrlicht/IGUISkin.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -37,11 +37,14 @@ namespace gui EGST_BURNING_SKIN, //! An unknown skin, not serializable at present - EGST_UNKNOWN + EGST_UNKNOWN, + + //! this value is not used, it only specifies the number of skin types + EGST_COUNT }; //! Names for gui element types - const c8* const GUISkinTypeNames[] = + const c8* const GUISkinTypeNames[EGST_COUNT+1] = { "windowsClassic", "windowsMetallic", @@ -102,7 +105,7 @@ namespace gui }; //! Names for default skin colors - const c8* const GUISkinColorNames[] = + const c8* const GUISkinColorNames[EGDC_COUNT+1] = { "3DDarkShadow", "3DShadow", @@ -139,9 +142,9 @@ namespace gui EGDS_WINDOW_BUTTON_WIDTH, //! width of a checkbox check EGDS_CHECK_BOX_WIDTH, - //! width of a messagebox + //! deprecated EGDS_MESSAGE_BOX_WIDTH, - //! height of a messagebox + //! deprecated EGDS_MESSAGE_BOX_HEIGHT, //! width of a default button EGDS_BUTTON_WIDTH, @@ -151,6 +154,23 @@ namespace gui EGDS_TEXT_DISTANCE_X, //! distance for text from background EGDS_TEXT_DISTANCE_Y, + //! distance for text in the title bar, from the left of the window rect + EGDS_TITLEBARTEXT_DISTANCE_X, + //! distance for text in the title bar, from the top of the window rect + EGDS_TITLEBARTEXT_DISTANCE_Y, + //! free space in a messagebox between borders and contents on all sides + EGDS_MESSAGE_BOX_GAP_SPACE, + //! minimal space to reserve for messagebox text-width + EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH, + //! maximal space to reserve for messagebox text-width + EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH, + //! deprecated - this was a typo. Should be removed for 1.8 + EGDS_MESSAGE_BOX_MAX_TEST_WIDTH = EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH, + //! minimal space to reserve for messagebox text-height + EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT, + //! maximal space to reserve for messagebox text-height + EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT, + //! this value is not used, it only specifies the amount of default sizes //! available. EGDS_COUNT @@ -158,7 +178,7 @@ namespace gui //! Names for default skin sizes - const c8* const GUISkinSizeNames[] = + const c8* const GUISkinSizeNames[EGDS_COUNT+1] = { "ScrollBarSize", "MenuHeight", @@ -170,7 +190,14 @@ namespace gui "ButtonHeight", "TextDistanceX", "TextDistanceY", - 0, + "TitleBarTextX", + "TitleBarTextY", + "MessageBoxGapSpace", + "MessageBoxMinTextWidth", + "MessageBoxMaxTextWidth", + "MessageBoxMinTextHeight", + "MessageBoxMaxTextHeight", + 0 }; @@ -198,7 +225,7 @@ namespace gui }; //! Names for default skin sizes - const c8* const GUISkinTextNames[] = + const c8* const GUISkinTextNames[EGDT_COUNT+1] = { "MessageBoxOkay", "MessageBoxCancel", @@ -208,7 +235,7 @@ namespace gui "WindowButtonMaximize", "WindowButtonMinimize", "WindowButtonRestore", - 0, + 0 }; //! Customizable symbols for GUI @@ -265,7 +292,7 @@ namespace gui EGDI_COUNT }; - const c8* const GUISkinIconNames[] = + const c8* const GUISkinIconNames[EGDI_COUNT+1] = { "windowMaximize", "windowRestore", @@ -311,7 +338,7 @@ namespace gui EGDF_COUNT }; - const c8* const GUISkinFontNames[] = + const c8* const GUISkinFontNames[EGDF_COUNT+1] = { "defaultFont", "buttonFont", @@ -423,11 +450,16 @@ namespace gui \param drawTitleBar: True to enable title drawing. \param rect: Defining area where to draw. \param clip: Clip area. - \return Returns rect where it would be good to draw title bar text. */ + \param checkClientArea: When set to non-null the function will not draw anything, + but will instead return the clientArea which can be used for drawing by the calling window. + That is the area without borders and without titlebar. + \return Returns rect where it would be good to draw title bar text. This will + work even when checkClientArea is set to a non-null value.*/ virtual core::rect draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& rect, - const core::rect* clip=0) = 0; + const core::rect* clip=0, + core::rect* checkClientArea=0) = 0; //! draws a standard 3d menu pane /** Used for drawing for menus and context menus. @@ -460,7 +492,8 @@ namespace gui implementations to find out how to draw the part exactly. \param active: Specifies if the tab is currently active. \param rect: Defining area where to draw. - \param clip: Clip area. */ + \param clip: Clip area. + \param alignment Alignment of GUI element. */ virtual void draw3DTabButton(IGUIElement* element, bool active, const core::rect& rect, const core::rect* clip=0, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT) = 0; @@ -471,7 +504,9 @@ namespace gui \param border: Specifies if the border should be drawn. \param background: Specifies if the background should be drawn. \param rect: Defining area where to draw. - \param clip: Clip area. */ + \param clip: Clip area. + \param tabHeight Height of tab. + \param alignment Alignment of GUI element. */ 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; @@ -511,6 +546,3 @@ namespace gui #endif - - - diff --git a/src/dep/include/irrlicht/IGUISpinBox.h b/src/dep/include/irrlicht/IGUISpinBox.h index f8dafbe..b93335e 100644 --- a/src/dep/include/irrlicht/IGUISpinBox.h +++ b/src/dep/include/irrlicht/IGUISpinBox.h @@ -1,65 +1,65 @@ -// Copyright (C) 2006-2008 Michael Zeilfelder -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __I_GUI_SPIN_BOX_H_INCLUDED__ -#define __I_GUI_SPIN_BOX_H_INCLUDED__ - -#include "IGUIElement.h" - -namespace irr -{ -namespace gui -{ - class IGUIEditBox; - - //! Single line edit box + spin buttons - class IGUISpinBox : public IGUIElement - { - public: - - //! constructor - IGUISpinBox(IGUIEnvironment* environment, IGUIElement* parent, - s32 id, core::rect rectangle) - : IGUIElement(EGUIET_SPIN_BOX, environment, parent, id, rectangle) {} - - //! Access the edit box used in the spin control - virtual IGUIEditBox* getEditBox() const = 0; - - //! set the current value of the spinbox - /** \param val: value to be set in the spinbox */ - virtual void setValue(f32 val) = 0; - - //! Get the current value of the spinbox - virtual f32 getValue() const = 0; - - //! set the range of values which can be used in the spinbox - /** \param min: minimum value - \param max: maximum value */ - virtual void setRange(f32 min, f32 max) = 0; - - //! get the minimum value which can be used in the spinbox - virtual f32 getMin() const = 0; - - //! get the maximum value which can be used in the spinbox - virtual f32 getMax() const = 0; - - //! Step size by which values are changed when pressing the spinbuttons - /** The step size also determines the number of decimal places to display - \param step: stepsize used for value changes when pressing spinbuttons */ - virtual void setStepSize(f32 step=1.f) = 0; - - //! Sets the number of decimal places to display. - /** \param places: The number of decimal places to display, use -1 to reset */ - virtual void setDecimalPlaces(s32 places) = 0; - - //! get the current step size - virtual f32 getStepSize() const = 0; - }; - - -} // end namespace gui -} // end namespace irr - -#endif // __I_GUI_SPIN_BOX_H_INCLUDED__ - +// Copyright (C) 2006-2010 Michael Zeilfelder +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_SPIN_BOX_H_INCLUDED__ +#define __I_GUI_SPIN_BOX_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ +namespace gui +{ + class IGUIEditBox; + + //! Single line edit box + spin buttons + class IGUISpinBox : public IGUIElement + { + public: + + //! constructor + IGUISpinBox(IGUIEnvironment* environment, IGUIElement* parent, + s32 id, core::rect rectangle) + : IGUIElement(EGUIET_SPIN_BOX, environment, parent, id, rectangle) {} + + //! Access the edit box used in the spin control + virtual IGUIEditBox* getEditBox() const = 0; + + //! set the current value of the spinbox + /** \param val: value to be set in the spinbox */ + virtual void setValue(f32 val) = 0; + + //! Get the current value of the spinbox + virtual f32 getValue() const = 0; + + //! set the range of values which can be used in the spinbox + /** \param min: minimum value + \param max: maximum value */ + virtual void setRange(f32 min, f32 max) = 0; + + //! get the minimum value which can be used in the spinbox + virtual f32 getMin() const = 0; + + //! get the maximum value which can be used in the spinbox + virtual f32 getMax() const = 0; + + //! Step size by which values are changed when pressing the spinbuttons + /** The step size also determines the number of decimal places to display + \param step: stepsize used for value changes when pressing spinbuttons */ + virtual void setStepSize(f32 step=1.f) = 0; + + //! Sets the number of decimal places to display. + /** \param places: The number of decimal places to display, use -1 to reset */ + virtual void setDecimalPlaces(s32 places) = 0; + + //! get the current step size + virtual f32 getStepSize() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif // __I_GUI_SPIN_BOX_H_INCLUDED__ + diff --git a/src/dep/include/irrlicht/IGUISpriteBank.h b/src/dep/include/irrlicht/IGUISpriteBank.h index df46002..431c07c 100644 --- a/src/dep/include/irrlicht/IGUISpriteBank.h +++ b/src/dep/include/irrlicht/IGUISpriteBank.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -39,6 +39,9 @@ struct SGUISprite //! Sprite bank interface. +/** See http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=25742&highlight=spritebank +* for more information how to use the spritebank. +*/ class IGUISpriteBank : public virtual IReferenceCounted { public: @@ -61,12 +64,27 @@ public: //! Changes one of the textures in the sprite bank virtual void setTexture(u32 index, video::ITexture* texture) = 0; + //! Add the texture and use it for a single non-animated sprite. + //! The texture and the corresponding rectangle and sprite will all be added to the end of each array. + //! returns the index of the sprite or -1 on failure + virtual s32 addTextureAsSprite(video::ITexture* texture) = 0; + + //! clears sprites, rectangles and textures + virtual void clear() = 0; + //! Draws a sprite in 2d with position and color virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip=0, const video::SColor& color= video::SColor(255,255,255,255), u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false) = 0; + + //! Draws a sprite batch in 2d using an array of positions and a color + virtual void draw2DSpriteBatch(const core::array& indices, const core::array& pos, + const core::rect* clip=0, + const video::SColor& color= video::SColor(255,255,255,255), + u32 starttime=0, u32 currenttime=0, + bool loop=true, bool center=false) = 0; }; diff --git a/src/dep/include/irrlicht/IGUIStaticText.h b/src/dep/include/irrlicht/IGUIStaticText.h index b207b0f..a7a8a1d 100644 --- a/src/dep/include/irrlicht/IGUIStaticText.h +++ b/src/dep/include/irrlicht/IGUIStaticText.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -29,7 +29,7 @@ namespace gui virtual void setOverrideFont(IGUIFont* font=0) = 0; //! Gets the override font (if any) - //! \return The override font (may be 0) + /** \return The override font (may be 0) */ virtual IGUIFont* getOverrideFont(void) const = 0; //! Sets another color for the text. @@ -43,7 +43,7 @@ namespace gui virtual void setOverrideColor(video::SColor color) = 0; //! Gets the override color - //! \return: The override color + /** \return: The override color */ virtual video::SColor const& getOverrideColor(void) const = 0; //! Sets if the static text should use the overide color or the color in the gui skin. @@ -53,7 +53,7 @@ namespace gui virtual void enableOverrideColor(bool enable) = 0; //! Checks if an override color is enabled - //! \return true if the override color is enabled, false otherwise + /** \return true if the override color is enabled, false otherwise */ virtual bool isOverrideColorEnabled(void) const = 0; //! Sets another color for the background. @@ -78,7 +78,7 @@ namespace gui virtual void setWordWrap(bool enable) = 0; //! Checks if word wrap is enabled - //! \return true if word wrap is enabled, false otherwise + /** \return true if word wrap is enabled, false otherwise */ virtual bool isWordWrapEnabled(void) const = 0; //! Returns the height of the text in pixels when it is drawn. diff --git a/src/dep/include/irrlicht/IGUITabControl.h b/src/dep/include/irrlicht/IGUITabControl.h index 3725172..b51a148 100644 --- a/src/dep/include/irrlicht/IGUITabControl.h +++ b/src/dep/include/irrlicht/IGUITabControl.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -13,7 +13,8 @@ namespace irr { namespace gui { - //! A tab, onto which other gui elements could be added. + //! A tab-page, onto which other gui elements could be added. + /** IGUITab refers to the page itself, not to the tab in the tabbar of an IGUITabControl. */ class IGUITab : public IGUIElement { public: @@ -86,8 +87,14 @@ namespace gui /** return Returns the height of the tabs */ virtual s32 getTabHeight() const = 0; + //! set the maximal width of a tab. Per default width is 0 which means "no width restriction". + virtual void setTabMaxWidth(s32 width ) = 0; + + //! get the maximal width of a tab + virtual s32 getTabMaxWidth() const = 0; + //! Set the alignment of the tabs - //! Use EGUIA_UPPERLEFT or EGUIA_LOWERRIGHT + /** Use EGUIA_UPPERLEFT or EGUIA_LOWERRIGHT */ virtual void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment ) = 0; //! Get the alignment of the tabs @@ -108,7 +115,3 @@ namespace gui #endif - - - - diff --git a/src/dep/include/irrlicht/IGUITable.h b/src/dep/include/irrlicht/IGUITable.h index 86f6f70..657288b 100644 --- a/src/dep/include/irrlicht/IGUITable.h +++ b/src/dep/include/irrlicht/IGUITable.h @@ -1,4 +1,4 @@ -// Copyright (C) 2003-2008 Nikolaus Gebhardt +// Copyright (C) 2003-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -21,7 +21,7 @@ namespace gui //! Do not use ordering EGCO_NONE, - //! Send a EGET_TABLE_HEADER_CHANGED message when a column header is clicked. + //! Send a EGET_TABLE_HEADER_CHANGED message when a column header is clicked. EGCO_CUSTOM, //! Sort it ascending by it's ascii value like: a,b,c,... @@ -48,7 +48,7 @@ namespace gui 0, }; - enum EGUI_ORDERING_MODE + enum EGUI_ORDERING_MODE { //! No element ordering EGOM_NONE, @@ -66,6 +66,7 @@ namespace gui const c8* const GUIOrderingModeNames[] = { + "none", "ascending", "descending", 0 @@ -79,8 +80,6 @@ namespace gui EGTDF_COUNT }; - class IGUIFont; - //! Default list box GUI element. class IGUITable : public IGUIElement { @@ -90,7 +89,7 @@ namespace gui : IGUIElement(EGUIET_TABLE, environment, parent, id, rectangle) {} //! Adds a column - //! If columnIndex is outside the current range, do push new colum at the end + /** If columnIndex is outside the current range, do push new colum at the end */ virtual void addColumn(const wchar_t* caption, s32 columnIndex=-1) = 0; //! remove a column from the table @@ -101,8 +100,8 @@ namespace gui //! Makes a column active. This will trigger an ordering process. /** \param idx: The id of the column to make active. - //! \param doOrder: Do also the ordering which depending on mode for active column - \return Returns true if successful. */ + \param doOrder: Do also the ordering which depending on mode for active column + \return True if successful. */ virtual bool setActiveColumn(s32 idx, bool doOrder=false) = 0; //! Returns which header is currently active @@ -113,32 +112,36 @@ namespace gui //! Set the width of a column virtual void setColumnWidth(u32 columnIndex, u32 width) = 0; - + //! columns can be resized by drag 'n drop virtual void setResizableColumns(bool resizable) = 0; - + //! can columns be resized by dran 'n drop? virtual bool hasResizableColumns() const = 0; - //! This tells the table control which ordering mode should be used when - //! a column header is clicked. - /** \param columnIndex: The index of the column header. - \param state: If true, a EGET_TABLE_HEADER_CHANGED message will be sent and you can order the table data as you whish.*/ - //! \param mode: One of the modes defined in EGUI_COLUMN_ORDERING + //! This tells the table control which ordering mode should be used when a column header is clicked. + /** \param columnIndex The index of the column header. + \param mode: One of the modes defined in EGUI_COLUMN_ORDERING */ virtual void setColumnOrdering(u32 columnIndex, EGUI_COLUMN_ORDERING mode) = 0; //! Returns which row is currently selected virtual s32 getSelected() const = 0; - //! Returns amount of rows in the tabcontrol + //! set wich row is currently selected + virtual void setSelected( s32 index ) = 0; + + //! Get amount of rows in the tabcontrol virtual s32 getRowCount() const = 0; //! adds a row to the table - /** \param rowIndex: zero based index of rows. The row will be inserted at this - position, if a row already exist there, it will be placed after it. If the row - is larger than the actual number of row by more than one, it won't be created. - Note that if you create a row that's not at the end, there might be performance issues*/ - virtual void addRow(u32 rowIndex) = 0; + /** \param rowIndex Zero based index of rows. The row will be + inserted at this position, if a row already exist there, it + will be placed after it. If the row is larger than the actual + number of row by more than one, it won't be created. Note that + if you create a row that's not at the end, there might be + performance issues. + \return index of inserted row. */ + virtual u32 addRow(u32 rowIndex) = 0; //! Remove a row from the table virtual void removeRow(u32 rowIndex) = 0; @@ -146,21 +149,23 @@ namespace gui //! clears the table rows, but keeps the columns intact virtual void clearRows() = 0; - //! Swap two row positions. This is useful for a custom ordering algo. + //! Swap two row positions. virtual void swapRows(u32 rowIndexA, u32 rowIndexB) = 0; - //! This tells the table to start ordering all the rows. You need to explicitly - //! tell the table to re order the rows when a new row is added or the cells data is - //! changed. This makes the system more flexible and doesn't make you pay the cost of - //! ordering when adding a lot of rows. - //! \param columnIndex: When set to -1 the active column is used. + //! This tells the table to start ordering all the rows. + /** You need to explicitly tell the table to re order the rows + when a new row is added or the cells data is changed. This + makes the system more flexible and doesn't make you pay the + cost of ordering when adding a lot of rows. + \param columnIndex: When set to -1 the active column is used. + \param mode Ordering mode of the rows. */ virtual void orderRows(s32 columnIndex=-1, EGUI_ORDERING_MODE mode=EGOM_NONE) = 0; //! Set the text of a cell - virtual void setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text) = 0; + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text) = 0; //! Set the text of a cell, and set a color of this cell. - virtual void setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text, video::SColor color) = 0; + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color) = 0; //! Set the data of a cell virtual void setCellData(u32 rowIndex, u32 columnIndex, void *data) = 0; diff --git a/src/dep/include/irrlicht/IGUIToolbar.h b/src/dep/include/irrlicht/IGUIToolbar.h index f70fb28..f95bdad 100644 --- a/src/dep/include/irrlicht/IGUIToolbar.h +++ b/src/dep/include/irrlicht/IGUIToolbar.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IGUITreeView.h b/src/dep/include/irrlicht/IGUITreeView.h new file mode 100644 index 0000000..931d354 --- /dev/null +++ b/src/dep/include/irrlicht/IGUITreeView.h @@ -0,0 +1,255 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de + +#ifndef __I_GUI_TREE_VIEW_H_INCLUDED__ +#define __I_GUI_TREE_VIEW_H_INCLUDED__ + +#include "IGUIElement.h" +#include "IGUIImageList.h" +#include "irrTypes.h" + +namespace irr +{ +namespace gui +{ + class IGUIFont; + class IGUITreeView; + + + //! Node for gui tree view + class IGUITreeViewNode : public IReferenceCounted + { + public: + //! returns the owner (tree view) of this node + virtual IGUITreeView* getOwner() const = 0; + + //! Returns the parent node of this node. + /** For the root node this will return 0. */ + virtual IGUITreeViewNode* getParent() const = 0; + + //! returns the text of the node + virtual const wchar_t* getText() const = 0; + + //! sets the text of the node + virtual void setText( const wchar_t* text ) = 0; + + //! returns the icon text of the node + virtual const wchar_t* getIcon() const = 0; + + //! sets the icon text of the node + virtual void setIcon( const wchar_t* icon ) = 0; + + //! returns the image index of the node + virtual u32 getImageIndex() const = 0; + + //! sets the image index of the node + virtual void setImageIndex( u32 imageIndex ) = 0; + + //! returns the image index of the node + virtual u32 getSelectedImageIndex() const = 0; + + //! sets the image index of the node + virtual void setSelectedImageIndex( u32 imageIndex ) = 0; + + //! returns the user data (void*) of this node + virtual void* getData() const = 0; + + //! sets the user data (void*) of this node + virtual void setData( void* data ) = 0; + + //! returns the user data2 (IReferenceCounted) of this node + virtual IReferenceCounted* getData2() const = 0; + + //! sets the user data2 (IReferenceCounted) of this node + virtual void setData2( IReferenceCounted* data ) = 0; + + //! returns the child item count + virtual u32 getChildCount() const = 0; + + //! removes all childs (recursive) from this node + virtual void clearChilds() = 0; + + //! returns true if this node has child nodes + virtual bool hasChilds() const = 0; + + //! Adds a new node behind the last child node. + /** \param text text of the new node + \param icon icon text of the new node + \param imageIndex index of the image for the new node (-1 = none) + \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + \param data user data (void*) of the new node + \param data2 user data2 (IReferenceCounted*) of the new node + \return The new node + */ + virtual IGUITreeViewNode* addChildBack( + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0) =0; + + //! Adds a new node before the first child node. + /** \param text text of the new node + \param icon icon text of the new node + \param imageIndex index of the image for the new node (-1 = none) + \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + \param data user data (void*) of the new node + \param data2 user data2 (IReferenceCounted*) of the new node + \return The new node + */ + virtual IGUITreeViewNode* addChildFront( + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0 ) =0; + + //! Adds a new node behind the other node. + /** The other node has also te be a child node from this node. + \param other Node to insert after + \param text text of the new node + \param icon icon text of the new node + \param imageIndex index of the image for the new node (-1 = none) + \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + \param data user data (void*) of the new node + \param data2 user data2 (IReferenceCounted*) of the new node + \return The new node or 0 if other is no child node from this + */ + virtual IGUITreeViewNode* insertChildAfter( + IGUITreeViewNode* other, + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0) =0; + + //! Adds a new node before the other node. + /** The other node has also te be a child node from this node. + \param other Node to insert before + \param text text of the new node + \param icon icon text of the new node + \param imageIndex index of the image for the new node (-1 = none) + \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + \param data user data (void*) of the new node + \param data2 user data2 (IReferenceCounted*) of the new node + \return The new node or 0 if other is no child node from this + */ + virtual IGUITreeViewNode* insertChildBefore( + IGUITreeViewNode* other, + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0) = 0; + + //! Return the first child node from this node. + /** \return The first child node or 0 if this node has no childs. */ + virtual IGUITreeViewNode* getFirstChild() const = 0; + + //! Return the last child node from this node. + /** \return The last child node or 0 if this node has no childs. */ + virtual IGUITreeViewNode* getLastChild() const = 0; + + //! Returns the previous sibling node from this node. + /** \return The previous sibling node from this node or 0 if this is + the first node from the parent node. + */ + virtual IGUITreeViewNode* getPrevSibling() const = 0; + + //! Returns the next sibling node from this node. + /** \return The next sibling node from this node or 0 if this is + the last node from the parent node. + */ + virtual IGUITreeViewNode* getNextSibling() const = 0; + + //! Returns the next visible (expanded, may be out of scrolling) node from this node. + /** \return The next visible node from this node or 0 if this is + the last visible node. */ + virtual IGUITreeViewNode* getNextVisible() const = 0; + + //! Deletes a child node. + /** \return Returns true if the node was found as a child and is deleted. */ + virtual bool deleteChild( IGUITreeViewNode* child ) = 0; + + //! Moves a child node one position up. + /** \return True if the node was found as achild node and was not already the first child. */ + virtual bool moveChildUp( IGUITreeViewNode* child ) = 0; + + //! Moves a child node one position down. + /** \return True if the node was found as achild node and was not already the last child. */ + virtual bool moveChildDown( IGUITreeViewNode* child ) = 0; + + //! Returns true if the node is expanded (childs are visible). + virtual bool getExpanded() const = 0; + + //! Sets if the node is expanded. + virtual void setExpanded( bool expanded ) = 0; + + //! Returns true if the node is currently selected. + virtual bool getSelected() const = 0; + + //! Sets this node as selected. + virtual void setSelected( bool selected ) = 0; + + //! Returns true if this node is the root node. + virtual bool isRoot() const = 0; + + //! Returns the level of this node. + /** The root node has level 0. Direct childs of the root has level 1 ... */ + virtual s32 getLevel() const = 0; + + //! Returns true if this node is visible (all parents are expanded). + virtual bool isVisible() const = 0; + }; + + + //! Default tree view GUI element. + /** Displays a windows like tree buttons to expand/collaps the child + nodes of an node and optional tree lines. Each node consits of an + text, an icon text and a void pointer for user data. */ + class IGUITreeView : public IGUIElement + { + public: + //! constructor + IGUITreeView(IGUIEnvironment* environment, IGUIElement* parent, + s32 id, core::rect rectangle) + : IGUIElement( EGUIET_TREE_VIEW, environment, parent, id, rectangle ) {} + + //! returns the root node (not visible) from the tree. + virtual IGUITreeViewNode* getRoot() const = 0; + + //! returns the selected node of the tree or 0 if none is selected + virtual IGUITreeViewNode* getSelected() const = 0; + + //! returns true if the tree lines are visible + virtual bool getLinesVisible() const = 0; + + //! sets if the tree lines are visible + /** \param visible true for visible, false for invisible */ + virtual void setLinesVisible( bool visible ) = 0; + + //! Sets the font which should be used as icon font. + /** This font is set to the Irrlicht engine built-in-font by + default. Icons can be displayed in front of every list item. + An icon is a string, displayed with the icon font. When using + the build-in-font of the Irrlicht engine as icon font, the icon + strings defined in GUIIcons.h can be used. + */ + virtual void setIconFont( IGUIFont* font ) = 0; + + //! Sets the image list which should be used for the image and selected image of every node. + /** The default is 0 (no images). */ + virtual void setImageList( IGUIImageList* imageList ) = 0; + + //! Returns the image list which is used for the nodes. + virtual IGUIImageList* getImageList() const = 0; + + //! Sets if the image is left of the icon. Default is true. + virtual void setImageLeftOfIcon( bool bLeftOf ) = 0; + + //! Returns if the Image is left of the icon. Default is true. + virtual bool getImageLeftOfIcon() const = 0; + + //! Returns the node which is associated to the last event. + /** This pointer is only valid inside the OnEvent call! */ + virtual IGUITreeViewNode* getLastEventNode() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/src/dep/include/irrlicht/IGUIWindow.h b/src/dep/include/irrlicht/IGUIWindow.h index 761cbef..dc35e6b 100644 --- a/src/dep/include/irrlicht/IGUIWindow.h +++ b/src/dep/include/irrlicht/IGUIWindow.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,13 +24,43 @@ namespace gui : IGUIElement(EGUIET_WINDOW, environment, parent, id, rectangle) {} //! Returns pointer to the close button + /** You can hide the button by calling setVisible(false) on the result. */ virtual IGUIButton* getCloseButton() const = 0; //! Returns pointer to the minimize button + /** You can hide the button by calling setVisible(false) on the result. */ virtual IGUIButton* getMinimizeButton() const = 0; //! Returns pointer to the maximize button + /** You can hide the button by calling setVisible(false) on the result. */ virtual IGUIButton* getMaximizeButton() const = 0; + + //! Returns true if the window can be dragged with the mouse, false if not + virtual bool isDraggable() const = 0; + + //! Sets whether the window can be dragged by the mouse + virtual void setDraggable(bool draggable) = 0; + + //! Set if the window background will be drawn + virtual void setDrawBackground(bool draw) = 0; + + //! Get if the window background will be drawn + virtual bool getDrawBackground() const = 0; + + //! Set if the window titlebar will be drawn + //! Note: If the background is not drawn, then the titlebar is automatically also not drawn + virtual void setDrawTitlebar(bool draw) = 0; + + //! Get if the window titlebar will be drawn + virtual bool getDrawTitlebar() const = 0; + + //! Returns the rectangle of the drawable area (without border and without titlebar) + /** The coordinates are given relative to the top-left position of the gui element.
+ So to get absolute positions you have to add the resulting rectangle to getAbsolutePosition().UpperLeftCorner.
+ To get it relative to the parent element you have to add the resulting rectangle to getRelativePosition().UpperLeftCorner. + Beware that adding a menu will not change the clientRect as menus are own gui elements, so in that case you might want to subtract + the menu area additionally. */ + virtual core::rect getClientRect() const = 0; }; diff --git a/src/dep/include/irrlicht/IGeometryCreator.h b/src/dep/include/irrlicht/IGeometryCreator.h new file mode 100644 index 0000000..f750956 --- /dev/null +++ b/src/dep/include/irrlicht/IGeometryCreator.h @@ -0,0 +1,177 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GEOMETRY_CREATOR_H_INCLUDED__ +#define __I_GEOMETRY_CREATOR_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "IMesh.h" +#include "IImage.h" + +namespace irr +{ +namespace video +{ + class IVideoDriver; + class SMaterial; +} + +namespace scene +{ + +//! Helper class for creating geometry on the fly. +/** You can get an instance of this class through ISceneManager::getGeometryCreator() */ +class IGeometryCreator : public IReferenceCounted +{ +public: + + //! Creates a simple cube mesh. + /** + \param size Dimensions of the cube. + \return Generated mesh. + */ + virtual IMesh* createCubeMesh(const core::vector3df& size=core::vector3df(5.f,5.f,5.f)) const =0; + + //! Create a pseudo-random mesh representing a hilly terrain. + /** + \param tileSize The size of each tile. + \param tileCount The number of tiles in each dimension. + \param material The material to apply to the mesh. + \param hillHeight The maximum height of the hills. + \param countHills The number of hills along each dimension. + \param textureRepeatCount The number of times to repeat the material texture along each dimension. + \return Generated mesh. + */ + virtual IMesh* createHillPlaneMesh( + const core::dimension2d& tileSize, + const core::dimension2d& tileCount, + video::SMaterial* material, f32 hillHeight, + const core::dimension2d& countHills, + const core::dimension2d& textureRepeatCount) const =0; + + //! Create a simple rectangular textured plane mesh. + /** + \param tileSize The size of each tile. + \param tileCount The number of tiles in each dimension. + \param material The material to apply to the mesh. + \param textureRepeatCount The number of times to repeat the material texture along each dimension. + \return Generated mesh. + */ + IMesh* createPlaneMesh( + const core::dimension2d& tileSize, + const core::dimension2d& tileCount, + video::SMaterial* material, + const core::dimension2d& textureRepeatCount) const + { + return createHillPlaneMesh(tileSize, tileCount, material, 0.f, core::dimension2df(), textureRepeatCount); + } + + //! Create a terrain mesh from an image representing a heightfield. + /** + \param texture The texture to apply to the terrain. + \param heightmap An image that will be interpreted as a heightmap. The + brightness (average colour) of each pixel is interpreted as a height, + with a 255 brightness pixel producing the maximum height. + \param stretchSize The size that each pixel will produce, i.e. a + 512x512 heightmap + and a stretchSize of (10.f, 20.f) will produce a mesh of size + 5120.f x 10240.f + \param maxHeight The maximum height of the terrain. + \param driver The current video driver. + \param defaultVertexBlockSize (to be documented) + \param debugBorders (to be documented) + \return Generated mesh. + */ + virtual IMesh* createTerrainMesh(video::IImage* texture, + video::IImage* heightmap, + const core::dimension2d& stretchSize, + f32 maxHeight, video::IVideoDriver* driver, + const core::dimension2d& defaultVertexBlockSize, + bool debugBorders=false) const =0; + + //! Create an arrow mesh, composed of a cylinder and a cone. + /** + \param tesselationCylinder Number of quads composing the cylinder. + \param tesselationCone Number of triangles composing the cone's roof. + \param height Total height of the arrow + \param cylinderHeight Total height of the cylinder, should be lesser + than total height + \param widthCylinder Diameter of the cylinder + \param widthCone Diameter of the cone's base, should be not smaller + than the cylinder's diameter + \param colorCylinder color of the cylinder + \param colorCone color of the cone + \return Generated mesh. + */ + virtual IMesh* createArrowMesh(const u32 tesselationCylinder = 4, + const u32 tesselationCone = 8, const f32 height = 1.f, + const f32 cylinderHeight = 0.6f, const f32 widthCylinder = 0.05f, + const f32 widthCone = 0.3f, const video::SColor colorCylinder = 0xFFFFFFFF, + const video::SColor colorCone = 0xFFFFFFFF) const =0; + + + //! Create a sphere mesh. + /** + \param radius Radius of the sphere + \param polyCountX Number of quads used for the horizontal tiling + \param polyCountY Number of quads used for the vertical tiling + \return Generated mesh. + */ + virtual IMesh* createSphereMesh(f32 radius = 5.f, + u32 polyCountX = 16, u32 polyCountY = 16) const =0; + + //! Create a cylinder mesh. + /** + \param radius Radius of the cylinder. + \param length Length of the cylinder. + \param tesselation Number of quads around the circumference of the cylinder. + \param color The color of the cylinder. + \param closeTop If true, close the ends of the cylinder, otherwise leave them open. + \param oblique (to be documented) + \return Generated mesh. + */ + virtual IMesh* createCylinderMesh(f32 radius, f32 length, + u32 tesselation, + const video::SColor& color=video::SColor(0xffffffff), + bool closeTop=true, f32 oblique=0.f) const =0; + + //! Create a cone mesh. + /** + \param radius Radius of the cone. + \param length Length of the cone. + \param tesselation Number of quads around the circumference of the cone. + \param colorTop The color of the top of the cone. + \param colorBottom The color of the bottom of the cone. + \param oblique (to be documented) + \return Generated mesh. + */ + virtual IMesh* createConeMesh(f32 radius, f32 length, u32 tesselation, + const video::SColor& colorTop=video::SColor(0xffffffff), + const video::SColor& colorBottom=video::SColor(0xffffffff), + f32 oblique=0.f) const =0; + + //! Create a volume light mesh. + /** + \param subdivideU Horizontal patch count. + \param subdivideV Vertical patch count. + \param footColor Color at the bottom of the light. + \param tailColor Color at the mid of the light. + \param lpDistance Virtual distance of the light point for normals. + \param lightDim Dimensions of the light. + \return Generated mesh. + */ + virtual IMesh* createVolumeLightMesh( + const u32 subdivideU=32, const u32 subdivideV=32, + const video::SColor footColor = 0xffffffff, + const video::SColor tailColor = 0xffffffff, + const f32 lpDistance = 8.f, + const core::vector3df& lightDim = core::vector3df(1.f,1.2f,1.f)) const =0; +}; + + +} // end namespace scene +} // end namespace irr + +#endif // __I_GEOMETRY_CREATOR_H_INCLUDED__ + diff --git a/src/dep/include/irrlicht/IImage.h b/src/dep/include/irrlicht/IImage.h index 6bb2e21..463d9ea 100644 --- a/src/dep/include/irrlicht/IImage.h +++ b/src/dep/include/irrlicht/IImage.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -32,7 +32,30 @@ enum ECOLOR_FORMAT ECF_R8G8B8, //! Default 32 bit color format. 8 bits are used for every component: red, green, blue and alpha. - ECF_A8R8G8B8 + ECF_A8R8G8B8, + + /** Floating Point formats. The following formats may only be used for render target textures. */ + + //! 16 bit floating point format using 16 bits for the red channel. + ECF_R16F, + + //! 32 bit floating point format using 16 bits for the red channel and 16 bits for the green channel. + ECF_G16R16F, + + //! 64 bit floating point format 16 bits are used for the red, green, blue and alpha channels. + ECF_A16B16G16R16F, + + //! 32 bit floating point format using 32 bits for the red channel. + ECF_R32F, + + //! 64 bit floating point format using 32 bits for the red channel and 32 bits for the green channel. + ECF_G32R32F, + + //! 128 bit floating point format. 32 bits are used for the red, green, blue and alpha channels. + ECF_A32B32G32R32F, + + //! Unknown color format: + ECF_UNKNOWN }; @@ -58,7 +81,7 @@ public: virtual void unlock() = 0; //! Returns width and height of image data. - virtual const core::dimension2d& getDimension() const = 0; + virtual const core::dimension2d& getDimension() const = 0; //! Returns bits per pixel. virtual u32 getBitsPerPixel() const = 0; @@ -76,7 +99,7 @@ public: virtual SColor getPixel(u32 x, u32 y) const = 0; //! Sets a pixel - virtual void setPixel(u32 x, u32 y, const SColor &color ) = 0; + virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) = 0; //! Returns the color format virtual ECOLOR_FORMAT getColorFormat() const = 0; @@ -97,7 +120,7 @@ public: virtual u32 getPitch() const =0; //! Copies the image into the target, scaling the image to fit - virtual void copyToScaling(void* target, s32 width, s32 height, ECOLOR_FORMAT format=ECF_A8R8G8B8, u32 pitch=0) =0; + virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format=ECF_A8R8G8B8, u32 pitch=0) =0; //! Copies the image into the target, scaling the image to fit virtual void copyToScaling(IImage* target) =0; @@ -108,14 +131,65 @@ public: //! copies this surface into another virtual void copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect=0) =0; - //! copies this surface into another, using the alpha mask, an cliprect and a color to add with + //! copies this surface into another, using the alpha mask and cliprect and a color to add with virtual void copyToWithAlpha(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const SColor &color, const core::rect* clipRect = 0) =0; + //! copies this surface into another, scaling it to fit, appyling a box filter + virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0; + //! fills the surface with black or white virtual void fill(const SColor &color) =0; + //! get the amount of Bits per Pixel of the given color format + static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format) + { + switch(format) + { + case ECF_A1R5G5B5: + return 16; + case ECF_R5G6B5: + return 16; + case ECF_R8G8B8: + return 24; + case ECF_A8R8G8B8: + return 32; + case ECF_R16F: + return 16; + case ECF_G16R16F: + return 32; + case ECF_A16B16G16R16F: + return 64; + case ECF_R32F: + return 32; + case ECF_G32R32F: + return 64; + case ECF_A32B32G32R32F: + return 128; + default: + return 0; + } + } + + //! test if the color format is only viable for RenderTarget textures + /** Since we don't have support for e.g. floating point IImage formats + one should test if the color format can be used for arbitrary usage, or + if it is restricted to RTTs. */ + static bool isRenderTargetOnlyFormat(const ECOLOR_FORMAT format) + { + switch(format) + { + case ECF_A1R5G5B5: + case ECF_R5G6B5: + case ECF_R8G8B8: + case ECF_A8R8G8B8: + return false; + default: + return true; + } + } + }; } // end namespace video diff --git a/src/dep/include/irrlicht/IImageLoader.h b/src/dep/include/irrlicht/IImageLoader.h index f4f81b8..19c9d3b 100644 --- a/src/dep/include/irrlicht/IImageLoader.h +++ b/src/dep/include/irrlicht/IImageLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,6 +7,7 @@ #include "IReferenceCounted.h" #include "IImage.h" +#include "path.h" namespace irr { @@ -28,9 +29,9 @@ public: //! Check if the file might be loaded by this class /** Check is based on the file extension (e.g. ".tga") - \param fileName Name of file to check. + \param filename Name of file to check. \return True if file seems to be loadable. */ - virtual bool isALoadableFileExtension(const c8* fileName) const = 0; + virtual bool isALoadableFileExtension(const io::path& filename) const = 0; //! Check if the file might be loaded by this class /** Check might look into the file. diff --git a/src/dep/include/irrlicht/IImageWriter.h b/src/dep/include/irrlicht/IImageWriter.h index 17759e8..aaa07e9 100644 --- a/src/dep/include/irrlicht/IImageWriter.h +++ b/src/dep/include/irrlicht/IImageWriter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,8 @@ #define _I_IMAGE_WRITER_H_INCLUDED__ #include "IReferenceCounted.h" +#include "irrString.h" +#include "coreutil.h" namespace irr { @@ -24,9 +26,9 @@ class IImageWriter : public IReferenceCounted { public: //! Check if this writer can write a file with the given extension - /** \param fileName Name of the file to check. + /** \param filename Name of the file to check. \return True if file extension specifies a writable type. */ - virtual bool isAWriteableFileExtension(const c8* fileName) const = 0; + virtual bool isAWriteableFileExtension(const io::path& filename) const = 0; //! Write image to file /** \param file File handle to write to. diff --git a/src/dep/include/irrlicht/IIndexBuffer.h b/src/dep/include/irrlicht/IIndexBuffer.h index a2fe01d..a60498c 100644 --- a/src/dep/include/irrlicht/IIndexBuffer.h +++ b/src/dep/include/irrlicht/IIndexBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2008 Nikolaus Gebhardt +// Copyright (C) 2008-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/ILightManager.h b/src/dep/include/irrlicht/ILightManager.h new file mode 100644 index 0000000..6238786 --- /dev/null +++ b/src/dep/include/irrlicht/ILightManager.h @@ -0,0 +1,62 @@ +// Written by Colin MacDonald - all rights assigned to Nikolaus Gebhardt +// Copyright (C) 2008-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_LIGHT_MANAGER_H_INCLUDED__ +#define __I_LIGHT_MANAGER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrArray.h" + +namespace irr +{ +namespace scene +{ + class ILightSceneNode; + + //! ILightManager provides an interface for user applications to manipulate the list of lights in the scene. + /** The light list can be trimmed or re-ordered before device/ hardware + lights are created, and/or individual lights can be switched on and off + before or after each scene node is rendered. It is assumed that the + ILightManager implementation will store any data that it wishes to + retain, i.e. the ISceneManager to which it is assigned, the lightList, + the current render pass, and the current scene node. */ + class ILightManager : public IReferenceCounted + { + public: + //! Called after the scene's light list has been built, but before rendering has begun. + /** As actual device/hardware lights are not created until the + ESNRP_LIGHT render pass, this provides an opportunity for the + light manager to trim or re-order the light list, before any + device/hardware lights have actually been created. + \param lightList: the Scene Manager's light list, which + the light manager may modify. This reference will remain valid + until OnPostRender(). + */ + virtual void OnPreRender(core::array & lightList) = 0; + + //! Called after the last scene node is rendered. + /** After this call returns, the lightList passed to OnPreRender() becomes invalid. */ + virtual void OnPostRender(void) = 0; + + //! Called before a render pass begins + /** \param renderPass: the render pass that's about to begin */ + virtual void OnRenderPassPreRender(E_SCENE_NODE_RENDER_PASS renderPass) = 0; + + //! Called after the render pass specified in OnRenderPassPreRender() ends + /** \param[in] renderPass: the render pass that has finished */ + virtual void OnRenderPassPostRender(E_SCENE_NODE_RENDER_PASS renderPass) = 0; + + //! Called before the given scene node is rendered + /** \param[in] node: the scene node that's about to be rendered */ + virtual void OnNodePreRender(ISceneNode* node) = 0; + + //! Called after the the node specified in OnNodePreRender() has been rendered + /** \param[in] node: the scene node that has just been rendered */ + virtual void OnNodePostRender(ISceneNode* node) = 0; + }; +} // end namespace scene +} // end namespace irr + +#endif diff --git a/src/dep/include/irrlicht/ILightSceneNode.h b/src/dep/include/irrlicht/ILightSceneNode.h index 3bc89c0..66027c8 100644 --- a/src/dep/include/irrlicht/ILightSceneNode.h +++ b/src/dep/include/irrlicht/ILightSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -40,6 +40,12 @@ public: /** \return The light data. */ virtual video::SLight& getLightData() = 0; + //! Sets if the node should be visible or not. + /** All children of this node won't be visible either, when set + to true. + \param isVisible If the node shall be visible. */ + virtual void setVisible(bool isVisible) = 0; + //! Sets the light's radius of influence. /** Outside this radius the light won't lighten geometry and cast no shadows. Setting the radius will also influence the attenuation, setting diff --git a/src/dep/include/irrlicht/ILogger.h b/src/dep/include/irrlicht/ILogger.h index 4377b1b..4f7467f 100644 --- a/src/dep/include/irrlicht/ILogger.h +++ b/src/dep/include/irrlicht/ILogger.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -66,6 +66,7 @@ public: filtered with these levels. If you want to be a text displayed, independent on what level filter is set, use ELL_NONE. */ virtual void log(const c8* text, const c8* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; + virtual void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; //! Prints out a text into the log /** \param text: Text to print out. diff --git a/src/dep/include/irrlicht/IMaterialRenderer.h b/src/dep/include/irrlicht/IMaterialRenderer.h index 1adc8b5..200c9d5 100644 --- a/src/dep/include/irrlicht/IMaterialRenderer.h +++ b/src/dep/include/irrlicht/IMaterialRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IMaterialRendererServices.h b/src/dep/include/irrlicht/IMaterialRendererServices.h index 0670e69..0cd46ea 100644 --- a/src/dep/include/irrlicht/IMaterialRendererServices.h +++ b/src/dep/include/irrlicht/IMaterialRendererServices.h @@ -1,11 +1,10 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_MATERIAL_RENDERER_SERVICES_H_INCLUDED__ #define __I_MATERIAL_RENDERER_SERVICES_H_INCLUDED__ -#include "IReferenceCounted.h" #include "SMaterial.h" #include "S3DVertex.h" diff --git a/src/dep/include/irrlicht/IMesh.h b/src/dep/include/irrlicht/IMesh.h index 44820da..b737be5 100644 --- a/src/dep/include/irrlicht/IMesh.h +++ b/src/dep/include/irrlicht/IMesh.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -15,36 +15,37 @@ namespace scene { class IMeshBuffer; - //! Class for accessing a mesh with multiple mesh buffers. + //! Class which holds the geometry of an object. /** An IMesh is nothing more than a collection of some mesh buffers (IMeshBuffer). SMesh is a simple implementation of an IMesh. + A mesh is usually added to an IMeshSceneNode in order to be rendered. */ class IMesh : public virtual IReferenceCounted { public: - //! Returns the amount of mesh buffers. - /** \return Returns the amount of mesh buffers (IMeshBuffer) in this mesh. */ + //! Get the amount of mesh buffers. + /** \return Amount of mesh buffers (IMeshBuffer) in this mesh. */ virtual u32 getMeshBufferCount() const = 0; - //! Returns pointer to a mesh buffer. + //! Get pointer to a mesh buffer. /** \param nr: Zero based index of the mesh buffer. The maximum value is getMeshBufferCount() - 1; - \return Returns the pointer to the mesh buffer or - NULL if there is no such mesh buffer. */ + \return Pointer to the mesh buffer or 0 if there is no such + mesh buffer. */ virtual IMeshBuffer* getMeshBuffer(u32 nr) const = 0; - //! Returns pointer to a mesh buffer which fits a material + //! Get pointer to a mesh buffer which fits a material /** \param material: material to search for - \return Returns the pointer to the mesh buffer or - NULL if there is no such mesh buffer. */ + \return Pointer to the mesh buffer or 0 if there is no such + mesh buffer. */ virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const = 0; - //! Returns an axis aligned bounding box of the mesh. - /** \return A bounding box of this mesh is returned. */ + //! Get an axis aligned bounding box of the mesh. + /** \return Bounding box of this mesh. */ virtual const core::aabbox3d& getBoundingBox() const = 0; - //! set user axis aligned bounding box + //! Set user-defined axis aligned bounding box /** \param box New bounding box to use for the mesh. */ virtual void setBoundingBox( const core::aabbox3df& box) = 0; @@ -53,10 +54,17 @@ namespace scene \param newvalue: New value to set in all materials. */ virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) = 0; - //! set the hardware mapping hint, for driver - virtual void setHardwareMappingHint( E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) = 0; + //! Set the hardware mapping hint + /** This methods allows to define optimization hints for the + hardware. This enables, e.g., the use of hardware buffers on + pltforms that support this feature. This can lead to noticeable + performance gains. */ + virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; - //! flags the meshbuffer as changed, reloads hardware buffers + //! Flag the meshbuffer as changed, reloads hardware buffers + /** This method has to be called every time the vertices or + indices have changed. Otherwise, changes won't be updated + on the GPU in the next render cycle. */ virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; }; diff --git a/src/dep/include/irrlicht/IMeshBuffer.h b/src/dep/include/irrlicht/IMeshBuffer.h index 3fee873..e5447a0 100644 --- a/src/dep/include/irrlicht/IMeshBuffer.h +++ b/src/dep/include/irrlicht/IMeshBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,58 +11,29 @@ #include "S3DVertex.h" #include "SVertexIndex.h" #include "EHardwareBufferFlags.h" +#include "EPrimitiveTypes.h" namespace irr { namespace scene { - - //! Enumeration for all primitive types there are. - enum E_PRIMITIVE_TYPE - { - //! All vertices are non-connected points. - EPT_POINTS=0, - - //! All vertices form a single connected line. - EPT_LINE_STRIP, - - //! Just as LINE_STRIP, but the last and the first vertex is also connected. - EPT_LINE_LOOP, - - //! Every two vertices are connected creating n/2 lines. - EPT_LINES, - - //! After the first two vertices each vertex defines a new triangle. - //! Always the two last and the new one form a new triangle. - EPT_TRIANGLE_STRIP, - - //! After the first two vertices each vertex defines a new triangle. - //! All around the common first vertex. - EPT_TRIANGLE_FAN, - - //! Explicitly set all vertices for each triangle. - EPT_TRIANGLES, - - //! After the first two vertices each further tw vetices create a quad with the preceding two. - EPT_QUAD_STRIP, - - //! Every four vertices create a quad. - EPT_QUADS, - - //! Just as LINE_LOOP, but filled. - EPT_POLYGON, - - //! The single vertices are expanded to quad billboards on the GPU. - EPT_POINT_SPRITES - }; - - //! Struct for holding a mesh with a single material - /** SMeshBuffer is a simple implementation of a MeshBuffer. + //! Struct for holding a mesh with a single material. + /** A part of an IMesh which has the same material on each face of that + group. Logical groups of an IMesh need not be put into separate mesh + buffers, but can be. Separately animated parts of the mesh must be put + into separate mesh buffers. + Some mesh buffer implementations have limitations on the number of + vertices the buffer can hold. In that case, logical grouping can help. + Moreover, the number of vertices should be optimized for the GPU upload, + which often depends on the type of gfx card. Typial figures are + 1000-10000 vertices per buffer. + SMeshBuffer is a simple implementation of a MeshBuffer, which supports + up to 65535 vertices. Since meshbuffers are used for drawing, and hence will be exposed to the driver, chances are high that they are grab()'ed from somewhere. It's therefore required to dynamically allocate meshbuffers which are - passed to a video driver and only drop hte buffer once it's not used in + passed to a video driver and only drop the buffer once it's not used in the current code block anymore. */ class IMeshBuffer : public virtual IReferenceCounted @@ -166,7 +137,6 @@ namespace scene //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; - //to be spit into vertex and index buffers: //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID_Vertex() const = 0; diff --git a/src/dep/include/irrlicht/IMeshCache.h b/src/dep/include/irrlicht/IMeshCache.h index b2f293a..3984c1a 100644 --- a/src/dep/include/irrlicht/IMeshCache.h +++ b/src/dep/include/irrlicht/IMeshCache.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,7 +6,7 @@ #define __I_MESH_CACHE_H_INCLUDED__ #include "IReferenceCounted.h" -#include "irrString.h" +#include "path.h" namespace irr { @@ -42,12 +42,12 @@ namespace scene with one call. They can add additional meshes with this method to the scene manager. The COLLADA loader for example uses this method. - \param filename Filename of the mesh. When calling + \param name Name of the mesh. When calling ISceneManager::getMesh() with this name it will return the mesh set by this method. \param mesh Pointer to a mesh which will now be referenced by this name. */ - virtual void addMesh(const c8* filename, IAnimatedMesh* mesh) = 0; + virtual void addMesh(const io::path& name, IAnimatedMesh* mesh) = 0; //! Removes a mesh from the cache. /** After loading a mesh with getMesh(), the mesh can be @@ -67,7 +67,7 @@ namespace scene /** You can load new meshes into the cache using getMesh() and addMesh(). If you ever need to access the internal mesh cache, you can do this using removeMesh(), getMeshNumber(), - getMeshByIndex() and getMeshFilename(). + getMeshByIndex() and getMeshName(). \return Number of meshes in cache. */ virtual u32 getMeshCount() const = 0; @@ -90,60 +90,106 @@ namespace scene number. */ virtual IAnimatedMesh* getMeshByIndex(u32 index) = 0; - //! Returns a mesh based on its filename. - /** \param filename Name of the mesh. + //! Returns a mesh based on its name (often a filename). + /** \deprecated Use getMeshByName() instead. */ + _IRR_DEPRECATED_ IAnimatedMesh* getMeshByFilename(const io::path& filename) + { + return getMeshByName(filename); + } + + //! Get the name of a loaded mesh, based on its index. (Name is often identical to the filename). + /** \deprecated Use getMeshName() instead. */ + _IRR_DEPRECATED_ const io::path& getMeshFilename(u32 index) const + { + return getMeshName(index).getInternalName(); + } + + //! Get the name of a loaded mesh, if there is any. (Name is often identical to the filename). + /** \deprecated Use getMeshName() instead. */ + _IRR_DEPRECATED_ const io::path& getMeshFilename(const IAnimatedMesh* const mesh) const + { + return getMeshName(mesh).getInternalName(); + } + + //! Get the name of a loaded mesh, if there is any. (Name is often identical to the filename). + /** \deprecated Use getMeshName() instead. */ + _IRR_DEPRECATED_ const io::path& getMeshFilename(const IMesh* const mesh) const + { + return getMeshName(mesh).getInternalName(); + } + + //! Renames a loaded mesh. + /** \deprecated Use renameMesh() instead. */ + _IRR_DEPRECATED_ bool setMeshFilename(u32 index, const io::path& filename) + { + return renameMesh(index, filename); + } + + //! Renames a loaded mesh. + /** \deprecated Use renameMesh() instead. */ + _IRR_DEPRECATED_ bool setMeshFilename(const IAnimatedMesh* const mesh, const io::path& filename) + { + return renameMesh(mesh, filename); + } + + //! Renames a loaded mesh. + /** \deprecated Use renameMesh() instead. */ + _IRR_DEPRECATED_ bool setMeshFilename(const IMesh* const mesh, const io::path& filename) + { + return renameMesh(mesh, filename); + } + + //! Returns a mesh based on its name. + /** \param name Name of the mesh. Usually a filename. \return Pointer to the mesh or 0 if there is none with this number. */ - virtual IAnimatedMesh* getMeshByFilename(const c8* filename) = 0; + virtual IAnimatedMesh* getMeshByName(const io::path& name) = 0; - //! Get the filename of a loaded mesh, based on its index. + //! Get the name of a loaded mesh, based on its index. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. - \return String with name if mesh was found and has a name, else - 0. */ - virtual const c8* getMeshFilename(u32 index) const = 0; + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(u32 index) const = 0; - //! Get the filename of a loaded mesh, if there is any. + //! Get the name of a loaded mesh, if there is any. /** \param mesh Pointer to mesh to query. - \return String with name if mesh was found and has a name, else - 0. */ - virtual const c8* getMeshFilename(const IAnimatedMesh* const mesh) const = 0; + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(const IAnimatedMesh* const mesh) const = 0; - //! Get the filename of a loaded mesh, if there is any. + //! Get the name of a loaded mesh, if there is any. /** \param mesh Pointer to mesh to query. - \return String with name if mesh was found and has a name, else - 0. */ - virtual const c8* getMeshFilename(const IMesh* const mesh) const = 0; + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(const IMesh* const mesh) const = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param index The index of the mesh in the cache. - \param filename New name for the mesh. + \param name New name for the mesh. \return True if mesh was renamed. */ - virtual bool setMeshFilename(u32 index, const c8* filename) = 0; + virtual bool renameMesh(u32 index, const io::path& name) = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param mesh Mesh to be renamed. - \param filename New name for the mesh. + \param name New name for the mesh. \return True if mesh was renamed. */ - virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const c8* filename) = 0; + virtual bool renameMesh(const IAnimatedMesh* const mesh, const io::path& name) = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param mesh Mesh to be renamed. - \param filename New name for the mesh. + \param name New name for the mesh. \return True if mesh was renamed. */ - virtual bool setMeshFilename(const IMesh* const mesh, const c8* filename) = 0; + virtual bool renameMesh(const IMesh* const mesh, const io::path& name) = 0; //! Check if a mesh was already loaded. - /** \param filename Name of the mesh. + /** \param name Name of the mesh. Usually a filename. \return True if the mesh has been loaded, else false. */ - virtual bool isMeshLoaded(const c8* filename) = 0; + virtual bool isMeshLoaded(const io::path& name) = 0; //! Clears the whole mesh cache, removing all meshes. /** All meshes will be reloaded completely when using ISceneManager::getMesh() diff --git a/src/dep/include/irrlicht/IMeshLoader.h b/src/dep/include/irrlicht/IMeshLoader.h index 9d30ac8..23372f4 100644 --- a/src/dep/include/irrlicht/IMeshLoader.h +++ b/src/dep/include/irrlicht/IMeshLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,7 @@ #define __I_MESH_LOADER_H_INCLUDED__ #include "IReferenceCounted.h" +#include "path.h" namespace irr { @@ -32,9 +33,9 @@ public: //! Returns true if the file might be loaded by this class. /** This decision should be based on the file extension (e.g. ".cob") only. - \param fileName Name of the file to test. + \param filename Name of the file to test. \return True if the file might be loaded by this class. */ - virtual bool isALoadableFileExtension(const c8* fileName) const = 0; + virtual bool isALoadableFileExtension(const io::path& filename) const = 0; //! Creates/loads an animated mesh from the file. /** \param file File handler to load the file from. diff --git a/src/dep/include/irrlicht/IMeshManipulator.h b/src/dep/include/irrlicht/IMeshManipulator.h index 512e33e..89ea6f8 100644 --- a/src/dep/include/irrlicht/IMeshManipulator.h +++ b/src/dep/include/irrlicht/IMeshManipulator.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -10,15 +10,14 @@ #include "aabbox3d.h" #include "matrix4.h" #include "IAnimatedMesh.h" -#include "SColor.h" +#include "IMeshBuffer.h" +#include "SVertexManipulator.h" namespace irr { namespace scene { - class IMesh; - class IMeshBuffer; struct SMesh; //! An interface for easy manipulation of meshes. @@ -40,12 +39,18 @@ namespace scene //! Sets the alpha vertex color value of the whole mesh to a new value. /** \param mesh Mesh on which the operation is performed. \param alpha New alpha value. Must be a value between 0 and 255. */ - virtual void setVertexColorAlpha(IMesh* mesh, s32 alpha) const = 0; + void setVertexColorAlpha(IMesh* mesh, s32 alpha) const + { + apply(scene::SVertexColorSetAlphaManipulator(alpha), mesh); + } //! Sets the colors of all vertices to one color /** \param mesh Mesh on which the operation is performed. \param color New color. */ - virtual void setVertexColors(IMesh* mesh, video::SColor color) const = 0; + void setVertexColors(IMesh* mesh, video::SColor color) const + { + apply(scene::SVertexColorSetManipulator(color), mesh); + } //! Recalculates all normals of the mesh. /** \param mesh: Mesh on which the operation is performed. @@ -59,46 +64,74 @@ namespace scene \param angleWeighted: If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */ virtual void recalculateNormals(IMeshBuffer* buffer, bool smooth = false, bool angleWeighted = false) const = 0; + //! Recalculates tangents, requires a tangent mesh + /** \param mesh Mesh on which the operation is performed. + \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the mesh are used unchanged. + \param smooth If the normals shall be smoothed. + \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. + */ + virtual void recalculateTangents(IMesh* mesh, + bool recalculateNormals=false, bool smooth=false, + bool angleWeighted=false) const=0; + //! Scales the actual mesh, not a scene node. /** \param mesh Mesh on which the operation is performed. \param factor Scale factor for each axis. */ - virtual void scale(IMesh* mesh, const core::vector3df& factor) const = 0; + void scale(IMesh* mesh, const core::vector3df& factor) const + { + apply(SVertexPositionScaleManipulator(factor), mesh, true); + } //! Scales the actual meshbuffer, not a scene node. /** \param buffer Meshbuffer on which the operation is performed. \param factor Scale factor for each axis. */ - virtual void scale(IMeshBuffer* buffer, const core::vector3df& factor) const = 0; + void scale(IMeshBuffer* buffer, const core::vector3df& factor) const + { + apply(SVertexPositionScaleManipulator(factor), buffer, true); + } //! Scales the actual mesh, not a scene node. - /** \deprecated + /** \deprecated Use scale() instead \param mesh Mesh on which the operation is performed. \param factor Scale factor for each axis. */ - virtual void scaleMesh(IMesh* mesh, const core::vector3df& factor) const {return scale(mesh,factor);} + void scaleMesh(IMesh* mesh, const core::vector3df& factor) const {return scale(mesh,factor);} //! Scale the texture coords of a mesh. /** \param mesh Mesh on which the operation is performed. \param factor Vector which defines the scale for each axis. \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */ - virtual void scaleTCoords(scene::IMesh* mesh, const core::vector2df& factor, u32 layer=1) const =0; + void scaleTCoords(scene::IMesh* mesh, const core::vector2df& factor, u32 level=1) const + { + apply(SVertexTCoordsScaleManipulator(factor, level), mesh); + } //! Scale the texture coords of a meshbuffer. - /** \param mesh Mesh on which the operation is performed. + /** \param buffer Meshbuffer on which the operation is performed. \param factor Vector which defines the scale for each axis. \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */ - virtual void scaleTCoords(scene::IMeshBuffer* buffer, const core::vector2df& factor, u32 level=1) const =0; + void scaleTCoords(scene::IMeshBuffer* buffer, const core::vector2df& factor, u32 level=1) const + { + apply(SVertexTCoordsScaleManipulator(factor, level), buffer); + } //! Applies a transformation to a mesh /** \param mesh Mesh on which the operation is performed. \param m transformation matrix. */ - virtual void transform(IMesh* mesh, const core::matrix4& m) const = 0; + void transform(IMesh* mesh, const core::matrix4& m) const + { + apply(SVertexPositionTransformManipulator(m), mesh, true); + } //! Applies a transformation to a meshbuffer /** \param buffer Meshbuffer on which the operation is performed. \param m transformation matrix. */ - virtual void transform(IMeshBuffer* buffer, const core::matrix4& m) const = 0; + void transform(IMeshBuffer* buffer, const core::matrix4& m) const + { + apply(SVertexPositionTransformManipulator(m), buffer, true); + } //! Applies a transformation to a mesh - /** \deprecated + /** \deprecated Use transform() instead \param mesh Mesh on which the operation is performed. \param m transformation matrix. */ virtual void transformMesh(IMesh* mesh, const core::matrix4& m) const {return transform(mesh,m);} @@ -106,8 +139,8 @@ namespace scene //! Clones a static IMesh into a modifiable SMesh. /** All meshbuffers in the returned SMesh are of type SMeshBuffer or SMeshBufferLightMap. - \param mesh: Mesh to copy. - \return Returns the cloned mesh. If you no longer need the + \param mesh Mesh to copy. + \return Cloned mesh. If you no longer need the cloned mesh, you should call SMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual SMesh* createMeshCopy(IMesh* mesh) const = 0; @@ -117,7 +150,24 @@ namespace scene \param resolution: resolution of the planar mapping. This is the value specifying which is the relation between world space and texture coordinate space. */ - virtual void makePlanarTextureMapping(IMesh* mesh, f32 resolution=0.001f) const = 0; + virtual void makePlanarTextureMapping(IMesh* mesh, f32 resolution=0.001f) const =0; + + //! Creates a planar texture mapping on the meshbuffer + /** \param meshbuffer: Buffer on which the operation is performed. + \param resolution: resolution of the planar mapping. This is + the value specifying which is the relation between world space + and texture coordinate space. */ + virtual void makePlanarTextureMapping(scene::IMeshBuffer* meshbuffer, f32 resolution=0.001f) const =0; + + //! Creates a planar texture mapping on the meshbuffer + /** This method is currently implemented towards the LWO planar mapping. A more general biasing might be required. + \param buffer Buffer on which the operation is performed. + \param resolutionS Resolution of the planar mapping in horizontal direction. This is the ratio between object space and texture space. + \param resolutionT Resolution of the planar mapping in vertical direction. This is the ratio between object space and texture space. + \param axis The axis along which the texture is projected. The allowed values are 0 (X), 1(Y), and 2(Z). + \param offset Vector added to the vertex positions (in object coordinates). + */ + virtual void makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const =0; //! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices. /** This is useful if you want to draw tangent space normal @@ -131,11 +181,12 @@ namespace scene \param smooth The normals/tangents are smoothed across the meshbuffer's faces if this flag is set. \param angleWeighted Improved smoothing calculation used + \param recalculateTangents Whether are actually calculated, or just the mesh with proper type is created. \return Mesh consisting only of S3DVertexTangents vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more information. */ - virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const = 0; + virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false, bool recalculateTangents=true) const = 0; //! Creates a copy of the mesh, which will only consist of S3DVertex2TCoord vertices. /** \param mesh Input mesh @@ -145,6 +196,14 @@ namespace scene information. */ virtual IMesh* createMeshWith2TCoords(IMesh* mesh) const = 0; + //! Creates a copy of the mesh, which will only consist of S3DVertex vertices. + /** \param mesh Input mesh + \return Mesh consisting only of S3DVertex vertices. If + you no longer need the cloned mesh, you should call + IMesh::drop(). See IReferenceCounted::drop() for more + information. */ + virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const = 0; + //! Creates a copy of a mesh with all vertices unwelded /** \param mesh Input mesh \return Mesh consisting only of unique faces. All vertices @@ -159,7 +218,7 @@ namespace scene \return Mesh without redundant vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more information. */ - virtual IMesh* createMeshWelded(IMesh* mesh, f32 tolerance=core::ROUNDING_ERROR_32) const = 0; + virtual IMesh* createMeshWelded(IMesh* mesh, f32 tolerance=core::ROUNDING_ERROR_f32) const = 0; //! Get amount of polygons in mesh. /** \param mesh Input mesh @@ -180,11 +239,100 @@ namespace scene IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh * createAnimatedMesh(IMesh* mesh, scene::E_ANIMATED_MESH_TYPE type = scene::EAMT_UNKNOWN) const = 0; - }; + + //! Apply a manipulator on the Meshbuffer + /** \param func A functor defining the mesh manipulation. + \param buffer The Meshbuffer to apply the manipulator to. + \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation. + \return True if the functor was successfully applied, else false. */ + template + bool apply(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate=false) const + { + return apply_(func, buffer, boundingBoxUpdate, func); + } + + + //! Apply a manipulator on the Mesh + /** \param func A functor defining the mesh manipulation. + \param mesh The Mesh to apply the manipulator to. + \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation. + \return True if the functor was successfully applied, else false. */ + template + bool apply(const Functor& func, IMesh* mesh, bool boundingBoxUpdate=false) const + { + if (!mesh) + return true; + bool result = true; + core::aabbox3df bufferbox; + for (u32 i=0; igetMeshBufferCount(); ++i) + { + result &= apply(func, mesh->getMeshBuffer(i), boundingBoxUpdate); + if (boundingBoxUpdate) + { + if (0==i) + bufferbox.reset(mesh->getMeshBuffer(i)->getBoundingBox()); + else + bufferbox.addInternalBox(mesh->getMeshBuffer(i)->getBoundingBox()); + } + } + if (boundingBoxUpdate) + mesh->setBoundingBox(bufferbox); + return result; + } + +protected: + //! Apply a manipulator based on the type of the functor + /** \param func A functor defining the mesh manipulation. + \param buffer The Meshbuffer to apply the manipulator to. + \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation. + \param typeTest Unused parameter, which handles the proper call selection based on the type of the Functor which is passed in two times. + \return True if the functor was successfully applied, else false. */ + template + bool apply_(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate, const IVertexManipulator& typeTest) const + { + if (!buffer) + return true; + + core::aabbox3df bufferbox; + for (u32 i=0; igetVertexCount(); ++i) + { + switch (buffer->getVertexType()) + { + case video::EVT_STANDARD: + { + video::S3DVertex* verts = (video::S3DVertex*)buffer->getVertices(); + func(verts[i]); + } + break; + case video::EVT_2TCOORDS: + { + video::S3DVertex2TCoords* verts = (video::S3DVertex2TCoords*)buffer->getVertices(); + func(verts[i]); + } + break; + case video::EVT_TANGENTS: + { + video::S3DVertexTangents* verts = (video::S3DVertexTangents*)buffer->getVertices(); + func(verts[i]); + } + break; + } + if (boundingBoxUpdate) + { + if (0==i) + bufferbox.reset(buffer->getPosition(0)); + else + bufferbox.addInternalPoint(buffer->getPosition(i)); + } + } + if (boundingBoxUpdate) + buffer->setBoundingBox(bufferbox); + return true; + } +}; } // end namespace scene } // end namespace irr #endif - diff --git a/src/dep/include/irrlicht/IMeshSceneNode.h b/src/dep/include/irrlicht/IMeshSceneNode.h index c6df634..4070c88 100644 --- a/src/dep/include/irrlicht/IMeshSceneNode.h +++ b/src/dep/include/irrlicht/IMeshSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,9 +24,9 @@ public: /** Use setMesh() to set the mesh to display. */ IMeshSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, - const core::vector3df& position, - const core::vector3df& rotation, - const core::vector3df& scale) + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1,1,1)) : ISceneNode(parent, mgr, id, position, rotation, scale) {} //! Sets a new mesh to display diff --git a/src/dep/include/irrlicht/IMeshWriter.h b/src/dep/include/irrlicht/IMeshWriter.h index 79e7dde..977f18a 100644 --- a/src/dep/include/irrlicht/IMeshWriter.h +++ b/src/dep/include/irrlicht/IMeshWriter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IMetaTriangleSelector.h b/src/dep/include/irrlicht/IMetaTriangleSelector.h index ba7dee7..b6c8eb9 100644 --- a/src/dep/include/irrlicht/IMetaTriangleSelector.h +++ b/src/dep/include/irrlicht/IMetaTriangleSelector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IOSOperator.h b/src/dep/include/irrlicht/IOSOperator.h index bf5f0bc..45655fb 100644 --- a/src/dep/include/irrlicht/IOSOperator.h +++ b/src/dep/include/irrlicht/IOSOperator.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -26,7 +26,7 @@ public: //! Get text from the clipboard /** \return Returns 0 if no string is in there. */ - virtual c8* getTextFromClipboard() const = 0; + virtual const c8* getTextFromClipboard() const = 0; //! Get the processor speed in megahertz /** \param MHz The integer variable to store the speed in. diff --git a/src/dep/include/irrlicht/IParticleAffector.h b/src/dep/include/irrlicht/IParticleAffector.h index 3af8452..4e927a6 100644 --- a/src/dep/include/irrlicht/IParticleAffector.h +++ b/src/dep/include/irrlicht/IParticleAffector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -57,20 +57,6 @@ public: //! Gets whether or not the affector is currently enabled. virtual bool getEnabled() const { return Enabled; } - //! Writes attributes of the object. - /** Implement this to expose the attributes of your scene node animator for - scripting languages, editors, debuggers or xml serialization purposes. */ - virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} - - //! Reads attributes of the object. - /** Implement this to set the attributes of your scene node animator for - scripting languages, editors, debuggers or xml deserialization purposes. - \param startIndex start index where to start reading attributes. - \param in The attributes to work with. - \param options Additional options. - \return Last index of an attribute read by this affector */ - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { return 0; } - //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const = 0; diff --git a/src/dep/include/irrlicht/IParticleAnimatedMeshSceneNodeEmitter.h b/src/dep/include/irrlicht/IParticleAnimatedMeshSceneNodeEmitter.h index 608af5c..29bda28 100644 --- a/src/dep/include/irrlicht/IParticleAnimatedMeshSceneNodeEmitter.h +++ b/src/dep/include/irrlicht/IParticleAnimatedMeshSceneNodeEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleAttractionAffector.h b/src/dep/include/irrlicht/IParticleAttractionAffector.h index 3a8d5eb..1ed6dee 100644 --- a/src/dep/include/irrlicht/IParticleAttractionAffector.h +++ b/src/dep/include/irrlicht/IParticleAttractionAffector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleBoxEmitter.h b/src/dep/include/irrlicht/IParticleBoxEmitter.h index 350253a..07a0824 100644 --- a/src/dep/include/irrlicht/IParticleBoxEmitter.h +++ b/src/dep/include/irrlicht/IParticleBoxEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleCylinderEmitter.h b/src/dep/include/irrlicht/IParticleCylinderEmitter.h index 1f88cd8..3ce4d09 100644 --- a/src/dep/include/irrlicht/IParticleCylinderEmitter.h +++ b/src/dep/include/irrlicht/IParticleCylinderEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleEmitter.h b/src/dep/include/irrlicht/IParticleEmitter.h index 5c2173b..f2842f3 100644 --- a/src/dep/include/irrlicht/IParticleEmitter.h +++ b/src/dep/include/irrlicht/IParticleEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -96,21 +96,6 @@ public: //! Get the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const = 0; - //! Writes attributes of the object. - /** Implement this to expose the attributes of your scene node animator for - scripting languages, editors, debuggers or xml serialization purposes. */ - virtual void serializeAttributes(io::IAttributes* out, - io::SAttributeReadWriteOptions* options=0) const {} - - //! Reads attributes of the object. - /** Implement this to set the attributes of your scene node animator for - scripting languages, editors, debuggers or xml deserialization purposes. - \param startIndex start index where to start reading attributes. - \param in The attributes to work with. - \param options Additional options. - \return Last index of an attribute read by this affector */ - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, - io::SAttributeReadWriteOptions* options=0) { return 0; } //! Get emitter type virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_POINT; } diff --git a/src/dep/include/irrlicht/IParticleFadeOutAffector.h b/src/dep/include/irrlicht/IParticleFadeOutAffector.h index 09a5f4c..8174881 100644 --- a/src/dep/include/irrlicht/IParticleFadeOutAffector.h +++ b/src/dep/include/irrlicht/IParticleFadeOutAffector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleGravityAffector.h b/src/dep/include/irrlicht/IParticleGravityAffector.h index 5fd4984..749a7b9 100644 --- a/src/dep/include/irrlicht/IParticleGravityAffector.h +++ b/src/dep/include/irrlicht/IParticleGravityAffector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleMeshEmitter.h b/src/dep/include/irrlicht/IParticleMeshEmitter.h index 30034cf..de79307 100644 --- a/src/dep/include/irrlicht/IParticleMeshEmitter.h +++ b/src/dep/include/irrlicht/IParticleMeshEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleRingEmitter.h b/src/dep/include/irrlicht/IParticleRingEmitter.h index 37078f4..53fe828 100644 --- a/src/dep/include/irrlicht/IParticleRingEmitter.h +++ b/src/dep/include/irrlicht/IParticleRingEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleRotationAffector.h b/src/dep/include/irrlicht/IParticleRotationAffector.h index 738316d..215332b 100644 --- a/src/dep/include/irrlicht/IParticleRotationAffector.h +++ b/src/dep/include/irrlicht/IParticleRotationAffector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleSphereEmitter.h b/src/dep/include/irrlicht/IParticleSphereEmitter.h index c008e8e..8b91b0a 100644 --- a/src/dep/include/irrlicht/IParticleSphereEmitter.h +++ b/src/dep/include/irrlicht/IParticleSphereEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IParticleSystemSceneNode.h b/src/dep/include/irrlicht/IParticleSystemSceneNode.h index 80268e5..83b79a3 100644 --- a/src/dep/include/irrlicht/IParticleSystemSceneNode.h +++ b/src/dep/include/irrlicht/IParticleSystemSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IQ3LevelMesh.h b/src/dep/include/irrlicht/IQ3LevelMesh.h index 19041e8..db10bb7 100644 --- a/src/dep/include/irrlicht/IQ3LevelMesh.h +++ b/src/dep/include/irrlicht/IQ3LevelMesh.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -20,19 +20,17 @@ namespace scene { public: - //! releases a Mesh from the Q3 Loader - virtual void releaseMesh(s32 index) = 0; - //! loads the shader definition from file /** \param filename Name of the shaderfile, defaults to /scripts if fileNameIsValid is false. \param fileNameIsValid Specifies whether the filename is valid in the current situation. */ - virtual const quake3::SShader* getShader( const c8* filename, bool fileNameIsValid=true ) = 0; + virtual const quake3::IShader* getShader( const c8* filename, bool fileNameIsValid=true ) = 0; //! returns a already loaded Shader - virtual const quake3::SShader* getShader(u32 index) const = 0; + virtual const quake3::IShader* getShader(u32 index) const = 0; //! get's an interface to the entities - virtual const quake3::tQ3EntityList& getEntityList() = 0; + virtual quake3::tQ3EntityList& getEntityList() = 0; + }; } // end namespace scene diff --git a/src/dep/include/irrlicht/IQ3Shader.h b/src/dep/include/irrlicht/IQ3Shader.h index 4c0dcf3..771c387 100644 --- a/src/dep/include/irrlicht/IQ3Shader.h +++ b/src/dep/include/irrlicht/IQ3Shader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2006-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2006-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,7 +18,7 @@ namespace scene namespace quake3 { - static const core::stringc irrEmptyStringc(""); + static core::stringc irrEmptyStringc(""); //! Hold the different Mesh Types used for getMesh enum eQ3MeshIndex @@ -26,47 +26,65 @@ namespace quake3 E_Q3_MESH_GEOMETRY = 0, E_Q3_MESH_ITEMS, E_Q3_MESH_BILLBOARD, + E_Q3_MESH_FOG, + E_Q3_MESH_UNRESOLVED, E_Q3_MESH_SIZE }; - // we are not using gamma, so quake3 is very dark. - // define the standard multiplication for lightmaps and vertex colors - const video::E_MATERIAL_TYPE defaultMaterialType = video::EMT_LIGHTMAP_M4; - const video::E_MODULATE_FUNC defaultModulate = video::EMFN_MODULATE_4X; + /*! used to customize Quake3 BSP Loader + */ + + struct Q3LevelLoadParameter + { + Q3LevelLoadParameter () + :defaultLightMapMaterial ( video::EMT_LIGHTMAP_M4 ), + defaultModulate ( video::EMFN_MODULATE_4X ), + defaultFilter ( video::EMF_BILINEAR_FILTER ), + patchTesselation ( 8 ), + verbose ( 0 ), + startTime ( 0 ), endTime ( 0 ), + mergeShaderBuffer ( 1 ), + cleanUnResolvedMeshes ( 1 ), + loadAllShaders ( 0 ), + loadSkyShader ( 0 ), + alpharef ( 1 ), + swapLump ( 0 ), + #ifdef __BIG_ENDIAN__ + swapHeader ( 1 ) + #else + swapHeader ( 0 ) + #endif + { + memcpy ( scriptDir, "scripts\x0", 8 ); + } + + video::E_MATERIAL_TYPE defaultLightMapMaterial; + video::E_MODULATE_FUNC defaultModulate; + video::E_MATERIAL_FLAG defaultFilter; + s32 patchTesselation; + s32 verbose; + u32 startTime; + u32 endTime; + s32 mergeShaderBuffer; + s32 cleanUnResolvedMeshes; + s32 loadAllShaders; + s32 loadSkyShader; + s32 alpharef; + s32 swapLump; + s32 swapHeader; + c8 scriptDir [ 64 ]; + }; // some useful typedefs typedef core::array< core::stringc > tStringList; typedef core::array< video::ITexture* > tTexArray; - // name = "a b c .." - struct SVariable - { - core::stringc name; - core::stringc content; - - void clear () - { - name = ""; - content = ""; - } - - s32 isValid () const - { - return name.size(); - } - - bool operator == ( const SVariable &other ) const - { - return name == other.name; - } - }; - // string helper.. TODO: move to generic files - inline s32 isEqual ( const core::stringc &string, u32 &pos, const c8 *list[], u32 listSize ) + inline s16 isEqual ( const core::stringc &string, u32 &pos, const c8 *list[], u16 listSize ) { const char * in = string.c_str () + pos; - for ( u32 i = 0; i != listSize; ++i ) + for ( u16 i = 0; i != listSize; ++i ) { if (string.size() < pos) return -2; @@ -79,7 +97,7 @@ namespace quake3 continue; pos += len + 1; - return (s32) i; + return (s16) i; } return -2; } @@ -93,6 +111,7 @@ namespace quake3 return value; } + //! get a quake3 vector translated to irrlicht position (x,-z,y ) inline core::vector3df getAsVector3df ( const core::stringc &string, u32 &pos ) { core::vector3df v; @@ -104,6 +123,7 @@ namespace quake3 return v; } + /* extract substrings */ @@ -135,31 +155,33 @@ namespace quake3 //! A blend function for a q3 shader. struct SBlendFunc { - SBlendFunc () - : type ( video::EMT_SOLID ), modulate ( defaultModulate ), param ( 0.f ), - isTransparent ( false ) {} + SBlendFunc ( video::E_MODULATE_FUNC mod ) + : type ( video::EMT_SOLID ), modulate ( mod ), + param0( 0.f ), + isTransparent ( 0 ) {} video::E_MATERIAL_TYPE type; video::E_MODULATE_FUNC modulate; - f32 param; - bool isTransparent; + f32 param0; + u32 isTransparent; }; // parses the content of Variable cull - inline bool isDisabled ( const core::stringc &string ) + inline bool getCullingFunction ( const core::stringc &cull ) { - if ( string.size() == 0 ) + if ( cull.size() == 0 ) return true; bool ret = true; - static const c8 * funclist[] = { "none", "disable" }; + static const c8 * funclist[] = { "none", "disable", "twosided" }; u32 pos = 0; - switch ( isEqual ( string, pos, funclist, 2 ) ) + switch ( isEqual ( cull, pos, funclist, 3 ) ) { case 0: case 1: + case 2: ret = false; break; } @@ -168,28 +190,39 @@ namespace quake3 // parses the content of Variable depthfunc // return a z-test - inline u32 getDepthFunction ( const core::stringc &string ) + inline u8 getDepthFunction ( const core::stringc &string ) { - if ( string.size() == 0 ) - return 1; + u8 ret = video::ECFN_LESSEQUAL; + + if ( string.size() == 0 ) + return ret; - u32 ret = 1; static const c8 * funclist[] = { "lequal","equal" }; u32 pos = 0; switch ( isEqual ( string, pos, funclist, 2 ) ) { case 0: - ret = 1; + ret = video::ECFN_LESSEQUAL; case 1: - ret = 2; + ret = video::ECFN_EQUAL; break; } return ret; } - // parses the content of Variable blendfunc,alphafunc + /*! + parses the content of Variable blendfunc,alphafunc + it also make a hint for rendering as transparent or solid node. + + we assume a typical quake scene would look like this.. + 1) Big Static Mesh ( solid ) + 2) static scene item ( may use transparency ) but rendered in the solid pass + 3) additional transparency item in the transparent pass + + it's not 100% accurate! it just empirical.. + */ inline static void getBlendFunc ( const core::stringc &string, SBlendFunc &blendfunc ) { if ( string.size() == 0 ) @@ -215,7 +248,7 @@ namespace quake3 "blend", "ge128", - "gt0" + "gt0", }; @@ -230,20 +263,32 @@ namespace quake3 switch ( srcFact ) { + case video::EBF_ZERO: + switch ( dstFact ) + { + // gl_zero gl_src_color == gl_dst_color gl_zero + case video::EBF_SRC_COLOR: + blendfunc.type = video::EMT_ONETEXTURE_BLEND; + blendfunc.param0 = video::pack_texureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); + blendfunc.isTransparent = 1; + resolved = 1; + break; + } break; + case video::EBF_ONE: switch ( dstFact ) { // gl_one gl_zero case video::EBF_ZERO: blendfunc.type = video::EMT_SOLID; - blendfunc.isTransparent = false; + blendfunc.isTransparent = 0; resolved = 1; break; // gl_one gl_one case video::EBF_ONE: blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; - blendfunc.isTransparent = true; + blendfunc.isTransparent = 1; resolved = 1; break; } break; @@ -254,8 +299,8 @@ namespace quake3 // gl_src_alpha gl_one_minus_src_alpha case video::EBF_ONE_MINUS_SRC_ALPHA: blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - blendfunc.param = 1.f / 255.f; - blendfunc.isTransparent = true; + blendfunc.param0 = 1.f/255.f; + blendfunc.isTransparent = 1; resolved = 1; break; } break; @@ -263,74 +308,133 @@ namespace quake3 case 11: // add blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; - blendfunc.isTransparent = true; + blendfunc.isTransparent = 1; resolved = 1; break; case 12: - // filter = gl_dst_color gl_zero + // filter = gl_dst_color gl_zero or gl_zero gl_src_color blendfunc.type = video::EMT_ONETEXTURE_BLEND; - blendfunc.param = video::pack_texureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, defaultModulate ); - blendfunc.isTransparent = false; + blendfunc.param0 = video::pack_texureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); + blendfunc.isTransparent = 1; resolved = 1; break; case 13: - // blend + // blend = gl_src_alpha gl_one_minus_src_alpha blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - blendfunc.param = 1.f / 255.f; - blendfunc.isTransparent = true; + blendfunc.param0 = 1.f/255.f; + blendfunc.isTransparent = 1; resolved = 1; break; case 14: // alphafunc ge128 - blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - blendfunc.param = 0.5f; - blendfunc.isTransparent = true; + blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + blendfunc.param0 = 0.5f; + blendfunc.isTransparent = 1; resolved = 1; break; case 15: // alphafunc gt0 - blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - blendfunc.param = 1.f / 255.f; - blendfunc.isTransparent = true; + blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + blendfunc.param0 = 1.f / 255.f; + blendfunc.isTransparent = 1; resolved = 1; break; + } // use the generic blender if ( 0 == resolved ) { blendfunc.type = video::EMT_ONETEXTURE_BLEND; - blendfunc.param = video::pack_texureBlendFunc ( + blendfunc.param0 = video::pack_texureBlendFunc ( (video::E_BLEND_FACTOR) srcFact, (video::E_BLEND_FACTOR) dstFact, blendfunc.modulate); - if (srcFact == video::EBF_SRC_COLOR && dstFact == video::EBF_ZERO) - { - blendfunc.isTransparent = 0; - } - else - { - blendfunc.isTransparent = true; - } - + blendfunc.isTransparent = 1; } } + // random noise [-1;1] + struct Noiser + { + static f32 get () + { + static u32 RandomSeed = 0x69666966; + RandomSeed = (RandomSeed * 3631 + 1); + + f32 value = ( (f32) (RandomSeed & 0x7FFF ) * (1.0f / (f32)(0x7FFF >> 1) ) ) - 1.f; + return value; + } + }; + + enum eQ3ModifierFunction + { + TCMOD = 0, + DEFORMVERTEXES = 1, + RGBGEN = 2, + TCGEN = 3, + MAP = 4, + ALPHAGEN = 5, + + FUNCTION2 = 0x10, + SCROLL = FUNCTION2 + 1, + SCALE = FUNCTION2 + 2, + ROTATE = FUNCTION2 + 3, + STRETCH = FUNCTION2 + 4, + TURBULENCE = FUNCTION2 + 5, + WAVE = FUNCTION2 + 6, + + IDENTITY = FUNCTION2 + 7, + VERTEX = FUNCTION2 + 8, + TEXTURE = FUNCTION2 + 9, + LIGHTMAP = FUNCTION2 + 10, + ENVIRONMENT = FUNCTION2 + 11, + DOLLAR_LIGHTMAP = FUNCTION2 + 12, + BULGE = FUNCTION2 + 13, + AUTOSPRITE = FUNCTION2 + 14, + AUTOSPRITE2 = FUNCTION2 + 15, + TRANSFORM = FUNCTION2 + 16, + EXACTVERTEX = FUNCTION2 + 17, + CONSTANT = FUNCTION2 + 18, + LIGHTINGSPECULAR = FUNCTION2 + 19, + MOVE = FUNCTION2 + 20, + NORMAL = FUNCTION2 + 21, + IDENTITYLIGHTING = FUNCTION2 + 22, + + WAVE_MODIFIER_FUNCTION = 0x30, + SINUS = WAVE_MODIFIER_FUNCTION + 1, + COSINUS = WAVE_MODIFIER_FUNCTION + 2, + SQUARE = WAVE_MODIFIER_FUNCTION + 3, + TRIANGLE = WAVE_MODIFIER_FUNCTION + 4, + SAWTOOTH = WAVE_MODIFIER_FUNCTION + 5, + SAWTOOTH_INVERSE = WAVE_MODIFIER_FUNCTION + 6, + NOISE = WAVE_MODIFIER_FUNCTION + 7, + + + UNKNOWN = -2 + + }; + struct SModifierFunction { SModifierFunction () - : masterfunc0 ( -2 ), masterfunc1(0), func ( 0 ), - tcgen( 8 ), base ( 0 ), amp ( 1 ), phase ( 0 ), freq ( 1 ), wave(1) {} + : masterfunc0 ( UNKNOWN ), masterfunc1( UNKNOWN ), func ( SINUS ), + tcgen( TEXTURE ), rgbgen ( IDENTITY ), alphagen ( UNKNOWN ), + base ( 0 ), amp ( 1 ), phase ( 0 ), frequency ( 1 ), + wave ( 1 ), + x ( 0 ), y ( 0 ), z( 0 ), count( 0 ) {} // "tcmod","deformvertexes","rgbgen", "tcgen" - s32 masterfunc0; + eQ3ModifierFunction masterfunc0; // depends - s32 masterfunc1; + eQ3ModifierFunction masterfunc1; // depends - s32 func; + eQ3ModifierFunction func; - s32 tcgen; + eQ3ModifierFunction tcgen; + eQ3ModifierFunction rgbgen; + eQ3ModifierFunction alphagen; union { @@ -348,44 +452,52 @@ namespace quake3 union { - f32 freq; + f32 frequency; f32 bulgespeed; }; - f32 wave; + union + { + f32 wave; + f32 div; + }; + + f32 x; + f32 y; + f32 z; + u32 count; f32 evaluate ( f32 dt ) const { // phase in 0 and 1.. - f32 x = core::fract( (dt + phase ) * freq ); + f32 x = core::fract( (dt + phase ) * frequency ); f32 y = 0.f; switch ( func ) { - // sin - case 0: - y = (f32) sin ( x * core::PI64 * 2.0 ); + case SINUS: + y = sinf ( x * core::PI * 2.f ); break; - // cos - case 1: - y = (f32) cos ( x * core::PI64 * 2.0 ); + case COSINUS: + y = cosf ( x * core::PI * 2.f ); break; - // square - case 2: + case SQUARE: y = x < 0.5f ? 1.f : -1.f; break; - // triangle - case 3: - y = x < 0.5f ? ( 2.f * x ) - 1.f : ( -2.f * x ) + 2.f; + case TRIANGLE: + y = x < 0.5f ? ( 4.f * x ) - 1.f : ( -4.f * x ) + 3.f; break; - // sawtooth: - case 4: + case SAWTOOTH: y = x; break; - // inverse sawtooth: - case 5: + case SAWTOOTH_INVERSE: y = 1.f - x; break; + case NOISE: + y = Noiser::get(); + break; + default: + break; } return base + ( y * amp ); @@ -394,6 +506,15 @@ namespace quake3 }; + inline core::vector3df getMD3Normal ( u32 i, u32 j ) + { + const f32 lng = i * 2.0f * core::PI / 255.0f; + const f32 lat = j * 2.0f * core::PI / 255.0f; + return core::vector3df(cosf ( lat ) * sinf ( lng ), + sinf ( lat ) * sinf ( lng ), + cosf ( lng )); + } + // inline void getModifierFunc ( SModifierFunction& fill, const core::stringc &string, u32 &pos ) { @@ -402,64 +523,110 @@ namespace quake3 static const c8 * funclist[] = { - "sin","cos","square", "triangle", "sawtooth","inversesawtooth" + "sin","cos","square", + "triangle", "sawtooth","inversesawtooth", "noise" }; - fill.func = quake3::isEqual ( string,pos, funclist,6 ); - if ( fill.func == -2 ) - fill.func = 0; + fill.func = (eQ3ModifierFunction) isEqual ( string,pos, funclist,7 ); + fill.func = fill.func == UNKNOWN ? SINUS : (eQ3ModifierFunction) ((u32) fill.func + WAVE_MODIFIER_FUNCTION + 1); - fill.base = quake3::getAsFloat ( string, pos ); - fill.amp = quake3::getAsFloat ( string, pos ); - fill.phase = quake3::getAsFloat ( string, pos ); - fill.freq = quake3::getAsFloat ( string, pos ); + fill.base = getAsFloat ( string, pos ); + fill.amp = getAsFloat ( string, pos ); + fill.phase = getAsFloat ( string, pos ); + fill.frequency = getAsFloat ( string, pos ); } + // name = "a b c .." + struct SVariable + { + core::stringc name; + core::stringc content; + SVariable ( const c8 * n, const c8 *c = 0 ) : name ( n ), content (c) {} + virtual ~SVariable () {} + + void clear () + { + name = ""; + content = ""; + } + + s32 isValid () const + { + return name.size(); + } + + bool operator == ( const SVariable &other ) const + { + return 0 == strcmp ( name.c_str(), other.name.c_str () ); + } + + bool operator < ( const SVariable &other ) const + { + return 0 > strcmp ( name.c_str(), other.name.c_str () ); + } + + }; + + + // string database. "a" = "Hello", "b" = "1234.6" struct SVarGroup { - // simple assoziative array - s32 getIndex( const c8 * name ) const - { - SVariable search; - search.name = name; + SVarGroup () { Variable.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); } + virtual ~SVarGroup () {} - return Variable.linear_search ( search ); + u32 isDefined ( const c8 * name, const c8 * content = 0 ) const + { + for ( u32 i = 0; i != Variable.size (); ++i ) + { + if ( 0 == strcmp ( Variable[i].name.c_str(), name ) && + ( 0 == content || strstr ( Variable[i].content.c_str(), content ) ) + ) + { + return i + 1; + } + } + return 0; } // searches for Variable name and returns is content // if Variable is not found a reference to an Empty String is returned const core::stringc &get( const c8 * name ) const { - s32 index = getIndex ( name ); + SVariable search ( name ); + s32 index = Variable.linear_search ( search ); if ( index < 0 ) return irrEmptyStringc; return Variable [ index ].content; } - bool isDefined ( const c8 * name, const c8 * content = 0 ) const + // set the Variable name + void set ( const c8 * name, const c8 * content = 0 ) { - for ( u32 i = 0; i != Variable.size (); ++i ) + u32 index = isDefined ( name, 0 ); + if ( 0 == index ) { - if ( 0 == strcmp ( Variable[i].name.c_str(), name ) ) - { - if ( 0 == content ) - return true; - if ( 0 == strcmp ( Variable[i].content.c_str(), content ) ) - return true; - } + Variable.push_back ( SVariable ( name, content ) ); + } + else + { + Variable [ index ].content = content; } - return false; } + core::array < SVariable > Variable; }; + //! holding a group a variable struct SVarGroupList: public IReferenceCounted { - SVarGroupList () {} + SVarGroupList () + { + VariableGroup.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); + } virtual ~SVarGroupList () {} core::array < SVarGroup > VariableGroup; @@ -467,39 +634,58 @@ namespace quake3 //! A Parsed Shader Holding Variables ordered in Groups - class SShader + struct IShader { - public: - bool operator == (const SShader &other ) const - { - return name == other.name; - } + IShader () + : ID ( 0 ), VarGroup ( 0 ) {} + virtual ~IShader () {} - bool operator < (const SShader &other ) const - { - return name < other.name; - } + void operator = (const IShader &other ) + { + ID = other.ID; + VarGroup = other.VarGroup; + name = other.name; + } - const SVarGroup * getGroup ( u32 stage ) const - { - if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () ) - return 0; + bool operator == (const IShader &other ) const + { + return 0 == strcmp ( name.c_str(), other.name.c_str () ); + //return name == other.name; + } - return &VarGroup->VariableGroup [ stage ]; - } + bool operator < (const IShader &other ) const + { + return strcmp ( name.c_str(), other.name.c_str () ) < 0; + //return name < other.name; + } - // id - s32 id; + u32 getGroupSize () const + { + if ( 0 == VarGroup ) + return 0; + return VarGroup->VariableGroup.size (); + } - // Shader: shader name ( also first variable in first Vargroup ) - // Entity: classname ( variable in Group(1) ) - core::stringc name; - SVarGroupList *VarGroup; // reference + const SVarGroup * getGroup ( u32 stage ) const + { + if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () ) + return 0; + + return &VarGroup->VariableGroup [ stage ]; + } + + // id + s32 ID; + SVarGroupList *VarGroup; // reference + + // Shader: shader name ( also first variable in first Vargroup ) + // Entity: classname ( variable in Group(1) ) + core::stringc name; }; - typedef SShader SEntity; + typedef IShader IEntity; - typedef core::array < SEntity > tQ3EntityList; + typedef core::array < IEntity > tQ3EntityList; /* dump shader like original layout, regardless of internal data holding @@ -546,33 +732,35 @@ namespace quake3 } - inline core::stringc & dumpShader ( core::stringc &dest, const SShader * shader ) + /*! + dump a Shader or an Entity + */ + inline core::stringc & dumpShader ( core::stringc &dest, const IShader * shader, bool entity = false ) { - dest = ""; if ( 0 == shader ) return dest; const SVarGroup * group; const u32 size = shader->VarGroup->VariableGroup.size (); - for ( u32 i = 0; i != size; ++i ) { group = &shader->VarGroup->VariableGroup[ i ]; dumpVarGroup ( dest, group, core::clamp( (int)i, 0, 2 ) ); } - if ( size <= 1 ) + if ( !entity ) { - dest.append ( "{\n" ); + if ( size <= 1 ) + { + dest.append ( "{\n" ); + } + dest.append ( "}\n" ); } - - dest.append ( "}\n" ); return dest; } - /* quake3 doesn't care much about tga & jpg load one or multiple files stored in name started at startPos to the texture array textures @@ -594,21 +782,82 @@ namespace quake3 textures.clear(); - core::stringc loadFile; + io::path loadFile; for ( u32 i = 0; i!= stringList.size (); ++i ) { video::ITexture* texture = 0; for ( u32 g = 0; g != 2 ; ++g ) { - core::cutFilenameExtension ( loadFile, stringList[i] ).append ( extension[g] ); + core::cutFilenameExtension ( loadFile, stringList[i] ); - if ( fileSystem->existFile ( loadFile.c_str() ) ) + if ( loadFile == "$whiteimage" ) { - texture = driver->getTexture( loadFile.c_str () ); - if ( texture ) + texture = driver->getTexture( "$whiteimage" ); + if ( 0 == texture ) { - break; + core::dimension2du s ( 2, 2 ); + u32 image[4] = { 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }; + video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); + texture = driver->addTexture( "$whiteimage", w ); + w->drop (); } + + } + else + if ( loadFile == "$redimage" ) + { + texture = driver->getTexture( "$redimage" ); + if ( 0 == texture ) + { + core::dimension2du s ( 2, 2 ); + u32 image[4] = { 0xFFFF0000, 0xFFFF0000,0xFFFF0000,0xFFFF0000 }; + video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); + texture = driver->addTexture( "$redimage", w ); + w->drop (); + } + } + else + if ( loadFile == "$blueimage" ) + { + texture = driver->getTexture( "$blueimage" ); + if ( 0 == texture ) + { + core::dimension2du s ( 2, 2 ); + u32 image[4] = { 0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF }; + video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); + texture = driver->addTexture( "$blueimage", w ); + w->drop (); + } + } + else + if ( loadFile == "$checkerimage" ) + { + texture = driver->getTexture( "$checkerimage" ); + if ( 0 == texture ) + { + core::dimension2du s ( 2, 2 ); + u32 image[4] = { 0xFFFFFFFF, 0xFF000000,0xFF000000,0xFFFFFFFF }; + video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); + texture = driver->addTexture( "$checkerimage", w ); + w->drop (); + } + } + else + if ( loadFile == "$lightmap" ) + { + texture = 0; + } + else + { + loadFile.append ( extension[g] ); + } + + if ( fileSystem->existFile ( loadFile ) ) + { + texture = driver->getTexture( loadFile ); + if ( texture ) + break; + texture = 0; } } // take 0 Texture diff --git a/src/dep/include/irrlicht/IReadFile.h b/src/dep/include/irrlicht/IReadFile.h index 0abbf13..8dc7b2c 100644 --- a/src/dep/include/irrlicht/IReadFile.h +++ b/src/dep/include/irrlicht/IReadFile.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,7 @@ #define __I_READ_FILE_H_INCLUDED__ #include "IReferenceCounted.h" +#include "coreutil.h" namespace irr { @@ -19,7 +20,7 @@ namespace io //! Reads an amount of bytes from the file. /** \param buffer Pointer to buffer where read bytes are written to. \param sizeToRead Amount of bytes to read from the file. - \return How much bytes were read. */ + \return How many bytes were read. */ virtual s32 read(void* buffer, u32 sizeToRead) = 0; //! Changes position in file @@ -40,15 +41,15 @@ namespace io //! Get name of file. /** \return File name as zero terminated character string. */ - virtual const c8* getFileName() const = 0; + virtual const io::path& getFileName() const = 0; }; //! Internal function, please do not use. - IReadFile* createReadFile(const c8* fileName); + IReadFile* createReadFile(const io::path& fileName); //! Internal function, please do not use. - IReadFile* createLimitReadFile(const c8* fileName, IReadFile* alreadyOpenedFile, long areaSize); + IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize); //! Internal function, please do not use. - IReadFile* createMemoryReadFile(void* memory, long size, const c8* fileName, bool deleteMemoryWhenDropped); + IReadFile* createMemoryReadFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped); } // end namespace io } // end namespace irr diff --git a/src/dep/include/irrlicht/IReferenceCounted.h b/src/dep/include/irrlicht/IReferenceCounted.h index 74397a7..822cde9 100644 --- a/src/dep/include/irrlicht/IReferenceCounted.h +++ b/src/dep/include/irrlicht/IReferenceCounted.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,7 +28,7 @@ namespace irr If you want to create a texture, you may want to call an imaginable method IDriver::createTexture. You call - ITexture* texture = driver->createTexture(dimension2d(128, 128)); + ITexture* texture = driver->createTexture(dimension2d(128, 128)); If you no longer need the texture, call texture->drop(). If you want to load a texture, you may want to call imaginable method @@ -44,7 +44,7 @@ namespace irr //! Constructor. IReferenceCounted() - : ReferenceCounter(1), DebugName(0) + : DebugName(0), ReferenceCounter(1) { } @@ -75,7 +75,7 @@ namespace irr If you want to create a texture, you may want to call an imaginable method IDriver::createTexture. You call - ITexture* texture = driver->createTexture(dimension2d(128, 128)); + ITexture* texture = driver->createTexture(dimension2d(128, 128)); If you no longer need the texture, call texture->drop(). If you want to load a texture, you may want to call imaginable method IDriver::loadTexture. You do this like @@ -104,7 +104,7 @@ namespace irr If you want to create a texture, you may want to call an imaginable method IDriver::createTexture. You call - ITexture* texture = driver->createTexture(dimension2d(128, 128)); + ITexture* texture = driver->createTexture(dimension2d(128, 128)); If you no longer need the texture, call texture->drop(). If you want to load a texture, you may want to call imaginable method IDriver::loadTexture. You do this like @@ -156,10 +156,12 @@ namespace irr } private: - //! The reference counter. Mutable to do reference counting on const objects. - mutable s32 ReferenceCounter; + //! The debug name. const c8* DebugName; + + //! The reference counter. Mutable to do reference counting on const objects. + mutable s32 ReferenceCounter; }; } // end namespace irr diff --git a/src/dep/include/irrlicht/ISceneCollisionManager.h b/src/dep/include/irrlicht/ISceneCollisionManager.h index 8d2b822..4021844 100644 --- a/src/dep/include/irrlicht/ISceneCollisionManager.h +++ b/src/dep/include/irrlicht/ISceneCollisionManager.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -25,23 +25,22 @@ namespace scene { public: - //! Destructor - virtual ~ISceneCollisionManager() {} - - //! Finds the collision point of a line and lots of triangles, if there is one. - /** \param ray: Line with witch collisions are tested. + //! Finds the nearest collision point of a line and lots of triangles, if there is one. + /** \param ray: Line with which collisions are tested. \param selector: TriangleSelector containing the triangles. It can be created for example using ISceneManager::createTriangleSelector() or - ISceneManager::createTriangleOctTreeSelector(). + ISceneManager::createTriangleOctreeSelector(). \param outCollisionPoint: If a collision is detected, this will - contain the position of the nearest collision. + contain the position of the nearest collision to the line-start. \param outTriangle: If a collision is detected, this will contain the triangle with which the ray collided. + \param outNode: If a collision is detected, this will contain + the scene node associated with the triangle that was hit. \return True if a collision was detected and false if not. */ virtual bool getCollisionPoint(const core::line3d& ray, - ITriangleSelector* selector, core::vector3df& outCollisionPoint, - core::triangle3df& outTriangle) = 0; + ITriangleSelector* selector, core::vector3df& outCollisionPoint, + core::triangle3df& outTriangle, const ISceneNode*& outNode) =0; //! Collides a moving ellipsoid with a 3d world with gravity and returns the resulting new position of the ellipsoid. /** This can be used for moving a character in a 3d world: The @@ -52,15 +51,17 @@ namespace scene \param selector: TriangleSelector containing the triangles of the world. It can be created for example using ISceneManager::createTriangleSelector() or - ISceneManager::createTriangleOctTreeSelector(). + ISceneManager::createTriangleOctreeSelector(). \param ellipsoidPosition: Position of the ellipsoid. \param ellipsoidRadius: Radius of the ellipsoid. \param ellipsoidDirectionAndSpeed: Direction and speed of the movement of the ellipsoid. \param triout: Optional parameter where the last triangle causing a collision is stored, if there is a collision. + \param hitPosition: Return value for the position of the collision \param outFalling: Is set to true if the ellipsoid is falling down, caused by gravity. + \param outNode: the node with which the ellipoid collided (if any) \param slidingSpeed: DOCUMENTATION NEEDED. \param gravityDirectionAndSpeed: Direction and force of gravity. \return New position of the ellipsoid. */ @@ -70,7 +71,9 @@ namespace scene const core::vector3df& ellipsoidRadius, const core::vector3df& ellipsoidDirectionAndSpeed, core::triangle3df& triout, + core::vector3df& hitPosition, bool& outFalling, + const ISceneNode*& outNode, f32 slidingSpeed = 0.0005f, const core::vector3df& gravityDirectionAndSpeed = core::vector3df(0.0f, 0.0f, 0.0f)) = 0; @@ -83,7 +86,7 @@ namespace scene at a length of the far value of the camera at a position which would be behind the 2d screen coodinates. */ virtual core::line3d getRayFromScreenCoordinates( - core::position2d pos, ICameraSceneNode* camera = 0) = 0; + const core::position2d & pos, ICameraSceneNode* camera = 0) = 0; //! Calculates 2d screen position from a 3d position. /** \param pos: 3D position in world space to be transformed @@ -97,48 +100,55 @@ namespace scene method for drawing a decorator over a 3d object, it will be clipped by the screen borders. */ virtual core::position2d getScreenCoordinatesFrom3DPosition( - core::vector3df pos, ICameraSceneNode* camera=0) = 0; + const core::vector3df & pos, ICameraSceneNode* camera=0) = 0; //! Gets the scene node, which is currently visible under the given screencoordinates, viewed from the currently active camera. /** The collision tests are done using a bounding box for each - scene node. + scene node. You can limit the recursive search so just all children of the specified root are tested. \param pos: Position in pixel screen coordinates, under which the returned scene node will be. \param idBitMask: Only scene nodes with an id with bits set like in this mask will be tested. If the BitMask is 0, this feature is disabled. + Please note that the default node id of -1 will match with + every bitmask != 0 \param bNoDebugObjects: Doesn't take debug objects into account when true. These are scene nodes with IsDebugObject() = true. + \param root If different from 0, the search is limited to the children of this node. \return Visible scene node under screen coordinates with matching bits in its id. If there is no scene node under this position, 0 is returned. */ - virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(core::position2d pos, - s32 idBitMask=0, bool bNoDebugObjects = false) = 0; + virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(const core::position2d& pos, + s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; - //! Get the nearest scene node which collides with a 3d ray and whose id matches a bitmask. + //! Returns the nearest scene node which collides with a 3d ray and whose id matches a bitmask. /** The collision tests are done using a bounding box for each - scene node. - \param ray: Line with witch collisions are tested. - \param idBitMask: Only scene nodes with an id with bits set - like in this mask will be tested. If the BitMask is 0, this - feature is disabled. - \param bNoDebugObjects: Doesn't take debug objects into account - when true. These are scene nodes with IsDebugObject() = true. + scene node. The recursive search can be limited be specifying a scene node. + \param ray Line with which collisions are tested. + \param idBitMask Only scene nodes with an id which matches at + least one of the bits contained in this mask will be tested. + However, if this parameter is 0, then all nodes are checked. + \param bNoDebugObjects: Doesn't take debug objects into account when true. These + are scene nodes with IsDebugObject() = true. + \param root If different from 0, the search is limited to the children of this node. \return Scene node nearest to ray.start, which collides with the ray and matches the idBitMask, if the mask is not null. If no scene node is found, 0 is returned. */ - virtual ISceneNode* getSceneNodeFromRayBB(core::line3d ray, - s32 idBitMask=0, bool bNoDebugObjects = false) = 0; + virtual ISceneNode* getSceneNodeFromRayBB(const core::line3d& ray, + s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; - //! Get the scene node, which the overgiven camera is looking at and whose id matches the bitmask. + //! Get the scene node, which the given camera is looking at and whose id matches the bitmask. /** A ray is simply casted from the position of the camera to the view target position, and all scene nodes are tested against this ray. The collision tests are done using a bounding box for each scene node. \param camera: Camera from which the ray is casted. - \param idBitMask: Only scene nodes with an id with bits set - like in this mask will be tested. If the BitMask is 0, this + \param idBitMask: Only scene nodes with an id which matches at least one of the + bits contained in this mask will be tested. However, if this parameter is 0, then + all nodes are checked. feature is disabled. + Please note that the default node id of -1 will match with + every bitmask != 0 \param bNoDebugObjects: Doesn't take debug objects into account when true. These are scene nodes with IsDebugObject() = true. \return Scene node nearest to the camera, which collides with @@ -146,6 +156,41 @@ namespace scene no scene node is found, 0 is returned. */ virtual ISceneNode* getSceneNodeFromCameraBB(ICameraSceneNode* camera, s32 idBitMask=0, bool bNoDebugObjects = false) = 0; + + //! Perform a ray/box and ray/triangle collision check on a heirarchy of scene nodes. + /** This checks all scene nodes under the specified one, first by ray/bounding + box, and then by accurate ray/triangle collision, finding the nearest collision, + and the scene node containg it. It returns the node hit, and (via output + parameters) the position of the collision, and the triangle that was hit. + + All scene nodes in the hierarchy tree under the specified node are checked. Only + nodes that are visible, with an ID that matches at least one bit in the supplied + bitmask, and which have a triangle selector are considered as candidates for being hit. + You do not have to build a meta triangle selector; the individual triangle selectors + of each candidate scene node are used automatically. + + \param ray: Line with which collisions are tested. + \param outCollisionPoint: If a collision is detected, this will contain the + position of the nearest collision. + \param outTriangle: If a collision is detected, this will contain the triangle + with which the ray collided. + \param idBitMask: Only scene nodes with an id which matches at least one of the + bits contained in this mask will be tested. However, if this parameter is 0, then + all nodes are checked. + \param collisionRootNode: the scene node at which to begin checking. Only this + node and its children will be checked. If you want to check the entire scene, + pass 0, and the root scene node will be used (this is the default). + \param noDebugObjects: when true, debug objects are not considered viable targets. + Debug objects are scene nodes with IsDebugObject() = true. + \return Returns the scene node containing the hit triangle nearest to ray.start. + If no collision is detected, then 0 is returned. */ + virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( + core::line3df ray, + core::vector3df & outCollisionPoint, + core::triangle3df & outTriangle, + s32 idBitMask = 0, + ISceneNode * collisionRootNode = 0, + bool noDebugObjects = false) = 0; }; diff --git a/src/dep/include/irrlicht/ISceneManager.h b/src/dep/include/irrlicht/ISceneManager.h index c0b3c36..153b0b9 100644 --- a/src/dep/include/irrlicht/ISceneManager.h +++ b/src/dep/include/irrlicht/ISceneManager.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,13 +7,18 @@ #include "IReferenceCounted.h" #include "irrArray.h" +#include "irrString.h" +#include "path.h" #include "vector3d.h" #include "dimension2d.h" #include "SColor.h" #include "ETerrainElements.h" #include "ESceneNodeTypes.h" +#include "ESceneNodeAnimatorTypes.h" #include "EMeshWriterEnums.h" #include "SceneParameters.h" +#include "IGeometryCreator.h" +#include "ISkinnedMesh.h" namespace irr { @@ -25,6 +30,7 @@ namespace io class IReadFile; class IAttributes; class IWriteFile; + class IFileSystem; } // end namespace io namespace gui @@ -50,14 +56,17 @@ namespace scene specifying when the node wants to be drawn in relation to the other nodes. */ enum E_SCENE_NODE_RENDER_PASS { + //! No pass currently active + ESNRP_NONE =0, + //! Camera pass. The active view is set up here. The very first pass. - ESNRP_CAMERA, + ESNRP_CAMERA =1, //! In this pass, lights are transformed into camera space and added to the driver - ESNRP_LIGHT, + ESNRP_LIGHT =2, //! This is used for sky boxes. - ESNRP_SKY_BOX, + ESNRP_SKY_BOX =4, //! All normal objects can use this for registering themselves. /** This value will never be returned by @@ -72,19 +81,19 @@ namespace scene render() method call getSceneNodeRenderPass() to find out the current render pass and render only the corresponding parts of the node. */ - ESNRP_AUTOMATIC, + ESNRP_AUTOMATIC =24, //! Solid scene nodes or special scene nodes without materials. - ESNRP_SOLID, + ESNRP_SOLID =8, + + //! Transparent scene nodes, drawn after solid nodes. They are sorted from back to front and drawn in that order. + ESNRP_TRANSPARENT =16, + + //! Transparent effect scene nodes, drawn after Transparent nodes. They are sorted from back to front and drawn in that order. + ESNRP_TRANSPARENT_EFFECT =32, //! Drawn after the transparent nodes, the time for drawing shadow volumes - ESNRP_SHADOW, - - //! Transparent scene nodes, drawn after shadow nodes. They are sorted from back to front and drawn in that order. - ESNRP_TRANSPARENT, - - //! Never used, value specifing how much parameters there are. - ESNRP_COUNT + ESNRP_SHADOW =64 }; class IMesh; @@ -113,16 +122,17 @@ namespace scene class ISceneNodeFactory; class ISceneNodeAnimatorFactory; class ISceneUserDataSerializer; + class ILightManager; namespace quake3 { - class SShader; + struct IShader; } // end namespace quake3 //! The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff. /** All Scene nodes can be created only here. There is a always growing list of scene nodes for lots of purposes: Indoor rendering scene nodes - like the Octree (addOctTreeSceneNode()) or the terrain renderer + like the Octree (addOctreeSceneNode()) or the terrain renderer (addTerrainSceneNode()), different Camera scene nodes (addCameraSceneNode(), addCameraSceneNodeMaya()), scene nodes for Light (addLightSceneNode()), Billboards (addBillboardSceneNode()) and so on. @@ -144,7 +154,7 @@ namespace scene //! Destructor virtual ~ISceneManager() {} - //! Returns pointer to an animateable mesh. Loads the file if not loaded already. + //! Get pointer to an animateable mesh. Loads the file if not loaded already. /** * If you want to remove a loaded mesh from the cache again, use removeMesh(). * Currently there are the following mesh formats supported: @@ -174,57 +184,58 @@ namespace scene * please note that you'll have to set the path of the * textures before loading .csm files. You can do this * using - * SceneManager->getParameters()->setParameter(scene::CSM_TEXTURE_PATH, + * SceneManager->getParameters()->setAttribute(scene::CSM_TEXTURE_PATH, * "path/to/your/textures"); * * * 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()->setAttribute(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) @@ -251,119 +262,123 @@ namespace scene * 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()->setAttribute(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()->setAttribute(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. + * \return Null if failed, otherwise pointer to the mesh. * This pointer should not be dropped. See IReferenceCounted::drop() for more information. **/ - virtual IAnimatedMesh* getMesh(const c8* filename) = 0; + virtual IAnimatedMesh* getMesh(const io::path& filename) = 0; - //! Returns pointer to an animateable mesh. Loads the file if not loaded already. + //! Get pointer to an animateable mesh. Loads the file if not loaded already. /** 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 0 if failed and pointer to the mesh if successful. + \return NULL 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; - //! Returns an interface to the mesh cache which is shared beween all existing scene managers. + //! Get interface to the mesh cache which is shared beween all existing scene managers. /** With this interface, it is possible to manually add new loaded meshes (if ISceneManager::getMesh() is not sufficient), to remove them and to iterate through already loaded meshes. */ virtual IMeshCache* getMeshCache() = 0; - //! Returns the video driver. - /** \return Returns pointer to the video Driver. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + //! Get the video driver. + /** \return Pointer to the video Driver. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual video::IVideoDriver* getVideoDriver() = 0; - //! Returns the active GUIEnvironment - /** \return Returns pointer to the GUIEnvironment - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + //! Get the active GUIEnvironment + /** \return Pointer to the GUIEnvironment + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual gui::IGUIEnvironment* getGUIEnvironment() = 0; + //! Get the active FileSystem + /** \return Pointer to the FileSystem + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual io::IFileSystem* getFileSystem() = 0; + //! adds Volume Lighting Scene Node. - //! the returned pointer must not be dropped. /** Example Usage: - scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(NULL, -1, + scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(0, -1, 32, 32, //Subdivide U/V video::SColor(0, 180, 180, 180), //foot color video::SColor(0, 0, 0, 0) //tail color @@ -373,7 +388,8 @@ namespace scene n->setScale(core::vector3df(46.0f, 45.0f, 46.0f)); n->getMaterial(0).setTexture(0, smgr->getVideoDriver()->getTexture("lightFalloff.png")); } - **/ + \return Pointer to the volumeLight if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IVolumeLightSceneNode* addVolumeLightSceneNode(ISceneNode* parent=0, s32 id=-1, const u32 subdivU = 32, const u32 subdivV = 32, const video::SColor foot = video::SColor(51, 0, 230, 180), @@ -382,17 +398,15 @@ namespace scene const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; - - //! Adds a test scene node for test purposes to the scene. - /** It is a simple cube of (1,1,1) size. - \param size: Size of the cube. - \param parent: Parent of the scene node. Can be NULL if no parent. + //! Adds a cube scene node + /** \param size: Size of the cube, uniformly in each dimension. + \param parent: Parent of the scene node. Can be 0 if no parent. \param id: Id of the node. This id can be used to identify the scene node. - \param position: Position of the space relative to its parent where the - scene node will be placed. + \param position: Position of the space relative to its parent + where the scene node will be placed. \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. - \return Returns pointer to the created test scene node. This + \return Pointer to the created test scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, @@ -400,17 +414,19 @@ namespace scene const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; - //! Adds a sphere scene node for test purposes to the scene. - /** It is a simple sphere. - \param radius: Radius of the sphere. - \param polyCount: Polycount of the sphere. - \param parent: Parent of the scene node. Can be NULL if no parent. + //! Adds a sphere scene node of the given radius and detail + /** \param radius: Radius of the sphere. + \param polyCount: The number of vertices in horizontal and + vertical direction. The total polyCount of the sphere is + polyCount*polyCount. This parameter must be less than 256 to + stay within the 16-bit limit of the indices of a meshbuffer. + \param parent: Parent of the scene node. Can be 0 if no parent. \param id: Id of the node. This id can be used to identify the scene node. - \param position: Position of the space relative to its parent where the - scene node will be placed. + \param position: Position of the space relative to its parent + where the scene node will be placed. \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. - \return Returns pointer to the created test scene node. This + \return Pointer to the created test scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, @@ -428,7 +444,7 @@ namespace scene \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Returns pointer to the created scene node. + \return Pointer to the created scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IAnimatedMeshSceneNode* addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, @@ -446,7 +462,7 @@ namespace scene \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Returns pointer to the created scene node. + \return Pointer to the created scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshSceneNode* addMeshSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), @@ -477,67 +493,92 @@ namespace scene const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; - //! Adds a scene node for rendering using a octtree to the scene graph. - /** This a good method for rendering - scenes with lots of geometry. The Octree is built on the fly from the mesh. - \param mesh: The mesh containing all geometry from which the octtree will be build. - If this animated mesh has more than one frames in it, the first frame is taken. - \param parent: Parent node of the octtree node. - \param id: id of the node. This id can be used to identify the node. - \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. - If a node gets less polys than this value it will not be split into - smaller nodes. - \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Pointer to the OctTree if successful, otherwise 0. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, - s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; - - //! Adds a scene node for rendering using a octtree to the scene graph. - /** This a good method for rendering scenes with lots of - geometry. The Octree is built on the fly from the mesh, much - faster then a bsp tree. - \param mesh: The mesh containing all geometry from which the octtree will be build. - \param parent: Parent node of the octtree node. + //! Adds a scene node for rendering using a octree to the scene graph. + /** This a good method for rendering + scenes with lots of geometry. The Octree is built on the fly from the mesh. + \param mesh: The mesh containing all geometry from which the octree will be build. + If this animated mesh has more than one frames in it, the first frame is taken. + \param parent: Parent node of the octree node. \param id: id of the node. This id can be used to identify the node. \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. If a node gets less polys than this value it will not be split into smaller nodes. \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Pointer to the octtree if successful, otherwise 0. + \return Pointer to the Octree if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + virtual IMeshSceneNode* addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; + + //! Adds a scene node for rendering using a octree to the scene graph. + /** \deprecated Use addOctreeSceneNode instead. */ + _IRR_DEPRECATED_ IMeshSceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) + { + return addOctreeSceneNode(mesh, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); + } + + //! Adds a scene node for rendering using a octree to the scene graph. + /** This a good method for rendering scenes with lots of + geometry. The Octree is built on the fly from the mesh, much + faster then a bsp tree. + \param mesh: The mesh containing all geometry from which the octree will be build. + \param parent: Parent node of the octree node. + \param id: id of the node. This id can be used to identify the node. + \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. + If a node gets less polys than this value it will not be split into + smaller nodes. + \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. + \return Pointer to the octree if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IMeshSceneNode* addOctreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; + //! Adds a scene node for rendering using a octree to the scene graph. + /** \deprecated Use addOctreeSceneNode instead. */ + _IRR_DEPRECATED_ IMeshSceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) + { + return addOctreeSceneNode(mesh, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); + } + //! Adds a camera scene node to the scene graph and sets it as active camera. /** This camera does not react on user input like for example the one created with addCameraSceneNodeFPS(). If you want to move or animate it, use animators or the ISceneNode::setPosition(), ICameraSceneNode::setTarget() etc methods. - \param position: Position of the space relative to its parent where the camera will be placed. - \param lookat: Position where the camera will look at. Also known as target. - \param parent: Parent scene node of the camera. Can be null. If the parent moves, - the camera will move too. - \param id: id of the camera. This id can be used to identify the camera. - \return Returns pointer to interface to camera if successful, otherwise 0. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + By default, a camera's look at position (set with setTarget()) and its scene node + rotation (set with setRotation()) are independent. If you want to be able to + control the direction that the camera looks by using setRotation() then call + ICameraSceneNode::bindTargetAndRotation(true) on it. + \param position: Position of the space relative to its parent where the camera will be placed. + \param lookat: Position where the camera will look at. Also known as target. + \param parent: Parent scene node of the camera. Can be null. If the parent moves, + the camera will move too. + \param id: id of the camera. This id can be used to identify the camera. + \param makeActive Flag whether this camera should become the active one. + Make sure you always have one active camera. + \return Pointer to interface to camera if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ICameraSceneNode* addCameraSceneNode(ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& lookat = core::vector3df(0,0,100), s32 id=-1) = 0; + const core::vector3df& lookat = core::vector3df(0,0,100), + s32 id=-1, bool makeActive=true) = 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. + /** 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: Translation 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 Pointer to the interface of the camera if successful, otherwise 0. - This pointer should not be dropped. See - IReferenceCounted::drop() for more information. */ + \param makeActive Flag whether this camera should become the active one. + Make sure you always have one active 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. */ virtual ICameraSceneNode* addCameraSceneNodeMaya(ISceneNode* parent = 0, f32 rotateSpeed = -1500.0f, f32 zoomSpeed = 200.0f, - f32 translationSpeed = 1500.0f, s32 id=-1) = 0; + f32 translationSpeed = 1500.0f, s32 id=-1, + bool makeActive=true) = 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 @@ -545,32 +586,32 @@ namespace scene 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, + 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; + 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 @@ -579,39 +620,49 @@ namespace scene 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 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 + \param jumpSpeed: Speed with which the camera is moved when + jumping. + \param invertMouse: Setting this to true makes the camera look + up when the mouse is moved down and down when the mouse is + moved up, the default is 'false' which means it will follow the + movement of the mouse cursor. + \param makeActive Flag whether this camera should become the active one. + Make sure you always have one active 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* addCameraSceneNodeFPS(ISceneNode* parent = 0, - f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, s32 id=-1, + f32 rotateSpeed = 100.0f, f32 moveSpeed = 0.5f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, - f32 jumpSpeed = 0.f) = 0; + f32 jumpSpeed = 0.f, bool invertMouse=false, + bool makeActive=true) = 0; //! Adds a dynamic light scene node to the scene graph. /** The light will cast dynamic light on all - other scene nodes in the scene, which have the material flag video::MTF_LIGHTING - turned on. (This is the default setting in most scene nodes). - \param parent: Parent scene node of the light. Can be null. If the parent moves, - the light will move too. - \param position: Position of the space relative to its parent where the light will be placed. - \param color: Diffuse color of the light. Ambient or Specular colors can be set manually with - the ILightSceneNode::getLightData() method. - \param radius: Radius of the light. - \param id: id of the node. This id can be used to identify the node. - \return Returns pointer to the interface of the light if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + other scene nodes in the scene, which have the material flag video::MTF_LIGHTING + turned on. (This is the default setting in most scene nodes). + \param parent: Parent scene node of the light. Can be null. If the parent moves, + the light will move too. + \param position: Position of the space relative to its parent where the light will be placed. + \param color: Diffuse color of the light. Ambient or Specular colors can be set manually with + the ILightSceneNode::getLightData() method. + \param radius: Radius of the light. + \param id: id of the node. This id can be used to identify the node. + \return Pointer to the interface of the light if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ILightSceneNode* addLightSceneNode(ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), video::SColorf color = video::SColorf(1.0f, 1.0f, 1.0f), @@ -619,19 +670,19 @@ namespace scene //! Adds a billboard scene node to the scene graph. /** A billboard is like a 3d sprite: A 2d element, - which always looks to the camera. It is usually used for things like explosions, fire, - lensflares and things like that. - \param parent: Parent scene node of the billboard. Can be null. If the parent moves, - the billboard will move too. - \param position: Position of the space relative to its parent - where the billboard will be placed. - \param size: Size of the billboard. This size is 2 dimensional because a billboard only has - width and height. - \param id: An id of the node. This id can be used to identify the node. - \param colorTop: The color of the vertices at the top of the billboard (default: white). - \param colorBottom: The color of the vertices at the bottom of the billboard (default: white). - \return Returns pointer to the billboard if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + which always looks to the camera. It is usually used for things like explosions, fire, + lensflares and things like that. + \param parent: Parent scene node of the billboard. Can be null. If the parent moves, + the billboard will move too. + \param position: Position of the space relative to its parent + where the billboard will be placed. + \param size: Size of the billboard. This size is 2 dimensional because a billboard only has + width and height. + \param id: An id of the node. This id can be used to identify the node. + \param colorTop: The color of the vertices at the top of the billboard (default: white). + \param colorBottom: The color of the vertices at the bottom of the billboard (default: white). + \return Pointer to the billboard if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IBillboardSceneNode* addBillboardSceneNode(ISceneNode* parent = 0, const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, @@ -639,58 +690,59 @@ namespace scene //! Adds a skybox scene node to the scene graph. /** A skybox is a big cube with 6 textures on it and - is drawn around the camera position. - \param top: Texture for the top plane of the box. - \param bottom: Texture for the bottom plane of the box. - \param left: Texture for the left plane of the box. - \param right: Texture for the right plane of the box. - \param front: Texture for the front plane of the box. - \param back: Texture for the back plane of the box. - \param parent: Parent scene node of the skybox. A skybox usually has no parent, - so this should be null. Note: If a parent is set to the skybox, the box will not - change how it is drawn. - \param id: An id of the node. This id can be used to identify the node. - \return Returns a pointer to the sky box if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + is drawn around the camera position. + \param top: Texture for the top plane of the box. + \param bottom: Texture for the bottom plane of the box. + \param left: Texture for the left plane of the box. + \param right: Texture for the right plane of the box. + \param front: Texture for the front plane of the box. + \param back: Texture for the back plane of the box. + \param parent: Parent scene node of the skybox. A skybox usually has no parent, + so this should be null. Note: If a parent is set to the skybox, the box will not + change how it is drawn. + \param id: An id of the node. This id can be used to identify the node. + \return Pointer to the sky box if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, video::ITexture* left, video::ITexture* right, video::ITexture* front, video::ITexture* back, ISceneNode* parent = 0, s32 id=-1) = 0; //! Adds a skydome scene node to the scene graph. /** A skydome is a large (half-) sphere with a panoramic texture - on the inside and is drawn around the camera position. - \param texture: Texture for the dome. - \param horiRes: Number of vertices of a horizontal layer of the sphere. - \param vertRes: Number of vertices of a vertical layer of the sphere. - \param texturePercentage: How much of the height of the - texture is used. Should be between 0 and 1. - \param spherePercentage: How much of the sphere is drawn. - Value should be between 0 and 2, where 1 is an exact - half-sphere and 2 is a full sphere. - \param parent: Parent scene node of the dome. A dome usually has no parent, - so this should be null. Note: If a parent is set, the dome will not - change how it is drawn. - \param id: An id of the node. This id can be used to identify the node. - \return Returns a pointer to the sky dome if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + on the inside and is drawn around the camera position. + \param texture: Texture for the dome. + \param horiRes: Number of vertices of a horizontal layer of the sphere. + \param vertRes: Number of vertices of a vertical layer of the sphere. + \param texturePercentage: How much of the height of the + texture is used. Should be between 0 and 1. + \param spherePercentage: How much of the sphere is drawn. + Value should be between 0 and 2, where 1 is an exact + half-sphere and 2 is a full sphere. + \param radius The Radius of the sphere + \param parent: Parent scene node of the dome. A dome usually has no parent, + so this should be null. Note: If a parent is set, the dome will not + change how it is drawn. + \param id: An id of the node. This id can be used to identify the node. + \return 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=16, u32 vertRes=8, - f64 texturePercentage=0.9, f64 spherePercentage=2.0, + f32 texturePercentage=0.9, f32 spherePercentage=2.0,f32 radius = 1000.f, 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 - which emitts some particles. Set this to true to see a particle system - in action. If set to false, you'll have to set the emitter you want by - calling IParticleSystemSceneNode::setEmitter(). - \param parent: Parent of the scene node. Can be NULL if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: Position of the space relative to its parent where the - scene node will be placed. - \param rotation: Initital rotation of the scene node. - \param scale: Initial scale of the scene node. - \return Returns pointer to the created scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + which emitts some particles. Set this to true to see a particle system + in action. If set to false, you'll have to set the emitter you want by + calling IParticleSystemSceneNode::setEmitter(). + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \return Pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IParticleSystemSceneNode* addParticleSystemSceneNode( bool withDefaultEmitter=true, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), @@ -699,62 +751,62 @@ namespace scene //! Adds a terrain scene node to the scene graph. /** This node implements is a simple terrain renderer which uses - a technique known as geo mip mapping - for reducing the detail of triangle blocks which are far away. - The code for the TerrainSceneNode is based on the terrain - renderer by Soconne and the GeoMipMapSceneNode developed by - Spintz. They made their code available for Irrlicht and allowed - it to be distributed under this licence. I only modified some - parts. A lot of thanks go to them. + a technique known as geo mip mapping + for reducing the detail of triangle blocks which are far away. + The code for the TerrainSceneNode is based on the terrain + renderer by Soconne and the GeoMipMapSceneNode developed by + Spintz. They made their code available for Irrlicht and allowed + it to be distributed under this licence. I only modified some + parts. A lot of thanks go to them. - This scene node is capable of loading terrains and updating - the indices at runtime to enable viewing very large terrains - very quickly. 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. + This scene node is capable of loading terrains and updating + the indices at runtime to enable viewing very large terrains + very quickly. 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. - 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 of the indices to draw all - the triangles at the max detail for a patch. As each LOD goes - up by 1 the step taken, in generating indices increases by - -2^LOD, so for LOD 1, the step taken is 2, for LOD 2, the step - taken is 4, LOD 3 - 8, etc. The step can be no larger than - the size of the patch, so having a LOD of 8, with a patch size - of 17, is asking the algoritm to generate indices every 2^8 ( - 256 ) vertices, which is not possible with a patch size of 17. - The maximum LOD for a patch size of 17 is 2^4 ( 16 ). So, - with a MaxLOD of 5, you'll have LOD 0 ( full detail ), LOD 1 ( - every 2 vertices ), LOD 2 ( every 4 vertices ), LOD 3 ( every - 8 vertices ) and LOD 4 ( every 16 vertices ). - \param heightMapFileName: The name of the file on disk, to read vertex data from. This should - be a gray scale bitmap. - \param parent: Parent of the scene node. Can be 0 if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: The absolute position of this node. - \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) - \param scale: The scale factor for the terrain. If you're - using a heightmap of size 129x129 and would like your terrain - to be 12900x12900 in game units, then use a scale factor of ( - core::vector ( 100.0f, 100.0f, 100.0f ). If you use a Y - scaling factor of 0.0f, then your terrain will be flat. - \param vertexColor: The default color of all the vertices. If no texture is associated - with the scene node, then all vertices will be this color. Defaults to white. - \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you - know what you are doing, this might lead to strange behaviour. - \param patchSize: patch size of the terrain. Only change if you - know what you are doing, this might lead to strange behaviour. - \param smoothFactor: The number of times the vertices are smoothed. - \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. - \return Returns pointer to the created scene node. Can be null - if the terrain could not be created, for example because the - heightmap could not be loaded. The returned pointer should - not be dropped. See IReferenceCounted::drop() for more - information. */ + 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 of the indices to draw all + the triangles at the max detail for a patch. As each LOD goes + up by 1 the step taken, in generating indices increases by + -2^LOD, so for LOD 1, the step taken is 2, for LOD 2, the step + taken is 4, LOD 3 - 8, etc. The step can be no larger than + the size of the patch, so having a LOD of 8, with a patch size + of 17, is asking the algoritm to generate indices every 2^8 ( + 256 ) vertices, which is not possible with a patch size of 17. + The maximum LOD for a patch size of 17 is 2^4 ( 16 ). So, + with a MaxLOD of 5, you'll have LOD 0 ( full detail ), LOD 1 ( + every 2 vertices ), LOD 2 ( every 4 vertices ), LOD 3 ( every + 8 vertices ) and LOD 4 ( every 16 vertices ). + \param heightMapFileName: The name of the file on disk, to read vertex data from. This should + be a gray scale bitmap. + \param parent: Parent of the scene node. Can be 0 if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: The absolute position of this node. + \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) + \param scale: The scale factor for the terrain. If you're + using a heightmap of size 129x129 and would like your terrain + to be 12900x12900 in game units, then use a scale factor of ( + core::vector ( 100.0f, 100.0f, 100.0f ). If you use a Y + scaling factor of 0.0f, then your terrain will be flat. + \param vertexColor: The default color of all the vertices. If no texture is associated + with the scene node, then all vertices will be this color. Defaults to white. + \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you + know what you are doing, this might lead to strange behaviour. + \param patchSize: patch size of the terrain. Only change if you + know what you are doing, this might lead to strange behaviour. + \param smoothFactor: The number of times the vertices are smoothed. + \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. + \return Pointer to the created scene node. Can be null + if the terrain could not be created, for example because the + heightmap could not be loaded. The returned pointer should + not be dropped. See IReferenceCounted::drop() for more + information. */ virtual ITerrainSceneNode* addTerrainSceneNode( - const c8* heightMapFileName, + const io::path& heightMapFileName, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), @@ -765,32 +817,32 @@ namespace scene //! Adds a terrain scene node to the scene graph. /** Just like the other addTerrainSceneNode() method, but takes an IReadFile - pointer as parameter for the heightmap. For more informations take a look - at the other function. - \param heightMapFile: The file handle to read vertex data from. This should - be a gray scale bitmap. - \param parent: Parent of the scene node. Can be 0 if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: The absolute position of this node. - \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) - \param scale: The scale factor for the terrain. If you're - using a heightmap of size 129x129 and would like your terrain - to be 12900x12900 in game units, then use a scale factor of ( - core::vector ( 100.0f, 100.0f, 100.0f ). If you use a Y - scaling factor of 0.0f, then your terrain will be flat. - \param vertexColor: The default color of all the vertices. If no texture is associated - with the scene node, then all vertices will be this color. Defaults to white. - \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you - know what you are doing, this might lead to strange behaviour. - \param patchSize: patch size of the terrain. Only change if you - know what you are doing, this might lead to strange behaviour. - \param smoothFactor: The number of times the vertices are smoothed. - \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. - \return Returns pointer to the created scene node. Can be null - if the terrain could not be created, for example because the - heightmap could not be loaded. The returned pointer should - not be dropped. See IReferenceCounted::drop() for more - information. */ + pointer as parameter for the heightmap. For more informations take a look + at the other function. + \param heightMapFile: The file handle to read vertex data from. This should + be a gray scale bitmap. + \param parent: Parent of the scene node. Can be 0 if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: The absolute position of this node. + \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) + \param scale: The scale factor for the terrain. If you're + using a heightmap of size 129x129 and would like your terrain + to be 12900x12900 in game units, then use a scale factor of ( + core::vector ( 100.0f, 100.0f, 100.0f ). If you use a Y + scaling factor of 0.0f, then your terrain will be flat. + \param vertexColor: The default color of all the vertices. If no texture is associated + with the scene node, then all vertices will be this color. Defaults to white. + \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you + know what you are doing, this might lead to strange behaviour. + \param patchSize: patch size of the terrain. Only change if you + know what you are doing, this might lead to strange behaviour. + \param smoothFactor: The number of times the vertices are smoothed. + \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. + \return Pointer to the created scene node. Can be null + if the terrain could not be created, for example because the + heightmap could not be loaded. The returned pointer should + not be dropped. See IReferenceCounted::drop() for more + information. */ virtual ITerrainSceneNode* addTerrainSceneNode( io::IReadFile* heightMapFile, ISceneNode* parent=0, s32 id=-1, @@ -803,27 +855,27 @@ namespace scene //! Adds a quake3 scene node to the scene graph. /** A Quake3 Scene renders multiple meshes for a specific HighLanguage Shader (Quake3 Style ) - \return Returns a pointer to the quake3 scene node if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addQuake3SceneNode(IMeshBuffer* meshBuffer, const quake3::SShader * shader, + \return Pointer to the quake3 scene node if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent=0, s32 id=-1 ) = 0; //! Adds an empty scene node to the scene graph. /** Can be used for doing advanced transformations - or structuring the scene graph. - \return Returns pointer to the created scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + or structuring the scene graph. + \return Pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addEmptySceneNode(ISceneNode* parent=0, s32 id=-1) = 0; //! Adds a dummy transformation scene node to the scene graph. /** This scene node does not render itself, and does not respond to set/getPosition, - set/getRotation and set/getScale. Its just a simple scene node that takes a - matrix as relative transformation, making it possible to insert any transformation - anywhere into the scene graph. - \return Returns pointer to the created scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + set/getRotation and set/getScale. Its just a simple scene node that takes a + matrix as relative transformation, making it possible to insert any transformation + anywhere into the scene graph. + \return Pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IDummyTransformationSceneNode* addDummyTransformationSceneNode( ISceneNode* parent=0, s32 id=-1) = 0; @@ -840,9 +892,10 @@ namespace scene \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 id: An id of the node. This id can be used to identify the node. \param colorTop: The color of the vertices at the top of the billboard (default: white). \param colorBottom: The color of the vertices at the bottom of the billboard (default: white). - \return Returns pointer to the billboard if successful, otherwise NULL. + \return Pointer to the billboard if successful, otherwise NULL. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IBillboardTextSceneNode* addBillboardTextSceneNode( gui::IGUIFont* font, const wchar_t* text, ISceneNode* parent = 0, @@ -852,65 +905,65 @@ namespace scene //! Adds a Hill Plane mesh to the mesh pool. /** The mesh is generated on the fly - and looks like a plane with some hills on it. It is uses mostly for quick - tests of the engine only. You can specify how many hills there should be - on the plane and how high they should be. Also you must specify a name for - the mesh, because the mesh is added to the mesh pool, and can be retrieved - again using ISceneManager::getMesh() with the name as parameter. - \param name: The name of this mesh which must be specified in order - to be able to retrieve the mesh later with ISceneManager::getMesh(). - \param tileSize: Size of a tile of the mesh. (10.0f, 10.0f) would be a - good value to start, for example. - \param tileCount: Specifies how much tiles there will be. If you specifiy - for example that a tile has the size (10.0f, 10.0f) and the tileCount is - (10,10), than you get a field of 100 tiles which has the dimension 100.0fx100.0f. - \param material: Material of the hill mesh. - \param hillHeight: Height of the hills. If you specify a negative value - you will get holes instead of hills. If the height is 0, no hills will be - created. - \param countHills: Amount of hills on the plane. There will be countHills.X - hills along the X axis and countHills.Y along the Y axis. So in total there - will be countHills.X * countHills.Y hills. - \param textureRepeatCount: Defines how often the texture will be repeated in - x and y direction. - \return Returns null if the creation failed. The reason could be that you - specified some invalid parameters or that a mesh with that name already - exists. If successful, a pointer to the mesh is returned. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IAnimatedMesh* addHillPlaneMesh(const c8* name, + and looks like a plane with some hills on it. It is uses mostly for quick + tests of the engine only. You can specify how many hills there should be + on the plane and how high they should be. Also you must specify a name for + the mesh, because the mesh is added to the mesh pool, and can be retrieved + again using ISceneManager::getMesh() with the name as parameter. + \param name: The name of this mesh which must be specified in order + to be able to retrieve the mesh later with ISceneManager::getMesh(). + \param tileSize: Size of a tile of the mesh. (10.0f, 10.0f) would be a + good value to start, for example. + \param tileCount: Specifies how much tiles there will be. If you specifiy + for example that a tile has the size (10.0f, 10.0f) and the tileCount is + (10,10), than you get a field of 100 tiles which has the dimension 100.0fx100.0f. + \param material: Material of the hill mesh. + \param hillHeight: Height of the hills. If you specify a negative value + you will get holes instead of hills. If the height is 0, no hills will be + created. + \param countHills: Amount of hills on the plane. There will be countHills.X + hills along the X axis and countHills.Y along the Y axis. So in total there + will be countHills.X * countHills.Y hills. + \param textureRepeatCount: Defines how often the texture will be repeated in + x and y direction. + return Null if the creation failed. The reason could be that you + specified some invalid parameters or that a mesh with that name already + exists. If successful, a pointer to the mesh is returned. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addHillPlaneMesh(const io::path& name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material = 0, f32 hillHeight = 0.0f, const core::dimension2d& countHills = core::dimension2d(0.0f, 0.0f), const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)) = 0; - //! Adds a static terrain mesh to the mesh pool. - /** The mesh is generated on the fly - from a texture file and a height map file. Both files may be huge - (8000x8000 pixels would be no problem) because the generator splits the - files into smaller textures if necessary. - You must specify a name for the mesh, because the mesh is added to the mesh pool, - and can be retrieved again using ISceneManager::getMesh() with the name as parameter. - \param meshname: The name of this mesh which must be specified in order - to be able to retrieve the mesh later with ISceneManager::getMesh(). - \param texture: Texture for the terrain. Please note that this is not a - hardware texture as usual (ITexture), but an IImage software texture. - You can load this texture with IVideoDriver::createImageFromFile(). - \param heightmap: A grayscaled heightmap image. Like the texture, - it can be created with IVideoDriver::createImageFromFile(). The amount - of triangles created depends on the size of this texture, so use a small - heightmap to increase rendering speed. - \param stretchSize: Parameter defining how big a is pixel on the heightmap. - \param maxHeight: Defines how high a white pixel on the heighmap is. - \param defaultVertexBlockSize: Defines the initial dimension between vertices. - \return Returns null if the creation failed. The reason could be that you - specified some invalid parameters, that a mesh with that name already - exists, or that a texture could not be found. If successful, a pointer to the mesh is returned. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IAnimatedMesh* addTerrainMesh(const c8* meshname, + //! Adds a static terrain mesh to the mesh pool. + /** The mesh is generated on the fly + from a texture file and a height map file. Both files may be huge + (8000x8000 pixels would be no problem) because the generator splits the + files into smaller textures if necessary. + You must specify a name for the mesh, because the mesh is added to the mesh pool, + and can be retrieved again using ISceneManager::getMesh() with the name as parameter. + \param meshname: The name of this mesh which must be specified in order + to be able to retrieve the mesh later with ISceneManager::getMesh(). + \param texture: Texture for the terrain. Please note that this is not a + hardware texture as usual (ITexture), but an IImage software texture. + You can load this texture with IVideoDriver::createImageFromFile(). + \param heightmap: A grayscaled heightmap image. Like the texture, + it can be created with IVideoDriver::createImageFromFile(). The amount + of triangles created depends on the size of this texture, so use a small + heightmap to increase rendering speed. + \param stretchSize: Parameter defining how big a is pixel on the heightmap. + \param maxHeight: Defines how high a white pixel on the heighmap is. + \param defaultVertexBlockSize: Defines the initial dimension between vertices. + \return Null if the creation failed. The reason could be that you + specified some invalid parameters, that a mesh with that name already + exists, or that a texture could not be found. If successful, a pointer to the mesh is returned. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addTerrainMesh(const io::path& meshname, video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize = core::dimension2d(10.0f,10.0f), f32 maxHeight=200.0f, - const core::dimension2d& defaultVertexBlockSize = core::dimension2d(64,64)) = 0; + const core::dimension2d& defaultVertexBlockSize = core::dimension2d(64,64)) = 0; //! add a static arrow mesh to the meshpool /** \param name Name of the mesh @@ -921,8 +974,10 @@ namespace scene \param height Total height of the arrow \param cylinderHeight Total height of the cylinder, should be lesser than total height \param width0 Diameter of the cylinder - \param width1 Diameter of the cone's base, should be not smaller than the cylinder's diameter */ - virtual IAnimatedMesh* addArrowMesh(const c8* name, + \param width1 Diameter of the cone's base, should be not smaller than the cylinder's diameter + \return Pointer to the arrow mesh if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addArrowMesh(const io::path& name, video::SColor vtxColor0=0xFFFFFFFF, video::SColor vtxColor1=0xFFFFFFFF, u32 tesselationCylinder=4, u32 tesselationCone=8, @@ -933,44 +988,64 @@ namespace scene /** \param name Name of the mesh \param radius Radius of the sphere \param polyCountX Number of quads used for the horizontal tiling - \param polyCountY Number of quads used for the vertical tiling */ - virtual IAnimatedMesh* addSphereMesh(const c8* name, + \param polyCountY Number of quads used for the vertical tiling + \return Pointer to the sphere mesh if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addSphereMesh(const io::path& name, f32 radius=5.f, u32 polyCountX = 16, u32 polyCountY = 16) = 0; - //! Returns the root scene node. + //! Add a volume light mesh to the meshpool + /** \param name Name of the mesh + \param SubdivideU Horizontal subdivision count + \param SubdivideV Vertical subdivision count + \param FootColor Color of the bottom of the light + \param TailColor Color of the top of the light + \return Pointer to the volume light mesh if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. + */ + virtual IAnimatedMesh* addVolumeLightMesh(const io::path& name, + const u32 SubdivideU = 32, const u32 SubdivideV = 32, + const video::SColor FootColor = video::SColor(51, 0, 230, 180), + const video::SColor TailColor = video::SColor(0, 0, 0, 0)) = 0; + + //! Gets the root scene node. /** This is the scene node which is parent - of all scene nodes. The root scene node is a special scene node which - only exists to manage all scene nodes. It will not be rendered and cannot - be removed from the scene. - \return Returns a pointer to the root scene node. */ + of all scene nodes. The root scene node is a special scene node which + only exists to manage all scene nodes. It will not be rendered and cannot + be removed from the scene. + \return Pointer to the root scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* getRootSceneNode() = 0; - //! Returns the first scene node with the specified id. + //! Get the first scene node with the specified id. /** \param id: The id to search for - \param start: Scene node to start from. All children of this scene - node are searched. If null is specified, the root scene node is - taken. - \return Returns pointer to the first scene node with this id, - and null if no scene node could be found. */ + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. + \return Pointer to the first scene node with this id, + and null if no scene node could be found. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* getSceneNodeFromId(s32 id, ISceneNode* start=0) = 0; - //! Returns the first scene node with the specified name. + //! Get the first scene node with the specified name. /** \param name: The name to search for - \param start: Scene node to start from. All children of this scene - node are searched. If null is specified, the root scene node is - taken. - \return Returns pointer to the first scene node with this id, - and null if no scene node could be found. */ + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. + \return Pointer to the first scene node with this id, + and null if no scene node could be found. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* getSceneNodeFromName(const c8* name, ISceneNode* start=0) = 0; - //! Returns the first scene node with the specified type. + //! Get the first scene node with the specified type. /** \param type: The type to search for - \param start: Scene node to start from. All children of this scene - node are searched. If null is specified, the root scene node is - taken. - \return Returns pointer to the first scene node with this type, - and null if no scene node could be found. */ + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. + \return Pointer to the first scene node with this type, + and null if no scene node could be found. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start=0) = 0; //! Get scene nodes by type. @@ -984,126 +1059,137 @@ namespace scene ISceneNode* start=0) = 0; //! Get the current active camera. - /** \return The active camera is returned. Note that this can be NULL, if there - was no camera created yet. */ - virtual ICameraSceneNode* getActiveCamera() = 0; + /** \return The active camera is returned. Note that this can + be NULL, if there was no camera created yet. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ICameraSceneNode* getActiveCamera() const =0; //! Sets the currently active camera. /** The previous active camera will be deactivated. - \param camera: The new camera which should be active. */ + \param camera: The new camera which should be active. */ virtual void setActiveCamera(ICameraSceneNode* camera) = 0; //! Sets the color of stencil buffers shadows drawn by the scene manager. virtual void setShadowColor(video::SColor color = video::SColor(150,0,0,0)) = 0; - //! Returns the current color of shadows. + //! Get the current color of shadows. virtual video::SColor getShadowColor() const = 0; //! Registers a node for rendering it at a specific time. /** This method should only be used by SceneNodes when they get a - ISceneNode::OnRegisterSceneNode() call. - \param node: Node to register for drawing. Usually scene nodes would set 'this' - as parameter here because they want to be drawn. - \param pass: Specifies when the node wants to be drawn in relation to the other nodes. - For example, if the node is a shadow, it usually wants to be drawn after all other nodes - and will use ESNRP_SHADOW for this. See scene::E_SCENE_NODE_RENDER_PASS for details. - \return scene will be rendered ( passed culling ) */ + ISceneNode::OnRegisterSceneNode() call. + \param node: Node to register for drawing. Usually scene nodes would set 'this' + as parameter here because they want to be drawn. + \param pass: Specifies when the node wants to be drawn in relation to the other nodes. + For example, if the node is a shadow, it usually wants to be drawn after all other nodes + and will use ESNRP_SHADOW for this. See scene::E_SCENE_NODE_RENDER_PASS for details. + \return scene will be rendered ( passed culling ) */ virtual u32 registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass = ESNRP_AUTOMATIC) = 0; //! Draws all the scene nodes. /** This can only be invoked between - IVideoDriver::beginScene() and IVideoDriver::endScene(). Please note that - the scene is not only drawn when calling this, but also animated - by existing scene node animators, culling of scene nodes is done, etc. */ + IVideoDriver::beginScene() and IVideoDriver::endScene(). Please note that + the scene is not only drawn when calling this, but also animated + by existing scene node animators, culling of scene nodes is done, etc. */ virtual void drawAll() = 0; //! Creates a rotation animator, which rotates the attached scene node around itself. - /** \param rotationPerSecond: Specifies the speed of the animation - \return The animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ISceneNodeAnimator* createRotationAnimator(const core::vector3df& rotationPerSecond) = 0; + /** \param rotationSpeed Specifies the speed of the animation in degree per 10 milliseconds. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createRotationAnimator(const core::vector3df& rotationSpeed) = 0; //! Creates a fly circle animator, which lets the attached scene node fly around a center. /** \param center: Center of the circle. - \param radius: Radius of the circle. - \param speed: Specifies the speed of the flight. - \param direction: Specifies the upvector used for alignment of the mesh. - \return The animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ + \param radius: Radius of the circle. + \param speed: The orbital speed, in radians per millisecond. + \param direction: Specifies the upvector used for alignment of the mesh. + \param startPosition: The position on the circle where the animator will + begin. Value is in multiples of a circle, i.e. 0.5 is half way around. (phase) + \param radiusEllipsoid: if radiusEllipsoid != 0 then radius2 froms a ellipsoid + begin. Value is in multiples of a circle, i.e. 0.5 is half way around. (phase) + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createFlyCircleAnimator( const core::vector3df& center=core::vector3df(0.f,0.f,0.f), f32 radius=100.f, f32 speed=0.001f, - const core::vector3df& direction=core::vector3df(0.f, 1.f, 0.f)) = 0; + const core::vector3df& direction=core::vector3df(0.f, 1.f, 0.f), + f32 startPosition = 0.f, + f32 radiusEllipsoid = 0.f) = 0; //! Creates a fly straight animator, which lets the attached scene node fly or move along a line between two points. /** \param startPoint: Start point of the line. - \param endPoint: End point of the line. - \param timeForWay: Time in milli seconds how long the node should need to - move from the start point to the end point. - \param loop: If set to false, the node stops when the end point is reached. - If loop is true, the node begins again at the start. - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ + \param endPoint: End point of the line. + \param timeForWay: Time in milli seconds how long the node should need to + move from the start point to the end point. + \param loop: If set to false, the node stops when the end point is reached. + If loop is true, the node begins again at the start. + \param pingpong Flag to set whether the animator should fly + back from end to start again. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createFlyStraightAnimator(const core::vector3df& startPoint, - const core::vector3df& endPoint, u32 timeForWay, bool loop=false) = 0; + const core::vector3df& endPoint, u32 timeForWay, bool loop=false, bool pingpong = false) = 0; //! Creates a texture animator, which switches the textures of the target scene node based on a list of textures. /** \param textures: List of textures to use. - \param timePerFrame: Time in milliseconds, how long any texture in the list - should be visible. - \param loop: If set to to false, the last texture remains set, and the animation - stops. If set to true, the animation restarts with the first texture. - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ + \param timePerFrame: Time in milliseconds, how long any texture in the list + should be visible. + \param loop: If set to to false, the last texture remains set, and the animation + stops. If set to true, the animation restarts with the first texture. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createTextureAnimator(const core::array& textures, s32 timePerFrame, bool loop=true) = 0; //! Creates a scene node animator, which deletes the scene node after some time automatically. /** \param timeMs: Time in milliseconds, after when the node will be deleted. - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createDeleteAnimator(u32 timeMs) = 0; //! Creates a special scene node animator for doing automatic collision detection and response. /** See ISceneNodeAnimatorCollisionResponse for details. - \param world: Triangle selector holding all triangles of the world with which - the scene node may collide. You can create a triangle selector with - 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. - \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 - it: - \code - 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 - 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 - the center of the scene node, which means that the ellipsoid surrounds - it completely. If this is not what you want, you may specify a translation - for the ellipsoid. - \param slidingValue: DOCUMENTATION NEEDED. - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will cause it to do collision detection and response. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ + \param world: Triangle selector holding all triangles of the world with which + the scene node may collide. You can create a triangle selector with + 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. 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 + it: + \code + 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 + 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 + the center of the scene node, which means that the ellipsoid surrounds + it completely. If this is not what you want, you may specify a translation + for the ellipsoid. + \param slidingValue: DOCUMENTATION NEEDED. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will cause it to do collision detection and response. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimatorCollisionResponse* createCollisionResponseAnimator( ITriangleSelector* world, ISceneNode* sceneNode, const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), @@ -1113,142 +1199,170 @@ namespace scene //! Creates a follow spline animator. /** The animator modifies the position of - the attached scene node to make it follow a hermite spline. - It uses a subset of hermite splines: either cardinal splines - (tightness != 0.5) or catmull-rom-splines (tightness == 0.5). - The animator moves from one control point to the next in - 1/speed seconds. This code was sent in by Matthias Gall. */ + the attached scene node to make it follow a hermite spline. + It uses a subset of hermite splines: either cardinal splines + (tightness != 0.5) or catmull-rom-splines (tightness == 0.5). + The animator moves from one control point to the next in + 1/speed seconds. This code was sent in by Matthias Gall. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, const core::array< core::vector3df >& points, - f32 speed = 1.0f, f32 tightness = 0.5f) = 0; + f32 speed = 1.0f, f32 tightness = 0.5f, bool loop=true, bool pingpong=false) = 0; //! Creates a simple ITriangleSelector, based on a mesh. /** Triangle selectors - can be used for doing collision detection. Don't use this selector - for a huge amount of triangles like in Quake3 maps. - Instead, use for example ISceneManager::createOctTreeTriangleSelector(). - Please note that the created triangle selector is not automaticly attached - to the scene node. You will have to call ISceneNode::setTriangleSelector() - for this. To create and attach a triangle selector is done like this: - \code - ITriangleSelector* s = sceneManager->createTriangleSelector(yourMesh, + can be used for doing collision detection. Don't use this selector + for a huge amount of triangles like in Quake3 maps. + Instead, use for example ISceneManager::createOctreeTriangleSelector(). + Please note that the created triangle selector is not automaticly attached + to the scene node. You will have to call ISceneNode::setTriangleSelector() + for this. To create and attach a triangle selector is done like this: + \code + ITriangleSelector* s = sceneManager->createTriangleSelector(yourMesh, yourSceneNode); - yourSceneNode->setTriangleSelector(s); - s->drop(); - \endcode - \param mesh: Mesh of which the triangles are taken. - \param node: Scene node of which visibility and transformation is used. - \return Returns the selector, or null if not successful. - If you no longer need the selector, you should call ITriangleSelector::drop(). - See IReferenceCounted::drop() for more information. */ + yourSceneNode->setTriangleSelector(s); + s->drop(); + \endcode + \param mesh: Mesh of which the triangles are taken. + \param node: Scene node of which visibility and transformation is used. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node) = 0; + //! Creates a simple ITriangleSelector, based on an animated mesh scene node. + /** Details of the mesh associated with the node will be extracted internally. + Call ITriangleSelector::update() to have the triangle selector updated based + on the current frame of the animated mesh scene node. + \param node The animated mesh scene node from which to build the selector + */ + virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node) = 0; + + //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. /** Triangle selectors - can be used for doing collision detection. Every time when triangles are - queried, the triangle selector gets the bounding box of the scene node, - an creates new triangles. In this way, it works good with animated scene nodes. - \param node: Scene node of which the bounding box, visibility and transformation is used. - \return Returns the selector, or null if not successful. - If you no longer need the selector, you should call ITriangleSelector::drop(). - See IReferenceCounted::drop() for more information. */ + can be used for doing collision detection. Every time when triangles are + queried, the triangle selector gets the bounding box of the scene node, + an creates new triangles. In this way, it works good with animated scene nodes. + \param node: Scene node of which the bounding box, visibility and transformation is used. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ virtual ITriangleSelector* createTriangleSelectorFromBoundingBox(ISceneNode* node) = 0; - //! Creates a Triangle Selector, optimized by an octtree. + //! Creates a Triangle Selector, optimized by an octree. /** Triangle selectors - can be used for doing collision detection. This triangle selector is - optimized for huge amounts of triangle, it organizes them in an octtree. - Please note that the created triangle selector is not automaticly attached - to the scene node. You will have to call ISceneNode::setTriangleSelector() - for this. To create and attach a triangle selector is done like this: - \code - ITriangleSelector* s = sceneManager->createOctTreeTriangleSelector(yourMesh, + can be used for doing collision detection. This triangle selector is + optimized for huge amounts of triangle, it organizes them in an octree. + Please note that the created triangle selector is not automaticly attached + to the scene node. You will have to call ISceneNode::setTriangleSelector() + for this. To create and attach a triangle selector is done like this: + \code + ITriangleSelector* s = sceneManager->createOctreeTriangleSelector(yourMesh, yourSceneNode); - yourSceneNode->setTriangleSelector(s); - s->drop(); - \endcode - For more informations and examples on this, take a look at the collision - tutorial in the SDK. - \param mesh: Mesh of which the triangles are taken. - \param node: Scene node of which visibility and transformation is used. - \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. - If a node gets less polys the this value, it will not be splitted into - smaller nodes. - \return Returns the selector, or null if not successful. - If you no longer need the selector, you should call ITriangleSelector::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, + yourSceneNode->setTriangleSelector(s); + s->drop(); + \endcode + For more informations and examples on this, take a look at the collision + tutorial in the SDK. + \param mesh: Mesh of which the triangles are taken. + \param node: Scene node of which visibility and transformation is used. + \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. + If a node gets less polys the this value, it will not be splitted into + smaller nodes. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode=32) = 0; + //! //! Creates a Triangle Selector, optimized by an octree. + /** \deprecated Use createOctreeTriangleSelector instead. */ + _IRR_DEPRECATED_ ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, + ISceneNode* node, s32 minimalPolysPerNode=32) + { + return createOctreeTriangleSelector(mesh, node, minimalPolysPerNode); + } + //! Creates a meta triangle selector. /** A meta triangle selector is nothing more than a - collection of one or more triangle selectors providing together - the interface of one triangle selector. In this way, - collision tests can be done with different triangle soups in one pass. - \return Returns the selector, or null if not successful. - If you no longer need the selector, you should call ITriangleSelector::drop(). - See IReferenceCounted::drop() for more information. */ + collection of one or more triangle selectors providing together + the interface of one triangle selector. In this way, + collision tests can be done with different triangle soups in one pass. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ virtual IMetaTriangleSelector* createMetaTriangleSelector() = 0; //! Creates a triangle selector which can select triangles from a terrain scene node. /** \param node: Pointer to the created terrain scene node - \param LOD: Level of detail, 0 for highest detail. */ + \param LOD: Level of detail, 0 for highest detail. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ virtual ITriangleSelector* createTerrainTriangleSelector( ITerrainSceneNode* node, s32 LOD=0) = 0; //! Adds an external mesh loader for extending the engine with new file formats. /** If you want the engine to be extended with - file formats it currently is not able to load (e.g. .cob), just implement - the IMeshLoader interface in your loading class and add it with this method. - Using this method it is also possible to override built-in mesh loaders with - newer or updated versions without the need of recompiling the engine. - \param externalLoader: Implementation of a new mesh loader. */ + file formats it currently is not able to load (e.g. .cob), just implement + the IMeshLoader interface in your loading class and add it with this method. + Using this method it is also possible to override built-in mesh loaders with + newer or updated versions without the need of recompiling the engine. + \param externalLoader: Implementation of a new mesh loader. */ virtual void addExternalMeshLoader(IMeshLoader* externalLoader) = 0; - //! Returns a pointer to the scene collision manager. + //! Get pointer to the scene collision manager. + /** \return Pointer to the collision manager + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneCollisionManager* getSceneCollisionManager() = 0; - //! Returns a pointer to the mesh manipulator. + //! Get pointer to the mesh manipulator. + /** \return Pointer to the mesh manipulator + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshManipulator* getMeshManipulator() = 0; //! Adds a scene node to the deletion queue. /** The scene node is immediatly - deleted when it's secure. Which means when the scene node does not - execute animators and things like that. This method is for example - used for deleting scene nodes by their scene node animators. In - most other cases, a ISceneNode::remove() call is enough, using this - deletion queue is not necessary. - See ISceneManager::createDeleteAnimator() for details. - \param node: Node to detete. */ + deleted when it's secure. Which means when the scene node does not + execute animators and things like that. This method is for example + used for deleting scene nodes by their scene node animators. In + most other cases, a ISceneNode::remove() call is enough, using this + deletion queue is not necessary. + See ISceneManager::createDeleteAnimator() for details. + \param node: Node to detete. */ virtual void addToDeletionQueue(ISceneNode* node) = 0; //! Posts an input event to the environment. /** Usually you do not have to - use this method, it is used by the internal engine. */ + use this method, it is used by the internal engine. */ virtual bool postEventFromUser(const SEvent& event) = 0; //! Clears the whole scene. /** All scene nodes are removed. */ virtual void clear() = 0; - //! Returns interface to the parameters set in this scene. + //! Get interface to the parameters set in this scene. /** String parameters can be used by plugins and mesh loaders. - For example the CMS and LMTS loader want a parameter named 'CSM_TexturePath' - and 'LMTS_TexturePath' set to the path were attached textures can be found. See - CSM_TEXTURE_PATH, LMTS_TEXTURE_PATH, MY3D_TEXTURE_PATH, - COLLADA_CREATE_SCENE_INSTANCES, DMF_TEXTURE_PATH and DMF_USE_MATERIALS_DIRS*/ + For example the CMS and LMTS loader want a parameter named 'CSM_TexturePath' + and 'LMTS_TexturePath' set to the path were attached textures can be found. See + CSM_TEXTURE_PATH, LMTS_TEXTURE_PATH, MY3D_TEXTURE_PATH, + COLLADA_CREATE_SCENE_INSTANCES, DMF_TEXTURE_PATH and DMF_USE_MATERIALS_DIRS*/ virtual io::IAttributes* getParameters() = 0; - //! Returns current render pass. + //! Get current render pass. /** All scene nodes are being rendered in a specific order. - First lights, cameras, sky boxes, solid geometry, and then transparent - stuff. During the rendering process, scene nodes may want to know what the scene - manager is rendering currently, because for example they registered for rendering - twice, once for transparent geometry and once for solid. When knowing what rendering - pass currently is active they can render the correct part of their geometry. */ + First lights, cameras, sky boxes, solid geometry, and then transparent + stuff. During the rendering process, scene nodes may want to know what the scene + manager is rendering currently, because for example they registered for rendering + twice, once for transparent geometry and once for solid. When knowing what rendering + pass currently is active they can render the correct part of their geometry. */ virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const = 0; - //! Returns the default scene node factory which can create all built in scene nodes + //! Get the default scene node factory which can create all built in scene nodes + /** \return Pointer to the default scene node factory + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNodeFactory* getDefaultSceneNodeFactory() = 0; //! Adds a scene node factory to the scene manager. @@ -1256,13 +1370,17 @@ namespace scene able to create automaticly, for example when loading data from xml files. */ virtual void registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd) = 0; - //! Returns amount of registered scene node factories. + //! Get amount of registered scene node factories. virtual u32 getRegisteredSceneNodeFactoryCount() const = 0; - //! Returns a scene node factory by index + //! Get a scene node factory by index + /** \return Pointer to the requested scene node factory, or 0 if it does not exist. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNodeFactory* getSceneNodeFactory(u32 index) = 0; - //! Returns the default scene node animator factory which can create all built-in scene node animators + //! Get the default scene node animator factory which can create all built-in scene node animators + /** \return Pointer to the default scene node animator factory + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimatorFactory* getDefaultSceneNodeAnimatorFactory() = 0; //! Adds a scene node animator factory to the scene manager. @@ -1270,16 +1388,23 @@ namespace scene able to create automaticly, for example when loading data from xml files. */ virtual void registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd) = 0; - //! Returns amount of registered scene node animator factories. + //! Get amount of registered scene node animator factories. virtual u32 getRegisteredSceneNodeAnimatorFactoryCount() const = 0; - //! Returns a scene node animator factory by index + //! Get scene node animator factory by index + /** \return Pointer to the requested scene node animator factory, or 0 if it does not exist. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimatorFactory* getSceneNodeAnimatorFactory(u32 index) = 0; - //! Returns a typename from a scene node type or null if not found + //! Get typename from a scene node type or null if not found virtual const c8* getSceneNodeTypeName(ESCENE_NODE_TYPE type) = 0; + //! Returns a typename from a scene node animator type or null if not found + virtual const c8* getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) = 0; + //! Adds a scene node to the scene by name + /** \return Pointer to the scene node added by a factory + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent=0) = 0; //! Creates a new scene manager. @@ -1312,8 +1437,8 @@ namespace scene \param userDataSerializer: If you want to save some user data for every scene node into the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. - \return Returns true if successful. */ - virtual bool saveScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; + \return True if successful. */ + virtual bool saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; //! Saves the current scene into a file. /** Scene nodes with the option isDebugObject set to true are not being saved. @@ -1324,7 +1449,7 @@ namespace scene \param userDataSerializer: If you want to save some user data for every scene node into the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. - \return Returns true if successful. */ + \return True if successful. */ virtual bool saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer=0) = 0; //! Loads a scene. Note that the current scene is not cleared before. @@ -1337,8 +1462,8 @@ namespace scene implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. - \return Returns true if successful. */ - virtual bool loadScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; + \return True if successful. */ + virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; //! Loads a scene. Note that the current scene is not cleared before. /** The scene is usually load from an .irr file, an xml based format. .irr files can @@ -1350,19 +1475,45 @@ namespace scene implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. - \return Returns true if successful. */ + \return True if successful. */ virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0) = 0; - //! Returns a mesh writer implementation if available + //! Get a mesh writer implementation if available /** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop() for details. */ virtual IMeshWriter* createMeshWriter(EMESH_WRITER_TYPE type) = 0; + //! Get a skinned mesh, which is not available as header-only code + /** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop() + for details. */ + virtual ISkinnedMesh* createSkinnedMesh() = 0; + //! Sets ambient color of the scene virtual void setAmbientLight(const video::SColorf &ambientColor) = 0; - //! Returns ambient color of the scene + //! Get ambient color of the scene virtual const video::SColorf& getAmbientLight() const = 0; + + //! Register a custom callbacks manager which gets callbacks during scene rendering. + /** \param[in] lightManager: the new callbacks manager. You may pass 0 to remove the + current callbacks manager and restore the default behaviour. */ + virtual void setLightManager(ILightManager* lightManager) = 0; + + //! Get an instance of a geometry creator. + /** The geometry creator provides some helper methods to create various types of + basic geometry. This can be useful for custom scene nodes. */ + virtual const IGeometryCreator* getGeometryCreator(void) const = 0; + + //! Check if node is culled in current view frustum + /** Please note that depending on the used culling method this + check can be rather coarse, or slow. A positive result is + correct, though, i.e. if this method returns true the node is + positively not visible. The node might still be invisible even + if this method returns false. + \param node The scene node which is checked for culling. + \return True if node is not visible in the current scene, else + false. */ + virtual bool isCulled(const ISceneNode* node) const =0; }; diff --git a/src/dep/include/irrlicht/ISceneNode.h b/src/dep/include/irrlicht/ISceneNode.h index 9442547..d20175e 100644 --- a/src/dep/include/irrlicht/ISceneNode.h +++ b/src/dep/include/irrlicht/ISceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,6 +24,11 @@ namespace scene { class ISceneManager; + //! Typedef for list of scene nodes + typedef core::list ISceneNodeList; + //! Typedef for list of scene node animators + typedef core::list ISceneNodeAnimatorList; + //! Scene node interface. /** A scene node is a node in the hierarchical scene graph. Every scene node may have children, which are also scene nodes. Children move @@ -42,9 +47,9 @@ namespace scene const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) : RelativeTranslation(position), RelativeRotation(rotation), RelativeScale(scale), - Parent(0), ID(id), SceneManager(mgr), TriangleSelector(0), - AutomaticCullingState(EAC_BOX), IsVisible(true), - DebugDataVisible(EDS_OFF), IsDebugObject(false) + Parent(0), SceneManager(mgr), TriangleSelector(0), ID(id), + AutomaticCullingState(EAC_BOX), DebugDataVisible(EDS_OFF), + IsVisible(true), IsDebugObject(false) { if (parent) parent->addChild(this); @@ -60,7 +65,7 @@ namespace scene removeAll(); // delete all animators - core::list::Iterator ait = Animators.begin(); + ISceneNodeAnimatorList::Iterator ait = Animators.begin(); for (; ait != Animators.end(); ++ait) (*ait)->drop(); @@ -87,7 +92,7 @@ namespace scene { if (IsVisible) { - core::list::Iterator it = Children.begin(); + ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnRegisterSceneNode(); } @@ -106,16 +111,23 @@ namespace scene { // animate this node with all animators - core::list::Iterator ait = Animators.begin(); - for (; ait != Animators.end(); ++ait) - (*ait)->animateNode(this, timeMs); + ISceneNodeAnimatorList::Iterator ait = Animators.begin(); + while (ait != Animators.end()) + { + // continue to the next node before calling animateNode() + // so that the animator may remove itself from the scene + // node without the iterator becoming invalid + ISceneNodeAnimator* anim = *ait; + ++ait; + anim->animateNode(this, timeMs); + } // update absolute position updateAbsolutePosition(); // perform the post render process on all children - core::list::Iterator it = Children.begin(); + ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnAnimate(timeMs); } @@ -201,20 +213,36 @@ namespace scene } - //! Returns true if the node is visible. + //! Returns whether the node should be visible (if all of its parents are visible). /** This is only an option set by the user, but has nothing to do with geometry culling - \return The visibility of the node, true means visible. */ + \return The requested visibility of the node, true means + visible (if all parents are also visible). */ virtual bool isVisible() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsVisible; } + //! Check whether the node is truly visible, taking into accounts its parents' visibility + /** \return true if the node and all its parents are visible, + false if this or any parent node is invisible. */ + virtual bool isTrulyVisible() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + if(!IsVisible) + return false; + + if(!Parent) + return true; + + return Parent->isTrulyVisible(); + } //! Sets if the node should be visible or not. /** All children of this node won't be visible either, when set - to false. + to false. Invisible nodes are not valid candidates for selection by + collision manager bounding box methods. \param isVisible If the node shall be visible. */ virtual void setVisible(bool isVisible) { @@ -261,12 +289,14 @@ namespace scene //! Removes a child from this scene node. - /** \param child A pointer to the new child. + /** If found in the children list, the child pointer is also + dropped and might be deleted if no other grab exists. + \param child A pointer to the child which shall be removed. \return True if the child was removed, and false if not, e.g. because it couldn't be found in the children list. */ virtual bool removeChild(ISceneNode* child) { - core::list::Iterator it = Children.begin(); + ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) if ((*it) == child) { @@ -282,9 +312,12 @@ namespace scene //! Removes all children of this scene node + /** The scene nodes found in the children list are also dropped + and might be deleted if no other grab exists on them. + */ virtual void removeAll() { - core::list::Iterator it = Children.begin(); + ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) { (*it)->Parent = 0; @@ -295,7 +328,9 @@ namespace scene } - //! Removes this scene node from the scene, deleting it. + //! Removes this scene node from the scene + /** If no other grab exists for this node, it will be deleted. + */ virtual void remove() { if (Parent) @@ -324,24 +359,30 @@ namespace scene //! Removes an animator from this scene node. - /** \param animator A pointer to the animator to be deleted. */ + /** If the animator is found, it is also dropped and might be + deleted if not other grab exists for it. + \param animator A pointer to the animator to be deleted. */ virtual void removeAnimator(ISceneNodeAnimator* animator) { - core::list::Iterator it = Animators.begin(); + ISceneNodeAnimatorList::Iterator it = Animators.begin(); for (; it != Animators.end(); ++it) + { if ((*it) == animator) { (*it)->drop(); Animators.erase(it); return; } + } } //! Removes all animators from this scene node. + /** The animators might also be deleted if no other grab exists + for them. */ virtual void removeAnimators() { - core::list::Iterator it = Animators.begin(); + ISceneNodeAnimatorList::Iterator it = Animators.begin(); for (; it != Animators.end(); ++it) (*it)->drop(); @@ -359,7 +400,7 @@ namespace scene \return The material at that index. */ virtual video::SMaterial& getMaterial(u32 num) { - return *((video::SMaterial*)0); + return video::IdentityMaterial; } @@ -406,8 +447,11 @@ namespace scene } - //! Gets the relative scale of the scene node. - /** \return The scale of the scene node. */ + //! Gets the scale of the scene node relative to its parent. + /** This is the scale of this node relative to its parent. + If you want the absolute scale, use + getAbsoluteTransformation().getScale() + \return The scale of the scene node. */ virtual const core::vector3df& getScale() const { return RelativeScale; @@ -415,15 +459,17 @@ namespace scene //! Sets the relative scale of the scene node. - /** \param scale New scale of the node */ + /** \param scale New scale of the node, relative to its parent. */ virtual void setScale(const core::vector3df& scale) { RelativeScale = scale; } - //! Gets the rotation of the node. + //! Gets the rotation of the node relative to its parent. /** Note that this is the relative rotation of the node. + If you want the absolute rotation, use + getAbsoluteTransformation().getRotation() \return Current relative rotation of the scene node. */ virtual const core::vector3df& getRotation() const { @@ -431,7 +477,7 @@ namespace scene } - //! Sets the rotation of the node. + //! Sets the rotation of the node relative to its parent. /** This only modifies the relative rotation of the node. \param rotation New rotation of the node in degrees. */ virtual void setRotation(const core::vector3df& rotation) @@ -440,8 +486,9 @@ namespace scene } - //! Gets the position of the node. - /** Note that the position is relative to the parent. + //! Gets the position of the node relative to its parent. + /** Note that the position is relative to the parent. If you want + the position in world coordinates, use getAbsolutePosition() instead. \return The current position of the node relative to the parent. */ virtual const core::vector3df& getPosition() const { @@ -449,17 +496,19 @@ namespace scene } - //! Sets the position of the node. + //! Sets the position of the node relative to its parent. /** Note that the position is relative to the parent. - \param newpos New relative postition of the scene node. */ + \param newpos New relative position of the scene node. */ virtual void setPosition(const core::vector3df& newpos) { RelativeTranslation = newpos; } - //! Gets the abolute position of the node. - /** \return The current absolute position of the scene node. */ + //! Gets the absolute position of the node in world coordinates. + /** If you want the position of the node relative to its parent, + use getPosition() instead. + \return The current absolute position of the scene node. */ virtual core::vector3df getAbsolutePosition() const { return AbsoluteTransformation.getTranslation(); @@ -488,7 +537,7 @@ namespace scene //! Sets if debug data like bounding boxes should be drawn. - /** A bitwise OR of the types from @ref irr::scene::E_DEBUG_SCENE_TYPE. + /** A bitwise OR of the types from @ref irr::scene::E_DEBUG_SCENE_TYPE. Please note that not all scene nodes support all debug data types. \param state The debug data visibility state to be used. */ virtual void setDebugDataVisible(s32 state) @@ -497,7 +546,7 @@ namespace scene } //! Returns if debug data like bounding boxes are drawn. - /** \return A bitwise OR of the debug data values from + /** \return A bitwise OR of the debug data values from @ref irr::scene::E_DEBUG_SCENE_TYPE that are currently visible. */ s32 isDebugDataVisible() const { @@ -553,7 +602,7 @@ namespace scene /** The Selector can be used by the engine for doing collision detection. You can create a TriangleSelector with ISceneManager::createTriangleSelector() or - ISceneManager::createOctTreeTriangleSelector and set it with + ISceneManager::createOctreeTriangleSelector and set it with ISceneNode::setTriangleSelector(). If a scene node got no triangle selector, but collision tests should be done with it, a triangle selector is created using the bounding box of the scene node. @@ -569,23 +618,28 @@ namespace scene /** The Selector can be used by the engine for doing collision detection. You can create a TriangleSelector with ISceneManager::createTriangleSelector() or - ISceneManager::createOctTreeTriangleSelector(). Some nodes may + ISceneManager::createOctreeTriangleSelector(). Some nodes may create their own selector by default, so it would be good to check if there is already a selector in this node by calling ISceneNode::getTriangleSelector(). \param selector New triangle selector for this scene node. */ virtual void setTriangleSelector(ITriangleSelector* selector) { - if (TriangleSelector) - TriangleSelector->drop(); + if (TriangleSelector != selector) + { + if (TriangleSelector) + TriangleSelector->drop(); - TriangleSelector = selector; - if (TriangleSelector) - TriangleSelector->grab(); + TriangleSelector = selector; + if (TriangleSelector) + TriangleSelector->grab(); + } } //! Updates the absolute position based on the relative and the parents position + /** Note: This does not recursively update the parents absolute positions, so if you have a deeper + hierarchy you might want to update the parents first.*/ virtual void updateAbsolutePosition() { if (Parent) @@ -676,6 +730,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. @@ -704,13 +762,13 @@ namespace scene // clone children - core::list::Iterator it = toCopyFrom->Children.begin(); + ISceneNodeList::Iterator it = toCopyFrom->Children.begin(); for (; it != toCopyFrom->Children.end(); ++it) (*it)->clone(this, newManager); // clone animators - core::list::Iterator ait = toCopyFrom->Animators.begin(); + ISceneNodeAnimatorList::Iterator ait = toCopyFrom->Animators.begin(); for (; ait != toCopyFrom->Animators.end(); ++ait) { ISceneNodeAnimator* anim = (*ait)->createClone(this, SceneManager); @@ -728,7 +786,7 @@ namespace scene { SceneManager = newManager; - core::list::Iterator it = Children.begin(); + ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->setSceneManager(newManager); } @@ -757,28 +815,29 @@ namespace scene //! List of all animator nodes core::list Animators; - //! ID of the node. - s32 ID; - //! Pointer to the scene manager ISceneManager* SceneManager; //! Pointer to the triangle selector ITriangleSelector* TriangleSelector; + //! ID of the node. + s32 ID; + //! Automatic culling state E_CULLING_TYPE AutomaticCullingState; - //! Is the node visible? - bool IsVisible; - //! Flag if debug data should be drawn, such as Bounding Boxes. s32 DebugDataVisible; + //! Is the node visible? + bool IsVisible; + //! Is debug object? bool IsDebugObject; }; + } // end namespace scene } // end namespace irr diff --git a/src/dep/include/irrlicht/ISceneNodeAnimator.h b/src/dep/include/irrlicht/ISceneNodeAnimator.h index c834636..b5cd34b 100644 --- a/src/dep/include/irrlicht/ISceneNodeAnimator.h +++ b/src/dep/include/irrlicht/ISceneNodeAnimator.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -30,20 +30,16 @@ namespace scene class ISceneNodeAnimator : public io::IAttributeExchangingObject, public IEventReceiver { public: - - //! Destructor - virtual ~ISceneNodeAnimator() {} - //! Animates a scene node. /** \param node Node to animate. \param timeMs Current time in milli seconds. */ - virtual void animateNode(ISceneNode* node, u32 timeMs) = 0; + virtual void animateNode(ISceneNode* node, u32 timeMs) =0; //! 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) = 0; + (IReferenceCounted::drop()) the returned pointer after calling this. */ + virtual ISceneNodeAnimator* createClone(ISceneNode* node, + ISceneManager* newManager=0) =0; //! Returns true if this animator receives events. /** When attached to an active camera, this animator will be @@ -64,6 +60,14 @@ namespace scene { return ESNAT_UNKNOWN; } + + //! Returns if the animator has finished. + /** This is only valid for non-looping animators with a discrete end state. + \return true if the animator has finished, false if it is still running. */ + virtual bool hasFinished(void) const + { + return false; + } }; diff --git a/src/dep/include/irrlicht/ISceneNodeAnimatorCameraFPS.h b/src/dep/include/irrlicht/ISceneNodeAnimatorCameraFPS.h index 7676d57..9110a6b 100644 --- a/src/dep/include/irrlicht/ISceneNodeAnimatorCameraFPS.h +++ b/src/dep/include/irrlicht/ISceneNodeAnimatorCameraFPS.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -39,8 +39,8 @@ namespace scene virtual void setRotateSpeed(f32 rotateSpeed) = 0; //! Sets the keyboard mapping for this animator - /** \param keymap Array of keyboard mappings, see SKeyMap - \param count Size of the keyboard map array */ + /** \param map Array of keyboard mappings, see irr::SKeyMap + \param count Size of the keyboard map array. */ virtual void setKeyMap(SKeyMap *map, u32 count) = 0; //! Sets whether vertical movement should be allowed. @@ -48,6 +48,11 @@ namespace scene gravity causing camera shake. Disable this if the camera has a collision animator with gravity enabled. */ virtual void setVerticalMovement(bool allow) = 0; + + //! Sets whether the Y axis of the mouse should be inverted. + /** If enabled then moving the mouse down will cause + the camera to look up. It is disabled by default. */ + virtual void setInvertMouse(bool invert) = 0; }; } // end namespace scene } // end namespace irr diff --git a/src/dep/include/irrlicht/ISceneNodeAnimatorCameraMaya.h b/src/dep/include/irrlicht/ISceneNodeAnimatorCameraMaya.h index 4169814..0d16eff 100644 --- a/src/dep/include/irrlicht/ISceneNodeAnimatorCameraMaya.h +++ b/src/dep/include/irrlicht/ISceneNodeAnimatorCameraMaya.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/ISceneNodeAnimatorCollisionResponse.h b/src/dep/include/irrlicht/ISceneNodeAnimatorCollisionResponse.h index e7ad068..bd111ab 100644 --- a/src/dep/include/irrlicht/ISceneNodeAnimatorCollisionResponse.h +++ b/src/dep/include/irrlicht/ISceneNodeAnimatorCollisionResponse.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,15 +12,44 @@ namespace irr namespace scene { + class ISceneNodeAnimatorCollisionResponse; + + //! Callback interface for catching events of collisions. + /** Implement this interface and use + ISceneNodeAnimatorCollisionResponse::setCollisionCallback to be able to + be notified if a collision has occurred. + **/ + class ICollisionCallback : public virtual IReferenceCounted + { + public: + + //! Will be called when a collision occurrs. + /** See ISceneNodeAnimatorCollisionResponse::setCollisionCallback for more information. + \param animator: Collision response animator in which the collision occurred. You can call + this animator's methods to find the node, collisionPoint and/or collision triangle. + \retval true if the collision was handled in the animator. The animator's target + node will *not* be stopped at the collision point, but will instead move fully + to the location that triggered the collision check. + \retval false if the collision was not handled in the animator. The animator's + target node will be moved to the collision position. + */ + virtual bool onCollision(const ISceneNodeAnimatorCollisionResponse& animator) = 0; + }; + //! 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: @@ -68,6 +97,10 @@ namespace scene to this animator's gravity vector. */ virtual void jump(f32 jumpSpeed) = 0; + //! Should the Target react on collision ( default = true ) + virtual void setAnimateTarget ( bool enable ) = 0; + virtual bool getAnimateTarget () const = 0; + //! Set translation of the collision ellipsoid. /** By default, the ellipsoid for collision detection is created around the center of the scene node, which means that @@ -92,6 +125,42 @@ 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; + + //! Returns true if a collision occurred during the last animateNode() + virtual bool collisionOccurred() const = 0; + + //! Returns the last point of collision. + virtual const core::vector3df & getCollisionPoint() const = 0; + + //! Returns the last triangle that caused a collision + virtual const core::triangle3df & getCollisionTriangle() const = 0; + + //! Returns the position that the target node will be moved to, unless the collision is consumed in a callback. + /** + If you have a collision callback registered, and it consumes the collision, then the + node will ignore the collision and will not stop at this position. Instead, it will + move fully to the position that caused the collision to occur. */ + virtual const core::vector3df & getCollisionResultPosition(void) const = 0; + + //! Returns the node that was collided with. + virtual const ISceneNode* getCollisionNode(void) const = 0; + + //! Sets a callback interface which will be called if a collision occurs. + /** \param callback: collision callback handler that will be called when a collision + occurs. Set this to 0 to disable the callback. + */ + virtual void setCollisionCallback(ICollisionCallback* callback) = 0; + }; diff --git a/src/dep/include/irrlicht/ISceneNodeAnimatorFactory.h b/src/dep/include/irrlicht/ISceneNodeAnimatorFactory.h index 5e220e5..5c2bd96 100644 --- a/src/dep/include/irrlicht/ISceneNodeAnimatorFactory.h +++ b/src/dep/include/irrlicht/ISceneNodeAnimatorFactory.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/ISceneNodeFactory.h b/src/dep/include/irrlicht/ISceneNodeFactory.h index 4ca6bf1..52ef9d9 100644 --- a/src/dep/include/irrlicht/ISceneNodeFactory.h +++ b/src/dep/include/irrlicht/ISceneNodeFactory.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -27,19 +27,18 @@ namespace scene class ISceneNodeFactory : public virtual IReferenceCounted { public: - - virtual ~ISceneNodeFactory() {} - //! adds a scene node to the scene graph based on its type id /** \param type: Type of the scene node to add. \param parent: Parent scene node of the new node, can be null to add the scene node to the root. - \return Returns pointer to the new scene node or null if not successful. */ + \return Returns pointer to the new scene node or null if not successful. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent=0) = 0; //! adds a scene node to the scene graph based on its type name /** \param typeName: Type name of the scene node to add. \param parent: Parent scene node of the new node, can be null to add the scene node to the root. - \return Returns pointer to the new scene node or null if not successful. */ + \return Returns pointer to the new scene node or null if not successful. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSceneNode(const c8* typeName, ISceneNode* parent=0) = 0; //! returns amount of scene node types this factory is able to create diff --git a/src/dep/include/irrlicht/ISceneUserDataSerializer.h b/src/dep/include/irrlicht/ISceneUserDataSerializer.h index d756fe3..dea2072 100644 --- a/src/dep/include/irrlicht/ISceneUserDataSerializer.h +++ b/src/dep/include/irrlicht/ISceneUserDataSerializer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IShaderConstantSetCallBack.h b/src/dep/include/irrlicht/IShaderConstantSetCallBack.h index f486b34..d3564ff 100644 --- a/src/dep/include/irrlicht/IShaderConstantSetCallBack.h +++ b/src/dep/include/irrlicht/IShaderConstantSetCallBack.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IShadowVolumeSceneNode.h b/src/dep/include/irrlicht/IShadowVolumeSceneNode.h index 8a77fab..728726a 100644 --- a/src/dep/include/irrlicht/IShadowVolumeSceneNode.h +++ b/src/dep/include/irrlicht/IShadowVolumeSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/ISkinnedMesh.h b/src/dep/include/irrlicht/ISkinnedMesh.h index 765be5a..2c9e638 100644 --- a/src/dep/include/irrlicht/ISkinnedMesh.h +++ b/src/dep/include/irrlicht/ISkinnedMesh.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,7 +17,7 @@ namespace scene enum E_INTERPOLATION_MODE { - // constant interpolation + // constant does use the current key-values without interpolation EIM_CONSTANT = 0, // linear interpolation @@ -34,33 +34,35 @@ namespace scene public: //! Gets joint count. - //! \return Returns amount of joints in the skeletal animated mesh. + /** \return Amount of joints in the skeletal animated mesh. */ virtual u32 getJointCount() const = 0; //! Gets the name of a joint. - //! \param number: Zero based index of joint. The last joint - //! has the number getJointCount()-1; - //! \return Returns name of joint and null if an error happened. + /** \param number: Zero based index of joint. The last joint + has the number getJointCount()-1; + \return Name of joint and null if an error happened. */ virtual const c8* getJointName(u32 number) const = 0; //! Gets a joint number from its name - //! \param name: Name of the joint. - //! \return Returns the number of the joint or -1 if not found. + /** \param name: Name of the joint. + \return Number of the joint or -1 if not found. */ virtual s32 getJointNumber(const c8* name) const = 0; - //! uses animation from another mesh - //! the animation is linked (not copied) based on joint names (so make sure they are unique) - //! \return Returns true if all joints in this mesh were - //! matched up (empty names will not be matched, and it's case - //! sensitive). Unmatched joints will not be animated. + //! Use animation from another mesh + /** The animation is linked (not copied) based on joint names + so make sure they are unique. + \return True if all joints in this mesh were + matched up (empty names will not be matched, and it's case + sensitive). Unmatched joints will not be animated. */ virtual bool useAnimationFrom(const ISkinnedMesh *mesh) = 0; - //!Update Normals when Animating - //!False= Don't animate, faster - //!True= Update normals + //! Update Normals when Animating + /** \param on If false don't animate, which is faster. + Else update normals, which allows for proper lighting of + animated meshes. */ virtual void updateNormalsWhenAnimating(bool on) = 0; - //!Sets Interpolation Mode + //! Sets Interpolation Mode virtual void setInterpolationMode(E_INTERPOLATION_MODE mode) = 0; //! Animates this mesh's joints based on frame input @@ -69,10 +71,12 @@ namespace scene //! Preforms a software skin on this mesh based of joint positions virtual void skinMesh() = 0; - //! converts the vertex type of all meshbuffers to tangents. eg for bumpmapping + //! converts the vertex type of all meshbuffers to tangents. + /** E.g. used for bump mapping. */ virtual void convertMeshToTangents() = 0; - //! (This feature is not implementated in irrlicht yet) + //! Allows to enable hardware skinning. + /* This feature is not implementated in Irrlicht yet */ virtual bool setHardwareSkinning(bool on) = 0; //! A vertex weight @@ -90,7 +94,7 @@ namespace scene private: //! Internal members used by CSkinnedMesh friend class CSkinnedMesh; - friend class CM2Mesh; + friend class CM2Mesh; //PSEUWOW bool *Moved; core::vector3df StaticPos; core::vector3df StaticNormal; @@ -163,7 +167,7 @@ namespace scene private: //! Internal members used by CSkinnedMesh friend class CSkinnedMesh; - friend class CM2Mesh; + friend class CM2Mesh; //PSEUWOW SJoint *UseAnimationFrom; bool LocalAnimatedMatrix_Animated; @@ -181,26 +185,34 @@ namespace scene //these functions will use the needed arrays, set values, etc to help the loaders //! exposed for loaders: to add mesh buffers - virtual core::array &getMeshBuffers() = 0; + virtual core::array& getMeshBuffers() = 0; //! exposed for loaders: joints list - virtual core::array &getAllJoints() = 0; + virtual core::array& getAllJoints() = 0; //! exposed for loaders: joints list - virtual const core::array &getAllJoints() const = 0; + virtual const core::array& getAllJoints() const = 0; //! loaders should call this after populating the mesh virtual void finalize() = 0; - virtual SSkinMeshBuffer *createBuffer() = 0; + //! Adds a new meshbuffer to the mesh, access it as last one + virtual SSkinMeshBuffer* addMeshBuffer() = 0; - virtual SJoint *createJoint(SJoint *parent=0) = 0; - virtual SWeight *createWeight(SJoint *joint) = 0; + //! Adds a new joint to the mesh, access it as last one + virtual SJoint* addJoint(SJoint *parent=0) = 0; - virtual SPositionKey *createPositionKey(SJoint *joint) = 0; - virtual SScaleKey *createScaleKey(SJoint *joint) = 0; - virtual SRotationKey *createRotationKey(SJoint *joint) = 0; + //! Adds a new weight to the mesh, access it as last one + virtual SWeight* addWeight(SJoint *joint) = 0; + //! Adds a new position key to the mesh, access it as last one + virtual SPositionKey* addPositionKey(SJoint *joint) = 0; + //! Adds a new scale key to the mesh, access it as last one + virtual SScaleKey* addScaleKey(SJoint *joint) = 0; + //! Adds a new rotation key to the mesh, access it as last one + virtual SRotationKey* addRotationKey(SJoint *joint) = 0; + + //! Check if the mesh is non-animated virtual bool isStatic()=0; }; diff --git a/src/dep/include/irrlicht/ITerrainSceneNode.h b/src/dep/include/irrlicht/ITerrainSceneNode.h index 75f29ad..19a14ed 100644 --- a/src/dep/include/irrlicht/ITerrainSceneNode.h +++ b/src/dep/include/irrlicht/ITerrainSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/ITextSceneNode.h b/src/dep/include/irrlicht/ITextSceneNode.h index 770693f..5b0c549 100644 --- a/src/dep/include/irrlicht/ITextSceneNode.h +++ b/src/dep/include/irrlicht/ITextSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/ITexture.h b/src/dep/include/irrlicht/ITexture.h index 11731b9..70b782f 100644 --- a/src/dep/include/irrlicht/ITexture.h +++ b/src/dep/include/irrlicht/ITexture.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,7 @@ #include "IImage.h" #include "dimension2d.h" #include "EDriverTypes.h" -#include "irrString.h" +#include "path.h" #include "matrix4.h" namespace irr @@ -18,90 +18,75 @@ namespace video { -//! Enumeration flags telling the video driver in which format textures -//! should be created. +//! Enumeration flags telling the video driver in which format textures should be created. enum E_TEXTURE_CREATION_FLAG { - //! Forces the driver to create 16 bit textures always, independent of - //! which format the file on disk has. When choosing this you may loose - //! some color detail, but gain much speed and memory. 16 bit textures - //! can be transferred twice as fast as 32 bit textures and only use - //! half of the space in memory. - //! When using this flag, it does not make sense to use the flags - //! ETCF_ALWAYS_32_BIT, ETCF_OPTIMIZED_FOR_QUALITY, - //! or ETCF_OPTIMIZED_FOR_SPEED at the same time. + /** Forces the driver to create 16 bit textures always, independent of + which format the file on disk has. When choosing this you may lose + some color detail, but gain much speed and memory. 16 bit textures can + be transferred twice as fast as 32 bit textures and only use half of + the space in memory. + When using this flag, it does not make sense to use the flags + ETCF_ALWAYS_32_BIT, ETCF_OPTIMIZED_FOR_QUALITY, or + ETCF_OPTIMIZED_FOR_SPEED at the same time. */ ETCF_ALWAYS_16_BIT = 0x00000001, - //! Forces the driver to create 32 bit textures always, independent of - //! which format the file on disk has. Please note that some drivers - //! (like the software device) will ignore this, because they are only - //! able to create and use 16 bit textures. - //! When using this flag, it does not make sense to use the flags - //! ETCF_ALWAYS_16_BIT, ETCF_OPTIMIZED_FOR_QUALITY, - //! or ETCF_OPTIMIZED_FOR_SPEED at the same time. + /** Forces the driver to create 32 bit textures always, independent of + which format the file on disk has. Please note that some drivers (like + the software device) will ignore this, because they are only able to + create and use 16 bit textures. + When using this flag, it does not make sense to use the flags + ETCF_ALWAYS_16_BIT, ETCF_OPTIMIZED_FOR_QUALITY, or + ETCF_OPTIMIZED_FOR_SPEED at the same time. */ ETCF_ALWAYS_32_BIT = 0x00000002, - //! Lets the driver decide in which format the textures are created and - //! tries to make the textures look as good as possible. - //! Usually it simply chooses the format in which the texture was stored on disk. - //! When using this flag, it does not make sense to use the flags - //! ETCF_ALWAYS_16_BIT, ETCF_ALWAYS_32_BIT, - //! or ETCF_OPTIMIZED_FOR_SPEED at the same time. + /** Lets the driver decide in which format the textures are created and + tries to make the textures look as good as possible. Usually it simply + chooses the format in which the texture was stored on disk. + When using this flag, it does not make sense to use the flags + ETCF_ALWAYS_16_BIT, ETCF_ALWAYS_32_BIT, or ETCF_OPTIMIZED_FOR_SPEED at + the same time. */ ETCF_OPTIMIZED_FOR_QUALITY = 0x00000004, - //! Lets the driver decide in which format the textures are created and - //! tries to create them maximizing render speed. - //! When using this flag, it does not make sense to use the flags - //! ETCF_ALWAYS_16_BIT, ETCF_ALWAYS_32_BIT, or ETCF_OPTIMIZED_FOR_QUALITY, - //! at the same time. + /** Lets the driver decide in which format the textures are created and + tries to create them maximizing render speed. + When using this flag, it does not make sense to use the flags + ETCF_ALWAYS_16_BIT, ETCF_ALWAYS_32_BIT, or ETCF_OPTIMIZED_FOR_QUALITY, + at the same time. */ ETCF_OPTIMIZED_FOR_SPEED = 0x00000008, - //! Automatically creates mip map levels for the textures. + /** Automatically creates mip map levels for the textures. */ ETCF_CREATE_MIP_MAPS = 0x00000010, - //! Discard any alpha layer and use non-alpha color format. + /** Discard any alpha layer and use non-alpha color format. */ ETCF_NO_ALPHA_CHANNEL = 0x00000020, - //! This flag is never used, it only forces the compiler to - //! compile these enumeration values to 32 bit. + //! Allow the Driver to use Non-Power-2-Textures + /** BurningVideo can handle Non-Power-2 Textures in 2D (GUI), but not in 3D. */ + ETCF_ALLOW_NON_POWER_2 = 0x00000040, + + /** This flag is never used, it only forces the compiler to compile + these enumeration values to 32 bit. */ ETCF_FORCE_32_BIT_DO_NOT_USE = 0x7fffffff }; -//! Helper function, helps to get the desired texture creation format from the flags. -//! Returns either ETCF_ALWAYS_32_BIT, ETCF_ALWAYS_16_BIT, ETCF_OPTIMIZED_FOR_QUALITY, -//! or ETCF_OPTIMIZED_FOR_SPEED. -inline E_TEXTURE_CREATION_FLAG getTextureFormatFromFlags(u32 flags) -{ - if (flags & ETCF_OPTIMIZED_FOR_SPEED) - return ETCF_OPTIMIZED_FOR_SPEED; - if (flags & ETCF_ALWAYS_16_BIT) - return ETCF_ALWAYS_16_BIT; - if (flags & ETCF_ALWAYS_32_BIT) - return ETCF_ALWAYS_32_BIT; - if (flags & ETCF_OPTIMIZED_FOR_QUALITY) - return ETCF_OPTIMIZED_FOR_QUALITY; - return ETCF_OPTIMIZED_FOR_SPEED; -} - - //! Interface of a Video Driver dependent Texture. -/** - An ITexture is created by an IVideoDriver by using IVideoDriver::addTexture or - IVideoDriver::getTexture. After that, the texture may only be used by this VideoDriver. - As you can imagine, textures of the DirectX and the OpenGL device will, e.g., not be compatible. - An exception is the Software device and the NULL device, their textures are compatible. - If you try to use a texture created by one device with an other device, the device - will refuse to do that and write a warning or an error message to the output buffer. +/** An ITexture is created by an IVideoDriver by using IVideoDriver::addTexture +or IVideoDriver::getTexture. After that, the texture may only be used by this +VideoDriver. As you can imagine, textures of the DirectX and the OpenGL device +will, e.g., not be compatible. An exception is the Software device and the +NULL device, their textures are compatible. If you try to use a texture +created by one device with an other device, the device will refuse to do that +and write a warning or an error message to the output buffer. */ class ITexture : public virtual IReferenceCounted { public: //! constructor - ITexture(const c8* name) : Name(name) + ITexture(const io::path& name) : NamedPath(name) { - Name.make_lower(); } //! Lock function. @@ -112,66 +97,87 @@ public: number of previous locks. \param readOnly Specifies that no changes to the locked texture are made. Unspecified behavior will arise if still write access happens. + \param mipmapLevel Number of the mipmapLevel to lock. 0 is main texture. + Non-existing levels will silently fail and return 0. \return Returns a pointer to the pixel data. The format of the pixel can be determined by using getColorFormat(). 0 is returned, if the texture cannot be locked. */ - virtual void* lock(bool readOnly = false) = 0; + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0) = 0; //! Unlock function. Must be called after a lock() to the texture. /** One should avoid to call unlock more than once before another lock. */ virtual void unlock() = 0; - //! Returns original size of the texture. - /** The texture is usually - scaled, if it was created with an unoptimal size. For example if the size - of the texture file it was loaded from was not a power of two. This returns - the size of the texture, it had before it was scaled. Can be useful - when drawing 2d images on the screen, which should have the exact size - of the original texture. Use ITexture::getSize() if you want to know - the real size it has now stored in the system. - \return Returns the original size of the texture. */ - virtual const core::dimension2d& getOriginalSize() const = 0; + //! Get original size of the texture. + /** The texture is usually scaled, if it was created with an unoptimal + size. For example if the size was not a power of two. This method + returns the size of the texture it had before it was scaled. Can be + useful when drawing 2d images on the screen, which should have the + exact size of the original texture. Use ITexture::getSize() if you want + to know the real size it has now stored in the system. + \return The original size of the texture. */ + virtual const core::dimension2d& getOriginalSize() const = 0; - //! Returns dimension (=size) of the texture. - /** \return Returns the size of the texture. */ - virtual const core::dimension2d& getSize() const = 0; + //! Get dimension (=size) of the texture. + /** \return The size of the texture. */ + virtual const core::dimension2d& getSize() const = 0; - //! Returns driver type of texture. - /** This is the driver, which created the texture. - This method is used internally by the video devices, to check, if they may - use a texture because textures may be incompatible between different - devices. - \return Returns driver type of texture. */ + //! Get driver type of texture. + /** This is the driver, which created the texture. This method is used + internally by the video devices, to check, if they may use a texture + because textures may be incompatible between different devices. + \return Driver type of texture. */ virtual E_DRIVER_TYPE getDriverType() const = 0; - //! Returns the color format of texture. - /** \return Returns the color format of texture. */ + //! Get the color format of texture. + /** \return The color format of texture. */ virtual ECOLOR_FORMAT getColorFormat() const = 0; - //! Returns pitch of texture (in bytes). - /** The pitch is the amount of bytes - used for a row of pixels in a texture. - \return Returns pitch of texture in bytes. */ + //! Get pitch of texture (in bytes). + /** The pitch is the amount of bytes used for a row of pixels in a + texture. + \return Pitch of texture in bytes. */ virtual u32 getPitch() const = 0; - //! Returns whether the texture has MipMaps - /** \return Returns true if texture has MipMaps, else false. */ + //! Check whether the texture has MipMaps + /** \return True if texture has MipMaps, else false. */ virtual bool hasMipMaps() const { return false; } - //! Regenerates the mip map levels of the texture. - /** Required after locking and modifying the texture */ - virtual void regenerateMipMapLevels() = 0; + //! Returns if the texture has an alpha channel + virtual bool hasAlpha() const { + return getColorFormat () == video::ECF_A8R8G8B8 || getColorFormat () == video::ECF_A1R5G5B5; + } - //! Returns whether the texture is a render target - /** \return Returns true if this is a render target, otherwise false. */ + //! Regenerates the mip map levels of the texture. + /** Required after modifying the texture, usually after calling unlock(). */ + virtual void regenerateMipMapLevels(void* mipmapData=0) = 0; + + //! Check whether the texture is a render target + /** \return True if this is a render target, otherwise false. */ virtual bool isRenderTarget() const { return false; } - //! Returns name of texture (in most cases this is the filename) - const core::stringc& getName() const { return Name; } + //! Get name of texture (in most cases this is the filename) + const io::SNamedPath& getName() const { return NamedPath; } protected: - core::stringc Name; + //! Helper function, helps to get the desired texture creation format from the flags. + /** \return Either ETCF_ALWAYS_32_BIT, ETCF_ALWAYS_16_BIT, + ETCF_OPTIMIZED_FOR_QUALITY, or ETCF_OPTIMIZED_FOR_SPEED. */ + inline E_TEXTURE_CREATION_FLAG getTextureFormatFromFlags(u32 flags) + { + if (flags & ETCF_OPTIMIZED_FOR_SPEED) + return ETCF_OPTIMIZED_FOR_SPEED; + if (flags & ETCF_ALWAYS_16_BIT) + return ETCF_ALWAYS_16_BIT; + if (flags & ETCF_ALWAYS_32_BIT) + return ETCF_ALWAYS_32_BIT; + if (flags & ETCF_OPTIMIZED_FOR_QUALITY) + return ETCF_OPTIMIZED_FOR_QUALITY; + return ETCF_OPTIMIZED_FOR_SPEED; + } + + io::SNamedPath NamedPath; }; diff --git a/src/dep/include/irrlicht/ITimer.h b/src/dep/include/irrlicht/ITimer.h index 88634bb..8f32c13 100644 --- a/src/dep/include/irrlicht/ITimer.h +++ b/src/dep/include/irrlicht/ITimer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/ITriangleSelector.h b/src/dep/include/irrlicht/ITriangleSelector.h index 1502d57..4614d7d 100644 --- a/src/dep/include/irrlicht/ITriangleSelector.h +++ b/src/dep/include/irrlicht/ITriangleSelector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -16,6 +16,8 @@ namespace irr namespace scene { +class ISceneNode; + //! Interface to return triangles with specific properties. /** Every ISceneNode may have a triangle selector, available with ISceneNode::getTriangleScelector() or ISceneManager::createTriangleSelector. @@ -33,8 +35,13 @@ public: //! Returns amount of all available triangles in this selector virtual s32 getTriangleCount() const = 0; - //! Gets all triangles. - /** \param triangles: Array where the resulting triangles will be + //! Gets the triangles for one associated node. + /** + This returns all triangles for one scene node associated with this + selector. If there is more than one scene node associated (e.g. for + an IMetaTriangleSelector) this this function may be called multiple + times to retrieve all triangles. + \param triangles: Array where the resulting triangles will be written to. \param arraySize: Size of the target array. \param outTriangleCount: Amount of triangles which have been written @@ -46,9 +53,15 @@ public: virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform=0) const = 0; - //! Gets all triangles which lie within a specific bounding box. - /** Please note that unoptimized triangle selectors also may return - triangles which are not in the specific box at all. + //! Gets the triangles for one associated node which lie or may lie within a specific bounding box. + /** + This returns all triangles for one scene node associated with this + selector. If there is more than one scene node associated (e.g. for + an IMetaTriangleSelector) this this function may be called multiple + times to retrieve all triangles. + + This method will return at least the triangles that intersect the box, + but may return other triangles as well. \param triangles: Array where the resulting triangles will be written to. \param arraySize: Size of the target array. @@ -64,8 +77,14 @@ public: s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform=0) const = 0; - //! Gets all triangles which have or may have contact with a 3d line. - /** Please note that unoptimized triangle selectors also may return + //! Gets the triangles for one associated node which have or may have contact with a 3d line. + /** + This returns all triangles for one scene node associated with this + selector. If there is more than one scene node associated (e.g. for + an IMetaTriangleSelector) this this function may be called multiple + times to retrieve all triangles. + + Please note that unoptimized triangle selectors also may return triangles which are not in contact at all with the 3d line. \param triangles: Array where the resulting triangles will be written to. @@ -81,6 +100,18 @@ public: virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const = 0; + + //! Return the scene node associated with a given triangle. + /** + This allows you to find which scene node (potentially of several) is + associated with a specific triangle. + + \param triangleIndex: the index of the triangle for which you want to find + the associated scene node. + \return The scene node associated with that triangle. + */ + virtual const ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const = 0; + }; } // end namespace scene diff --git a/src/dep/include/irrlicht/IVertexBuffer.h b/src/dep/include/irrlicht/IVertexBuffer.h index 5192139..d012256 100644 --- a/src/dep/include/irrlicht/IVertexBuffer.h +++ b/src/dep/include/irrlicht/IVertexBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2008 Nikolaus Gebhardt +// Copyright (C) 2008-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IVideoDriver.h b/src/dep/include/irrlicht/IVideoDriver.h index 329a6a3..bcd8255 100644 --- a/src/dep/include/irrlicht/IVideoDriver.h +++ b/src/dep/include/irrlicht/IVideoDriver.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,6 +18,7 @@ #include "triangle3d.h" #include "EDriverTypes.h" #include "EDriverFeatures.h" +#include "SExposedVideoData.h" namespace irr { @@ -25,6 +26,7 @@ namespace io { class IAttributes; class IReadFile; + class IWriteFile; } // end namespace io namespace scene { @@ -38,7 +40,6 @@ namespace video struct S3DVertex2TCoords; struct S3DVertexTangents; struct SLight; - struct SExposedVideoData; class IImageLoader; class IImageWriter; class IMaterialRenderer; @@ -61,10 +62,30 @@ namespace video ETS_TEXTURE_2, //! Texture transformation ETS_TEXTURE_3, +#if _IRR_MATERIAL_MAX_TEXTURES_>4 + //! Texture transformation + ETS_TEXTURE_4, +#if _IRR_MATERIAL_MAX_TEXTURES_>5 + //! Texture transformation + ETS_TEXTURE_5, +#if _IRR_MATERIAL_MAX_TEXTURES_>6 + //! Texture transformation + ETS_TEXTURE_6, +#if _IRR_MATERIAL_MAX_TEXTURES_>7 + //! Texture transformation + ETS_TEXTURE_7, +#endif +#endif +#endif +#endif //! Not used ETS_COUNT }; + //! enumeration for signalling ressources which were lost after the last render cycle + /** These values can be signalled by the driver, telling the app that some ressources + were lost and need to be recreated. Irrlicht will sometimes recreate the actual objects, + but the content needs to be recreated by the application. */ enum E_LOST_RESSOURCE { //! The whole device/driver is lost @@ -77,6 +98,135 @@ namespace video ELR_HW_BUFFERS = 8 }; + //! Special render targets, which usually map to dedicated hardware + /** These render targets (besides 0 and 1) need not be supported by gfx cards */ + enum E_RENDER_TARGET + { + //! Render target is the main color frame buffer + ERT_FRAME_BUFFER=0, + //! Render target is a render texture + ERT_RENDER_TEXTURE, + //! Multi-Render target textures + ERT_MULTI_RENDER_TEXTURES, + //! Render target is the main color frame buffer + ERT_STEREO_LEFT_BUFFER, + //! Render target is the right color buffer (left is the main buffer) + ERT_STEREO_RIGHT_BUFFER, + //! Render to both stereo buffers at once + ERT_STEREO_BOTH_BUFFERS, + //! Auxiliary buffer 0 + ERT_AUX_BUFFER0, + //! Auxiliary buffer 1 + ERT_AUX_BUFFER1, + //! Auxiliary buffer 2 + ERT_AUX_BUFFER2, + //! Auxiliary buffer 3 + ERT_AUX_BUFFER3, + //! Auxiliary buffer 4 + ERT_AUX_BUFFER4 + }; + + //! Enum for the types of fog distributions to choose from + enum E_FOG_TYPE + { + EFT_FOG_EXP=0, + EFT_FOG_LINEAR, + EFT_FOG_EXP2 + }; + + const c8* const FogTypeNames[] = + { + "FogExp", + "FogLinear", + "FogExp2", + 0 + }; + + struct SOverrideMaterial + { + //! The Material values + SMaterial Material; + //! Which values are taken for override + /** OR'ed values from E_MATERIAL_FLAGS. */ + u32 EnableFlags; + //! Set in which render passes the material override is active. + /** OR'ed values from E_SCENE_NODE_RENDER_PASS. */ + u16 EnablePasses; + //! Global enable flag, overwritten by the SceneManager in each pass + /** The Scenemanager uses the EnablePass array and sets Enabled to + true if the Override material is enabled in the current pass. */ + bool Enabled; + + //! Default constructor + SOverrideMaterial() : EnableFlags(0), EnablePasses(0), Enabled(false) {} + + //! Apply the enabled overrides + void apply(SMaterial& material) + { + if (Enabled) + { + for (u32 i=0; i<32; ++i) + { + const u32 num=(1<* sourceRect=0) = 0; + const SExposedVideoData& videoData=SExposedVideoData(), + core::rect* sourceRect=0) =0; //! Presents the rendered image to the screen. /** Applications must call this method after performing any rendering. \return False if failed and true if succeeded. */ - virtual bool endScene() = 0; + virtual bool endScene() =0; //! Queries the features of the driver. /** Returns true if a feature is available \param feature Feature to query. \return True if the feature is available, false if not. */ - virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const = 0; + virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const =0; //! Disable a feature of the driver. /** Can also be used to enable the features again. It is not @@ -141,17 +291,37 @@ namespace video /** \param state Transformation type to be set, e.g. view, world, or projection. \param mat Matrix describing the transformation. */ - virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) = 0; + virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) =0; //! Returns the transformation set by setTransform /** \param state Transformation type to query \return Matrix describing the transformation. */ - virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const = 0; + virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const =0; + + //! Retrieve the number of image loaders + /** \return Number of image loaders */ + virtual u32 getImageLoaderCount() const = 0; + + //! Retrieve the given image loader + /** \param n The index of the loader to retrieve. This parameter is an 0-based + array index. + \return A pointer to the specified loader, 0 if the index is uncorrect. */ + virtual IImageLoader* getImageLoader(u32 n) = 0; + + //! Retrieve the number of image writers + /** \return Number of image writers */ + virtual u32 getImageWriterCount() const = 0; + + //! Retrieve the given image writer + /** \param n The index of the writer to retrieve. This parameter is an 0-based + array index. + \return A pointer to the specified writer, 0 if the index is uncorrect. */ + virtual IImageWriter* getImageWriter(u32 n) = 0; //! Sets a material. /** All 3d drawing functions will draw geometry using this material thereafter. \param material: Material to be used from now on. */ - virtual void setMaterial(const SMaterial& material) = 0; + virtual void setMaterial(const SMaterial& material) =0; //! Get access to a named texture. /** Loads the texture from disk if it is not @@ -163,19 +333,7 @@ namespace video \return Pointer to the texture, or 0 if the texture could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ITexture* getTexture(const c8* filename) = 0; - - //! Get access to a named texture. - /** Loads the texture from disk if it is not - already loaded and generates mipmap levels if desired. - Texture loading can be influenced using the - setTextureCreationFlag() method. The texture can be in several - imageformats, such as BMP, JPG, TGA, PCX, PNG, and PSD. - \param filename Filename of the texture to be loaded. - \return Pointer to the texture, or 0 if the texture - could not be loaded. This pointer should not be dropped. See - IReferenceCounted::drop() for more information. */ - virtual ITexture* getTexture(const core::stringc& filename) = 0; + virtual ITexture* getTexture(const io::path& filename) = 0; //! Get access to a named texture. /** Loads the texture from disk if it is not @@ -187,7 +345,7 @@ namespace video \return Pointer to the texture, or 0 if the texture could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ITexture* getTexture(io::IReadFile* file) = 0; + virtual ITexture* getTexture(io::IReadFile* file) =0; //! Returns a texture by index /** \param index: Index of the texture, must be smaller than @@ -196,7 +354,7 @@ namespace video \return Pointer to the texture, or 0 if the texture was not set or index is out of bounds. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ITexture* getTextureByIndex(u32 index) = 0; + virtual ITexture* getTextureByIndex(u32 index) =0; //! Returns amount of textures currently loaded /** \return Amount of textures currently loaded */ @@ -205,7 +363,7 @@ namespace video //! Renames a texture /** \param texture Pointer to the texture to rename. \param newName New name for the texture. This should be a unique name. */ - virtual void renameTexture(ITexture* texture, const c8* newName) = 0; + virtual void renameTexture(ITexture* texture, const io::path& newName) = 0; //! Creates an empty texture of specified size. /** \param size: Size of the texture. @@ -217,17 +375,21 @@ namespace video \return Pointer to the newly created texture. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ITexture* addTexture(const core::dimension2d& size, - const c8* name, ECOLOR_FORMAT format = ECF_A8R8G8B8) = 0; + virtual ITexture* addTexture(const core::dimension2d& size, + const io::path& name, ECOLOR_FORMAT format = ECF_A8R8G8B8) = 0; //! Creates a texture from an IImage. /** \param name A name for the texture. Later calls of getTexture() with this name will return this texture \param image Image the texture is created from. + \param mipmapData Optional pointer to a set of images which + build up the whole mipmap set. Must be images of the same color + type as image. If this parameter is not given, the mipmaps are + derived from image. \return Pointer to the newly created texture. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ITexture* addTexture(const c8* name, IImage* image) = 0; + virtual ITexture* addTexture(const io::path& name, IImage* image, void* mipmapData=0) = 0; //! Adds a new render target texture to the texture cache. /** \param size Size of the texture, in pixels. Width and @@ -235,16 +397,12 @@ namespace video and it should not be bigger than the backbuffer, because it shares the zbuffer with the screen buffer. \param name An optional name for the RTT. + \param format The color format of the render target. Floating point formats are supported. \return Pointer to the created texture or 0 if the texture could not be created. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name=0) =0; - - //! Adds a new render target texture - /** \deprecated use addRenderTargetTexture instead. */ - virtual ITexture* createRenderTargetTexture(const core::dimension2d& size, - const c8* name=0) =0; + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name = "rt", const ECOLOR_FORMAT format = ECF_UNKNOWN) =0; //! Removes a texture from the texture cache and deletes it. /** This method can free a lot of memory! @@ -254,7 +412,7 @@ namespace video good idea to set all materials which are using this texture to 0 or another texture first. \param texture Texture to delete from the engine cache. */ - virtual void removeTexture(ITexture* texture) = 0; + virtual void removeTexture(ITexture* texture) =0; //! Removes all textures from the texture cache and deletes them. /** This method can free a lot of memory! @@ -263,38 +421,49 @@ namespace video by other parts of the engine for storing it longer. So it is a good idea to set all materials which are using this texture to 0 or another texture first. */ - virtual void removeAllTextures() = 0; + virtual void removeAllTextures() =0; //! Remove hardware buffer - virtual void removeHardwareBuffer(const scene::IMeshBuffer* mb) = 0; + virtual void removeHardwareBuffer(const scene::IMeshBuffer* mb) =0; //! Remove all hardware buffers - virtual void removeAllHardwareBuffers() = 0; + virtual void removeAllHardwareBuffers() =0; - //! Creates a 1bit alpha channel of the texture based of an color key. - /** This makes the texture transparent at the regions where + //! Sets a boolean alpha channel on the texture based on a color key. + /** This makes the texture fully transparent at the texels where this color key can be found when using for example draw2DImage - with useAlphachannel==true. + with useAlphachannel==true. The alpha of other texels is not modified. \param texture Texture whose alpha channel is modified. - \param color Color key color. Every pixel with this color will - become transparent as described above. Please note that the + \param color Color key color. Every texel with this color will + become fully transparent as described above. Please note that the colors of a texture may be converted when loading it, so the color values may not be exactly the same in the engine and for example in picture edit programs. To avoid this problem, you could use the makeColorKeyTexture method, which takes the - position of a pixel instead a color value. */ - virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color) const = 0; + position of a pixel instead a color value. + \param zeroTexels \deprecated If set to true, then any texels that match + the color key will have their color, as well as their alpha, set to zero + (i.e. black). This behaviour matches the legacy (buggy) behaviour prior + to release 1.5 and is provided for backwards compatibility only.*/ + virtual void makeColorKeyTexture(video::ITexture* texture, + video::SColor color, + bool zeroTexels = false) const =0; - //! Creates a 1bit alpha channel of the texture based of an color key position. - /** This makes the texture transparent at the regions where - this color key can be found when using for example draw2DImage - with useAlphachannel==true. + //! Sets a boolean alpha channel on the texture based on the color at a position. + /** This makes the texture fully transparent at the texels where + the color key can be found when using for example draw2DImage + with useAlphachannel==true. The alpha of other texels is not modified. \param texture Texture whose alpha channel is modified. \param colorKeyPixelPos Position of a pixel with the color key - color. Every pixel with this color will become transparent as - described above. */ + color. Every texel with this color will become fully transparent as + described above. + \param zeroTexels \deprecated If set to true, then any texels that match + the color key will have their color, as well as their alpha, set to zero + (i.e. black). This behaviour matches the legacy (buggy) behaviour prior + to release 1.5 and is provided for backwards compatibility only.*/ virtual void makeColorKeyTexture(video::ITexture* texture, - core::position2d colorKeyPixelPos) const = 0; + core::position2d colorKeyPixelPos, + bool zeroTexels = false) const =0; //! Creates a normal map from a height map texture. /** If the target texture has 32 bit, the height value is @@ -304,7 +473,7 @@ namespace video \param texture Texture whose alpha channel is modified. \param amplitude Constant value by which the height information is multiplied.*/ - virtual void makeNormalMapTexture(video::ITexture* texture, f32 amplitude=1.0f) const = 0; + virtual void makeNormalMapTexture(video::ITexture* texture, f32 amplitude=1.0f) const =0; //! Sets a new render target. /** This will only work if the driver supports the @@ -313,7 +482,7 @@ namespace video way: \code // create render target - ITexture* target = driver->addRenderTargetTexture(core::dimension2d(128,128), "rtt1"); + ITexture* target = driver->addRenderTargetTexture(core::dimension2d(128,128), "rtt1"); // ... @@ -340,32 +509,85 @@ namespace video \return True if sucessful and false if not. */ virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer=true, bool clearZBuffer=true, - SColor color=video::SColor(0,0,0,0)) = 0; + SColor color=video::SColor(0,0,0,0)) =0; + + //! set or reset special render targets + /** This method enables access to special color buffers such as + stereoscopic buffers or auxiliary buffers. + \param target Enum value for the render target + \param clearTarget Clears the target buffer with the color + parameter + \param clearZBuffer Clears the zBuffer of the rendertarget. + Note that because the main frame buffer may share the zbuffer with + the rendertarget, its zbuffer might be partially cleared too + by this. + \param color The background color for the render target. + \return True if sucessful and false if not. */ + virtual bool setRenderTarget(E_RENDER_TARGET target, bool clearTarget=true, + bool clearZBuffer=true, + SColor color=video::SColor(0,0,0,0)) =0; + + //! Sets new multiple render targets. + virtual bool setRenderTarget(const core::array& texture, + bool clearBackBuffer=true, bool clearZBuffer=true, + SColor color=video::SColor(0,0,0,0)) =0; //! Sets a new viewport. /** Every rendering operation is done into this new area. \param area: Rectangle defining the new area of rendering operations. */ - virtual void setViewPort(const core::rect& area) = 0; + virtual void setViewPort(const core::rect& area) =0; //! Gets the area of the current viewport. /** \return Rectangle of the current viewport. */ - virtual const core::rect& getViewPort() const = 0; + virtual const core::rect& getViewPort() const =0; //! Draws a vertex primitive list - /** Note that there may be at maximum 65536 vertices, because - the index list is an array of 16 bit values each with a maximum - value of 65536. If there are more than 65536 vertices in the - list, results of this operation are not defined. + /** Note that, depending on the index type, some vertices might be not + accessible through the index list. The limit is at 65535 vertices for 16bit + indices. Please note that currently not all primitives are available for + all drivers, and some might be emulated via triangle renders. \param vertices Pointer to array of vertices. \param vertexCount Amount of vertices in the array. - \param indexList Pointer to array of indices. + \param indexList Pointer to array of indices. These define the vertices used + for each primitive. Depending on the pType, indices are interpreted as single + objects (for point like primitives), pairs (for lines), triplets (for + triangles), or quads. \param primCount Amount of Primitives - \param vType Vertex type, e.g. EVT_STANDARD for S3DVertex. - \param pType Primitive type, e.g. EPT_TRIANGLE_FAN for a triangle fan. */ + \param vType Vertex type, e.g. video::EVT_STANDARD for S3DVertex. + \param pType Primitive type, e.g. scene::EPT_TRIANGLE_FAN for a triangle fan. + \param iType Index type, e.g. video::EIT_16BIT for 16bit indices. */ 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; + E_VERTEX_TYPE vType=EVT_STANDARD, + scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, + E_INDEX_TYPE iType=EIT_16BIT) =0; + + //! Draws a vertex primitive list in 2d + /** Compared to the general (3d) version of this method, this + one sets up a 2d render mode, and uses only x and y of vectors. + Note that, depending on the index type, some vertices might be + not accessible through the index list. The limit is at 65535 + vertices for 16bit indices. Please note that currently not all + primitives are available for all drivers, and some might be + emulated via triangle renders. This function is not available + for the sw drivers. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. These define the + vertices used for each primitive. Depending on the pType, + indices are interpreted as single objects (for point like + primitives), pairs (for lines), triplets (for triangles), or + quads. + \param primCount Amount of Primitives + \param vType Vertex type, e.g. video::EVT_STANDARD for S3DVertex. + \param pType Primitive type, e.g. scene::EPT_TRIANGLE_FAN for a triangle fan. + \param iType Index type, e.g. video::EIT_16BIT for 16bit indices. */ + virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primCount, + E_VERTEX_TYPE vType=EVT_STANDARD, + scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, + E_INDEX_TYPE iType=EIT_16BIT) =0; //! Draws an indexed triangle list. /** Note that there may be at maximum 65536 vertices, because @@ -376,8 +598,11 @@ namespace video \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices / 3. */ - virtual void drawIndexedTriangleList(const S3DVertex* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; + void drawIndexedTriangleList(const S3DVertex* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); + } //! Draws an indexed triangle list. /** Note that there may be at maximum 65536 vertices, because @@ -388,8 +613,11 @@ namespace video \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices / 3. */ - virtual void drawIndexedTriangleList(const S3DVertex2TCoords* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; + void drawIndexedTriangleList(const S3DVertex2TCoords* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_2TCOORDS, scene::EPT_TRIANGLES, EIT_16BIT); + } //! Draws an indexed triangle list. /** Note that there may be at maximum 65536 vertices, because @@ -400,8 +628,11 @@ namespace video \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices / 3. */ - virtual void drawIndexedTriangleList(const S3DVertexTangents* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; + void drawIndexedTriangleList(const S3DVertexTangents* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_TANGENTS, scene::EPT_TRIANGLES, EIT_16BIT); + } //! Draws an indexed triangle fan. /** Note that there may be at maximum 65536 vertices, because @@ -412,8 +643,11 @@ namespace video \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices - 2. */ - virtual void drawIndexedTriangleFan(const S3DVertex* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; + void drawIndexedTriangleFan(const S3DVertex* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_STANDARD, scene::EPT_TRIANGLE_FAN, EIT_16BIT); + } //! Draws an indexed triangle fan. /** Note that there may be at maximum 65536 vertices, because @@ -424,18 +658,36 @@ namespace video \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices - 2. */ - virtual void drawIndexedTriangleFan(const S3DVertex2TCoords* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; + void drawIndexedTriangleFan(const S3DVertex2TCoords* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_2TCOORDS, scene::EPT_TRIANGLE_FAN, EIT_16BIT); + } + + //! Draws an indexed triangle fan. + /** Note that there may be at maximum 65536 vertices, because + the index list is an array of 16 bit values each with a maximum + value of 65536. If there are more than 65536 vertices in the + list, results of this operation are not defined. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. + \param triangleCount Amount of Triangles. Usually amount of indices - 2. */ + void drawIndexedTriangleFan(const S3DVertexTangents* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_TANGENTS, scene::EPT_TRIANGLE_FAN, EIT_16BIT); + } //! Draws a 3d line. /** For some implementations, this method simply calls - drawIndexedTriangles for some triangles. + drawVertexPrimitiveList for some triangles. Note that the line is drawn using the current transformation matrix and material. So if you need to draw the 3D line independently of the current transformation, use \code - driver->setMaterial(unlitMaterial); - driver->setTransform(video::ETS_WORLD, core::matrix4()); + driver->setMaterial(someMaterial); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); \endcode for some properly set up material before drawing the line. Some drivers support line thickness set in the material. @@ -443,24 +695,24 @@ namespace video \param end End of the 3d line. \param color Color of the line. */ virtual void draw3DLine(const core::vector3df& start, - const core::vector3df& end, SColor color = SColor(255,255,255,255)) = 0; + const core::vector3df& end, SColor color = SColor(255,255,255,255)) =0; //! Draws a 3d triangle. - /** This method calls drawIndexedTriangles for some triangles. + /** This method calls drawVertexPrimitiveList for some triangles. This method works with all drivers because it simply calls - drawIndexedTriangleList but it is hence not very fast. + drawVertexPrimitiveList, but it is hence not very fast. Note that the triangle is drawn using the current transformation matrix and material. So if you need to draw it independently of the current transformation, use \code - driver->setMaterial(unlitMaterial); - driver->setTransform(video::ETS_WORLD, core::matrix4()); + driver->setMaterial(someMaterial); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); \endcode for some properly set up material before drawing the triangle. \param triangle The triangle to draw. \param color Color of the line. */ virtual void draw3DTriangle(const core::triangle3df& triangle, - SColor color = SColor(255,255,255,255)) = 0; + SColor color = SColor(255,255,255,255)) =0; //! Draws a 3d axis aligned box. /** This method simply calls draw3DLine for the edges of the @@ -468,21 +720,21 @@ namespace video matrix and material. So if you need to draw it independently of the current transformation, use \code - driver->setMaterial(unlitMaterial); - driver->setTransform(video::ETS_WORLD, core::matrix4()); + driver->setMaterial(someMaterial); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); \endcode for some properly set up material before drawing the box. \param box The axis aligned box to draw \param color Color to use while drawing the box. */ virtual void draw3DBox(const core::aabbox3d& box, - SColor color = SColor(255,255,255,255)) = 0; + SColor color = SColor(255,255,255,255)) =0; //! Draws a 2d image without any special effects /** \param texture Pointer to texture to use. \param destPos Upper left 2d destination position where the image will be drawn. */ virtual void draw2DImage(const video::ITexture* texture, - const core::position2d& destPos) = 0; + const core::position2d& destPos) =0; //! Draws a 2d image using a color /** (if color is other than @@ -501,8 +753,8 @@ namespace video \param useAlphaChannelOfTexture: If true, the alpha channel of the texture is used to draw the image.*/ virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, - const core::rect& sourceRect, const core::rect* clipRect = 0, - SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) = 0; + const core::rect& sourceRect, const core::rect* clipRect =0, + SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) =0; //! Draws a set of 2d images, using a color and the alpha channel of the texture. /** The images are drawn beginning at pos and concatenated in @@ -524,14 +776,37 @@ namespace video 255, the image will be transparent. \param useAlphaChannelOfTexture: If true, the alpha channel of the texture is used to draw the image. */ - virtual void draw2DImage(const video::ITexture* texture, + virtual void draw2DImageBatch(const video::ITexture* texture, const core::position2d& pos, const core::array >& sourceRects, const core::array& indices, s32 kerningWidth=0, const core::rect* clipRect=0, SColor color=SColor(255,255,255,255), - bool useAlphaChannelOfTexture=false) = 0; + bool useAlphaChannelOfTexture=false) =0; + + //! Draws a set of 2d images, using a color and the alpha channel of the texture. + /** All drawings are clipped against clipRect (if != 0). + The subtextures are defined by the array of sourceRects and are + positioned using the array of positions. + \param texture Texture to be drawn. + \param positions Array of upper left 2d destinations where the + images will be drawn. + \param sourceRects Source rectangles of the image. + \param clipRect Pointer to rectangle on the screen where the + images are clipped to. + If this pointer is 0 then the image is not clipped. + \param color Color with which the image is drawn. + Note that the alpha component is used. If alpha is other than + 255, the image will be transparent. + \param useAlphaChannelOfTexture: If true, the alpha channel of + the texture is used to draw the image. */ + virtual void draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect=0, + SColor color=SColor(255,255,255,255), + bool useAlphaChannelOfTexture=false) =0; //! Draws a part of the texture into the rectangle. Note that colors must be an array of 4 colors if used. /** Suggested and first implemented by zola. @@ -544,8 +819,8 @@ namespace video \param useAlphaChannelOfTexture True if alpha channel will be blended. */ 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; + const core::rect& sourceRect, const core::rect* clipRect =0, + const video::SColor * const colors=0, bool useAlphaChannelOfTexture=false) =0; //! Draws a 2d rectangle. /** \param color Color of the rectangle to draw. The alpha @@ -556,9 +831,9 @@ namespace video will be clipped. If the pointer is null, no clipping will be performed. */ virtual void draw2DRectangle(SColor color, const core::rect& pos, - const core::rect* clip = 0) = 0; + const core::rect* clip =0) =0; - //! Draws an 2d rectangle with a gradient. + //! Draws a 2d rectangle with a gradient. /** \param colorLeftUp Color of the upper left corner to draw. The alpha component will not be ignored and specifies how transparent the rectangle will be. @@ -578,22 +853,30 @@ namespace video virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, - const core::rect* clip = 0) = 0; + const core::rect* clip =0) =0; + + //! Draws the outline of a 2D rectangle. + /** \param pos Position of the rectangle. + \param color Color of the rectangle to draw. The alpha component + specifies how transparent the rectangle outline will be. */ + virtual void draw2DRectangleOutline(const core::recti& pos, + SColor color=SColor(255,255,255,255)) =0; //! Draws a 2d line. - /** \param start: Screen coordinates of the start of the line + /** \param start Screen coordinates of the start of the line in pixels. - \param end: Screen coordinates of the start of the line in + \param end Screen coordinates of the start of the line in pixels. - \param color: Color of the line to draw. */ + \param color Color of the line to draw. */ virtual void draw2DLine(const core::position2d& start, const core::position2d& end, - SColor color=SColor(255,255,255,255)) = 0; + SColor color=SColor(255,255,255,255)) =0; //! Draws a pixel. - /** \param position: the position of the pixel. - \param color: Color of the pixel to draw. */ - virtual void drawPixel(u32 x, u32 y, const SColor & color) = 0; + /** \param x The x-position of the pixel. + \param y The y-position of the pixel. + \param color Color of the pixel to draw. */ + virtual void drawPixel(u32 x, u32 y, const SColor& color) =0; //! Draws a non filled concyclic regular 2d polyon. /** This method can be used to draw circles, but also @@ -611,7 +894,7 @@ namespace video virtual void draw2DPolygon(core::position2d center, f32 radius, video::SColor color=SColor(100,255,255,255), - s32 vertexCount=10) = 0; + s32 vertexCount=10) =0; //! Draws a shadow volume into the stencil buffer. /** To draw a stencil shadow, do this: First, draw all geometry. @@ -625,7 +908,7 @@ namespace video \param count Amount of triangles in the array. \param zfail If set to true, zfail method is used, otherwise zpass. */ - virtual void drawStencilShadowVolume(const core::vector3df* triangles, s32 count, bool zfail=true) = 0; + virtual void drawStencilShadowVolume(const core::vector3df* triangles, s32 count, bool zfail=true) =0; //! Fills the stencil shadow with color. /** After the shadow volume has been drawn into the stencil @@ -651,18 +934,17 @@ namespace video video::SColor leftUpEdge = video::SColor(255,0,0,0), video::SColor rightUpEdge = video::SColor(255,0,0,0), video::SColor leftDownEdge = video::SColor(255,0,0,0), - video::SColor rightDownEdge = video::SColor(255,0,0,0)) = 0; + video::SColor rightDownEdge = video::SColor(255,0,0,0)) =0; //! Draws a mesh buffer - /** \param mb: Buffer to draw; */ - virtual void drawMeshBuffer( const scene::IMeshBuffer* mb) = 0; + /** \param mb Buffer to draw; */ + virtual void drawMeshBuffer(const scene::IMeshBuffer* mb) =0; //! Sets the fog mode. /** These are global values attached to each 3d object rendered, which has the fog flag enabled in its material. \param color Color of the fog - \param linearFog Set this to true for linear fog, otherwise - exponential fog is applied. + \param fogType Type of fog used \param start Only used in linear fog mode (linearFog=true). Specifies where fog starts. \param end Only used in linear fog mode (linearFog=true). @@ -673,27 +955,32 @@ namespace video you want per-pixel fog. \param rangeFog Set this to true to enable range-based vertex fog. The distance from the viewer is used to compute the fog, - not the z-coordinate. This is better, but slower. This is only - available with D3D and vertex fog. */ + not the z-coordinate. This is better, but slower. This might not + be available with all drivers and fog settings. */ virtual void setFog(SColor color=SColor(0,255,255,255), - bool linearFog=true, f32 start=50.0f, f32 end=100.0f, - f32 density=0.01f, - bool pixelFog=false, bool rangeFog=false) = 0; + E_FOG_TYPE fogType=EFT_FOG_LINEAR, + f32 start=50.0f, f32 end=100.0f, f32 density=0.01f, + bool pixelFog=false, bool rangeFog=false) =0; + + //! Gets the fog mode. + virtual void getFog(SColor& color, E_FOG_TYPE& fogType, + f32& start, f32& end, f32& density, + bool& pixelFog, bool& rangeFog) = 0; //! Get the current color format of the color buffer /** \return Color format of the color buffer. */ - virtual ECOLOR_FORMAT getColorFormat() const = 0; + virtual ECOLOR_FORMAT getColorFormat() const =0; //! Get the size of the screen or render window. /** \return Size of screen or render window. */ - virtual const core::dimension2d& getScreenSize() const = 0; + virtual const core::dimension2d& getScreenSize() const =0; //! Get the size of the current render target /** This method will return the screen size if the driver doesn't support render to texture, or if the current render target is the screen. \return Size of render target or screen/window */ - virtual const core::dimension2d& getCurrentRenderTargetSize() const = 0; + virtual const core::dimension2d& getCurrentRenderTargetSize() const =0; //! Returns current frames per second value. /** This value is updated approximately every 1.5 seconds and @@ -701,40 +988,46 @@ namespace video rate. It is not suitable for use in performing timing calculations or framerate independent movement. \return Approximate amount of frames per second drawn. */ - virtual s32 getFPS() const = 0; + virtual s32 getFPS() const =0; //! Returns amount of primitives (mostly triangles) which were drawn in the last frame. /** Together with getFPS() very useful method for statistics. \param mode Defines if the primitives drawn are accumulated or counted per frame. \return Amount of primitives drawn in the last frame. */ - virtual u32 getPrimitiveCountDrawn( u32 mode = 0 ) const = 0; + virtual u32 getPrimitiveCountDrawn( u32 mode =0 ) const =0; //! Deletes all dynamic lights which were previously added with addDynamicLight(). - virtual void deleteAllDynamicLights() = 0; + virtual void deleteAllDynamicLights() =0; - //! Adds a dynamic light. - /** \param light Data specifying the dynamic light. */ - virtual void addDynamicLight(const SLight& light) = 0; + //! adds a dynamic light, returning an index to the light + //! \param light: the light data to use to create the light + //! \return An index to the light, or -1 if an error occurs + virtual s32 addDynamicLight(const SLight& light) =0; //! Returns the maximal amount of dynamic lights the device can handle /** \return Maximal amount of dynamic lights. */ - virtual u32 getMaximalDynamicLightAmount() const = 0; + virtual u32 getMaximalDynamicLightAmount() const =0; //! Returns amount of dynamic lights currently set /** \return Amount of dynamic lights currently set */ - virtual u32 getDynamicLightCount() const = 0; + virtual u32 getDynamicLightCount() const =0; //! Returns light data which was previously set by IVideoDriver::addDynamicLight(). /** \param idx Zero based index of the light. Must be 0 or greater and smaller than IVideoDriver()::getDynamicLightCount. \return Light data. */ - virtual const SLight& getDynamicLight(u32 idx) const = 0; + virtual const SLight& getDynamicLight(u32 idx) const =0; + + //! Turns a dynamic light on or off + //! \param lightIndex: the index returned by addDynamicLight + //! \param turnOn: true to turn the light on, false to turn it off + virtual void turnLightOn(s32 lightIndex, bool turnOn) =0; //! Gets name of this video driver. /** \return Returns the name of the video driver, e.g. in case of the Direct3D8 driver, it would return "Direct3D 8.1". */ - virtual const wchar_t* getName() const = 0; + virtual const wchar_t* getName() const =0; //! Adds an external image loader to the engine. /** This is useful if the Irrlicht Engine should be able to load @@ -743,7 +1036,7 @@ namespace video format. A pointer to the implementation can be passed to the engine using this method. \param loader Pointer to the external loader created. */ - virtual void addExternalImageLoader(IImageLoader* loader) = 0; + virtual void addExternalImageLoader(IImageLoader* loader) =0; //! Adds an external image writer to the engine. /** This is useful if the Irrlicht Engine should be able to @@ -752,13 +1045,13 @@ namespace video writing this file format. A pointer to the implementation can be passed to the engine using this method. \param writer: Pointer to the external writer created. */ - virtual void addExternalImageWriter(IImageWriter* writer) = 0; + virtual void addExternalImageWriter(IImageWriter* writer) =0; //! Returns the maximum amount of primitives /** (mostly vertices) which the device is able to render with - one drawIndexedTriangleList call. + one drawVertexPrimitiveList call. \return Maximum amount of primitives. */ - virtual u32 getMaximalPrimitiveCount() const = 0; + virtual u32 getMaximalPrimitiveCount() const =0; //! Enables or disables a texture creation flag. /** These flags define how textures should be created. By @@ -770,13 +1063,13 @@ namespace video \param flag Texture creation flag. \param enabled Specifies if the given flag should be enabled or disabled. */ - virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled) = 0; + virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled=true) =0; //! Returns if a texture creation flag is enabled or disabled. /** You can change this value using setTextureCreationMode(). \param flag Texture creation flag. \return The current texture creation mode. */ - virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const = 0; + virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const =0; //! Creates a software image from a file. /** No hardware texture will be created for this image. This @@ -787,7 +1080,7 @@ namespace video \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ - virtual IImage* createImageFromFile(const c8* filename) = 0; + virtual IImage* createImageFromFile(const io::path& filename) = 0; //! Creates a software image from a file. /** No hardware texture will be created for this image. This @@ -797,7 +1090,7 @@ namespace video \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ - virtual IImage* createImageFromFile(io::IReadFile* file) = 0; + virtual IImage* createImageFromFile(io::IReadFile* file) =0; //! Writes the provided image to a file. /** Requires that there is a suitable image writer registered @@ -807,7 +1100,18 @@ namespace video \param param Control parameter for the backend (e.g. compression level). \return True on successful write. */ - virtual bool writeImageToFile(IImage* image, const c8* filename, u32 param = 0) = 0; + virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0) = 0; + + //! Writes the provided image to a file. + /** Requires that there is a suitable image writer registered + for writing the image. + \param image Image to write. + \param file An already open io::IWriteFile object. The name will be used to determine + the appropriate image writer to use. + \param param Control parameter for the backend (e.g. compression + level). + \return True on successful write. */ + virtual bool writeImageToFile(IImage* image, io::IWriteFile* file, u32 param =0) =0; //! Creates a software image from a byte array. /** No hardware texture will be created for this image. This @@ -825,9 +1129,9 @@ namespace video If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ virtual IImage* createImageFromData(ECOLOR_FORMAT format, - const core::dimension2d& size, void *data, + const core::dimension2d& size, void *data, bool ownForeignMemory=false, - bool deleteMemory = true) = 0; + bool deleteMemory = true) =0; //! Creates an empty software image. /** @@ -836,10 +1140,10 @@ namespace video \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ - virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size) =0; + virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size) =0; //! Creates a software image by converting it to given format from another image. - /** + /** \deprecated Create an empty image and use copyTo() \param format Desired color format of the image. \param imageToCopy Image to copy to the new image. \return The created image. @@ -848,8 +1152,8 @@ namespace video virtual IImage* createImage(ECOLOR_FORMAT format, IImage *imageToCopy) =0; //! Creates a software image from a part of another image. - /** - \param imageToCopy Image to copy the the new image in part. + /** \deprecated Create an empty image and use copyTo() + \param imageToCopy Image to copy to the new image in part. \param pos Position of rectangle to copy. \param size Extents of rectangle to copy. \return The created image. @@ -857,12 +1161,24 @@ namespace video See IReferenceCounted::drop() for more information. */ virtual IImage* createImage(IImage* imageToCopy, const core::position2d& pos, - const core::dimension2d& size) =0; + const core::dimension2d& size) =0; + + //! Creates a software image from a part of a texture. + /** + \param texture Texture to copy to the new image in part. + \param pos Position of rectangle to copy. + \param size Extents of rectangle to copy. + \return The created image. + If you no longer need the image, you should call IImage::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IImage* createImage(ITexture* texture, + const core::position2d& pos, + const core::dimension2d& size) =0; //! Event handler for resize events. Only used by the engine internally. /** Used to notify the driver that the window was resized. Usually, there is no need to call this method. */ - virtual void OnResize(const core::dimension2d& size) = 0; + virtual void OnResize(const core::dimension2d& size) =0; //! Adds a new material renderer to the video device. /** Use this method to extend the VideoDriver with new material @@ -885,18 +1201,18 @@ namespace video an error occured. For example if you tried to add an material renderer to the software renderer or the null device, which do not accept material renderers. */ - virtual s32 addMaterialRenderer(IMaterialRenderer* renderer, const c8* name = 0) = 0; + virtual s32 addMaterialRenderer(IMaterialRenderer* renderer, const c8* name =0) =0; //! Get access to a material renderer by index. /** \param idx Id of the material renderer. Can be a value of the E_MATERIAL_TYPE enum or a value which was returned by addMaterialRenderer(). \return Pointer to material renderer or null if not existing. */ - virtual IMaterialRenderer* getMaterialRenderer(u32 idx) = 0; + virtual IMaterialRenderer* getMaterialRenderer(u32 idx) =0; //! Get amount of currently available material renderers. /** \return Amount of currently available material renderers. */ - virtual u32 getMaterialRendererCount() const = 0; + virtual u32 getMaterialRendererCount() const =0; //! Get name of a material renderer /** This string can, e.g., be used to test if a specific @@ -908,7 +1224,7 @@ namespace video addMaterialRenderer(). \return String with the name of the renderer, or 0 if not exisiting */ - virtual const c8* getMaterialRendererName(u32 idx) const = 0; + virtual const c8* getMaterialRendererName(u32 idx) const =0; //! Sets the name of a material renderer. /** Will have no effect on built-in material renderers. @@ -916,7 +1232,7 @@ namespace video E_MATERIAL_TYPE enum or a value which was returned by addMaterialRenderer(). \param name: New name of the material renderer. */ - virtual void setMaterialRendererName(s32 idx, const c8* name) = 0; + virtual void setMaterialRendererName(s32 idx, const c8* name) =0; //! Creates material attributes list from a material /** This method is useful for serialization and more. @@ -926,7 +1242,7 @@ namespace video \param material The material to serialize. \return The io::IAttributes container holding the material properties. */ - virtual io::IAttributes* createAttributesFromMaterial(const video::SMaterial& material) = 0; + virtual io::IAttributes* createAttributesFromMaterial(const video::SMaterial& material) =0; //! Fills an SMaterial structure from attributes. /** Please note that for setting material types of the @@ -935,26 +1251,26 @@ namespace video have been created before calling this method. \param outMaterial The material to set the properties for. \param attributes The attributes to read from. */ - virtual void fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attributes) = 0; + virtual void fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attributes) =0; //! Returns driver and operating system specific data about the IVideoDriver. /** This method should only be used if the engine should be extended without having to modify the source of the engine. \return Collection of device dependent pointers. */ - virtual const SExposedVideoData& getExposedVideoData() = 0; + virtual const SExposedVideoData& getExposedVideoData() =0; //! Get type of video driver /** \return Type of driver. */ - virtual E_DRIVER_TYPE getDriverType() const = 0; + virtual E_DRIVER_TYPE getDriverType() const =0; //! Gets the IGPUProgrammingServices interface. /** \return Pointer to the IGPUProgrammingServices. Returns 0 if the video driver does not support this. For example the Software driver and the Null driver will always return 0. */ - virtual IGPUProgrammingServices* getGPUProgrammingServices() = 0; + virtual IGPUProgrammingServices* getGPUProgrammingServices() =0; //! Returns a pointer to the mesh manipulator. - virtual scene::IMeshManipulator* getMeshManipulator() = 0; + virtual scene::IMeshManipulator* getMeshManipulator() =0; //! Clears the ZBuffer. /** Note that you usually need not to call this method, as it @@ -963,18 +1279,18 @@ namespace video you have to render some special things, you can clear the zbuffer during the rendering process with this method any time. */ - virtual void clearZBuffer() = 0; + virtual void clearZBuffer() =0; //! Make a screenshot of the last rendered frame. /** \return An image created from the last rendered frame. */ - virtual IImage* createScreenShot() = 0; + virtual IImage* createScreenShot() =0; //! Check if the image is already loaded. /** Works similar to getTexture(), but does not load the texture if it is not currently loaded. \param filename Name of the texture. \return Pointer to loaded texture, or 0 if not found. */ - virtual video::ITexture* findTexture(const c8* filename) = 0; + virtual video::ITexture* findTexture(const io::path& filename) = 0; //! Set or unset a clipping plane. /** There are at least 6 clipping planes available for the user @@ -985,7 +1301,7 @@ namespace video \param enable If true, enable the clipping plane else disable it. \return True if the clipping plane is usable. */ - virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false) = 0; + virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false) =0; //! Enable or disable a clipping plane. /** There are at least 6 clipping planes available for the user @@ -994,22 +1310,57 @@ namespace video MaxUserClipPlanes. \param enable If true, enable the clipping plane else disable it. */ - virtual void enableClipPlane(u32 index, bool enable) = 0; + virtual void enableClipPlane(u32 index, bool enable) =0; + + //! Set the minimum number of vertices for which a hw buffer will be created + /** \param count Number of vertices to set as minimum. */ + virtual void setMinHardwareBufferVertexCount(u32 count) =0; + + //! Get the global Material, which might override local materials. + /** Depending on the enable flags, values from this Material + are used to override those of local materials of some + meshbuffer being rendered. + \return Reference to the Override Material. */ + virtual SOverrideMaterial& getOverrideMaterial() =0; + + //! Get the 2d override material for altering its values + /** The 2d override materual allows to alter certain render + states of the 2d methods. Not all members of SMaterial are + honored, especially not MaterialType and Textures. Moreover, + the zbuffer is always ignored, and lighting is always off. All + other flags can be changed, though some might have to effect + in most cases. + Please note that you have to enable/disable this effect with + enableInitMaterial2D(). This effect is costly, as it increases + the number of state changes considerably. Always reset the + values when done. + \return Material reference which should be altered to reflect + the new settings. + */ + virtual SMaterial& getMaterial2D() =0; + + //! Enable the 2d override material + /** \param enable Flag which tells whether the material shall be + enabled or disabled. */ + virtual void enableMaterial2D(bool enable=true) =0; //! Returns the graphics card vendor name. - virtual core::stringc getVendorInfo() = 0; + virtual core::stringc getVendorInfo() =0; //! Only used by the engine internally. /** The ambient color is set in the scene manager, see scene::ISceneManager::setAmbientLight(). \param color New color of the ambient light. */ - virtual void setAmbientLight(const SColorf& color) = 0; + virtual void setAmbientLight(const SColorf& color) =0; //! Only used by the engine internally. /** Passes the global material flag AllowZWriteOnTransparent. Use the SceneManager attribute to set this value from your app. \param flag Default behavior is to disable ZWrite, i.e. false. */ - virtual void setAllowZWriteOnTransparent(bool flag) = 0; + virtual void setAllowZWriteOnTransparent(bool flag) =0; + + //! Returns the maximum texture size supported. + virtual core::dimension2du getMaxTextureSize() const =0; }; } // end namespace video @@ -1018,5 +1369,3 @@ namespace video #endif - - diff --git a/src/dep/include/irrlicht/IVideoModeList.h b/src/dep/include/irrlicht/IVideoModeList.h index 1e181cc..ceb843e 100644 --- a/src/dep/include/irrlicht/IVideoModeList.h +++ b/src/dep/include/irrlicht/IVideoModeList.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -31,14 +31,14 @@ namespace video //! Get the screen size of a video mode in pixels. /** \param modeNumber: zero based index of the video mode. \return Size of screen in pixels of the specified video mode. */ - virtual core::dimension2d getVideoModeResolution(s32 modeNumber) const = 0; + virtual core::dimension2d getVideoModeResolution(s32 modeNumber) const = 0; //! Get a supported screen size with certain constraints. /** \param minSize: Minimum dimensions required. \param maxSize: Maximum dimensions allowed. \return Size of screen in pixels which matches the requirements. as good as possible. */ - virtual core::dimension2d getVideoModeResolution(const core::dimension2d& minSize, const core::dimension2d& maxSize) const = 0; + virtual core::dimension2d getVideoModeResolution(const core::dimension2d& minSize, const core::dimension2d& maxSize) const = 0; //! Get the pixel depth of a video mode in bits. /** \param modeNumber: zero based index of the video mode. @@ -47,7 +47,7 @@ namespace video //! Get current desktop screen resolution. /** \return Size of screen in pixels of the current desktop video mode. */ - virtual const core::dimension2d& getDesktopResolution() const = 0; + virtual const core::dimension2d& getDesktopResolution() const = 0; //! Get the pixel depth of a video mode in bits. /** \return Size of each pixel of the current desktop video mode in bits. */ diff --git a/src/dep/include/irrlicht/IVolumeLightSceneNode.h b/src/dep/include/irrlicht/IVolumeLightSceneNode.h index f3ef5ac..0ca2301 100644 --- a/src/dep/include/irrlicht/IVolumeLightSceneNode.h +++ b/src/dep/include/irrlicht/IVolumeLightSceneNode.h @@ -1,47 +1,60 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h -// -// created by Dean Wadsworth aka Varmint Dec 31 2007 - -#ifndef __I_VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ -#define __I_VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ - -#include "ISceneNode.h" - -namespace irr -{ -namespace scene -{ - class IVolumeLightSceneNode : public ISceneNode - { - public: - - //! constructor - IVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, - const core::vector3df& position, - const core::vector3df& rotation, - const core::vector3df& scale) - : ISceneNode(parent, mgr, id, position, rotation, scale) {}; - - //! Returns type of the scene node - virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; } - - virtual void setSubDivideU (const u32 inU) =0; - virtual void setSubDivideV (const u32 inV) =0; - - virtual u32 getSubDivideU () const =0; - virtual u32 getSubDivideV () const =0; - - virtual void setFootColour(const video::SColor inColour) =0; - virtual void setTailColour(const video::SColor inColour) =0; - - virtual video::SColor getFootColour () const =0; - virtual video::SColor getTailColour () const =0; - }; - -} // end namespace scene -} // end namespace irr - -#endif - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h +// +// created by Dean Wadsworth aka Varmint Dec 31 2007 + +#ifndef __I_VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ +#define __I_VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + class IMeshBuffer; + + class IVolumeLightSceneNode : public ISceneNode + { + public: + + //! constructor + IVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position, + const core::vector3df& rotation, + const core::vector3df& scale) + : ISceneNode(parent, mgr, id, position, rotation, scale) {}; + + //! Returns type of the scene node + virtual ESCENE_NODE_TYPE getType() const { return ESNT_VOLUME_LIGHT; } + + //! Sets the number of segments across the U axis + virtual void setSubDivideU(const u32 inU) =0; + + //! Sets the number of segments across the V axis + virtual void setSubDivideV(const u32 inV) =0; + + //! Returns the number of segments across the U axis + virtual u32 getSubDivideU() const =0; + + //! Returns the number of segments across the V axis + virtual u32 getSubDivideV() const =0; + + //! Sets the color of the base of the light + virtual void setFootColor(const video::SColor inColour) =0; + + //! Sets the color of the tip of the light + virtual void setTailColor(const video::SColor inColour) =0; + + //! Returns the color of the base of the light + virtual video::SColor getFootColor() const =0; + + //! Returns the color of the tip of the light + virtual video::SColor getTailColor() const =0; + }; + +} // end namespace scene +} // end namespace irr + +#endif diff --git a/src/dep/include/irrlicht/IWriteFile.h b/src/dep/include/irrlicht/IWriteFile.h index aaf182f..8b2dd8c 100644 --- a/src/dep/include/irrlicht/IWriteFile.h +++ b/src/dep/include/irrlicht/IWriteFile.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,13 +6,14 @@ #define __I_WRITE_FILE_H_INCLUDED__ #include "IReferenceCounted.h" +#include "path.h" namespace irr { namespace io { - //! Interface providing write acess to a file. + //! Interface providing write access to a file. class IWriteFile : public virtual IReferenceCounted { public: @@ -36,11 +37,11 @@ namespace io //! Get name of file. /** \return File name as zero terminated character string. */ - virtual const c8* getFileName() const = 0; + virtual const path& getFileName() const = 0; }; //! Internal function, please do not use. - IWriteFile* createWriteFile(const c8* fileName, bool append); + IWriteFile* createWriteFile(const io::path& fileName, bool append); } // end namespace io } // end namespace irr diff --git a/src/dep/include/irrlicht/IXMLReader.h b/src/dep/include/irrlicht/IXMLReader.h index 1058e4b..e6ea4af 100644 --- a/src/dep/include/irrlicht/IXMLReader.h +++ b/src/dep/include/irrlicht/IXMLReader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IXMLWriter.h b/src/dep/include/irrlicht/IXMLWriter.h index 1fc906d..2e6a8f3 100644 --- a/src/dep/include/irrlicht/IXMLWriter.h +++ b/src/dep/include/irrlicht/IXMLWriter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/IrrCompileConfig.h b/src/dep/include/irrlicht/IrrCompileConfig.h index b239251..85c2d40 100644 --- a/src/dep/include/irrlicht/IrrCompileConfig.h +++ b/src/dep/include/irrlicht/IrrCompileConfig.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,45 +6,75 @@ #define __IRR_COMPILE_CONFIG_H_INCLUDED__ //! Irrlicht SDK Version -#define IRRLICHT_SDK_VERSION "1.5" +#define IRRLICHT_VERSION_MAJOR 1 +#define IRRLICHT_VERSION_MINOR 7 +#define IRRLICHT_VERSION_REVISION 2 +// This flag will be defined only in SVN, the official release code will have +// it undefined +#define IRRLICHT_VERSION_SVN -beta +#define IRRLICHT_SDK_VERSION "1.7.2" #include // TODO: Although included elsewhere this is required at least for mingw //! The defines for different operating system are: //! _IRR_XBOX_PLATFORM_ for XBox //! _IRR_WINDOWS_ for all irrlicht supported Windows versions +//! _IRR_WINDOWS_CE_PLATFORM_ for Windows CE //! _IRR_WINDOWS_API_ for Windows or XBox //! _IRR_LINUX_PLATFORM_ for Linux (it is defined here if no other os is defined) //! _IRR_SOLARIS_PLATFORM_ for Solaris //! _IRR_OSX_PLATFORM_ for Apple systems running OSX //! _IRR_POSIX_API_ for Posix compatible systems -//! _IRR_USE_SDL_DEVICE_ for platform independent SDL framework -//! _IRR_USE_WINDOWS_DEVICE_ for Windows API based device -//! _IRR_USE_WINDOWS_CE_DEVICE_ for Windows CE API based device -//! _IRR_USE_LINUX_DEVICE_ for X11 based device -//! _IRR_USE_OSX_DEVICE_ for Cocoa native windowing on OSX -//! Note: PLATFORM defines the OS specific layer, API can groups several platforms -//! DEVICE is the windowing system used, several PLATFORMs support more than one DEVICE -//! Moreover, the DEVICE defined here is not directly related to the Irrlicht devices created in the app (but may depend on each other). +//! Note: PLATFORM defines the OS specific layer, API can group several platforms -//#define _IRR_USE_SDL_DEVICE_ 1 +//! DEVICE is the windowing system used, several PLATFORMs support more than one DEVICE +//! Irrlicht can be compiled with more than one device +//! _IRR_COMPILE_WITH_WINDOWS_DEVICE_ for Windows API based device +//! _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ for Windows CE API based device +//! _IRR_COMPILE_WITH_OSX_DEVICE_ for Cocoa native windowing on OSX +//! _IRR_COMPILE_WITH_X11_DEVICE_ for Linux X11 based device +//! _IRR_COMPILE_WITH_SDL_DEVICE_ for platform independent SDL framework +//! _IRR_COMPILE_WITH_CONSOLE_DEVICE_ for no windowing system, used as a fallback +//! _IRR_COMPILE_WITH_FB_DEVICE_ for framebuffer systems + + +//! Uncomment this line to compile with the SDL device +//#define _IRR_COMPILE_WITH_SDL_DEVICE_ + +//! Comment this line to compile without the fallback console device. +#define _IRR_COMPILE_WITH_CONSOLE_DEVICE_ //! WIN32 for Windows32 //! WIN64 for Windows64 // The windows platform and API support SDL and WINDOW device -#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) || defined(_WIN32_WCE) +#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) #define _IRR_WINDOWS_ #define _IRR_WINDOWS_API_ -#ifndef _IRR_USE_SDL_DEVICE_ -#define _IRR_USE_WINDOWS_DEVICE_ +#define _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #endif + +//! WINCE is a very restricted environment for mobile devices +#if defined(_WIN32_WCE) +#define _IRR_WINDOWS_ +#define _IRR_WINDOWS_API_ +#define _IRR_WINDOWS_CE_PLATFORM_ +#define _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1300) +# error "Only Microsoft Visual Studio 7.0 and later are supported." #endif // XBox only suppots the native Window stuff #if defined(_XBOX) -#define _IRR_XBOX_PLATFORM_ -#define _IRR_WINDOWS_API_ -#define _IRR_USE_WINDOWS_DEVICE_ + #undef _IRR_WINDOWS_ + #define _IRR_XBOX_PLATFORM_ + #define _IRR_WINDOWS_API_ + //#define _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + #undef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + //#define _IRR_COMPILE_WITH_SDL_DEVICE_ + + #include #endif #if defined(__APPLE__) || defined(MACOSX) @@ -52,46 +82,48 @@ #define MACOSX // legacy support #endif #define _IRR_OSX_PLATFORM_ -#if !defined(_IRR_USE_LINUX_DEVICE_) // for X11 windowing declare this -#define _IRR_USE_OSX_DEVICE_ -#endif +#define _IRR_COMPILE_WITH_OSX_DEVICE_ #endif #if !defined(_IRR_WINDOWS_API_) && !defined(_IRR_OSX_PLATFORM_) -#if defined(__sparc__) || defined(__sun__) -#define __BIG_ENDIAN__ -#define _IRR_SOLARIS_PLATFORM_ -#else +#ifndef _IRR_SOLARIS_PLATFORM_ #define _IRR_LINUX_PLATFORM_ #endif #define _IRR_POSIX_API_ - -#ifndef _IRR_USE_SDL_DEVICE_ -#define _IRR_USE_LINUX_DEVICE_ -#endif +#define _IRR_COMPILE_WITH_X11_DEVICE_ #endif //! Define _IRR_COMPILE_WITH_JOYSTICK_SUPPORT_ if you want joystick events. #define _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ +//! Maximum number of texture an SMaterial can have, up to 8 are supported by Irrlicht. +#define _IRR_MATERIAL_MAX_TEXTURES_ 4 + //! Define _IRR_COMPILE_WITH_DIRECT3D_8_ and _IRR_COMPILE_WITH_DIRECT3D_9_ to //! compile the Irrlicht engine with Direct3D8 and/or DIRECT3D9. -/** If you only want to use the software device or opengl this can be useful. +/** If you only want to use the software device or opengl you can disable those defines. This switch is mostly disabled because people do not get the g++ compiler compile -directX header files, and directX is only available on windows platforms. If you +directX header files, and directX is only available on Windows platforms. If you are using Dev-Cpp, and want to compile this using a DX dev pack, you can define _IRR_COMPILE_WITH_DX9_DEV_PACK_. So you simply need to add something like this to the compiler settings: -DIRR_COMPILE_WITH_DX9_DEV_PACK -and this to the linker settings: -ld3dx9 -ld3dx8 **/ +and this to the linker settings: -ld3dx9 -ld3dx8 + +Microsoft have chosen to remove D3D8 headers from their recent DXSDKs, and +so D3D8 support is now disabled by default. If you really want to build +with D3D8 support, then you will have to source a DXSDK with the appropriate +headers, e.g. Summer 2004. This is a Microsoft issue, not an Irrlicht one. +*/ #if defined(_IRR_WINDOWS_API_) && (!defined(__GNUC__) || defined(IRR_COMPILE_WITH_DX9_DEV_PACK)) -// #define _IRR_COMPILE_WITH_DIRECT3D_8_ +//! Only define _IRR_COMPILE_WITH_DIRECT3D_8_ if you have an appropriate DXSDK, e.g. Summer 2004 +//#define _IRR_COMPILE_WITH_DIRECT3D_8_ #define _IRR_COMPILE_WITH_DIRECT3D_9_ #endif //! Define _IRR_COMPILE_WITH_OPENGL_ to compile the Irrlicht engine with OpenGL. -/** If you do not wish the engine to be compiled with OpengGL, comment this +/** If you do not wish the engine to be compiled with OpenGL, comment this define out. */ #define _IRR_COMPILE_WITH_OPENGL_ @@ -129,17 +161,12 @@ define out. */ you will not be able to use anything provided by the GUI Environment, including loading fonts. */ #define _IRR_COMPILE_WITH_GUI_ -//! Define _IRR_COMPILE_WITH_ZLIB_ to enable compiling the engine using zlib. -/** This enables the engine to read from compressed .zip archives. If you -disable this feature, the engine can still read archives, but only uncompressed -ones. */ -#define _IRR_COMPILE_WITH_ZLIB_ - -//! Define _IRR_USE_NON_SYSTEM_ZLIB_ to let irrlicht use the zlib which comes with irrlicht. -/** If this is commented out, Irrlicht will try to compile using the zlib installed in the system. - This is only used when _IRR_COMPILE_WITH_ZLIB_ is defined. */ -#define _IRR_USE_NON_SYSTEM_ZLIB_ +//! Define _IRR_WCHAR_FILESYSTEM to enable unicode filesystem support for the engine. +/** This enables the engine to read/write from unicode filesystem. If you +disable this feature, the engine behave as before (ansi). This is currently only supported +for Windows based systems. */ +//#define _IRR_WCHAR_FILESYSTEM //! Define _IRR_COMPILE_WITH_JPEGLIB_ to enable compiling the engine using libjpeg. /** This enables the engine to read jpeg images. If you comment this out, @@ -175,6 +202,13 @@ watch registers, variables etc. This works with ASM, HLSL, and both with pixel a Note that the engine will run in D3D REF for this, which is a lot slower than HAL. */ #define _IRR_D3D_NO_SHADER_DEBUGGING +//! Define _IRR_D3D_USE_LEGACY_HLSL_COMPILER to enable the old HLSL compiler in recent DX SDKs +/** This enables support for ps_1_x shaders for recent DX SDKs. Otherwise, support +for this shader model is not available anymore in SDKs after Oct2006. You need to +distribute the OCT2006_d3dx9_31_x86.cab or OCT2006_d3dx9_31_x64.cab though, in order +to provide the user with the proper DLL. That's why it's disabled by default. */ +//#define _IRR_D3D_USE_LEGACY_HLSL_COMPILER + //! Define _IRR_USE_NVIDIA_PERFHUD_ to opt-in to using the nVidia PerHUD tool /** Enable, by opting-in, to use the nVidia PerfHUD performance analysis driver tool . */ @@ -201,7 +235,10 @@ tool . */ #define BURNINGVIDEO_RENDERER_BEAUTIFUL //#define BURNINGVIDEO_RENDERER_FAST //#define BURNINGVIDEO_RENDERER_ULTRA_FAST +//#define BURNINGVIDEO_RENDERER_CE +//! Uncomment the following line if you want to ignore the deprecated warnings +//#define IGNORE_DEPRECATED_WARNING //! Define _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ if you want to use bone based /** animated meshes. If you compile without this, you will be unable to load @@ -211,10 +248,12 @@ B3D, MS3D or X meshes */ #ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ //! Define _IRR_COMPILE_WITH_B3D_LOADER_ if you want to use Blitz3D files #define _IRR_COMPILE_WITH_B3D_LOADER_ -//! Define _IRR_COMPILE_WITH_B3D_LOADER_ if you want to Milkshape files +//! Define _IRR_COMPILE_WITH_MS3D_LOADER_ if you want to Milkshape files #define _IRR_COMPILE_WITH_MS3D_LOADER_ //! Define _IRR_COMPILE_WITH_X_LOADER_ if you want to use Microsoft X files #define _IRR_COMPILE_WITH_X_LOADER_ +//! Define _IRR_COMPILE_WITH_OGRE_LOADER_ if you want to load Ogre 3D files +#define _IRR_COMPILE_WITH_OGRE_LOADER_ #endif //! Define _IRR_COMPILE_WITH_IRR_MESH_LOADER_ if you want to load Irrlicht Engine .irrmesh files @@ -243,14 +282,14 @@ B3D, MS3D or X meshes */ #define _IRR_COMPILE_WITH_OBJ_LOADER_ //! Define _IRR_COMPILE_WITH_OCT_LOADER_ if you want to load FSRad OCT files #define _IRR_COMPILE_WITH_OCT_LOADER_ -//! Define _IRR_COMPILE_WITH_OGRE_LOADER_ if you want to load Ogre 3D files -#define _IRR_COMPILE_WITH_OGRE_LOADER_ //! Define _IRR_COMPILE_WITH_LWO_LOADER_ if you want to load Lightwave3D files #define _IRR_COMPILE_WITH_LWO_LOADER_ -//! Define _IRR_COMPILE_WITH_STL_LOADER_ if you want to load .stl files +//! Define _IRR_COMPILE_WITH_STL_LOADER_ if you want to load stereolithography files #define _IRR_COMPILE_WITH_STL_LOADER_ +//! Define _IRR_COMPILE_WITH_PLY_LOADER_ if you want to load Polygon (Stanford Triangle) files +#define _IRR_COMPILE_WITH_PLY_LOADER_ -//! Define _IRR_COMPILE_WITH_IRR_WRITER_ if you want to write static .irr files +//! Define _IRR_COMPILE_WITH_IRR_WRITER_ if you want to write static .irrMesh files #define _IRR_COMPILE_WITH_IRR_WRITER_ //! Define _IRR_COMPILE_WITH_COLLADA_WRITER_ if you want to write Collada files #define _IRR_COMPILE_WITH_COLLADA_WRITER_ @@ -258,6 +297,8 @@ B3D, MS3D or X meshes */ #define _IRR_COMPILE_WITH_STL_WRITER_ //! Define _IRR_COMPILE_WITH_OBJ_WRITER_ if you want to write .obj files #define _IRR_COMPILE_WITH_OBJ_WRITER_ +//! Define _IRR_COMPILE_WITH_PLY_WRITER_ if you want to write .ply files +#define _IRR_COMPILE_WITH_PLY_WRITER_ //! Define _IRR_COMPILE_WITH_BMP_LOADER_ if you want to load .bmp files //! Disabling this loader will also disable the built-in font @@ -276,6 +317,8 @@ B3D, MS3D or X meshes */ #define _IRR_COMPILE_WITH_TGA_LOADER_ //! Define _IRR_COMPILE_WITH_WAL_LOADER_ if you want to load .wal files #define _IRR_COMPILE_WITH_WAL_LOADER_ +//! Define _IRR_COMPILE_WITH_RGB_LOADER_ if you want to load Silicon Graphics .rgb/.rgba/.sgi/.int/.inta/.bw files +#define _IRR_COMPILE_WITH_RGB_LOADER_ //! Define _IRR_COMPILE_WITH_BMP_WRITER_ if you want to write .bmp files #define _IRR_COMPILE_WITH_BMP_WRITER_ @@ -292,6 +335,47 @@ B3D, MS3D or X meshes */ //! Define _IRR_COMPILE_WITH_TGA_WRITER_ if you want to write .tga files #define _IRR_COMPILE_WITH_TGA_WRITER_ +//! Define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ if you want to open ZIP and GZIP archives +/** ZIP reading has several more options below to configure. */ +#define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ +#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ +//! Define _IRR_COMPILE_WITH_ZLIB_ to enable compiling the engine using zlib. +/** This enables the engine to read from compressed .zip archives. If you +disable this feature, the engine can still read archives, but only uncompressed +ones. */ +#define _IRR_COMPILE_WITH_ZLIB_ +//! Define _IRR_USE_NON_SYSTEM_ZLIB_ to let irrlicht use the zlib which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the zlib +installed on the system. This is only used when _IRR_COMPILE_WITH_ZLIB_ is +defined. */ +#define _IRR_USE_NON_SYSTEM_ZLIB_ +//! Define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ if you want to read AES-encrypted ZIP archives +#define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ +//! Define _IRR_COMPILE_WITH_BZIP2_ if you want to support bzip2 compressed zip archives +/** bzip2 is superior to the original zip file compression modes, but requires +a certain amount of memory for decompression and adds several files to the +library. */ +#define _IRR_COMPILE_WITH_BZIP2_ +//! Define _IRR_USE_NON_SYSTEM_BZLIB_ to let irrlicht use the bzlib which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the bzlib +installed on the system. This is only used when _IRR_COMPILE_WITH_BZLIB_ is +defined. */ +#define _IRR_USE_NON_SYSTEM_BZLIB_ +//! Define _IRR_COMPILE_WITH_LZMA_ if you want to use LZMA compressed zip files. +/** LZMA is a very efficient compression code, known from 7zip. Irrlicht +currently only supports zip archives, though. */ +#define _IRR_COMPILE_WITH_LZMA_ +#endif + +//! Define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ if you want to mount folders as archives +#define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ +//! Define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ if you want to open ID software PAK archives +#define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ +//! Define __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ if you want to open Nebula Device NPK archives +#define __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ +//! Define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ if you want to open TAR archives +#define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ + //! Set FPU settings /** Irrlicht should use approximate float and integer fpu techniques precision will be lower but speed higher. currently X86 only @@ -323,9 +407,17 @@ precision will be lower but speed higher. currently X86 only #define IRRCALLCONV __cdecl #endif // STDCALL_SUPPORTED +#else // _IRR_WINDOWS_API_ + +// Force symbol export in shared libraries built with gcc. +#if (__GNUC__ >= 4) && !defined(_IRR_STATIC_LIB_) && defined(IRRLICHT_EXPORTS) +#define IRRLICHT_API __attribute__ ((visibility("default"))) #else #define IRRLICHT_API +#endif + #define IRRCALLCONV + #endif // _IRR_WINDOWS_API_ // We need to disable DIRECT3D9 support for Visual Studio 6.0 because @@ -341,24 +433,72 @@ precision will be lower but speed higher. currently X86 only // XBox does not have OpenGL or DirectX9 #if defined(_IRR_XBOX_PLATFORM_) -#undef _IRR_COMPILE_WITH_OPENGL_ -#undef _IRR_COMPILE_WITH_DIRECT3D_9_ + #undef _IRR_COMPILE_WITH_OPENGL_ + #undef _IRR_COMPILE_WITH_DIRECT3D_9_ #endif -// WinCE does not have OpenGL or DirectX9 +//! WinCE does not have OpenGL or DirectX9. use minimal loaders #if defined(_WIN32_WCE) #undef _IRR_COMPILE_WITH_OPENGL_ #undef _IRR_COMPILE_WITH_DIRECT3D_8_ #undef _IRR_COMPILE_WITH_DIRECT3D_9_ - #undef _IRR_COMPILE_WITH_SOFTWARE_ + #undef BURNINGVIDEO_RENDERER_BEAUTIFUL - #undef _IRR_USE_WINDOWS_DEVICE_ - #define _IRR_USE_WINDOWS_CE_DEVICE_ + #undef BURNINGVIDEO_RENDERER_FAST + #undef BURNINGVIDEO_RENDERER_ULTRA_FAST #define BURNINGVIDEO_RENDERER_CE + + #undef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + #define _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ + //#define _IRR_WCHAR_FILESYSTEM + + #undef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ + //#undef _IRR_COMPILE_WITH_MD2_LOADER_ + #undef _IRR_COMPILE_WITH_MD3_LOADER_ + #undef _IRR_COMPILE_WITH_3DS_LOADER_ + #undef _IRR_COMPILE_WITH_COLLADA_LOADER_ + #undef _IRR_COMPILE_WITH_CSM_LOADER_ + #undef _IRR_COMPILE_WITH_BSP_LOADER_ + #undef _IRR_COMPILE_WITH_DMF_LOADER_ + #undef _IRR_COMPILE_WITH_LMTS_LOADER_ + #undef _IRR_COMPILE_WITH_MY3D_LOADER_ + #undef _IRR_COMPILE_WITH_OBJ_LOADER_ + #undef _IRR_COMPILE_WITH_OCT_LOADER_ + #undef _IRR_COMPILE_WITH_OGRE_LOADER_ + #undef _IRR_COMPILE_WITH_LWO_LOADER_ + #undef _IRR_COMPILE_WITH_STL_LOADER_ + #undef _IRR_COMPILE_WITH_IRR_WRITER_ + #undef _IRR_COMPILE_WITH_COLLADA_WRITER_ + #undef _IRR_COMPILE_WITH_STL_WRITER_ + #undef _IRR_COMPILE_WITH_OBJ_WRITER_ + //#undef _IRR_COMPILE_WITH_BMP_LOADER_ + //#undef _IRR_COMPILE_WITH_JPG_LOADER_ + #undef _IRR_COMPILE_WITH_PCX_LOADER_ + //#undef _IRR_COMPILE_WITH_PNG_LOADER_ + #undef _IRR_COMPILE_WITH_PPM_LOADER_ + #undef _IRR_COMPILE_WITH_PSD_LOADER_ + //#undef _IRR_COMPILE_WITH_TGA_LOADER_ + #undef _IRR_COMPILE_WITH_WAL_LOADER_ + #undef _IRR_COMPILE_WITH_BMP_WRITER_ + #undef _IRR_COMPILE_WITH_JPG_WRITER_ + #undef _IRR_COMPILE_WITH_PCX_WRITER_ + #undef _IRR_COMPILE_WITH_PNG_WRITER_ + #undef _IRR_COMPILE_WITH_PPM_WRITER_ + #undef _IRR_COMPILE_WITH_PSD_WRITER_ + #undef _IRR_COMPILE_WITH_TGA_WRITER_ + +#endif + +#ifndef _IRR_WINDOWS_API_ + #undef _IRR_WCHAR_FILESYSTEM +#endif + +#if defined(__sparc__) || defined(__sun__) +#define __BIG_ENDIAN__ #endif #if defined(_IRR_SOLARIS_PLATFORM_) -#undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ + #undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #endif #endif // __IRR_COMPILE_CONFIG_H_INCLUDED__ diff --git a/src/dep/include/irrlicht/IrrlichtDevice.h b/src/dep/include/irrlicht/IrrlichtDevice.h index 4f7e98c..8237cba 100644 --- a/src/dep/include/irrlicht/IrrlichtDevice.h +++ b/src/dep/include/irrlicht/IrrlichtDevice.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,6 +9,7 @@ #include "dimension2d.h" #include "IVideoDriver.h" #include "EDriverTypes.h" +#include "EDeviceTypes.h" #include "IEventReceiver.h" #include "ICursorControl.h" #include "IVideoModeList.h" @@ -33,9 +34,10 @@ namespace irr } // end namespace scene //! The Irrlicht device. You can create it with createDevice() or createDeviceEx(). - /** This is the most important class of the Irrlicht Engine. You can access everything - in the engine if you have a pointer to an instance of this class. - There should be only one instance of this class at any time. + /** This is the most important class of the Irrlicht Engine. You can + access everything in the engine if you have a pointer to an instance of + this class. There should be only one instance of this class at any + time. */ class IrrlichtDevice : public virtual IReferenceCounted { @@ -177,8 +179,8 @@ namespace irr \return String which contains the version. */ virtual const c8* getVersion() const = 0; - //! Sets a new user event receiver which will receive events from the engine. - /** Return true in IEventReceiver::OnEvent to prevent the event from continuing along + //! Sets a new user event receiver which will receive events from the engine. + /** Return true in IEventReceiver::OnEvent to prevent the event from continuing along the chain of event receivers. The path that an event takes through the system depends on its type. See irr::EEVENT_TYPE for details. \param receiver New receiver to be used. */ @@ -202,21 +204,99 @@ namespace irr \param sceneManager New scene manager to be used. */ virtual void setInputReceivingSceneManager(scene::ISceneManager* sceneManager) = 0; - //! Sets if the window should be resizeable in windowed mode. + //! Sets if the window should be resizable in windowed mode. /** The default is false. This method only works in windowed mode. - \param resize Flag whether the window should be resizeable. */ - virtual void setResizeAble(bool resize=false) = 0; + \param resize Flag whether the window should be resizable. */ + virtual void setResizable(bool resize=false) = 0; + + //! Minimizes the window if possible. + virtual void minimizeWindow() =0; + + //! Maximizes the window if possible. + virtual void maximizeWindow() =0; + + //! Restore the window to normal size if possible. + virtual void restoreWindow() =0; //! Activate any joysticks, and generate events for them. /** Irrlicht contains support for joysticks, but does not generate joystick events by default, - as this would consume joystick info that 3rd party libraries might rely on. Call this method to - activate joystick support in Irrlicht and to receive @ref SJoystickEvent events. + as this would consume joystick info that 3rd party libraries might rely on. Call this method to + activate joystick support in Irrlicht and to receive irr::SJoystickEvent events. \param joystickInfo On return, this will contain an array of each joystick that was found and activated. \return true if joysticks are supported on this device and _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ is defined, false if joysticks are not supported or support is compiled out. */ - virtual bool activateJoysticks(core::array & joystickInfo) = 0; + virtual bool activateJoysticks(core::array& joystickInfo) =0; + + //! Set the current Gamma Value for the Display + virtual bool setGammaRamp(f32 red, f32 green, f32 blue, + f32 relativebrightness, f32 relativecontrast) =0; + + //! Get the current Gamma Value for the Display + virtual bool getGammaRamp(f32 &red, f32 &green, f32 &blue, + f32 &brightness, f32 &contrast) =0; + + //! Remove messages pending in the system message loop + /** This function is usually used after messages have been buffered for a longer time, for example + when loading a large scene. Clearing the message loop prevents that mouse- or buttonclicks which users + have pressed in the meantime will now trigger unexpected actions in the gui.
+ So far the following messages are cleared:
+ Win32: All keyboard and mouse messages
+ Linux: All keyboard and mouse messages
+ All other devices are not yet supported here.
+ The function is still somewhat experimental, as the kind of messages we clear is based on just a few use-cases. + If you think further messages should be cleared, or some messages should not be cleared here, then please tell us. */ + virtual void clearSystemMessages() = 0; + + //! Get the type of the device. + /** This allows the user to check which windowing system is currently being + used. */ + virtual E_DEVICE_TYPE getType() const = 0; + + //! Check if a driver type is supported by the engine. + /** Even if true is returned the driver may not be available + for a configuration requested when creating the device. */ + static bool isDriverSupported(video::E_DRIVER_TYPE driver) + { + switch (driver) + { + case video::EDT_NULL: + return true; + case video::EDT_SOFTWARE: +#ifdef _IRR_COMPILE_WITH_SOFTWARE_ + return true; +#else + return false; +#endif + case video::EDT_BURNINGSVIDEO: +#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + return true; +#else + return false; +#endif + case video::EDT_DIRECT3D8: +#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ + return true; +#else + return false; +#endif + case video::EDT_DIRECT3D9: +#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ + return true; +#else + return false; +#endif + case video::EDT_OPENGL: +#ifdef _IRR_COMPILE_WITH_OPENGL_ + return true; +#else + return false; +#endif + default: + return false; + } + } }; } // end namespace irr diff --git a/src/dep/include/irrlicht/Keycodes.h b/src/dep/include/irrlicht/Keycodes.h index 79dbc90..21601fa 100644 --- a/src/dep/include/irrlicht/Keycodes.h +++ b/src/dep/include/irrlicht/Keycodes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -91,7 +91,7 @@ namespace irr KEY_KEY_Z = 0x5A, // Z key KEY_LWIN = 0x5B, // Left Windows key (Microsoft® Natural® keyboard) KEY_RWIN = 0x5C, // Right Windows key (Natural keyboard) - KEY_APPS = 0x5D, //Applications key (Natural keyboard) + KEY_APPS = 0x5D, // Applications key (Natural keyboard) KEY_SLEEP = 0x5F, // Computer Sleep key KEY_NUMPAD0 = 0x60, // Numeric keypad 0 key KEY_NUMPAD1 = 0x61, // Numeric keypad 1 key diff --git a/src/dep/include/irrlicht/S3DVertex.h b/src/dep/include/irrlicht/S3DVertex.h index 15f472c..944af12 100644 --- a/src/dep/include/irrlicht/S3DVertex.h +++ b/src/dep/include/irrlicht/S3DVertex.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/SAnimatedMesh.h b/src/dep/include/irrlicht/SAnimatedMesh.h index 09e4c9c..03adfb1 100644 --- a/src/dep/include/irrlicht/SAnimatedMesh.h +++ b/src/dep/include/irrlicht/SAnimatedMesh.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -164,10 +164,12 @@ namespace scene Meshes[i]->setDirty(buffer); } - //! The bounding box of this mesh - core::aabbox3d Box; //! All meshes defining the animated mesh core::array Meshes; + + //! The bounding box of this mesh + core::aabbox3d Box; + //! Tyhe type fo the mesh. E_ANIMATED_MESH_TYPE Type; }; diff --git a/src/dep/include/irrlicht/SColor.h b/src/dep/include/irrlicht/SColor.h index d10255b..babe63e 100644 --- a/src/dep/include/irrlicht/SColor.h +++ b/src/dep/include/irrlicht/SColor.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -106,7 +106,7 @@ namespace video //! Returns the alpha component from A1R5G5B5 color - /** In Irrlicht, alpha refers to opacity. + /** In Irrlicht, alpha refers to opacity. \return The alpha value of the color. 0 is transparent, 1 is opaque. */ inline u32 getAlpha(u16 color) { @@ -152,6 +152,7 @@ namespace video 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. + This class must consist of only one u32 and must not use virtual functions. */ class SColor { @@ -171,7 +172,7 @@ namespace video : color(clr) {} //! Returns the alpha component of the color. - /** The alpha component defines how opaque a color is. + /** 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; } @@ -190,13 +191,19 @@ namespace video 0 means no blue, 255 means full blue. */ u32 getBlue() const { return color & 0xff; } - //! Returns the luminance of the color. + //! Get lightness of the color in the range [0,255] + f32 getLightness() const + { + return 0.5f*(core::max_(core::max_(getRed(),getGreen()),getBlue())+core::min_(core::min_(getRed(),getGreen()),getBlue())); + } + + //! Get luminance of the color in the range [0,255]. f32 getLuminance() const { return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue(); } - //! Returns the average intensity of the color. + //! Get average intensity of the color in the range [0,255]. u32 getAverage() const { return ( getRed() + getGreen() + getBlue() ) / 3; @@ -290,10 +297,10 @@ namespace video { d = core::clamp(d, 0.f, 1.f); const f32 inv = 1.0f - d; - return SColor((u32)(other.getAlpha()*inv + getAlpha()*d), - (u32)(other.getRed()*inv + getRed()*d), - (u32)(other.getGreen()*inv + getGreen()*d), - (u32)(other.getBlue()*inv + getBlue()*d)); + return SColor((u32)core::round32(other.getAlpha()*inv + getAlpha()*d), + (u32)core::round32(other.getRed()*inv + getRed()*d), + (u32)core::round32(other.getGreen()*inv + getGreen()*d), + (u32)core::round32(other.getBlue()*inv + getBlue()*d)); } //! Returns interpolated color. ( quadratic ) @@ -335,6 +342,10 @@ namespace video class SColorf { public: + //! Default constructor for SColorf. + /** Sets red, green and blue to 0.0f and alpha to 1.0f. */ + SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {} + //! Constructs a color from up to four color values: red, green, blue, and alpha. /** \param r: Red color component. Should be a value between 0.0f meaning no red and 1.0f, meaning full red. @@ -346,7 +357,7 @@ namespace video component defines how transparent a color should be. Has to be a value between 0.0f and 1.0f, 1.0f means not transparent (opaque), 0.0f means fully transparent. */ - SColorf(f32 r=0.f, f32 g=0.f, f32 b=0.f, f32 a=1.f) : r(r), g(g), b(b), a(a) {} + SColorf(f32 r, f32 g, f32 b, f32 a = 1.0f) : r(r), g(g), b(b), a(a) {} //! Constructs a color from 32 bit Color. /** \param c: 32 bit color from which this SColorf class is @@ -363,7 +374,7 @@ namespace video //! Converts this color to a SColor without floats. SColor toSColor() const { - return SColor((u32)(a*255.0f), (u32)(r*255.0f), (u32)(g*255.0f), (u32)(b*255.0f)); + return SColor((u32)core::round32(a*255.0f), (u32)core::round32(r*255.0f), (u32)core::round32(g*255.0f), (u32)core::round32(b*255.0f)); } //! Sets three color components to new values at once. @@ -481,10 +492,11 @@ namespace video inline void SColorHSL::fromRGB(const SColor &color) { - const f32 maxVal = (f32)core::max_(color.getRed(), color.getGreen(), color.getBlue()); + const u32 maxValInt = core::max_(color.getRed(), color.getGreen(), color.getBlue()); + const f32 maxVal = (f32)maxValInt; const f32 minVal = (f32)core::min_(color.getRed(), color.getGreen(), color.getBlue()); Luminance = (maxVal/minVal)*0.5f; - if (maxVal==minVal) + if (core::equals(maxVal, minVal)) { Hue=0.f; Saturation=0.f; @@ -501,11 +513,11 @@ namespace video Saturation = (delta)/(2-maxVal-minVal); } - if (maxVal==color.getRed()) - Hue = (color.getRed()-color.getBlue())/delta; - else if (maxVal==color.getGreen()) + if (maxValInt == color.getRed()) + Hue = (color.getGreen()-color.getBlue())/delta; + else if (maxValInt == color.getGreen()) Hue = 2+(color.getBlue()-color.getRed())/delta; - else if (maxVal==color.getBlue()) + else // blue is max Hue = 4+(color.getRed()-color.getGreen())/delta; Hue *= (60.0f * core::DEGTORAD); @@ -516,12 +528,12 @@ namespace video inline void SColorHSL::toRGB(SColor &color) const { - if ( Saturation == 0.0f) // grey + if (core::iszero(Saturation)) // grey { u8 c = (u8) ( Luminance * 255.0 ); - color.setRed ( c ); - color.setGreen ( c ); - color.setBlue ( c ); + color.setRed(c); + color.setGreen(c); + color.setBlue(c); return; } @@ -560,7 +572,7 @@ namespace video rm1 = rm1 + (rm2 - rm1) * ( ( 240.0f * core::DEGTORAD ) - rh) / (60.0f * core::DEGTORAD); - return (u32) (rm1 * 255.f); + return (u32) core::round32(rm1 * 255.f); } } // end namespace video diff --git a/src/dep/include/irrlicht/SExposedVideoData.h b/src/dep/include/irrlicht/SExposedVideoData.h index 0ad1232..5a4a6ae 100644 --- a/src/dep/include/irrlicht/SExposedVideoData.h +++ b/src/dep/include/irrlicht/SExposedVideoData.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,6 +24,9 @@ you are using the software or the null device. */ struct SExposedVideoData { + SExposedVideoData() {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=0;} + explicit SExposedVideoData(void* Window) {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=Window;} + union { struct diff --git a/src/dep/include/irrlicht/SIrrCreationParameters.h b/src/dep/include/irrlicht/SIrrCreationParameters.h index a24b4d7..7ff89c9 100644 --- a/src/dep/include/irrlicht/SIrrCreationParameters.h +++ b/src/dep/include/irrlicht/SIrrCreationParameters.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,7 +6,9 @@ #define __I_IRRLICHT_CREATION_PARAMETERS_H_INCLUDED__ #include "EDriverTypes.h" +#include "EDeviceTypes.h" #include "dimension2d.h" +#include "ILogger.h" namespace irr { @@ -18,19 +20,23 @@ namespace irr { //! Constructs a SIrrlichtCreationParameters structure with default values. SIrrlichtCreationParameters() : + DeviceType(EIDT_BEST), DriverType(video::EDT_BURNINGSVIDEO), - WindowSize(core::dimension2d(800, 600)), + WindowSize(core::dimension2d(800, 600)), Bits(16), ZBufferBits(16), Fullscreen(false), Stencilbuffer(false), Vsync(false), - AntiAlias(false), + AntiAlias(0), WithAlphaChannel(false), + Doublebuffer(true), IgnoreInput(false), + Stereobuffer(false), HighPrecisionFPU(false), EventReceiver(0), WindowId(0), + LoggingLevel(ELL_INFORMATION), SDK_version_do_not_use(IRRLICHT_SDK_VERSION) { } @@ -41,6 +47,7 @@ namespace irr SIrrlichtCreationParameters& operator=(const SIrrlichtCreationParameters& other) { + DeviceType = other.DeviceType; DriverType = other.DriverType; WindowSize = other.WindowSize; Bits = other.Bits; @@ -50,14 +57,30 @@ namespace irr Vsync = other.Vsync; AntiAlias = other.AntiAlias; WithAlphaChannel = other.WithAlphaChannel; + Doublebuffer = other.Doublebuffer; IgnoreInput = other.IgnoreInput; + Stereobuffer = other.Stereobuffer; HighPrecisionFPU = other.HighPrecisionFPU; EventReceiver = other.EventReceiver; WindowId = other.WindowId; + LoggingLevel = other.LoggingLevel; return *this; } //! Type of the device. + /** This setting decides the windowing system used by the device, most device types are native + to a specific operating system and so may not be available. + EIDT_WIN32 is only available on Windows desktops, + EIDT_WINCE is only available on Windows mobile devices, + EIDT_COCOA is only available on Mac OSX, + EIDT_X11 is available on Linux, Solaris, BSD and other operating systems which use X11, + EIDT_SDL is available on most systems if compiled in, + EIDT_CONSOLE is usually available but can only render to text, + EIDT_BEST will select the best available device for your operating system. + Default: EIDT_BEST. */ + E_DEVICE_TYPE DeviceType; + + //! Type of video driver used to render graphics. /** This can currently be video::EDT_NULL, video::EDT_SOFTWARE, video::EDT_BURNINGSVIDEO, video::EDT_DIRECT3D8, video::EDT_DIRECT3D9, and video::EDT_OPENGL. @@ -65,7 +88,7 @@ namespace irr video::E_DRIVER_TYPE DriverType; //! Size of the window or the video mode in fullscreen mode. Default: 800x600 - core::dimension2d WindowSize; + core::dimension2d WindowSize; //! Minimum Bits per pixel of the color buffer in fullscreen mode. Ignored if windowed mode. Default: 16. u8 Bits; @@ -79,14 +102,15 @@ namespace irr //! Specifies if the stencil buffer should be enabled. /** Set this to true, if you want the engine be able to draw - stencil buffer shadows. Note that not all devices are able to - use the stencil buffer. If they don't no shadows will be drawn. + stencil buffer shadows. Note that not all drivers are able to + use the stencil buffer, hence it can be ignored during device + creation. Without the stencil buffer no shadows will be drawn. Default: false. */ bool Stencilbuffer; //! Specifies vertical syncronisation. /** If set to true, the driver will wait for the vertical - retrace period, otherwise not. + retrace period, otherwise not. May be silently ignored. Default: false */ bool Vsync; @@ -99,25 +123,49 @@ namespace irr writing a game/application with AntiAlias switched on, it would be a good idea to make it possible to switch this option off again by the user. - This is curently not supported in OpenGL under Windows. - Default value: false */ - bool AntiAlias; + The value is the maximal antialiasing factor requested for + the device. The cretion method will automatically try smaller + values if no window can be created with the given value. + Value one is usually the same as 0 (disabled), but might be a + special value on some platforms. On D3D devices it maps to + NONMASKABLE. + Default value: 0 - disabled */ + u8 AntiAlias; //! Whether the main framebuffer uses an alpha channel. /** In some situations it might be desireable to get a color buffer with an alpha channel, e.g. when rendering into a transparent window or overlay. If this flag is set the device tries to create a framebuffer with alpha channel. + If this flag is set, only color buffers with alpha channel + are considered. Otherwise, it depends on the actual hardware + if the colorbuffer has an alpha channel or not. Default value: false */ bool WithAlphaChannel; + //! Whether the main framebuffer uses doublebuffering. + /** This should be usually enabled, in order to avoid render + artifacts on the visible framebuffer. However, it might be + useful to use only one buffer on very small devices. If no + doublebuffering is available, the drivers will fall back to + single buffers. Default value: true */ + bool Doublebuffer; + //! Specifies if the device should ignore input events /** This is only relevant when using external I/O handlers. External windows need to take care of this themselves. - Currently only supported under X11. + Currently only supported by X11. Default value: false */ bool IgnoreInput; + //! Specifies if the device should use stereo buffers + /** Some high-end gfx cards support two framebuffers for direct + support of stereoscopic output devices. If this flag is set the + device tries to create a stereo context. + Currently only supported by OpenGL. + Default value: false */ + bool Stereobuffer; + //! Specifies if the device should use high precision FPU setting /** This is only relevant for DirectX Devices, which switch to low FPU precision by default for performance reasons. However, @@ -183,6 +231,14 @@ namespace irr do it how you like. */ void* WindowId; + //! Specifies the logging level used in the logging interface. + /** The default value is ELL_INFORMATION. You can access the ILogger interface + later on from the IrrlichtDevice with getLogger() and set another level. + But if you need more or less logging information already from device creation, + then you have to change it here. + */ + ELOG_LEVEL LoggingLevel; + //! Don't use or change this parameter. /** Always set it to IRRLICHT_SDK_VERSION, which is done by default. This is needed for sdk version checks. */ diff --git a/src/dep/include/irrlicht/SKeyMap.h b/src/dep/include/irrlicht/SKeyMap.h index d86bbb9..89f8eee 100644 --- a/src/dep/include/irrlicht/SKeyMap.h +++ b/src/dep/include/irrlicht/SKeyMap.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,6 +18,7 @@ namespace irr EKA_STRAFE_LEFT, EKA_STRAFE_RIGHT, EKA_JUMP_UP, + EKA_CROUCH, EKA_COUNT, //! This value is not used. It only forces this enumeration to compile in 32 bit. diff --git a/src/dep/include/irrlicht/SLight.h b/src/dep/include/irrlicht/SLight.h index 5fcd765..2ad8c69 100644 --- a/src/dep/include/irrlicht/SLight.h +++ b/src/dep/include/irrlicht/SLight.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -78,14 +78,14 @@ struct SLight /** If Type is ELT_POINT, it is ignored. Changed via light scene node's rotation. */ core::vector3df Direction; - //! Read-ONLY! Radius of light. Everything within this radius be be lighted. + //! Read-ONLY! Radius of light. Everything within this radius will be lighted. f32 Radius; //! Read-ONLY! Type of the light. Default: ELT_POINT E_LIGHT_TYPE Type; //! Read-ONLY! Does the light cast shadows? - bool CastShadows; + bool CastShadows:1; }; } // end namespace video diff --git a/src/dep/include/irrlicht/SMaterial.h b/src/dep/include/irrlicht/SMaterial.h index 92a851e..6ae7fe7 100644 --- a/src/dep/include/irrlicht/SMaterial.h +++ b/src/dep/include/irrlicht/SMaterial.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -8,6 +8,7 @@ #include "SColor.h" #include "matrix4.h" #include "irrArray.h" +#include "irrMath.h" #include "EMaterialTypes.h" #include "EMaterialFlags.h" #include "SMaterialLayer.h" @@ -42,24 +43,147 @@ namespace video EMFN_MODULATE_4X = 4 }; - //! EMT_ONETEXTURE_BLEND: pack srcFact & dstFact and Modulo to MaterialTypeParam - inline f32 pack_texureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate ) + //! Comparison function, e.g. for depth buffer test + enum E_COMPARISON_FUNC { - return (f32)(modulate << 16 | srcFact << 8 | dstFact); + //! Test never succeeds, this equals disable + ECFN_NEVER=0, + //! <= test, default for e.g. depth test + ECFN_LESSEQUAL=1, + //! Exact equality + ECFN_EQUAL=2, + //! exclusive less comparison, i.e. < + ECFN_LESS, + //! Succeeds almost always, except for exact equality + ECFN_NOTEQUAL, + //! >= test + ECFN_GREATEREQUAL, + //! inverse of <= + ECFN_GREATER, + //! test succeeds always + ECFN_ALWAYS + }; + + //! Enum values for enabling/disabling color planes for rendering + enum E_COLOR_PLANE + { + //! No color enabled + ECP_NONE=0, + //! Alpha enabled + ECP_ALPHA=1, + //! Red enabled + ECP_RED=2, + //! Green enabled + ECP_GREEN=4, + //! Blue enabled + ECP_BLUE=8, + //! All colors, no alpha + ECP_RGB=14, + //! All planes enabled + ECP_ALL=15 + }; + + //! Source of the alpha value to take + /** This is currently only supported in EMT_ONETEXTURE_BLEND. You can use an + or'ed combination of values. Alpha values are modulated (multiplicated). */ + enum E_ALPHA_SOURCE + { + //! Use no alpha, somewhat redundant with other settings + EAS_NONE=0, + //! Use vertex color alpha + EAS_VERTEX_COLOR, + //! Use texture alpha channel + EAS_TEXTURE + }; + + //! EMT_ONETEXTURE_BLEND: pack srcFact, dstFact, Modulate and alpha source to MaterialTypeParam + /** alpha source can be an OR'ed combination of E_ALPHA_SOURCE values. */ + inline f32 pack_texureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE ) + { + const u32 tmp = (alphaSource << 12) | (modulate << 8) | (srcFact << 4) | dstFact; + return FR(tmp); } //! EMT_ONETEXTURE_BLEND: unpack srcFact & dstFact and Modulo to MaterialTypeParam + /** The fields don't use the full byte range, so we could pack even more... */ inline void unpack_texureBlendFunc ( E_BLEND_FACTOR &srcFact, E_BLEND_FACTOR &dstFact, - E_MODULATE_FUNC &modulo, const f32 param ) + E_MODULATE_FUNC &modulo, u32& alphaSource, const f32 param ) { - const u32 state = (u32)param; - modulo = E_MODULATE_FUNC( ( state & 0x00FF0000 ) >> 16 ); - srcFact = E_BLEND_FACTOR ( ( state & 0x0000FF00 ) >> 8 ); - dstFact = E_BLEND_FACTOR ( ( state & 0x000000FF ) ); + const u32 state = IR(param); + alphaSource = (state & 0x0000F000) >> 12; + modulo = E_MODULATE_FUNC( ( state & 0x00000F00 ) >> 8 ); + srcFact = E_BLEND_FACTOR ( ( state & 0x000000F0 ) >> 4 ); + dstFact = E_BLEND_FACTOR ( ( state & 0x0000000F ) ); } + //! EMT_ONETEXTURE_BLEND: has BlendFactor Alphablending + inline bool textureBlendFunc_hasAlpha ( const E_BLEND_FACTOR factor ) + { + switch ( factor ) + { + case EBF_SRC_ALPHA: + case EBF_ONE_MINUS_SRC_ALPHA: + case EBF_DST_ALPHA: + case EBF_ONE_MINUS_DST_ALPHA: + case EBF_SRC_ALPHA_SATURATE: + return true; + default: + return false; + } + } + + + //! These flags are used to specify the anti-aliasing and smoothing modes + /** Techniques supported are multisampling, geometry smoothing, and alpha + to coverage. + Some drivers don't support a per-material setting of the anti-aliasing + modes. In those cases, FSAA/multisampling is defined by the device mode + chosen upon creation via irr::SIrrCreationParameters. + */ + enum E_ANTI_ALIASING_MODE + { + //! Use to turn off anti-aliasing for this material + EAAM_OFF=0, + //! Default anti-aliasing mode + EAAM_SIMPLE=1, + //! High-quality anti-aliasing, not always supported, automatically enables SIMPLE mode + EAAM_QUALITY=3, + //! Line smoothing + EAAM_LINE_SMOOTH=4, + //! point smoothing, often in software and slow, only with OpenGL + EAAM_POINT_SMOOTH=8, + //! All typical anti-alias and smooth modes + EAAM_FULL_BASIC=15, + //! Enhanced anti-aliasing for transparent materials + /** Usually used with EMT_TRANSPARENT_ALPHA_REF and multisampling. */ + EAAM_ALPHA_TO_COVERAGE=16 + }; + + //! These flags allow to define the interpretation of vertex color when lighting is enabled + /** Without lighting being enabled the vertex color is the only value defining the fragment color. + Once lighting is enabled, the four values for diffuse, ambient, emissive, and specular take over. + With these flags it is possible to define which lighting factor shall be defined by the vertex color + instead of the lighting factor which is the same for all faces of that material. + The default is to use vertex color for the diffuse value, another pretty common value is to use + vertex color for both diffuse and ambient factor. */ + enum E_COLOR_MATERIAL + { + //! Don't use vertex color for lighting + ECM_NONE=0, + //! Use vertex color for diffuse light, this is default + ECM_DIFFUSE, + //! Use vertex color for ambient light + ECM_AMBIENT, + //! Use vertex color for emissive light + ECM_EMISSIVE, + //! Use vertex color for specular light + ECM_SPECULAR, + //! Use vertex color for both diffuse and ambient light + ECM_DIFFUSE_AND_AMBIENT + }; + //! Maximum number of texture an SMaterial can have. - const u32 MATERIAL_MAX_TEXTURES = 4; + const u32 MATERIAL_MAX_TEXTURES = _IRR_MATERIAL_MAX_TEXTURES_; //! Struct for holding parameters for a material renderer class SMaterial @@ -70,9 +194,10 @@ namespace video : MaterialType(EMT_SOLID), AmbientColor(255,255,255,255), DiffuseColor(255,255,255,255), EmissiveColor(0,0,0,0), SpecularColor(255,255,255,255), Shininess(0.0f), MaterialTypeParam(0.0f), MaterialTypeParam2(0.0f), Thickness(1.0f), - Wireframe(false), PointCloud(false), GouraudShading(true), Lighting(true), - ZWriteEnable(true), BackfaceCulling(true), FrontfaceCulling(false), - FogEnable(false), NormalizeNormals(false), ZBuffer(1) + ZBuffer(ECFN_LESSEQUAL), AntiAliasing(EAAM_SIMPLE), ColorMask(ECP_ALL), + ColorMaterial(ECM_DIFFUSE), + Wireframe(false), PointCloud(false), GouraudShading(true), Lighting(true), ZWriteEnable(true), + BackfaceCulling(true), FrontfaceCulling(false), FogEnable(false), NormalizeNormals(false) { } //! Copy constructor @@ -118,10 +243,16 @@ namespace video FogEnable = other.FogEnable; NormalizeNormals = other.NormalizeNormals; ZBuffer = other.ZBuffer; + AntiAliasing = other.AntiAliasing; + ColorMask = other.ColorMask; + ColorMaterial = other.ColorMaterial; return *this; } + //! Texture layer array. + SMaterialLayer TextureLayer[MATERIAL_MAX_TEXTURES]; + //! Type of the material. Specifies how everything is blended together E_MATERIAL_TYPE MaterialType; @@ -146,7 +277,7 @@ namespace video //! Value affecting the size of specular highlights. /** A value of 20 is common. If set to 0, no specular highlights are being used. To activate, simply set the - shininess of a material to a value other than 0: + shininess of a material to a value in the range [0.5;128]: \code sceneNode->getMaterial(0).Shininess = 20.0f; \endcode @@ -187,46 +318,64 @@ namespace video //! Thickness of non-3dimensional elements such as lines and points. f32 Thickness; - //! Texture layer array. - SMaterialLayer TextureLayer[MATERIAL_MAX_TEXTURES]; + //! Is the ZBuffer enabled? Default: ECFN_LESSEQUAL + /** Values are from E_COMPARISON_FUNC. */ + u8 ZBuffer; + + //! Sets the antialiasing mode + /** Values are chosen from E_ANTI_ALIASING_MODE. Default is + EAAM_SIMPLE|EAAM_LINE_SMOOTH, i.e. simple multi-sample + anti-aliasing and lime smoothing is enabled. */ + u8 AntiAliasing; + + //! Defines the enabled color planes + /** Values are defined as or'ed values of the E_COLOR_PLANE enum. + Only enabled color planes will be rendered to the current render + target. Typical use is to disable all colors when rendering only to + depth or stencil buffer, or using Red and Green for Stereo rendering. */ + u8 ColorMask:4; + + //! Defines the interpretation of vertex color in the lighting equation + /** Values should be chosen from E_COLOR_MATERIAL. + When lighting is enabled, vertex color can be used instead of the + material values for light modulation. This allows to easily change e.g. the + diffuse light behavior of each face. The default, ECM_DIFFUSE, will result in + a very similar rendering as with lighting turned off, just with light shading. */ + u8 ColorMaterial:3; //! Draw as wireframe or filled triangles? Default: false /** The user can access a material flag using \code material.Wireframe=true \endcode or \code material.setFlag(EMF_WIREFRAME, true); \endcode */ - bool Wireframe; + bool Wireframe:1; //! Draw as point cloud or filled triangles? Default: false - bool PointCloud; + bool PointCloud:1; //! Flat or Gouraud shading? Default: true - bool GouraudShading; + bool GouraudShading:1; //! Will this material be lighted? Default: true - bool Lighting; + bool Lighting:1; //! Is the zbuffer writeable or is it read-only. Default: true. - /** This flag is ignored if the MaterialType is a transparent - type. */ - bool ZWriteEnable; + /** This flag is forced to false if the MaterialType is a + transparent type and the scene parameter + ALLOW_ZWRITE_ON_TRANSPARENT is not set. */ + bool ZWriteEnable:1; //! Is backface culling enabled? Default: true - bool BackfaceCulling; + bool BackfaceCulling:1; //! Is frontface culling enabled? Default: false - bool FrontfaceCulling; + bool FrontfaceCulling:1; //! Is fog enabled? Default: false - bool FogEnable; + bool FogEnable:1; - //! Should normals be normalized? Default: false - bool NormalizeNormals; - - //! Is the ZBuffer enabled? Default: 1 - /** Changed from bool to integer - (0 == ZBuffer Off, 1 == ZBuffer LessEqual, 2 == ZBuffer Equal) - */ - char ZBuffer; + //! Should normals be normalized? + /** Always use this if the mesh lit and scaled. Default: false */ + bool NormalizeNormals:1; //! Gets the texture transformation matrix for level i /** \param i The desired level. Must not be larger than MATERIAL_MAX_TEXTURES. @@ -313,8 +462,12 @@ namespace video break; case EMF_ANISOTROPIC_FILTER: { - for (u32 i=0; i MatrixAllocator; diff --git a/src/dep/include/irrlicht/SMesh.h b/src/dep/include/irrlicht/SMesh.h index cb9275c..64c97a5 100644 --- a/src/dep/include/irrlicht/SMesh.h +++ b/src/dep/include/irrlicht/SMesh.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -116,6 +116,7 @@ namespace scene //! The meshbuffers of this mesh core::array MeshBuffers; + //! The bounding box of this mesh core::aabbox3d BoundingBox; }; diff --git a/src/dep/include/irrlicht/SMeshBuffer.h b/src/dep/include/irrlicht/SMeshBuffer.h index 4d48062..23e01a3 100644 --- a/src/dep/include/irrlicht/SMeshBuffer.h +++ b/src/dep/include/irrlicht/SMeshBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/SMeshBufferLightMap.h b/src/dep/include/irrlicht/SMeshBufferLightMap.h index 4d48062..23e01a3 100644 --- a/src/dep/include/irrlicht/SMeshBufferLightMap.h +++ b/src/dep/include/irrlicht/SMeshBufferLightMap.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/SMeshBufferTangents.h b/src/dep/include/irrlicht/SMeshBufferTangents.h index 4d48062..23e01a3 100644 --- a/src/dep/include/irrlicht/SMeshBufferTangents.h +++ b/src/dep/include/irrlicht/SMeshBufferTangents.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/SParticle.h b/src/dep/include/irrlicht/SParticle.h index 9dbb139..7291af3 100644 --- a/src/dep/include/irrlicht/SParticle.h +++ b/src/dep/include/irrlicht/SParticle.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/SSharedMeshBuffer.h b/src/dep/include/irrlicht/SSharedMeshBuffer.h index 4afe711..75dc984 100644 --- a/src/dep/include/irrlicht/SSharedMeshBuffer.h +++ b/src/dep/include/irrlicht/SSharedMeshBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -16,7 +16,7 @@ namespace scene struct SSharedMeshBuffer : public IMeshBuffer { //! constructor - SSharedMeshBuffer() : IMeshBuffer(), ChangedID_Vertex(1), ChangedID_Index(1), Vertices(0), MappingHint(EHM_NEVER) + SSharedMeshBuffer() : IMeshBuffer(), Vertices(0), ChangedID_Vertex(1), ChangedID_Index(1), MappingHintVertex(EHM_NEVER), MappingHintIndex(EHM_NEVER) { #ifdef _DEBUG setDebugName("SSharedMeshBuffer"); @@ -127,23 +127,33 @@ namespace scene //! get the current hardware mapping hint - virtual E_HARDWARE_MAPPING getHardwareMappingHint() const + virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const { - return MappingHint; + return MappingHintVertex; + } + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint_Index() const + { + return MappingHintIndex; } //! set the hardware mapping hint, for driver - virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) { - MappingHint=NewMappingHint; + if (buffer==EBT_VERTEX_AND_INDEX || buffer==EBT_VERTEX) + MappingHintVertex=NewMappingHint; + if (buffer==EBT_VERTEX_AND_INDEX || buffer==EBT_INDEX) + MappingHintIndex=NewMappingHint; } + //! flags the mesh as changed, reloads hardware buffers - virtual void setDirty(E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX) + virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) { - if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_VERTEX) + if (buffer==EBT_VERTEX_AND_INDEX || buffer==EBT_VERTEX) ++ChangedID_Vertex; - if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) + if (buffer==EBT_VERTEX_AND_INDEX || buffer==EBT_INDEX) ++ChangedID_Index; } @@ -155,22 +165,27 @@ namespace scene /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID_Index() const {return ChangedID_Index;} + //! Material of this meshBuffer + video::SMaterial Material; + + //! Shared Array of vertices + core::array *Vertices; + + //! Array of Indices + core::array Indices; + //! ID used for hardware buffer management u32 ChangedID_Vertex; //! ID used for hardware buffer management u32 ChangedID_Index; - //! Material of this meshBuffer - video::SMaterial Material; - //! Shared Array of vertices - core::array *Vertices; - //! Array of Indices - core::array Indices; //! Bounding box core::aabbox3df BoundingBox; + //! hardware mapping hint - E_HARDWARE_MAPPING MappingHint; + E_HARDWARE_MAPPING MappingHintVertex; + E_HARDWARE_MAPPING MappingHintIndex; }; diff --git a/src/dep/include/irrlicht/SSkinMeshBuffer.h b/src/dep/include/irrlicht/SSkinMeshBuffer.h index 34653ab..59c32d1 100644 --- a/src/dep/include/irrlicht/SSkinMeshBuffer.h +++ b/src/dep/include/irrlicht/SSkinMeshBuffer.h @@ -1,397 +1,401 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __I_SKIN_MESH_BUFFER_H_INCLUDED__ -#define __I_SKIN_MESH_BUFFER_H_INCLUDED__ - -#include "IMeshBuffer.h" -#include "S3DVertex.h" - - -namespace irr -{ -namespace scene -{ - - -//! A mesh buffer able to choose between S3DVertex2TCoords, S3DVertex and S3DVertexTangents at runtime -struct SSkinMeshBuffer : public IMeshBuffer -{ - //! Default constructor - SSkinMeshBuffer(video::E_VERTEX_TYPE vt=video::EVT_STANDARD) : - ChangedID_Vertex(1),ChangedID_Index(1),MappingHint_Vertex(EHM_NEVER), - MappingHint_Index(EHM_NEVER),VertexType(vt),BoundingBoxNeedsRecalculated(true) - { - #ifdef _DEBUG - setDebugName("SSkinMeshBuffer"); - #endif - } - - //! Get Material of this buffer. - virtual const video::SMaterial& getMaterial() const - { - return Material; - } - - //! Get Material of this buffer. - virtual video::SMaterial& getMaterial() - { - return Material; - } - - //! Get standard vertex at given index - virtual video::S3DVertex *getVertex(u32 index) - { - switch (VertexType) - { - case video::EVT_2TCOORDS: - return (video::S3DVertex*)&Vertices_2TCoords[index]; - case video::EVT_TANGENTS: - return (video::S3DVertex*)&Vertices_Tangents[index]; - default: - return &Vertices_Standard[index]; - } - } - - //! Get pointer to vertex array - virtual const void* getVertices() const - { - switch (VertexType) - { - case video::EVT_2TCOORDS: - return Vertices_2TCoords.const_pointer(); - case video::EVT_TANGENTS: - return Vertices_Tangents.const_pointer(); - default: - return Vertices_Standard.const_pointer(); - } - } - - //! Get pointer to vertex array - virtual void* getVertices() - { - switch (VertexType) - { - case video::EVT_2TCOORDS: - return Vertices_2TCoords.pointer(); - case video::EVT_TANGENTS: - return Vertices_Tangents.pointer(); - default: - return Vertices_Standard.pointer(); - } - } - - //! Get vertex count - virtual u32 getVertexCount() const - { - switch (VertexType) - { - case video::EVT_2TCOORDS: - return Vertices_2TCoords.size(); - case video::EVT_TANGENTS: - return Vertices_Tangents.size(); - default: - return Vertices_Standard.size(); - } - } - - //! Get type of index data which is stored in this meshbuffer. - /** \return Index type of this buffer. */ - virtual video::E_INDEX_TYPE getIndexType() const { return video::EIT_16BIT; } - - //! Get pointer to index array - virtual const u16* getIndices() const - { - return Indices.const_pointer(); - } - - //! Get pointer to index array - virtual u16* getIndices() - { - return Indices.pointer(); - } - - //! Get index count - virtual u32 getIndexCount() const - { - return Indices.size(); - } - - //! Get bounding box - virtual const core::aabbox3d& getBoundingBox() const - { - return BoundingBox; - } - - //! Set bounding box - virtual void setBoundingBox( const core::aabbox3df& box) - { - BoundingBox = box; - } - - //! Recalculate bounding box - virtual void recalculateBoundingBox() - { - if(!BoundingBoxNeedsRecalculated) - return; - - BoundingBoxNeedsRecalculated = false; - - switch (VertexType) - { - case video::EVT_STANDARD: - { - if (Vertices_Standard.empty()) - BoundingBox.reset(0,0,0); - else - { - BoundingBox.reset(Vertices_Standard[0].Pos); - for (u32 i=1; i Vertices_Tangents; - core::array Vertices_2TCoords; - core::array Vertices_Standard; - core::array Indices; - core::aabbox3d BoundingBox; - bool BoundingBoxNeedsRecalculated; -}; - - -} // end namespace scene -} // end namespace irr - -#endif - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SKIN_MESH_BUFFER_H_INCLUDED__ +#define __I_SKIN_MESH_BUFFER_H_INCLUDED__ + +#include "IMeshBuffer.h" +#include "S3DVertex.h" + + +namespace irr +{ +namespace scene +{ + + +//! A mesh buffer able to choose between S3DVertex2TCoords, S3DVertex and S3DVertexTangents at runtime +struct SSkinMeshBuffer : public IMeshBuffer +{ + //! Default constructor + SSkinMeshBuffer(video::E_VERTEX_TYPE vt=video::EVT_STANDARD) : + ChangedID_Vertex(1), ChangedID_Index(1), VertexType(vt), + MappingHint_Vertex(EHM_NEVER), MappingHint_Index(EHM_NEVER), + BoundingBoxNeedsRecalculated(true) + { + #ifdef _DEBUG + setDebugName("SSkinMeshBuffer"); + #endif + } + + //! Get Material of this buffer. + virtual const video::SMaterial& getMaterial() const + { + return Material; + } + + //! Get Material of this buffer. + virtual video::SMaterial& getMaterial() + { + return Material; + } + + //! Get standard vertex at given index + virtual video::S3DVertex *getVertex(u32 index) + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return (video::S3DVertex*)&Vertices_2TCoords[index]; + case video::EVT_TANGENTS: + return (video::S3DVertex*)&Vertices_Tangents[index]; + default: + return &Vertices_Standard[index]; + } + } + + //! Get pointer to vertex array + virtual const void* getVertices() const + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return Vertices_2TCoords.const_pointer(); + case video::EVT_TANGENTS: + return Vertices_Tangents.const_pointer(); + default: + return Vertices_Standard.const_pointer(); + } + } + + //! Get pointer to vertex array + virtual void* getVertices() + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return Vertices_2TCoords.pointer(); + case video::EVT_TANGENTS: + return Vertices_Tangents.pointer(); + default: + return Vertices_Standard.pointer(); + } + } + + //! Get vertex count + virtual u32 getVertexCount() const + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return Vertices_2TCoords.size(); + case video::EVT_TANGENTS: + return Vertices_Tangents.size(); + default: + return Vertices_Standard.size(); + } + } + + //! Get type of index data which is stored in this meshbuffer. + /** \return Index type of this buffer. */ + virtual video::E_INDEX_TYPE getIndexType() const { return video::EIT_16BIT; } + + //! Get pointer to index array + virtual const u16* getIndices() const + { + return Indices.const_pointer(); + } + + //! Get pointer to index array + virtual u16* getIndices() + { + return Indices.pointer(); + } + + //! Get index count + virtual u32 getIndexCount() const + { + return Indices.size(); + } + + //! Get bounding box + virtual const core::aabbox3d& getBoundingBox() const + { + return BoundingBox; + } + + //! Set bounding box + virtual void setBoundingBox( const core::aabbox3df& box) + { + BoundingBox = box; + } + + //! Recalculate bounding box + virtual void recalculateBoundingBox() + { + if(!BoundingBoxNeedsRecalculated) + return; + + BoundingBoxNeedsRecalculated = false; + + switch (VertexType) + { + case video::EVT_STANDARD: + { + if (Vertices_Standard.empty()) + BoundingBox.reset(0,0,0); + else + { + BoundingBox.reset(Vertices_Standard[0].Pos); + for (u32 i=1; i Vertices_Tangents; + core::array Vertices_2TCoords; + core::array Vertices_Standard; + core::array Indices; + + u32 ChangedID_Vertex; + u32 ChangedID_Index; + + //ISkinnedMesh::SJoint *AttachedJoint; + core::matrix4 Transformation; + + video::SMaterial Material; + video::E_VERTEX_TYPE VertexType; + + core::aabbox3d BoundingBox; + + // hardware mapping hint + E_HARDWARE_MAPPING MappingHint_Vertex:3; + E_HARDWARE_MAPPING MappingHint_Index:3; + + bool BoundingBoxNeedsRecalculated:1; +}; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/src/dep/include/irrlicht/SVertexIndex.h b/src/dep/include/irrlicht/SVertexIndex.h index 0fb47f3..7b7e8c8 100644 --- a/src/dep/include/irrlicht/SVertexIndex.h +++ b/src/dep/include/irrlicht/SVertexIndex.h @@ -1,4 +1,4 @@ -// Copyright (C) 2008 Nikolaus Gebhardt +// Copyright (C) 2008-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/include/irrlicht/SVertexManipulator.h b/src/dep/include/irrlicht/SVertexManipulator.h new file mode 100644 index 0000000..097eb9c --- /dev/null +++ b/src/dep/include/irrlicht/SVertexManipulator.h @@ -0,0 +1,292 @@ +// Copyright (C) 2009 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_VERTEX_MANIPULATOR_H_INCLUDED__ +#define __S_VERTEX_MANIPULATOR_H_INCLUDED__ + +#include "S3DVertex.h" +#include "SColor.h" + +namespace irr +{ +namespace scene +{ + + class IMesh; + class IMeshBuffer; + struct SMesh; + + //! Interface for vertex manipulators. + /** You should derive your manipulator from this class if it shall be called for every vertex, getting as parameter just the vertex. + */ + struct IVertexManipulator + { + }; + //! Vertex manipulator to set color to a fixed color for all vertices + class SVertexColorSetManipulator : public IVertexManipulator + { + public: + SVertexColorSetManipulator(video::SColor color) : Color(color) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=Color; + } + private: + video::SColor Color; + }; + //! Vertex manipulator to set the alpha value of the vertex color to a fixed value + class SVertexColorSetAlphaManipulator : public IVertexManipulator + { + public: + SVertexColorSetAlphaManipulator(u32 alpha) : Alpha(alpha) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setAlpha(Alpha); + } + private: + u32 Alpha; + }; + //! Vertex manipulator which invertes the RGB values + class SVertexColorInvertManipulator : public IVertexManipulator + { + public: + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(255-vertex.Color.getRed()); + vertex.Color.setGreen(255-vertex.Color.getGreen()); + vertex.Color.setBlue(255-vertex.Color.getBlue()); + } + }; + //! Vertex manipulator to set vertex color to one of two values depending on a given threshold + /** If average of the color value is >Threshold the High color is chosen, else Low. */ + class SVertexColorThresholdManipulator : public IVertexManipulator + { + public: + SVertexColorThresholdManipulator(u8 threshold, video::SColor low, + video::SColor high) : Threshold(threshold), Low(low), High(high) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color = ((u8)vertex.Color.getAverage()>Threshold)?High:Low; + } + private: + u8 Threshold; + video::SColor Low; + video::SColor High; + }; + //! Vertex manipulator which adjusts the brightness by the given amount + /** A positive value increases brightness, a negative value darkens the colors. */ + class SVertexColorBrightnessManipulator : public IVertexManipulator + { + public: + SVertexColorBrightnessManipulator(s32 amount) : Amount(amount) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(vertex.Color.getRed()+Amount, 0u, 255u)); + vertex.Color.setGreen(core::clamp(vertex.Color.getGreen()+Amount, 0u, 255u)); + vertex.Color.setBlue(core::clamp(vertex.Color.getBlue()+Amount, 0u, 255u)); + } + private: + s32 Amount; + }; + //! Vertex manipulator which adjusts the contrast by the given factor + /** Factors over 1 increase contrast, below 1 reduce it. */ + class SVertexColorContrastManipulator : public IVertexManipulator + { + public: + SVertexColorContrastManipulator(f32 factor) : Factor(factor) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(core::round32((vertex.Color.getRed()-128)*Factor)+128, 0, 255)); + vertex.Color.setGreen(core::clamp(core::round32((vertex.Color.getGreen()-128)*Factor)+128, 0, 255)); + vertex.Color.setBlue(core::clamp(core::round32((vertex.Color.getBlue()-128)*Factor)+128, 0, 255)); + } + private: + f32 Factor; + }; + //! Vertex manipulator which adjusts the contrast by the given factor and brightness by a signed amount. + /** Factors over 1 increase contrast, below 1 reduce it. + A positive amount increases brightness, a negative one darkens the colors. */ + class SVertexColorContrastBrightnessManipulator : public IVertexManipulator + { + public: + SVertexColorContrastBrightnessManipulator(f32 factor, s32 amount) : Factor(factor), Amount(amount+128) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(core::round32((vertex.Color.getRed()-128)*Factor)+Amount, 0, 255)); + vertex.Color.setGreen(core::clamp(core::round32((vertex.Color.getGreen()-128)*Factor)+Amount, 0, 255)); + vertex.Color.setBlue(core::clamp(core::round32((vertex.Color.getBlue()-128)*Factor)+Amount, 0, 255)); + } + private: + f32 Factor; + s32 Amount; + }; + //! Vertex manipulator which adjusts the brightness by a gamma operation + /** A value over one increases brightness, one below darkens the colors. */ + class SVertexColorGammaManipulator : public IVertexManipulator + { + public: + SVertexColorGammaManipulator(f32 gamma) : Gamma(1.f) + { + if (gamma != 0.f) + Gamma = 1.f/gamma; + } + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(core::round32(powf((f32)(vertex.Color.getRed()),Gamma)), 0, 255)); + vertex.Color.setGreen(core::clamp(core::round32(powf((f32)(vertex.Color.getGreen()),Gamma)), 0, 255)); + vertex.Color.setBlue(core::clamp(core::round32(powf((f32)(vertex.Color.getBlue()),Gamma)), 0, 255)); + } + private: + f32 Gamma; + }; + //! Vertex manipulator which scales the color values + /** Can e.g be used for white balance, factor would be 255.f/brightest color. */ + class SVertexColorScaleManipulator : public IVertexManipulator + { + public: + SVertexColorScaleManipulator(f32 factor) : Factor(factor) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(core::round32(vertex.Color.getRed()*Factor), 0, 255)); + vertex.Color.setGreen(core::clamp(core::round32(vertex.Color.getGreen()*Factor), 0, 255)); + vertex.Color.setBlue(core::clamp(core::round32(vertex.Color.getBlue()*Factor), 0, 255)); + } + private: + f32 Factor; + }; + //! Vertex manipulator which desaturates the color values + /** Uses the lightness value of the color. */ + class SVertexColorDesaturateToLightnessManipulator : public IVertexManipulator + { + public: + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=core::round32(vertex.Color.getLightness()); + } + }; + //! Vertex manipulator which desaturates the color values + /** Uses the average value of the color. */ + class SVertexColorDesaturateToAverageManipulator : public IVertexManipulator + { + public: + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=vertex.Color.getAverage(); + } + }; + //! Vertex manipulator which desaturates the color values + /** Uses the luminance value of the color. */ + class SVertexColorDesaturateToLuminanceManipulator : public IVertexManipulator + { + public: + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=core::round32(vertex.Color.getLuminance()); + } + }; + //! Vertex manipulator which interpolates the color values + /** Uses linear interpolation. */ + class SVertexColorInterpolateLinearManipulator : public IVertexManipulator + { + public: + SVertexColorInterpolateLinearManipulator(video::SColor color, f32 factor) : + Color(color), Factor(factor) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=vertex.Color.getInterpolated(Color, Factor); + } + private: + video::SColor Color; + f32 Factor; + }; + //! Vertex manipulator which interpolates the color values + /** Uses linear interpolation. */ + class SVertexColorInterpolateQuadraticManipulator : public IVertexManipulator + { + public: + SVertexColorInterpolateQuadraticManipulator(video::SColor color1, video::SColor color2, f32 factor) : + Color1(color1), Color2(color2), Factor(factor) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=vertex.Color.getInterpolated_quadratic(Color1, Color2, Factor); + } + private: + video::SColor Color1; + video::SColor Color2; + f32 Factor; + }; + + //! Vertex manipulator which scales the position of the vertex + class SVertexPositionScaleManipulator : public IVertexManipulator + { + public: + SVertexPositionScaleManipulator(const core::vector3df& factor) : Factor(factor) {} + template + void operator()(VType& vertex) const + { + vertex.Pos *= Factor; + } + private: + core::vector3df Factor; + }; + + //! Vertex manipulator which scales the position of the vertex along the normals + /** This can look more pleasing than the usual Scale operator, but + depends on the mesh geometry. + */ + class SVertexPositionScaleAlongNormalsManipulator : public IVertexManipulator + { + public: + SVertexPositionScaleAlongNormalsManipulator(const core::vector3df& factor) : Factor(factor) {} + template + void operator()(VType& vertex) const + { + vertex.Pos += vertex.Normal*Factor; + } + private: + core::vector3df Factor; + }; + + //! Vertex manipulator which transforms the position of the vertex + class SVertexPositionTransformManipulator : public IVertexManipulator + { + public: + SVertexPositionTransformManipulator(const core::matrix4& m) : Transformation(m) {} + template + void operator()(VType& vertex) const + { + Transformation.transformVect(vertex.Pos); + } + private: + core::matrix4 Transformation; + }; + + //! Vertex manipulator which scales the TCoords of the vertex + class SVertexTCoordsScaleManipulator : public IVertexManipulator + { + public: + SVertexTCoordsScaleManipulator(const core::vector2df& factor, u32 uvSet=1) : Factor(factor), UVSet(uvSet) {} + void operator()(video::S3DVertex2TCoords& vertex) const + { + if (1==UVSet) + vertex.TCoords *= Factor; + else if (2==UVSet) + vertex.TCoords2 *= Factor; + } + template + void operator()(VType& vertex) const + { + if (1==UVSet) + vertex.TCoords *= Factor; + } + private: + core::vector2df Factor; + u32 UVSet; + }; + +} // end namespace scene +} // end namespace irr + + +#endif diff --git a/src/dep/include/irrlicht/SViewFrustum.h b/src/dep/include/irrlicht/SViewFrustum.h index 020e425..4956f61 100644 --- a/src/dep/include/irrlicht/SViewFrustum.h +++ b/src/dep/include/irrlicht/SViewFrustum.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,6 +7,7 @@ #include "plane3d.h" #include "vector3d.h" +#include "line3d.h" #include "aabbox3d.h" #include "matrix4.h" #include "IVideoDriver.h" @@ -42,14 +43,6 @@ namespace scene VF_PLANE_COUNT }; - //! Hold a copy of important transform matrices - enum E_TRANSFORMATION_STATE_3 - { - ETS_VIEW_PROJECTION_3 = video::ETS_PROJECTION + 1, - ETS_VIEW_MODEL_INVERSE_3, - ETS_CURRENT_3, - ETS_COUNT_3 - }; //! Default Constructor SViewFrustum() {} @@ -85,8 +78,15 @@ namespace scene //! recalculates the bounding box member based on the planes inline void recalculateBoundingBox(); - //! update the given state's matrix - void setTransformState( video::E_TRANSFORMATION_STATE state); + //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE + core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state); + + //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE + const core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state) const; + + //! clips a line to the view frustum. + /** \return True if the line was clipped, false if not */ + bool clipLine(core::line3d& line) const; //! the position of the camera core::vector3df cameraPosition; @@ -97,11 +97,23 @@ namespace scene //! bounding box around the view frustum core::aabbox3d boundingBox; + private: //! Hold a copy of important transform matrices - core::matrix4 Matrices[ETS_COUNT_3]; + enum E_TRANSFORMATION_STATE_FRUSTUM + { + ETS_VIEW = 0, + ETS_PROJECTION = 1, + ETS_COUNT_FRUSTUM + }; + + //! Hold a copy of important transform matrices + core::matrix4 Matrices[ETS_COUNT_FRUSTUM]; }; + /*! + Copy constructor ViewFrustum + */ inline SViewFrustum::SViewFrustum(const SViewFrustum& other) { cameraPosition=other.cameraPosition; @@ -111,7 +123,7 @@ namespace scene for (i=0; i& line) const + { + bool wasClipped = false; + for (u32 i=0; i < VF_PLANE_COUNT; ++i) + { + if (planes[i].classifyPointRelation(line.start) == core::ISREL3D_FRONT) + { + line.start = line.start.getInterpolated(line.end, + planes[i].getKnownIntersectionWithLine(line.start, line.end)); + wasClipped = true; + } + if (planes[i].classifyPointRelation(line.end) == core::ISREL3D_FRONT) + { + line.end = line.start.getInterpolated(line.end, + planes[i].getKnownIntersectionWithLine(line.start, line.end)); + wasClipped = true; + } + } + return wasClipped; } diff --git a/src/dep/include/irrlicht/SceneParameters.h b/src/dep/include/irrlicht/SceneParameters.h index bc91172..dfc49cc 100644 --- a/src/dep/include/irrlicht/SceneParameters.h +++ b/src/dep/include/irrlicht/SceneParameters.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -67,7 +67,9 @@ namespace scene const c8* const COLLADA_CREATE_SCENE_INSTANCES = "COLLADA_CreateSceneInstances"; //! Name of the parameter for changing the texture path of the built-in DMF loader. - /** Use it like this: + /** This path is prefixed to the file names defined in the Deled file when loading + textures. This allows to alter the paths for a specific project setting. + Use it like this: \code SceneManager->getStringParameters()->setAttribute(scene::DMF_TEXTURE_PATH, "path/to/your/textures"); \endcode @@ -75,17 +77,20 @@ namespace scene const c8* const DMF_TEXTURE_PATH = "DMF_TexturePath"; //! Name of the parameter for preserving DMF textures dir structure with built-in DMF loader. - /** Use it like this: + /** If this parameter is set to true, the texture directory defined in the Deled file + is ignored, and only the texture name is used to find the proper file. Otherwise, the + texture path is also used, which allows to use a nicer media layout. + Use it like this: \code - //this way you won't use this setting - SceneManager->getParameters()->setAttribute(scene::DMF_USE_MATERIALS_DIRS, false); + //this way you won't use this setting (default) + SceneManager->getParameters()->setAttribute(scene::DMF_IGNORE_MATERIALS_DIRS, false); \endcode \code //this way you'll use this setting - SceneManager->getParameters()->setAttribute(scene::DMF_USE_MATERIALS_DIRS, true); + SceneManager->getParameters()->setAttribute(scene::DMF_IGNORE_MATERIALS_DIRS, true); \endcode **/ - const c8* const DMF_USE_MATERIALS_DIRS = "DMF_MaterialsDir"; + const c8* const DMF_IGNORE_MATERIALS_DIRS = "DMF_IgnoreMaterialsDir"; //! Name of the parameter for setting reference value of alpha in transparent materials. /** Use it like this: @@ -106,20 +111,70 @@ namespace scene const c8* const DMF_FLIP_ALPHA_TEXTURES = "DMF_FlipAlpha"; + //! Name of the parameter for changing the texture path of the built-in obj loader. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::OBJ_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const OBJ_TEXTURE_PATH = "OBJ_TexturePath"; + //! Flag to avoid loading group structures in .obj files /** Use it like this: - \code - SceneManager->getParameters()->setAttribute(scene::OBJ_LOADER_IGNORE_GROUPS, true); + \code + SceneManager->getParameters()->setAttribute(scene::OBJ_LOADER_IGNORE_GROUPS, true); \endcode - **/ + **/ const c8* const OBJ_LOADER_IGNORE_GROUPS = "OBJ_IgnoreGroups"; + //! Flag to avoid loading material .mtl file for .obj files + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::OBJ_LOADER_IGNORE_MATERIAL_FILES, true); + \endcode + **/ + const c8* const OBJ_LOADER_IGNORE_MATERIAL_FILES = "OBJ_IgnoreMaterialFiles"; + + + //! Flag to ignore the b3d file's mipmapping flag + /** Instead Irrlicht's texture creation flag is used. Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::B3D_LOADER_IGNORE_MIPMAP_FLAG, true); + \endcode + **/ + const c8* const B3D_LOADER_IGNORE_MIPMAP_FLAG = "B3D_IgnoreMipmapFlag"; + + //! Name of the parameter for changing the texture path of the built-in b3d loader. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::B3D_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const B3D_TEXTURE_PATH = "B3D_TexturePath"; + //! Flag set as parameter when the scene manager is used as editor /** In this way special animators like deletion animators can be stopped from deleting scene nodes for example */ const c8* const IRR_SCENE_MANAGER_IS_EDITOR = "IRR_Editor"; + //! Name of the parameter for setting the length of debug normals. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::DEBUG_NORMAL_LENGTH, 1.5f); + \endcode + **/ + const c8* const DEBUG_NORMAL_LENGTH = "DEBUG_Normal_Length"; + + //! Name of the parameter for setting the color of debug normals. + /** Use it like this: + \code + SceneManager->getParameters()->setAttributeAsColor(scene::DEBUG_NORMAL_COLOR, video::SColor(255, 255, 255, 255)); + \endcode + **/ + const c8* const DEBUG_NORMAL_COLOR = "DEBUG_Normal_Color"; + + } // end namespace scene } // end namespace irr diff --git a/src/dep/include/irrlicht/aabbox3d.h b/src/dep/include/irrlicht/aabbox3d.h index df27b9c..d90c8d7 100644 --- a/src/dep/include/irrlicht/aabbox3d.h +++ b/src/dep/include/irrlicht/aabbox3d.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -43,23 +43,6 @@ class aabbox3d // functions - //! Adds a point to the bounding box - /** The box grows bigger, if point was outside of the box. - \param p: Point to add into the box. */ - void addInternalPoint(const vector3d& p) - { - addInternalPoint(p.X, p.Y, p.Z); - } - - //! Adds another bounding box - /** The box grows bigger, if the new box was outside of the box. - \param b: Other bounding box to add into this box. */ - void addInternalBox(const aabbox3d& b) - { - addInternalPoint(b.MaxEdge); - addInternalPoint(b.MinEdge); - } - //! Resets the bounding box to a one-point box. /** \param x X coord of the point. \param y Y coord of the point. @@ -85,6 +68,23 @@ class aabbox3d MinEdge = initValue; } + //! Adds a point to the bounding box + /** The box grows bigger, if point was outside of the box. + \param p: Point to add into the box. */ + void addInternalPoint(const vector3d& p) + { + addInternalPoint(p.X, p.Y, p.Z); + } + + //! Adds another bounding box + /** The box grows bigger, if the new box was outside of the box. + \param b: Other bounding box to add into this box. */ + void addInternalBox(const aabbox3d& b) + { + addInternalPoint(b.MaxEdge); + addInternalPoint(b.MinEdge); + } + //! Adds a point to the bounding box /** The box grows bigger, if point is outside of the box. \param x X coordinate of the point to add to this box. @@ -101,8 +101,102 @@ class aabbox3d if (z getCenter() const + { + return (MinEdge + MaxEdge) / 2; + } + + //! Get extent of the box (maximal distance of two points in the box) + /** \return Extent of the bounding box. */ + vector3d getExtent() const + { + return MaxEdge - MinEdge; + } + + //! Check if the box is empty. + /** This means that there is no space between the min and max edge. + \return True if box is empty, else false. */ + bool isEmpty() const + { + return MinEdge.equals ( MaxEdge ); + } + + //! Get the volume enclosed by the box in cubed units + T getVolume() const + { + const vector3d e = getExtent(); + return e.X * e.Y * e.Z; + } + + //! Get the surface area of the box in squared units + T getArea() const + { + const vector3d e = getExtent(); + return 2*(e.X*e.Y + e.X*e.Z + e.Y*e.Z); + } + + //! Stores all 8 edges of the box into an array + /** \param edges: Pointer to array of 8 edges. */ + void getEdges(vector3d *edges) const + { + const core::vector3d middle = getCenter(); + const core::vector3d diag = middle - MaxEdge; + + /* + Edges are stored in this way: + Hey, am I an ascii artist, or what? :) niko. + /3--------/7 + / | / | + / | / | + 1---------5 | + | /2- - -|- -6 + | / | / + |/ | / + 0---------4/ + */ + + edges[0].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z + diag.Z); + edges[1].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z + diag.Z); + edges[2].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z - diag.Z); + edges[3].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z - diag.Z); + edges[4].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z + diag.Z); + edges[5].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z + diag.Z); + edges[6].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z - diag.Z); + edges[7].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z - diag.Z); + } + + //! Repairs the box. + /** Necessary if for example MinEdge and MaxEdge are swapped. */ + void repair() + { + T t; + + if (MinEdge.X > MaxEdge.X) + { t=MinEdge.X; MinEdge.X = MaxEdge.X; MaxEdge.X=t; } + if (MinEdge.Y > MaxEdge.Y) + { t=MinEdge.Y; MinEdge.Y = MaxEdge.Y; MaxEdge.Y=t; } + if (MinEdge.Z > MaxEdge.Z) + { t=MinEdge.Z; MinEdge.Z = MaxEdge.Z; MaxEdge.Z=t; } + } + + //! Calculates a new interpolated bounding box. + /** d=0 returns other, d=1 returns this, all other values blend between + the two boxes. + \param other Other box to interpolate between + \param d Value between 0.0f and 1.0f. + \return Interpolated box. */ + aabbox3d getInterpolated(const aabbox3d& other, f32 d) const + { + f32 inv = 1.0f - d; + return aabbox3d((other.MinEdge*inv) + (MinEdge*d), + (other.MaxEdge*inv) + (MaxEdge*d)); + } + //! Determines if a point is within this box. - /** \param p: Point to check. + /** Border is included (IS part of the box)! + \param p: Point to check. \return True if the point is within the box and false if not */ bool isPointInside(const vector3d& p) const { @@ -111,8 +205,9 @@ class aabbox3d p.Z >= MinEdge.Z && p.Z <= MaxEdge.Z); } - //! Determines if a point is within this box and its borders. - /** \param p: Point to check. + //! Determines if a point is within this box and not its borders. + /** Border is excluded (NOT part of the box)! + \param p: Point to check. \return True if the point is within the box and false if not. */ bool isPointTotalInside(const vector3d& p) const { @@ -121,22 +216,24 @@ class aabbox3d p.Z > MinEdge.Z && p.Z < MaxEdge.Z); } - //! Determines if the box intersects with another box. - /** \param other: Other box to check a intersection with. - \return True if there is an intersection with the other box, - otherwise false. */ - bool intersectsWithBox(const aabbox3d& other) const - { - return (MinEdge <= other.MaxEdge && MaxEdge >= other.MinEdge); - } - //! Check if this box is completely inside the 'other' box. /** \param other: Other box to check against. \return True if this box is completly inside the other box, otherwise false. */ bool isFullInside(const aabbox3d& other) const { - return MinEdge >= other.MinEdge && MaxEdge <= other.MaxEdge; + return (MinEdge.X >= other.MinEdge.X && MinEdge.Y >= other.MinEdge.Y && MinEdge.Z >= other.MinEdge.Z && + MaxEdge.X <= other.MaxEdge.X && MaxEdge.Y <= other.MaxEdge.Y && MaxEdge.Z <= other.MaxEdge.Z); + } + + //! Determines if the axis-aligned box intersects with another axis-aligned box. + /** \param other: Other box to check a intersection with. + \return True if there is an intersection with the other box, + otherwise false. */ + bool intersectsWithBox(const aabbox3d& other) const + { + return (MinEdge.X <= other.MaxEdge.X && MinEdge.Y <= other.MaxEdge.Y && MinEdge.Z <= other.MaxEdge.Z && + MaxEdge.X >= other.MinEdge.X && MaxEdge.Y >= other.MinEdge.Y && MaxEdge.Z >= other.MinEdge.Z); } //! Tests if the box intersects with a line @@ -154,8 +251,7 @@ class aabbox3d \param halflength Half length of the line. \return True if there is an intersection, else false. */ bool intersectsWithLine(const vector3d& linemiddle, - const vector3d& linevect, - T halflength) const + const vector3d& linevect, T halflength) const { const vector3d e = getExtent() * (T)0.5; const vector3d t = getCenter() - linemiddle; @@ -217,105 +313,9 @@ class aabbox3d return ISREL3D_BACK; } - - //! Get center of the bounding box - /** \return Center of the bounding box. */ - vector3d getCenter() const - { - return (MinEdge + MaxEdge) / 2; - } - - - //! Get extent of the box - /** \return Extent of the bounding box. */ - vector3d getExtent() const - { - return MaxEdge - MinEdge; - } - - - //! Stores all 8 edges of the box into an array - /** \param edges: Pointer to array of 8 edges. */ - void getEdges(vector3d *edges) const - { - const core::vector3d middle = getCenter(); - const core::vector3d diag = middle - MaxEdge; - - /* - Edges are stored in this way: - Hey, am I an ascii artist, or what? :) niko. - /3--------/7 - / | / | - / | / | - 1---------5 | - | 2- - -| -6 - | / | / - |/ | / - 0---------4/ - */ - - edges[0].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z + diag.Z); - edges[1].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z + diag.Z); - edges[2].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z - diag.Z); - edges[3].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z - diag.Z); - edges[4].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z + diag.Z); - edges[5].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z + diag.Z); - edges[6].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z - diag.Z); - edges[7].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z - diag.Z); - } - - - //! Check if the box is empty. - /** This means that there is no space between the min and max - edge. - \return True if box is empty, else false. */ - bool isEmpty() const - { - return MinEdge.equals ( MaxEdge ); - } - - - //! Repairs the box. - /** Necessary if for example MinEdge and MaxEdge are swapped. */ - void repair() - { - T t; - - if (MinEdge.X > MaxEdge.X) - { t=MinEdge.X; MinEdge.X = MaxEdge.X; MaxEdge.X=t; } - if (MinEdge.Y > MaxEdge.Y) - { t=MinEdge.Y; MinEdge.Y = MaxEdge.Y; MaxEdge.Y=t; } - if (MinEdge.Z > MaxEdge.Z) - { t=MinEdge.Z; MinEdge.Z = MaxEdge.Z; MaxEdge.Z=t; } - } - - //! Calculates a new interpolated bounding box. - /** \param other: other box to interpolate between - \param d: value between 0.0f and 1.0f. - \return Interpolated box. */ - aabbox3d getInterpolated(const aabbox3d& other, f32 d) const - { - f32 inv = 1.0f - d; - return aabbox3d((other.MinEdge*inv) + (MinEdge*d), - (other.MaxEdge*inv) + (MaxEdge*d)); - } - - //! Get the volume enclosed by the box in cubed units - T getVolume() const - { - const vector3d e = getExtent(); - return e.X * e.Y * e.Z; - } - - //! Get the surface area of the box in squared units - T getArea() const - { - const vector3d e = getExtent(); - return 2*(e.X*e.Y + e.X*e.Z + e.Y*e.Z); - } - //! The near edge vector3d MinEdge; + //! The far edge vector3d MaxEdge; }; diff --git a/src/dep/include/irrlicht/coreutil.h b/src/dep/include/irrlicht/coreutil.h index e3b56c6..cba3230 100644 --- a/src/dep/include/irrlicht/coreutil.h +++ b/src/dep/include/irrlicht/coreutil.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,7 @@ #define __IRR_CORE_UTIL_H_INCLUDED__ #include "irrString.h" +#include "path.h" namespace irr { @@ -18,16 +19,42 @@ namespace core // ----------- some basic quite often used string functions ----------------- -//! cut the filename extension from a string -inline stringc& cutFilenameExtension ( stringc &dest, const stringc &source ) +//! search if a filename has a proper extension +inline s32 isFileExtension ( const io::path& filename, + const io::path& ext0, + const io::path& ext1, + const io::path& ext2) +{ + s32 extPos = filename.findLast ( '.' ); + if ( extPos < 0 ) + return 0; + + extPos += 1; + if ( filename.equals_substring_ignore_case ( ext0, extPos ) ) return 1; + if ( filename.equals_substring_ignore_case ( ext1, extPos ) ) return 2; + if ( filename.equals_substring_ignore_case ( ext2, extPos ) ) return 3; + return 0; +} + +//! search if a filename has a proper extension +inline bool hasFileExtension ( const io::path& filename, + const io::path& ext0, + const io::path& ext1 = "", + const io::path& ext2 = "") +{ + return isFileExtension ( filename, ext0, ext1, ext2 ) > 0; +} + +//! cut the filename extension from a source file path and store it in a dest file path +inline io::path& cutFilenameExtension ( io::path &dest, const io::path &source ) { s32 endPos = source.findLast ( '.' ); dest = source.subString ( 0, endPos < 0 ? source.size () : endPos ); return dest; } -//! get the filename extension from a string -inline stringc& getFileNameExtension ( stringc &dest, const stringc &source ) +//! get the filename extension from a file path +inline io::path& getFileNameExtension ( io::path &dest, const io::path &source ) { s32 endPos = source.findLast ( '.' ); if ( endPos < 0 ) @@ -37,6 +64,81 @@ inline stringc& getFileNameExtension ( stringc &dest, const stringc &source ) return dest; } +//! delete path from filename +inline io::path& deletePathFromFilename(io::path& filename) +{ + // delete path from filename + const fschar_t* s = filename.c_str(); + const fschar_t* p = s + filename.size(); + + // search for path separator or beginning + while ( *p != '/' && *p != '\\' && p != s ) + p--; + + if ( p != s ) + { + ++p; + filename = p; + } + return filename; +} + +//! trim paths +inline io::path& deletePathFromPath(io::path& filename, s32 pathCount) +{ + // delete path from filename + s32 i = filename.size(); + + // search for path separator or beginning + while ( i>=0 ) + { + if ( filename[i] == '/' || filename[i] == '\\' ) + { + if ( --pathCount <= 0 ) + break; + } + --i; + } + + if ( i>0 ) + { + filename [ i + 1 ] = 0; + filename.validate(); + } + else + filename=""; + return filename; +} + +//! looks if file is in the same directory of path. returns offset of directory. +//! 0 means in same directory. 1 means file is direct child of path +inline s32 isInSameDirectory ( const io::path& path, const io::path& file ) +{ + s32 subA = 0; + s32 subB = 0; + s32 pos; + + if ( path.size() && !path.equalsn ( file, path.size() ) ) + return -1; + + pos = 0; + while ( (pos = path.findNext ( '/', pos )) >= 0 ) + { + subA += 1; + pos += 1; + } + + pos = 0; + while ( (pos = file.findNext ( '/', pos )) >= 0 ) + { + subB += 1; + pos += 1; + } + + return subB - subA; +} + + //! some standard function ( to remove dependencies ) #undef isdigit #undef isspace diff --git a/src/dep/include/irrlicht/dimension2d.h b/src/dep/include/irrlicht/dimension2d.h index 360f5ca..ad7a661 100644 --- a/src/dep/include/irrlicht/dimension2d.h +++ b/src/dep/include/irrlicht/dimension2d.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,11 +6,14 @@ #define __IRR_DIMENSION2D_H_INCLUDED__ #include "irrTypes.h" +#include "irrMath.h" // for irr::core::equals() namespace irr { namespace core { + template + class vector2d; //! Specifies a 2 dimensional size. template @@ -23,10 +26,27 @@ namespace core dimension2d(const T& width, const T& height) : Width(width), Height(height) {} + dimension2d(const vector2d& other); // Defined in vector2d.h + + //! Use this constructor only where you are sure that the conversion is valid. + template + explicit dimension2d(const dimension2d& other) : + Width((T)other.Width), Height((T)other.Height) { } + + template + dimension2d& operator=(const dimension2d& other) + { + Width = (T) other.Width; + Height = (T) other.Height; + return *this; + } + + //! Equality operator bool operator==(const dimension2d& other) const { - return Width == other.Width && Height == other.Height; + return core::equals(Width, other.Width) && + core::equals(Height, other.Height); } //! Inequality operator @@ -35,6 +55,12 @@ namespace core return ! (*this == other); } + bool operator==(const vector2d& other) const; // Defined in vector2d.h + + bool operator!=(const vector2d& other) const + { + return !(*this == other); + } //! Set to new values dimension2d& set(const T& width, const T& height) @@ -72,14 +98,23 @@ namespace core return dimension2d(Width*scale, Height*scale); } - //! Add two dimensions + //! Add another dimension to this one. dimension2d& operator+=(const dimension2d& other) { - Width *= other.Width; - Height *= other.Height; + Width += other.Width; + Height += other.Height; return *this; } + //! Subtract a dimension from this one + dimension2d& operator-=(const dimension2d& other) + { + Width -= other.Width; + Height -= other.Height; + return *this; + } + + //! Add two dimensions dimension2d operator+(const dimension2d& other) const { @@ -103,12 +138,15 @@ namespace core \param larger Choose whether the result is larger or smaller than the current dimension. If one dimension need not be changed it is kept with any value of larger. + \param maxValue Maximum texturesize. if value > 0 size is + clamped to maxValue \return The optimal dimension under the given constraints. */ dimension2d getOptimalSize( bool requirePowerOfTwo=true, bool requireSquare=false, - bool larger=true) const + bool larger=true, + u32 maxValue = 0) const { u32 i=1; u32 j=1; @@ -136,6 +174,13 @@ namespace core else i=j; } + + if ( maxValue > 0 && i > maxValue) + i = maxValue; + + if ( maxValue > 0 && j > maxValue) + j = maxValue; + return dimension2d((T)i,(T)j); } @@ -145,8 +190,8 @@ namespace core \return Interpolated dimension. */ dimension2d getInterpolated(const dimension2d& other, f32 d) const { - T inv = (T) (1.0f - d); - return dimension2d(other.Width*inv + Width*d, other.Height*inv + Height*d); + f32 inv = (1.0f - d); + return dimension2d( (T)(other.Width*inv + Width*d), (T)(other.Height*inv + Height*d)); } @@ -158,9 +203,15 @@ namespace core //! Typedef for an f32 dimension. typedef dimension2d dimension2df; + //! Typedef for an unsigned integer dimension. + typedef dimension2d dimension2du; + //! Typedef for an integer dimension. + /** There are few cases where negative dimensions make sense. Please consider using + dimension2du instead. */ typedef dimension2d dimension2di; + } // end namespace core } // end namespace irr diff --git a/src/dep/include/irrlicht/driverChoice.h b/src/dep/include/irrlicht/driverChoice.h new file mode 100644 index 0000000..c3827e1 --- /dev/null +++ b/src/dep/include/irrlicht/driverChoice.h @@ -0,0 +1,42 @@ +// Copyright (C) 2009-2010 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_DRIVER_CHOICE_H_INCLUDED__ +#define __E_DRIVER_CHOICE_H_INCLUDED__ + +#include +#include "EDriverTypes.h" + +namespace irr +{ + +//! ask user for driver +static irr::video::E_DRIVER_TYPE driverChoiceConsole(bool allDrivers=true) +{ + const char* const names[] = {"NullDriver","Software Renderer","Burning's Video","Direct3D 8.1","Direct3D 9.0c","OpenGL 1.x/2.x/3.x"}; + printf("Please select the driver you want:\n"); + irr::u32 i=0; + for (i=irr::video::EDT_COUNT; i>0; --i) + { + if (allDrivers || (irr::IrrlichtDevice::isDriverSupported(irr::video::E_DRIVER_TYPE(i-1)))) + printf(" (%c) %s\n", 'a'+irr::video::EDT_COUNT-i, names[i-1]); + } + + char c; + std::cin >> c; + c = irr::video::EDT_COUNT+'a'-c; + + for (i=irr::video::EDT_COUNT; i>0; --i) + { + if (!(allDrivers || (irr::IrrlichtDevice::isDriverSupported(irr::video::E_DRIVER_TYPE(i-1))))) + --c; + if ((char)i==c) + return irr::video::E_DRIVER_TYPE(i-1); + } + return irr::video::EDT_COUNT; +} + +} // end namespace irr + +#endif diff --git a/src/dep/include/irrlicht/fast_atof.h b/src/dep/include/irrlicht/fast_atof.h index e31af6e..b6d5aa7 100644 --- a/src/dep/include/irrlicht/fast_atof.h +++ b/src/dep/include/irrlicht/fast_atof.h @@ -1,22 +1,19 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h #ifndef __FAST_A_TO_F_H_INCLUDED__ #define __FAST_A_TO_F_H_INCLUDED__ -#include #include "irrMath.h" -#include // For FLT_MAX -#include // For INT_MAX / UINT_MAX namespace irr { namespace core { -// we write [16] here instead of [] to work around a swig bug -const float fast_atof_table[16] = { +// we write [17] here instead of [] to work around a swig bug +const float fast_atof_table[17] = { 0.f, 0.1f, 0.01f, @@ -32,7 +29,8 @@ const float fast_atof_table[16] = { 0.000000000001f, 0.0000000000001f, 0.00000000000001f, - 0.000000000000001f + 0.000000000000001f, + 0.0000000000000001f }; //! Convert a simple string of base 10 digits into a signed 32 bit integer. diff --git a/src/dep/include/irrlicht/heapsort.h b/src/dep/include/irrlicht/heapsort.h index 10bb08d..8c505ce 100644 --- a/src/dep/include/irrlicht/heapsort.h +++ b/src/dep/include/irrlicht/heapsort.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -53,9 +53,8 @@ inline void heapsort(T* array_, s32 size) for (i=((size-1)/2); i>=0; --i) heapsink(virtualArray, i+1, virtualSize-1); - // sort array - - for (i=size-1; i>=0; --i) + // sort array, leave out the last element (0) + for (i=size-1; i>0; --i) { T t = array_[0]; array_[0] = array_[i]; diff --git a/src/dep/include/irrlicht/irrAllocator.h b/src/dep/include/irrlicht/irrAllocator.h index 9d5b5d4..77452b0 100644 --- a/src/dep/include/irrlicht/irrAllocator.h +++ b/src/dep/include/irrlicht/irrAllocator.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h @@ -7,6 +7,7 @@ #include "irrTypes.h" #include +// necessary for older compilers #include namespace irr @@ -107,6 +108,14 @@ public: #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #endif +//! defines an allocation strategy +enum eAllocStrategy +{ + ALLOC_STRATEGY_SAFE = 0, + ALLOC_STRATEGY_DOUBLE = 1, + ALLOC_STRATEGY_SQRT = 2 +}; + } // end namespace core } // end namespace irr diff --git a/src/dep/include/irrlicht/irrArray.h b/src/dep/include/irrlicht/irrArray.h index c4a7185..04d14e5 100644 --- a/src/dep/include/irrlicht/irrArray.h +++ b/src/dep/include/irrlicht/irrArray.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h @@ -8,6 +8,7 @@ #include "irrTypes.h" #include "heapsort.h" #include "irrAllocator.h" +#include "irrMath.h" namespace irr { @@ -26,41 +27,34 @@ public: //! Default constructor for empty array. array() : data(0), allocated(0), used(0), - free_when_destroyed(true), is_sorted(true) + strategy(ALLOC_STRATEGY_DOUBLE), free_when_destroyed(true), is_sorted(true) { } + //! Constructs an array and allocates an initial chunk of memory. /** \param start_count Amount of elements to pre-allocate. */ array(u32 start_count) - : data(0), allocated(0), used(0), - free_when_destroyed(true), is_sorted(true) + : data(0), allocated(0), used(0), + strategy(ALLOC_STRATEGY_DOUBLE), free_when_destroyed(true), is_sorted(true) { reallocate(start_count); } //! Copy constructor - array(const array& other) - : data(0) + array(const array& other) : data(0) { *this = other; } - //! Destructor. /** Frees allocated memory, if set_free_when_destroyed was not set to false by the user before. */ ~array() { - if (free_when_destroyed) - { - for (u32 i=0; i allocated) - { - // reallocate(used * 2 +1); - // this doesn't work if the element is in the same array. So - // we'll copy the element first to be sure we'll get no data - // corruption - - T e(element); - reallocate(used * 2 +1); // increase data block - - allocator.construct(&data[used++], e); // data[used++] = e; // push_back - } - else - { - //data[used++] = element; - // instead of using this here, we copy it the safe way: - allocator.construct(&data[used++], element); - } - - is_sorted = false; + insert(element, used); } @@ -143,18 +128,63 @@ public: _IRR_DEBUG_BREAK_IF(index>used) // access violation if (used + 1 > allocated) - reallocate(used +1); - - for (u32 i=used; i>index; --i) { - if (i index) - allocator.destruct(&data[index]); - allocator.construct(&data[index], element); // data[index] = element; + // increase data block + u32 newAlloc; + switch ( strategy ) + { + case ALLOC_STRATEGY_DOUBLE: + newAlloc = used + 1 + (allocated < 500 ? + (allocated < 5 ? 5 : used) : used >> 2); + break; + default: + case ALLOC_STRATEGY_SAFE: + newAlloc = used + 1; + break; + } + reallocate( newAlloc); + + // move array content and construct new element + // first move end one up + for (u32 i=used; i>index; --i) + { + if (i index) + allocator.destruct(&data[index]); + allocator.construct(&data[index], e); // data[index] = e; + } + else + { + // element inserted not at end + if ( used > index ) + { + // create one new element at the end + allocator.construct(&data[used], data[used-1]); + + // move the rest of the array content + for (u32 i=used-1; i>index; --i) + { + data[i] = data[i-1]; + } + // insert the new element + data[index] = element; + } + else + { + // insert the new element to the end + allocator.construct(&data[index], element); + } + } + // set to false as we don't know if we have the comparison operators is_sorted = false; ++used; } @@ -163,10 +193,13 @@ public: //! Clears the array and deletes all allocated memory. void clear() { - for (u32 i=0; i& other) + const array& operator=(const array& other) { - if (data) - { - for (u32 i=0; i& other) const + bool operator == (const array& other) const { if (used != other.used) return false; @@ -251,8 +294,9 @@ public: return true; } + //! Inequality operator - bool operator != (const array& other) const + bool operator != (const array& other) const { return !(*this==other); } @@ -310,8 +354,8 @@ public: } - //! Get size of array. - /** \return Size of elements used in the array. */ + //! Get number of occupied elements of the array. + /** \return Size of elements in the array which are actually occupied. */ u32 size() const { return used; @@ -320,7 +364,7 @@ public: //! Get amount of memory allocated. /** \return Amount of memory allocated. The amount of bytes - allocated would be allocated_size() * sizeof(ElementsUsed); */ + allocated would be allocated_size() * sizeof(ElementTypeUsed); */ u32 allocated_size() const { return allocated; @@ -340,17 +384,16 @@ public: O(n*log n) in worst case. */ void sort() { - if (is_sorted || used<2) - return; - - heapsort(data, used); + if (!is_sorted && used>1) + heapsort(data, used); is_sorted = true; } //! Performs a binary search for an element, returns -1 if not found. /** The array will be sorted before the binary search if it is not - already sorted. + already sorted. Caution is advised! Be careful not to call this on + unsorted const arrays, or the slower method will be used. \param element Element to search for. \return Position of the searched element if it was found, otherwise -1 is returned. */ @@ -361,14 +404,18 @@ public: } - //! Performs a binary search for an element, returns -1 if not found. - /** The array must be sorted prior + //! Performs a binary search for an element if possible, returns -1 if not found. + /** This method is for const arrays and so cannot call sort(), if the array is + not sorted then linear_search will be used instead. Potentially very slow! \param element Element to search for. - \return Position of the searched element if it was found, otherwise -1 - is returned. */ - s32 binary_search_const(const T& element) const + \return Position of the searched element if it was found, + otherwise -1 is returned. */ + s32 binary_search(const T& element) const { - return binary_search(element, 0, used-1); + if (is_sorted) + return binary_search(element, 0, used-1); + else + return linear_search(element); } @@ -408,6 +455,39 @@ public: } + //! Performs a binary search for an element, returns -1 if not found. + //! it is used for searching a multiset + /** The array will be sorted before the binary search if it is not + already sorted. + \param element Element to search for. + \param &last return lastIndex of equal elements + \return Position of the first searched element if it was found, + otherwise -1 is returned. */ + s32 binary_search_multi(const T& element, s32 &last) + { + sort(); + s32 index = binary_search(element, 0, used-1); + if ( index < 0 ) + return index; + + // The search can be somewhere in the middle of the set + // look linear previous and past the index + last = index; + + while ( index > 0 && !(element < data[index - 1]) && !(data[index - 1] < element) ) + { + index -= 1; + } + // look linear up + while ( last < (s32) used - 1 && !(element < data[last + 1]) && !(data[last + 1] < element) ) + { + last += 1; + } + + return index; + } + + //! Finds an element in linear time, which is very slow. /** Use binary_search for faster finding. Only works if ==operator is implemented. @@ -467,7 +547,10 @@ public: \param count: Amount of elements to be erased. */ void erase(u32 index, s32 count) { - _IRR_DEBUG_BREAK_IF(index>=used || count<1 || index+count>used) // access violation + if (index>=used || count<1) + return; + if (index+count>used) + count = used-index; u32 i; for (i=index; i& other) + { + core::swap(data, other.data); + core::swap(allocated, other.allocated); + core::swap(used, other.used); + core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation + eAllocStrategy helper_strategy(strategy); // can't use core::swap with bitfields + strategy = other.strategy; + other.strategy = helper_strategy; + bool helper_free_when_destroyed(free_when_destroyed); + free_when_destroyed = other.free_when_destroyed; + other.free_when_destroyed = helper_free_when_destroyed; + bool helper_is_sorted(is_sorted); + is_sorted = other.is_sorted; + other.is_sorted = helper_is_sorted; + } + + +private: + T* data; + u32 allocated; + u32 used; + TAlloc allocator; + eAllocStrategy strategy:4; + bool free_when_destroyed:1; + bool is_sorted:1; }; } // end namespace core } // end namespace irr - #endif diff --git a/src/dep/include/irrlicht/irrList.h b/src/dep/include/irrlicht/irrList.h index 8c89a02..39a7bff 100644 --- a/src/dep/include/irrlicht/irrList.h +++ b/src/dep/include/irrlicht/irrList.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,8 @@ #define __IRR_LIST_H_INCLUDED__ #include "irrTypes.h" +#include "irrAllocator.h" +#include "irrMath.h" namespace irr { @@ -22,7 +24,7 @@ private: //! List element node with pointer to previous and next element in the list. struct SKListNode { - SKListNode() : Next(0), Prev(0) {} + SKListNode(const T& e) : Next(0), Prev(0), Element(e) {} SKListNode* Next; SKListNode* Prev; @@ -73,11 +75,12 @@ public: T * operator ->() { return &Current->Element; } private: - Iterator(SKListNode* begin) : Current(begin) {} + explicit Iterator(SKListNode* begin) : Current(begin) {} SKListNode* Current; friend class list; + friend class ConstIterator; }; //! List iterator for const access. @@ -86,6 +89,7 @@ public: public: ConstIterator() : Current(0) {} + ConstIterator(const Iterator& iter) : Current(iter.Current) {} ConstIterator& operator ++() { Current = Current->Next; return *this; } ConstIterator& operator --() { Current = Current->Prev; return *this; } @@ -120,7 +124,7 @@ public: ConstIterator & operator =(const Iterator & iterator) { Current = iterator.Current; return *this; } private: - ConstIterator(SKListNode* begin) : Current(begin) {} + explicit ConstIterator(SKListNode* begin) : Current(begin) {} SKListNode* Current; @@ -168,6 +172,10 @@ public: //! Returns amount of elements in list. /** \return Amount of elements in the list. */ + u32 size() const + { + return Size; + } u32 getSize() const { return Size; @@ -181,7 +189,8 @@ public: while(First) { SKListNode * next = First->Next; - delete First; + allocator.destruct(First); + allocator.deallocate(First); First = next; } @@ -203,8 +212,8 @@ public: /** \param element Element to add to the list. */ void push_back(const T& element) { - SKListNode* node = new SKListNode; - node->Element = element; + SKListNode* node = allocator.allocate(1); + allocator.construct(node, element); ++Size; @@ -224,8 +233,8 @@ public: /** \param element: Element to add to the list. */ void push_front(const T& element) { - SKListNode* node = new SKListNode; - node->Element = element; + SKListNode* node = allocator.allocate(1); + allocator.construct(node, element); ++Size; @@ -298,8 +307,8 @@ public: */ void insert_after(const Iterator& it, const T& element) { - SKListNode* node = new SKListNode; - node->Element = element; + SKListNode* node = allocator.allocate(1); + allocator.construct(node, element); node->Next = it.Current->Next; @@ -322,8 +331,8 @@ public: */ void insert_before(const Iterator& it, const T& element) { - SKListNode* node = new SKListNode; - node->Element = element; + SKListNode* node = allocator.allocate(1); + allocator.construct(node, element); node->Prev = it.Current->Prev; @@ -368,18 +377,34 @@ public: it.Current->Next->Prev = it.Current->Prev; } - delete it.Current; + allocator.destruct(it.Current); + allocator.deallocate(it.Current); it.Current = 0; --Size; return returnIterator; } + //! Swap the content of this list container with the content of another list + /** Afterwards this object will contain the content of the other object and the other + object will contain the content of this object. Iterators will afterwards be valid for + the swapped object. + \param other Swap content with this object */ + void swap(list& other) + { + core::swap(First, other.First); + core::swap(Last, other.Last); + core::swap(Size, other.Size); + core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation + } + + private: SKListNode* First; SKListNode* Last; u32 Size; + irrAllocator allocator; }; diff --git a/src/dep/include/irrlicht/irrMap.h b/src/dep/include/irrlicht/irrMap.h index b53b1c8..4406ab3 100644 --- a/src/dep/include/irrlicht/irrMap.h +++ b/src/dep/include/irrlicht/irrMap.h @@ -1,4 +1,4 @@ -// Copyright 2006-2008 by Kat'Oun +// Copyright (C) 2006-2010 by Kat'Oun // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,7 @@ #define __IRR_MAP_H_INCLUDED__ #include "irrTypes.h" +#include "irrMath.h" namespace irr { @@ -49,7 +50,7 @@ class map RBTree* getLeftChild() const { return LeftChild; } RBTree* getRightChild() const { return RightChild; } - RBTree* getParent() const { return Parent; } + RBTree* getParent() const { return Parent; } ValueTypeRB getValue() const { @@ -186,8 +187,7 @@ class map Node& operator* () { - if (atEnd()) - throw "Iterator at end"; + _IRR_DEBUG_BREAK_IF(atEnd()) // access violation return *Cur; } @@ -336,8 +336,8 @@ class map Node& operator* () { - if (atEnd()) - throw "ParentFirstIterator at end"; + _IRR_DEBUG_BREAK_IF(atEnd()) // access violation + return *getNode(); } @@ -436,8 +436,8 @@ class map Node& operator* () { - if (atEnd()) - throw "ParentLastIterator at end"; + _IRR_DEBUG_BREAK_IF(atEnd()) // access violation + return *getNode(); } private: @@ -483,7 +483,7 @@ class map // myTree["Foo"] = 32; // If "Foo" already exists update its value else insert a new element. // int i = myTree["Foo"] - // If "Foo" exists return its value, else throw an exception. + // If "Foo" exists return its value. class AccessClass { // Let map be the only one who can instantiate this class. @@ -504,8 +504,7 @@ class map Node* node = Tree.find(Key); // Not found - if (node==0) - throw "Item not found"; + _IRR_DEBUG_BREAK_IF(node==0) // access violation _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return node->getValue(); @@ -732,12 +731,18 @@ class map //! Is the tree empty? //! \return Returns true if empty, false if not - bool isEmpty() const + bool empty() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Root == 0; } + //! \deprecated Use empty() instead. + _IRR_DEPRECATED_ bool isEmpty() const + { + return empty(); + } + //! Search for a node with the specified key. //! \param keyToFind: The key to find //! \return Returns 0 if node couldn't be found. @@ -774,6 +779,17 @@ class map return Size; } + //! Swap the content of this map container with the content of another map + /** Afterwards this object will contain the content of the other object and the other + object will contain the content of this object. Iterators will afterwards be valid for + the swapped object. + \param other Swap content with this object */ + void swap(map& other) + { + core::swap(Root, other.Root); + core::swap(Size, other.Size); + } + //------------------------------ // Public Iterators //------------------------------ diff --git a/src/dep/include/irrlicht/irrMath.h b/src/dep/include/irrlicht/irrMath.h index 7da1c81..b1c88c4 100644 --- a/src/dep/include/irrlicht/irrMath.h +++ b/src/dep/include/irrlicht/irrMath.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -8,20 +8,27 @@ #include "IrrCompileConfig.h" #include "irrTypes.h" #include +#include #include // for abs() etc. +#include // For INT_MAX / UINT_MAX #if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) || defined (_WIN32_WCE) - #define sqrtf(X) (f32)sqrt((f64)(X)) - #define sinf(X) (f32)sin((f64)(X)) - #define cosf(X) (f32)cos((f64)(X)) - #define asinf(X) (f32)asin((f64)(X)) - #define acosf(X) (f32)acos((f64)(X)) - #define atan2f(X,Y) (f32)atan2((f64)(X),(f64)(Y)) - #define ceilf(X) (f32)ceil((f64)(X)) - #define floorf(X) (f32)floor((f64)(X)) - #define powf(X,Y) (f32)pow((f64)(X),(f64)(Y)) - #define fmodf(X,Y) (f32)fmod((f64)(X),(f64)(Y)) - #define fabsf(X) (f32)fabs((f64)(X)) + #define sqrtf(X) (irr::f32)sqrt((irr::f64)(X)) + #define sinf(X) (irr::f32)sin((irr::f64)(X)) + #define cosf(X) (irr::f32)cos((irr::f64)(X)) + #define asinf(X) (irr::f32)asin((irr::f64)(X)) + #define acosf(X) (irr::f32)acos((irr::f64)(X)) + #define atan2f(X,Y) (irr::f32)atan2((irr::f64)(X),(irr::f64)(Y)) + #define ceilf(X) (irr::f32)ceil((irr::f64)(X)) + #define floorf(X) (irr::f32)floor((irr::f64)(X)) + #define powf(X,Y) (irr::f32)pow((irr::f64)(X),(irr::f64)(Y)) + #define fmodf(X,Y) (irr::f32)fmod((irr::f64)(X),(irr::f64)(Y)) + #define fabsf(X) (irr::f32)fabs((irr::f64)(X)) + #define logf(X) (irr::f32)log((irr::f64)(X)) +#endif + +#ifndef FLT_MAX +#define FLT_MAX 3.402823466E+38F #endif namespace irr @@ -31,13 +38,9 @@ namespace core //! Rounding error constant often used when comparing f32 values. -#ifdef IRRLICHT_FAST_MATH - const f32 ROUNDING_ERROR_32 = 0.00005f; - const f64 ROUNDING_ERROR_64 = 0.000005; -#else - const f32 ROUNDING_ERROR_32 = 0.000001f; - const f64 ROUNDING_ERROR_64 = 0.00000001; -#endif + const s32 ROUNDING_ERROR_S32 = 0; + const f32 ROUNDING_ERROR_f32 = 0.000001f; + const f64 ROUNDING_ERROR_f64 = 0.00000001; #ifdef PI // make sure we don't collide with a define #undef PI @@ -158,34 +161,72 @@ namespace core return min_ (max_(value,low), high); } + //! swaps the content of the passed parameters + // Note: We use the same trick as boost and use two template arguments to + // avoid ambiguity when swapping objects of an Irrlicht type that has not + // it's own swap overload. Otherwise we get conflicts with some compilers + // in combination with stl. + template + inline void swap(T1& a, T2& b) + { + T1 c(a); + a = b; + b = c; + } + //! 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) + inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64) { 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) + inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32) + { + return (a + tolerance >= b) && (a - tolerance <= b); + } +#if 0 + //! returns if a equals b, not using any rounding tolerance + inline bool equals(const s32 a, const s32 b) + { + return (a == b); + } + + //! returns if a equals b, not using any rounding tolerance + inline bool equals(const u32 a, const u32 b) + { + return (a == b); + } +#endif + //! returns if a equals b, taking an explicit rounding tolerance into account + inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32) { return (a + tolerance >= b) && (a - tolerance <= b); } - //! returns if a equals b, taking possible rounding errors into account - inline bool equals(const s32 a, const s32 b, const s32 tolerance = 0) + //! returns if a equals b, taking an explicit rounding tolerance into account + inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32) { return (a + tolerance >= b) && (a - tolerance <= b); } - //! returns if a equals b, taking possible rounding errors into account - inline bool equals(const u32 a, const u32 b, const u32 tolerance = 0) + + //! returns if a equals zero, taking rounding errors into account + inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64) { - return (a + tolerance >= b) && (a - tolerance <= b); + return fabs(a) <= tolerance; } //! returns if a equals zero, taking rounding errors into account - inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_32) + inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32) { - return fabsf ( a ) <= tolerance; + return fabsf(a) <= tolerance; + } + + //! returns if a equals not zero, taking rounding errors into account + inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32) + { + return fabsf(a) > tolerance; } //! returns if a equals zero, taking rounding errors into account @@ -200,21 +241,21 @@ namespace core return a <= tolerance; } - inline s32 s32_min ( s32 a, s32 b) + inline s32 s32_min(s32 a, s32 b) { - s32 mask = (a - b) >> 31; + const s32 mask = (a - b) >> 31; return (a & mask) | (b & ~mask); } - inline s32 s32_max ( s32 a, s32 b) + inline s32 s32_max(s32 a, s32 b) { - s32 mask = (a - b) >> 31; + const s32 mask = (a - b) >> 31; return (b & mask) | (a & ~mask); } inline s32 s32_clamp (s32 value, s32 low, s32 high) { - return s32_min (s32_max(value,low), high); + return s32_min(s32_max(value,low), high); } /* @@ -296,6 +337,22 @@ namespace core #endif #endif +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) + + // 8-bit bools in borland builder + + //! conditional set based on mask and arithmetic shift + REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b ) + { + return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b; + } + + //! conditional set based on mask and arithmetic shift + REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a ) + { + return ( -condition >> 31 ) & a; + } +#else //! conditional set based on mask and arithmetic shift REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b ) @@ -303,11 +360,18 @@ namespace core return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b; } + //! conditional set based on mask and arithmetic shift + REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b ) + { + return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b; + } + //! conditional set based on mask and arithmetic shift REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a ) { return ( -condition >> 31 ) & a; } +#endif /* if (condition) state |= m; else state &= ~m; @@ -327,6 +391,7 @@ namespace core REALINLINE void clearFPUException () { #ifdef IRRLICHT_FAST_MATH + return; #ifdef feclearexcept feclearexcept(FE_ALL_EXCEPT); #elif defined(_MSC_VER) @@ -339,55 +404,137 @@ namespace core #endif } - REALINLINE f32 reciprocal_squareroot(const f32 x) + // calculate: sqrt ( x ) + REALINLINE f32 squareroot(const f32 f) { -#ifdef IRRLICHT_FAST_MATH + return sqrtf(f); + } + + // calculate: sqrt ( x ) + REALINLINE f64 squareroot(const f64 f) + { + return sqrt(f); + } + + // calculate: sqrt ( x ) + REALINLINE s32 squareroot(const s32 f) + { + return static_cast(squareroot(static_cast(f))); + } + + // calculate: 1 / sqrt ( x ) + REALINLINE f64 reciprocal_squareroot(const f64 x) + { + return 1.0 / sqrt(x); + } + + // calculate: 1 / sqrtf ( x ) + REALINLINE f32 reciprocal_squareroot(const f32 f) + { +#if defined ( IRRLICHT_FAST_MATH ) + #if defined(_MSC_VER) + // SSE reciprocal square root estimate, accurate to 12 significant + // bits of the mantissa + f32 recsqrt; + __asm rsqrtss xmm0, f // xmm0 = rsqrtss(f) + __asm movss recsqrt, xmm0 // return xmm0 + return recsqrt; + +/* // comes from Nvidia -#if 1 u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1; f32 y = *(f32*)&tmp; return y * (1.47f - 0.47f * x * y * y); -#elif defined(_MSC_VER) - // an sse2 version - __asm - { - movss xmm0, x - rsqrtss xmm0, xmm0 - movss x, xmm0 - } - return x; -#endif +*/ + #else + return 1.f / sqrtf(f); + #endif #else // no fast math - return 1.f / sqrtf ( x ); + return 1.f / sqrtf(f); #endif } - - - REALINLINE f32 reciprocal ( const f32 f ) + // calculate: 1 / sqrtf( x ) + REALINLINE s32 reciprocal_squareroot(const s32 x) { -#ifdef IRRLICHT_FAST_MATH + return static_cast(reciprocal_squareroot(static_cast(x))); + } + + // calculate: 1 / x + REALINLINE f32 reciprocal( const f32 f ) + { +#if defined (IRRLICHT_FAST_MATH) + + // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant + // bi ts of the mantissa + // One Newtown-Raphson Iteration: + // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f) + f32 rec; + __asm rcpss xmm0, f // xmm0 = rcpss(f) + __asm movss xmm1, f // xmm1 = f + __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) + __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) + __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) + __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) + // - f * rcpss(f) * rcpss(f) + __asm movss rec, xmm0 // return xmm0 + return rec; + + //! i do not divide through 0.. (fpu expection) // instead set f to a high value to get a return value near zero.. // -1000000000000.f.. is use minus to stay negative.. // must test's here (plane.normal dot anything ) checks on <= 0.f - return 1.f / f; //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5; //return 1.f / FR ( x ); + #else // no fast math return 1.f / f; #endif } - - REALINLINE f32 reciprocal_approxim ( const f32 p ) + // calculate: 1 / x + REALINLINE f64 reciprocal ( const f64 f ) { -#ifdef IRRLICHT_FAST_MATH + return 1.0 / f; + } + + + // calculate: 1 / x, low precision allowed + REALINLINE f32 reciprocal_approxim ( const f32 f ) + { +#if defined( IRRLICHT_FAST_MATH) + + // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant + // bi ts of the mantissa + // One Newtown-Raphson Iteration: + // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f) + f32 rec; + __asm rcpss xmm0, f // xmm0 = rcpss(f) + __asm movss xmm1, f // xmm1 = f + __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) + __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) + __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) + __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) + // - f * rcpss(f) * rcpss(f) + __asm movss rec, xmm0 // return xmm0 + return rec; + + +/* + // SSE reciprocal estimate, accurate to 12 significant bits of + f32 rec; + __asm rcpss xmm0, f // xmm0 = rcpss(f) + __asm movss rec , xmm0 // return xmm0 + return rec; +*/ +/* register u32 x = 0x7F000000 - IR ( p ); const f32 r = FR ( x ); return r * (2.0f - p * r); +*/ #else // no fast math - return 1.f / p; + return 1.f / f; #endif } @@ -505,5 +652,10 @@ namespace core } // end namespace core } // end namespace irr +#ifndef IRRLICHT_FAST_MATH + using irr::core::IR; + using irr::core::FR; +#endif + #endif diff --git a/src/dep/include/irrlicht/irrString.h b/src/dep/include/irrlicht/irrString.h index 26ea4bc..e053675 100644 --- a/src/dep/include/irrlicht/irrString.h +++ b/src/dep/include/irrlicht/irrString.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h @@ -23,15 +23,52 @@ so you can assign Unicode to string and ASCII/Latin-1 to string (and the other way round) if you want to. However, note that the conversation between both is not done using any encoding. -This means that c8 strings are treated as ASCII/Latin-1, not UTF-8, and -are simply expanded to the equivalent wchar_t, while Unicode/wchar_t +This means that c8 strings are treated as ASCII/Latin-1, not UTF-8, and +are simply expanded to the equivalent wchar_t, while Unicode/wchar_t characters are truncated to 8-bit ASCII/Latin-1 characters, discarding all other information in the wchar_t. - -Known bugs: -Special characters like umlauts are ignored in the -methods make_upper, make_lower and equals_ignore_case. */ + +enum eLocaleID +{ + IRR_LOCALE_ANSI = 0, + IRR_LOCALE_GERMAN = 1 +}; + +static eLocaleID locale_current = IRR_LOCALE_ANSI; +static inline void locale_set ( eLocaleID id ) +{ + locale_current = id; +} + +//! Returns a character converted to lower case +static inline u32 locale_lower ( u32 x ) +{ + switch ( locale_current ) + { + case IRR_LOCALE_GERMAN: + case IRR_LOCALE_ANSI: + break; + } + // ansi + return x >= 'A' && x <= 'Z' ? x + 0x20 : x; +} + +//! Returns a character converted to upper case +static inline u32 locale_upper ( u32 x ) +{ + switch ( locale_current ) + { + case IRR_LOCALE_GERMAN: + case IRR_LOCALE_ANSI: + break; + } + + // ansi + return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x; +} + + template > class string { @@ -47,15 +84,15 @@ public: //! Constructor - string(const string& other) + string(const string& other) : array(0), allocated(0), used(0) { *this = other; } //! Constructor from other string types - template - string(const string& other) + template + string(const string& other) : array(0), allocated(0), used(0) { *this = other; @@ -87,8 +124,7 @@ public: // temporary buffer for 16 numbers - c8 tmpbuf[16]; - tmpbuf[15] = 0; + c8 tmpbuf[16]={0}; u32 idx = 15; // special case '0' @@ -127,8 +163,7 @@ public: { // temporary buffer for 16 numbers - c8 tmpbuf[16]; - tmpbuf[15] = 0; + c8 tmpbuf[16]={0}; u32 idx = 15; // special case '0' @@ -184,7 +219,7 @@ public: } - //! destructor + //! Destructor ~string() { allocator.deallocate(array); // delete [] array; @@ -192,14 +227,18 @@ public: //! Assignment operator - string& operator=(const string& other) + string& operator=(const string& other) { if (this == &other) return *this; - allocator.deallocate(array); // delete [] array; - allocated = used = other.size()+1; - array = allocator.allocate(used); //new T[used]; + used = other.size()+1; + if (used>allocated) + { + allocator.deallocate(array); // delete [] array; + allocated = used; + array = allocator.allocate(used); //new T[used]; + } const T* p = other.c_str(); for (u32 i=0; i - string& operator=(const string& other) + template + string& operator=(const string& other) { *this = other.c_str(); return *this; @@ -219,7 +258,7 @@ public: //! Assignment operator for strings, ascii and unicode template - string& operator=(const B* const c) + string& operator=(const B* const c) { if (!c) { @@ -238,32 +277,36 @@ public: u32 len = 0; const B* p = c; - while(*p) + do { ++len; - ++p; - } + } while(*p++); - // we'll take the old string for a while, because the new + // we'll keep the old string for a while, because the new // string could be a part of the current string. T* oldArray = array; - ++len; - allocated = used = len; - array = allocator.allocate(used); //new T[used]; + used = len; + if (used>allocated) + { + allocated = used; + array = allocator.allocate(used); //new T[used]; + } for (u32 l = 0; l operator+(const string& other) const + string operator+(const string& other) const { - string str(*this); + string str(*this); str.append(other); return str; @@ -272,9 +315,9 @@ public: //! Append operator for strings, ascii and unicode template - string operator+(const B* const c) const + string operator+(const B* const c) const { - string str(*this); + string str(*this); str.append(c); return str; @@ -313,7 +356,7 @@ public: //! Equality operator - bool operator ==(const string& other) const + bool operator ==(const string& other) const { for(u32 i=0; array[i] && other.array[i]; ++i) if (array[i] != other.array[i]) @@ -324,17 +367,13 @@ public: //! Is smaller comparator - bool operator <(const string& other) const + bool operator <(const string& other) const { for(u32 i=0; array[i] && other.array[i]; ++i) { s32 diff = array[i] - other.array[i]; if ( diff ) return diff < 0; -/* - if (array[i] != other.array[i]) - return (array[i] < other.array[i]); -*/ } return used < other.used; @@ -349,14 +388,15 @@ public: //! Inequality operator - bool operator !=(const string& other) const + bool operator !=(const string& other) const { return !(*this == other); } - //! Returns length of string - /** \return Length of the string in characters. */ + //! Returns length of the string's content + /** \return Length of the string's content in characters, excluding + the trailing NUL. */ u32 size() const { return used-1; @@ -364,7 +404,7 @@ public: //! Returns character string - /** \return pointer to C-style zero terminated string. */ + /** \return pointer to C-style NUL terminated string. */ const T* c_str() const { return array; @@ -375,46 +415,56 @@ public: void make_lower() { for (u32 i=0; i=a && array[i]<=z) - array[i] += diff; - } + array[i] = locale_upper ( array[i] ); } //! Compares the strings ignoring case. /** \param other: Other string to compare. \return True if the strings are equal ignoring case. */ - bool equals_ignore_case(const string& other) const + bool equals_ignore_case(const string& other) const { for(u32 i=0; array[i] && other[i]; ++i) - if (ansi_lower(array[i]) != ansi_lower(other[i])) + if (locale_lower( array[i]) != locale_lower(other[i])) return false; return used == other.used; } + //! Compares the strings ignoring case. + /** \param other: Other string to compare. + \param sourcePos: where to start to compare in the string + \return True if the strings are equal ignoring case. */ + bool equals_substring_ignore_case(const string&other, const s32 sourcePos = 0 ) const + { + if ( (u32) sourcePos > used ) + return false; + + u32 i; + for( i=0; array[sourcePos + i] && other[i]; ++i) + if (locale_lower( array[sourcePos + i]) != locale_lower(other[i])) + return false; + + return array[sourcePos + i] == 0 && other[i] == 0; + } + //! Compares the strings ignoring case. /** \param other: Other string to compare. \return True if this string is smaller ignoring case. */ - bool lower_ignore_case(const string& other) const + bool lower_ignore_case(const string& other) const { for(u32 i=0; array[i] && other.array[i]; ++i) { - s32 diff = (s32) ansi_lower ( array[i] ) - (s32) ansi_lower ( other.array[i] ); + s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] ); if ( diff ) return diff < 0; } @@ -426,8 +476,8 @@ public: //! compares the first n characters of the strings /** \param other Other string to compare. \param n Number of characters to compare - \return True if the n first characters of this string are smaller. */ - bool equalsn(const string& other, u32 n) const + \return True if the n first characters of both strings are equal. */ + bool equalsn(const string& other, u32 n) const { u32 i; for(i=0; array[i] && other[i] && i < n; ++i) @@ -443,7 +493,7 @@ public: //! compares the first n characters of the strings /** \param str Other string to compare. \param n Number of characters to compare - \return True if the n first characters of this string are smaller. */ + \return True if the n first characters of both strings are equal. */ bool equalsn(const T* const str, u32 n) const { if (!str) @@ -503,7 +553,7 @@ public: //! Appends a string to this string /** \param other: String to append. */ - void append(const string& other) + void append(const string& other) { --used; u32 len = other.size()+1; @@ -521,7 +571,7 @@ public: //! Appends a string of the length l to this string. /** \param other: other String to append to this string. \param length: How much characters of the other string to add to this one. */ - void append(const string& other, u32 length) + void append(const string& other, u32 length) { if (other.size() < length) { @@ -690,10 +740,11 @@ public: //! finds another string in this string /** \param str: Another string + \param start: Start position of the search \return Positions where the string has been found, or -1 if not found. */ template - s32 find(const B* const str) const + s32 find(const B* const str, const u32 start = 0) const { if (str && *str) { @@ -705,7 +756,7 @@ public: if (len > used-1) return -1; - for (u32 i=0; i subString(u32 begin, s32 length) const + string subString(u32 begin, s32 length) const { // if start after string // or no proper substring length if ((length <= 0) || (begin>=size())) - return string(""); + return string(""); // clamp length to maximal value if ((length+begin) > size()) length = size()-begin; - string o; + string o; o.reserve(length+1); for (s32 i=0; i& operator += (T c) + /** \param c Character to append. */ + string& operator += (T c) { append(c); return *this; @@ -757,8 +808,8 @@ public: //! Appends a char string to this string - /** \param other: Char string to append. */ - string& operator += (const T* const c) + /** \param c Char string to append. */ + string& operator += (const T* const c) { append(c); return *this; @@ -766,57 +817,71 @@ public: //! Appends a string to this string - /** \param other: String to append. */ - string& operator += (const string& other) + /** \param other String to append. */ + string& operator += (const string& other) { append(other); return *this; } - string& operator += (const int i) + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const int i) { - append(string(i)); + append(string(i)); return *this; } - string& operator += (const unsigned int i) + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const unsigned int i) { - append(string(i)); + append(string(i)); return *this; } - string& operator += (const long i) + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const long i) { - append(string(i)); + append(string(i)); return *this; } - string& operator += (const unsigned long& i) + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const unsigned long& i) { - append(string(i)); + append(string(i)); return *this; } - string& operator += (const double i) + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const double i) { - append(string(i)); + append(string(i)); return *this; } - string& operator += (const float i) + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const float i) { - append(string(i)); + append(string(i)); return *this; } - //! replaces all characters of a special type with another one + //! Replaces all characters of a special type with another one + /** \param toReplace Character to replace. + \param replaceWith Character replacing the old one. */ void replace(T toReplace, T replaceWith) { for (u32 i=0; i toRemove) + { + u32 size = toRemove.size(); + if ( size == 0 ) + return; + u32 pos = 0; + u32 found = 0; + for (u32 i=0; i & characters) + { + u32 pos = 0; + u32 found = 0; + for (u32 i=0; i& trim(const string & whitespace = " \t\n\r") + string& trim(const string & whitespace = " \t\n\r") { // find start and end of the substring without the specified characters const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used); @@ -855,22 +1003,87 @@ public: --used; } -private: -/* - T toLower(const T& t) const + //! verify the existing string. + void validate() { - if (t>=(T)'A' && t<=(T)'Z') - return t + ((T)'a' - (T)'A'); + // terminate on existing null + for (u32 i=0; i 0 ) + { + used = allocated; + array[used-1] = 0; + } else - return t; - } -*/ - //! Returns a character converted to lower case - inline T ansi_lower ( u32 x ) const - { - return x >= 'A' && x <= 'Z' ? (T) x + 0x20 : (T) x; + { + used = 0; + } } + //! gets the last char of a string or null + T lastChar() const + { + return used > 1 ? array[used-2] : 0; + } + + //! split string into parts. + /** This method will split a string at certain delimiter characters + into the container passed in as reference. The type of the container + has to be given as template parameter. It must provide a push_back and + a size method. + \param ret The result container + \param c C-style string of delimiter characters + \param count Number of delimiter characters + \param ignoreEmptyTokens Flag to avoid empty substrings in the result + container. If two delimiters occur without a character in between, an + empty substring would be placed in the result. If this flag is set, + only non-empty strings are stored. + \param keepSeparators Flag which allows to add the separator to the + result string. If this flag is true, the concatenation of the + substrings results in the original string. Otherwise, only the + characters between the delimiters are returned. + \return The number of resulting substrings + */ + template + u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const + { + if (!c) + return 0; + + const u32 oldSize=ret.size(); + u32 lastpos = 0; + bool lastWasSeparator = false; + for (u32 i=0; i(&array[lastpos], i - lastpos)); + foundSeparator = true; + lastpos = (keepSeparators ? i : i + 1); + break; + } + } + lastWasSeparator = foundSeparator; + } + if ((used - 1) > lastpos) + ret.push_back(string(&array[lastpos], (used - 1) - lastpos)); + return ret.size()-oldSize; + } + +private: //! Reallocate the array, make it bigger or smaller void reallocate(u32 new_size) @@ -890,7 +1103,6 @@ private: allocator.deallocate(old_array); // delete [] old_array; } - //--- member variables T* array; @@ -906,6 +1118,7 @@ typedef string stringc; //! Typedef for wide character strings typedef string stringw; + } // end namespace core } // end namespace irr diff --git a/src/dep/include/irrlicht/irrTypes.h b/src/dep/include/irrlicht/irrTypes.h index dd76df5..7b4adb0 100644 --- a/src/dep/include/irrlicht/irrTypes.h +++ b/src/dep/include/irrlicht/irrTypes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -119,10 +119,27 @@ typedef unsigned short wchar_t; #endif // microsoft compiler #endif // _IRR_WINDOWS_API_ +namespace irr +{ + +//! Type name for character type used by the file system. +/** Should the wide character version of the FileSystem be used it is a +16 bit character variable. Used for unicode Filesystem and unicode strings. +Else it is a 8 bit character variable. Used for ansi Filesystem and non-unicode +strings +*/ +#if defined(_IRR_WCHAR_FILESYSTEM) + typedef wchar_t fschar_t; +#else + typedef char fschar_t; +#endif + +} // end namespace irr + //! define a break macro for debugging. #if defined(_DEBUG) #if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && !defined (_WIN32_WCE) - #if defined(_WIN64) // using portable common solution for x64 configuration + #if defined(WIN64) || defined(_WIN64) // using portable common solution for x64 configuration #include #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_CrtDbgBreak();} #else @@ -136,6 +153,23 @@ typedef unsigned short wchar_t; #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) #endif +//! Defines a deprecated macro which generates a warning at compile time +/** The usage is simple +For typedef: typedef _IRR_DEPRECATED_ int test1; +For classes/structs: class _IRR_DEPRECATED_ test2 { ... }; +For methods: class test3 { _IRR_DEPRECATED_ virtual void foo() {} }; +For functions: template _IRR_DEPRECATED_ void test4(void) {} +**/ +#if defined(IGNORE_DEPRECATED_WARNING) +#define _IRR_DEPRECATED_ +#elif _MSC_VER >= 1310 //vs 2003 or higher +#define _IRR_DEPRECATED_ __declspec(deprecated) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) // all versions above 3.0 should support this feature +#define _IRR_DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _IRR_DEPRECATED_ +#endif + //! Defines a small statement to work around a microsoft compiler bug. /** The microsoft compiler 7.0 - 7.1 has a bug: When you call unmanaged code that returns a bool type value of false from managed code, @@ -180,10 +214,12 @@ Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400 /** some compilers can create those by directly writing the code like 'code', but some generate warnings so we use this macro here */ #define MAKE_IRR_ID(c0, c1, c2, c3) \ - ((u32)(u8)(c0) | ((u32)(u8)(c1) << 8) | \ - ((u32)(u8)(c2) << 16) | ((u32)(u8)(c3) << 24 )) + ((irr::u32)(irr::u8)(c0) | ((irr::u32)(irr::u8)(c1) << 8) | \ + ((irr::u32)(irr::u8)(c2) << 16) | ((irr::u32)(irr::u8)(c3) << 24 )) +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#define _strcmpi(a,b) strcmpi(a,b) +#endif #endif // __IRR_TYPES_H_INCLUDED__ - diff --git a/src/dep/include/irrlicht/irrXML.h b/src/dep/include/irrlicht/irrXML.h index 3b03b7c..34abe35 100644 --- a/src/dep/include/irrlicht/irrXML.h +++ b/src/dep/include/irrlicht/irrXML.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h @@ -16,8 +16,8 @@ Welcome to the irrXML API documentation. Here you'll find any information you'll need to develop applications with irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample, - at the homepage of irrXML at xml.irrlicht3d.org - or into the SDK in the directory \example. + at the homepage of irrXML at www.ambiera.com/irrxml/ + or into the SDK in the directory example. irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and this documentation is an important part of it. If you have any questions or @@ -120,7 +120,7 @@ The irrXML license is based on the zlib license. Basicly, this means you can do with irrXML whatever you want: - Copyright (C) 2002-2008 Nikolaus Gebhardt + Copyright (C) 2002-2010 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 @@ -432,10 +432,13 @@ namespace io \param callback: Callback for file read abstraction. Implement your own callback to make the xml parser read in other things than just files. See IFileReadCallBack for more information about this. + \param deleteCallback: if true, the callback will be deleted after the file + has been read. Otherwise the caller si responsible for cleaning it up. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(IFileReadCallBack* callback); + IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(IFileReadCallBack* callback, + bool deleteCallback = false); //! Creates an instance of an UFT-16 xml parser. /** This means that @@ -469,10 +472,13 @@ namespace io \param callback: Callback for file read abstraction. Implement your own callback to make the xml parser read in other things than just files. See IFileReadCallBack for more information about this. + \param deleteCallback: if true, the callback will be deleted after the file + has been read. Otherwise the caller si responsible for cleaning it up. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(IFileReadCallBack* callback); + IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(IFileReadCallBack* callback, + bool deleteCallback = false); //! Creates an instance of an UFT-32 xml parser. @@ -507,13 +513,16 @@ namespace io \param callback: Callback for file read abstraction. Implement your own callback to make the xml parser read in other things than just files. See IFileReadCallBack for more information about this. + \param deleteCallback: if true, the callback will be deleted after the file + has been read. Otherwise the caller si responsible for cleaning it up. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(IFileReadCallBack* callback); + IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(IFileReadCallBack* callback, + bool deleteCallback = false); - /*! \file irrxml.h + /*! \file irrXML.h \brief Header file of the irrXML, the Irrlicht XML parser. This file includes everything needed for using irrXML, @@ -525,7 +534,7 @@ namespace io \endcode It is also common to use the two namespaces in which irrXML is included, - directly after #including irrXML.h: + directly after including irrXML.h: \code #include diff --git a/src/dep/include/irrlicht/irrlicht.h b/src/dep/include/irrlicht/irrlicht.h index 96a5158..e4efb35 100644 --- a/src/dep/include/irrlicht/irrlicht.h +++ b/src/dep/include/irrlicht/irrlicht.h @@ -1,6 +1,6 @@ /* irrlicht.h -- interface of the 'Irrlicht Engine' - Copyright (C) 2002-2008 Nikolaus Gebhardt + Copyright (C) 2002-2010 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 @@ -69,6 +69,7 @@ #include "IEventReceiver.h" #include "IFileList.h" #include "IFileSystem.h" +#include "IGeometryCreator.h" #include "IGPUProgrammingServices.h" #include "IGUIButton.h" #include "IGUICheckBox.h" @@ -95,6 +96,7 @@ #include "IGUITable.h" #include "IGUIToolbar.h" #include "IGUIWindow.h" +#include "IGUITreeView.h" #include "IImage.h" #include "IImageLoader.h" #include "IImageWriter.h" @@ -124,6 +126,7 @@ #include "irrMath.h" #include "irrString.h" #include "irrTypes.h" +#include "path.h" #include "irrXML.h" #include "ISceneCollisionManager.h" #include "ISceneManager.h" @@ -150,6 +153,7 @@ #include "IWriteFile.h" #include "IXMLReader.h" #include "IXMLWriter.h" +#include "ILightManager.h" #include "Keycodes.h" #include "line2d.h" #include "line3d.h" @@ -180,7 +184,7 @@ #include "vector2d.h" #include "vector3d.h" -/*! \mainpage Irrlicht Engine 1.5 API documentation +/*! \mainpage Irrlicht Engine 1.7.2 API documentation * *
* @@ -222,7 +226,7 @@ * { * // start up the engine * IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D8, - * core::dimension2d(640,480)); + * core::dimension2d(640,480)); * * video::IVideoDriver* driver = device->getVideoDriver(); * scene::ISceneManager* scenemgr = device->getSceneManager(); @@ -259,15 +263,15 @@ * * Irrlicht can load a lot of file formats automaticly, see irr::scene::ISceneManager::getMesh() * for a detailed list. So if you would like to replace the simple blue screen background by - * a cool Quake 3 Map, optimized by an octtree, just insert this code + * a cool Quake 3 Map, optimized by an octree, just insert this code * somewhere before the while loop: * * \code * // add .pk3 archive to the file system * device->getFileSystem()->addZipFileArchive("quake3map.pk3"); * - * // load .bsp file and show it using an octtree - * scenemgr->addOctTreeSceneNode( + * // load .bsp file and show it using an octree + * scenemgr->addOctreeSceneNode( * scenemgr->getMesh("quake3map.bsp")); * \endcode * @@ -314,16 +318,27 @@ namespace irr \return Returns pointer to the created IrrlichtDevice or null if the device could not be created. */ - IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice( + extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice( video::E_DRIVER_TYPE deviceType = video::EDT_SOFTWARE, // parantheses are necessary for some compilers - const core::dimension2d& windowSize = (core::dimension2d(640,480)), + const core::dimension2d& windowSize = (core::dimension2d(640,480)), u32 bits = 16, bool fullscreen = false, bool stencilbuffer = false, bool vsync = false, IEventReceiver* receiver = 0); + //! typedef for Function Pointer + typedef IrrlichtDevice* (IRRCALLCONV *funcptr_createDevice )( + video::E_DRIVER_TYPE deviceType, + const core::dimension2d& windowSize, + u32 bits, + bool fullscreen, + bool stencilbuffer, + bool vsync, + IEventReceiver* receiver); + + //! Creates an Irrlicht device with the option to specify advanced parameters. /** Usually you should used createDevice() for creating an Irrlicht Engine device. Use this function only if you wish to specify advanced parameters like a window @@ -332,14 +347,17 @@ namespace irr See irr::SIrrlichtCreationParameters for details. \return Returns pointer to the created IrrlichtDevice or null if the device could not be created. */ - IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( + extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( const SIrrlichtCreationParameters& parameters); + //! typedef for Function Pointer + typedef IrrlichtDevice* (IRRCALLCONV *funcptr_createDeviceEx )( const SIrrlichtCreationParameters& parameters ); + // THE FOLLOWING IS AN EMPTY LIST OF ALL SUB NAMESPACES // EXISTING ONLY FOR THE DOCUMENTATION SOFTWARE DOXYGEN. - //! In this namespace can be found basic classes like vectors, planes, arrays, lists and so on. + //! Basic classes such as vectors, planes, arrays, lists, and so on can be found in this namespace. namespace core { } @@ -349,14 +367,12 @@ namespace irr { } - //! This namespace provides interfaces for input/output: Reading and - //! writing files, accessing zip archives, xml files, ... + //! This namespace provides interfaces for input/output: Reading and writing files, accessing zip archives, xml files, ... namespace io { } - //! All scene management can be found in this namespace: Mesh loading, - //! special scene nodes like octrees and billboards, ... + //! All scene management can be found in this namespace: Mesh loading, special scene nodes like octrees and billboards, ... namespace scene { } @@ -373,4 +389,3 @@ namespace irr #endif - diff --git a/src/dep/include/irrlicht/line2d.h b/src/dep/include/irrlicht/line2d.h index 1e1c5b6..648aae3 100644 --- a/src/dep/include/irrlicht/line2d.h +++ b/src/dep/include/irrlicht/line2d.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -65,7 +65,7 @@ class line2d //! Get the vector of the line. /** \return The vector of the line. */ - vector2d getVector() const { return vector2d(start.X - end.X, start.Y - end.Y); } + vector2d getVector() const { return vector2d(end.X - start.X, end.Y - start.Y); } //! Tests if this line intersects with another line. /** \param l: Other line to test intersection with. @@ -88,6 +88,7 @@ class line2d if(equals(commonDenominator, 0.f)) { // The lines are either coincident or parallel + // if both numerators are 0, the lines are coincident if(equals(numeratorA, 0.f) && equals(numeratorB, 0.f)) { // Try and find a common endpoint @@ -95,10 +96,52 @@ class line2d out = start; else if(l.end == end || l.start == end) out = end; + // now check if the two segments are disjunct + else if (l.start.X>start.X && l.end.X>start.X && l.start.X>end.X && l.end.X>end.X) + return false; + else if (l.start.Y>start.Y && l.end.Y>start.Y && l.start.Y>end.Y && l.end.Y>end.Y) + return false; + else if (l.start.X maxp; + vector2d minp; + if ((start.X>l.start.X && start.X>l.end.X && start.X>end.X) || (start.Y>l.start.Y && start.Y>l.end.Y && start.Y>end.Y)) + maxp=start; + else if ((end.X>l.start.X && end.X>l.end.X && end.X>start.X) || (end.Y>l.start.Y && end.Y>l.end.Y && end.Y>start.Y)) + maxp=end; + else if ((l.start.X>start.X && l.start.X>l.end.X && l.start.X>end.X) || (l.start.Y>start.Y && l.start.Y>l.end.Y && l.start.Y>end.Y)) + maxp=l.start; + else + maxp=l.end; + if (maxp != start && ((start.X(); + if (start != maxp && start != minp) + out += start; + if (end != maxp && end != minp) + out += end; + if (l.start != maxp && l.start != minp) + out += l.start; + if (l.end != maxp && l.end != minp) + out += l.end; + out *= 0.5f; + } return true; // coincident } diff --git a/src/dep/include/irrlicht/line3d.h b/src/dep/include/irrlicht/line3d.h index 6aff4f6..41919cf 100644 --- a/src/dep/include/irrlicht/line3d.h +++ b/src/dep/include/irrlicht/line3d.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -120,7 +120,7 @@ class line3d if (d < 0.0) return false; - outdistance = v - sqrt((f64)d); + outdistance = v - core::squareroot ( d ); return true; } diff --git a/src/dep/include/irrlicht/matrix4.h b/src/dep/include/irrlicht/matrix4.h index ef15f07..2df4472 100644 --- a/src/dep/include/irrlicht/matrix4.h +++ b/src/dep/include/irrlicht/matrix4.h @@ -1,11 +1,11 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_MATRIX_H_INCLUDED__ #define __IRR_MATRIX_H_INCLUDED__ -#include "irrTypes.h" +#include "irrMath.h" #include "vector3d.h" #include "vector2d.h" #include "plane3d.h" @@ -13,6 +13,28 @@ #include "rect.h" #include "irrString.h" +// enable this to keep track of changes to the matrix +// and make simpler identity check for seldomly changing matrices +// otherwise identity check will always compare the elements +//#define USE_MATRIX_TEST + +// this is only for debugging purposes +//#define USE_MATRIX_TEST_DEBUG + +#if defined( USE_MATRIX_TEST_DEBUG ) + #include + + struct MatrixTest + { + MatrixTest () : ID(0), Calls(0) {} + char buf[256]; + int Calls; + int ID; + }; + static MatrixTest MTest; + +#endif + namespace irr { namespace core @@ -45,13 +67,25 @@ namespace core CMatrix4( const CMatrix4& other,eConstructor constructor = EM4CONST_COPY); //! Simple operator for directly accessing every element of the matrix. - T& operator()(const s32 row, const s32 col) { definitelyIdentityMatrix=false; return M[ row * 4 + col ]; } + T& operator()(const s32 row, const s32 col) + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return M[ row * 4 + col ]; + } //! Simple operator for directly accessing every element of the matrix. const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; } //! Simple operator for linearly accessing every element of the matrix. - T& operator[](u32 index) { definitelyIdentityMatrix=false; return M[index]; } + T& operator[](u32 index) + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return M[index]; + } //! Simple operator for linearly accessing every element of the matrix. const T& operator[](u32 index) const { return M[index]; } @@ -64,7 +98,13 @@ namespace core //! Returns pointer to internal array const T* pointer() const { return M; } - T* pointer() { definitelyIdentityMatrix=false; return M; } + T* pointer() + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return M; + } //! Returns true if other matrix is equal to this matrix. bool operator==(const CMatrix4 &other) const; @@ -110,6 +150,9 @@ namespace core //! Returns true if the matrix is the identity matrix inline bool isIdentity() const; + //! Returns true if the matrix is orthogonal + inline bool isOrthogonal() const; + //! Returns true if the matrix is the identity matrix bool isIdentity_integer_base () const; @@ -247,7 +290,7 @@ namespace core CMatrix4& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f); //! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates. - /** Used to scale <-1,-1><1,1> to viewport, for example from von <-1,-1> <1,1> to the viewport <0,0><0,640> */ + /** Used to scale <-1,-1><1,1> to viewport, for example from <-1,-1> <1,1> to the viewport <0,0><0,640> */ CMatrix4& buildNDCToDCMatrix( const core::rect& area, f32 zScale); //! Creates a new matrix as interpolated matrix from two other ones. @@ -261,6 +304,31 @@ namespace core //! Gets transposed matrix inline void getTransposed( CMatrix4& dest ) const; + //! Builds a matrix that rotates from one vector to another + /** \param from: vector to rotate from + \param to: vector to rotate to + */ + CMatrix4& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to); + + //! Builds a combined matrix which translates to a center before rotation and translates from origin afterwards + /** \param center Position to rotate around + \param translate Translation applied after the rotation + */ + void setRotationCenter(const core::vector3df& center, const core::vector3df& translate); + + //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis + /** \param camPos: viewer position in world coo + \param center: object position in world-coo and rotation pivot + \param translation: object final translation from center + \param axis: axis to rotate about + \param from: source vector to rotate from + */ + void buildAxisAlignedBillboard(const core::vector3df& camPos, + const core::vector3df& center, + const core::vector3df& translation, + const core::vector3df& axis, + const core::vector3df& from); + /* construct 2D Texture transformations rotate about center, scale, and transform. @@ -315,16 +383,32 @@ namespace core //! Gets if the matrix is definitely identity matrix bool getDefinitelyIdentityMatrix() const; + //! Compare two matrices using the equal method + bool equals(const core::CMatrix4& other, const T tolerance=(T)ROUNDING_ERROR_f64) const; + private: //! Matrix data, stored in row-major order T M[16]; +#if defined ( USE_MATRIX_TEST ) //! Flag is this matrix is identity matrix - mutable bool definitelyIdentityMatrix; + mutable u32 definitelyIdentityMatrix; +#endif +#if defined ( USE_MATRIX_TEST_DEBUG ) + u32 id; + mutable u32 calls; +#endif + }; // Default constructor template - inline CMatrix4::CMatrix4( eConstructor constructor ) : definitelyIdentityMatrix(false) + inline CMatrix4::CMatrix4( eConstructor constructor ) +#if defined ( USE_MATRIX_TEST ) + : definitelyIdentityMatrix(BIT_UNTESTED) +#endif +#if defined ( USE_MATRIX_TEST_DEBUG ) + ,id ( MTest.ID++), calls ( 0 ) +#endif { switch ( constructor ) { @@ -341,7 +425,13 @@ namespace core // Copy constructor template - inline CMatrix4::CMatrix4( const CMatrix4& other, eConstructor constructor) : definitelyIdentityMatrix(false) + inline CMatrix4::CMatrix4( const CMatrix4& other, eConstructor constructor) +#if defined ( USE_MATRIX_TEST ) + : definitelyIdentityMatrix(BIT_UNTESTED) +#endif +#if defined ( USE_MATRIX_TEST_DEBUG ) + ,id ( MTest.ID++), calls ( 0 ) +#endif { switch ( constructor ) { @@ -523,6 +613,7 @@ namespace core template inline CMatrix4& CMatrix4::operator*=(const CMatrix4& other) { +#if defined ( USE_MATRIX_TEST ) // do checks on your own in order to avoid copy creation if ( !other.isIdentity() ) { @@ -537,6 +628,10 @@ namespace core } } return *this; +#else + CMatrix4 temp ( *this ); + return setbyproduct_nocheck( temp, other ); +#endif } //! multiply by another matrix @@ -567,7 +662,9 @@ namespace core M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15]; M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15]; M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15]; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -578,6 +675,7 @@ namespace core template inline CMatrix4& CMatrix4::setbyproduct(const CMatrix4& other_a, const CMatrix4& other_b ) { +#if defined ( USE_MATRIX_TEST ) if ( other_a.isIdentity () ) return (*this = other_b); else @@ -585,17 +683,22 @@ namespace core return (*this = other_a); else return setbyproduct_nocheck(other_a,other_b); +#else + return setbyproduct_nocheck(other_a,other_b); +#endif } //! multiply by another matrix template inline CMatrix4 CMatrix4::operator*(const CMatrix4& m2) const { +#if defined ( USE_MATRIX_TEST ) // Testing purpose.. if ( this->isIdentity() ) return m2; if ( m2.isIdentity() ) return *this; +#endif CMatrix4 m3 ( EM4CONST_NOTHING ); @@ -638,7 +741,9 @@ namespace core M[12] = translation.X; M[13] = translation.Y; M[14] = translation.Z; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -648,7 +753,9 @@ namespace core M[12] = -translation.X; M[13] = -translation.Y; M[14] = -translation.Z; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -658,14 +765,36 @@ namespace core M[0] = scale.X; M[5] = scale.Y; M[10] = scale.Z; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } + //! Returns the absolute values of the scales of the matrix. + /** + Note that this always returns the absolute (positive) values. Unfortunately it + does not appear to be possible to extract any original negative values. The best + that we could do would be to arbitrarily make one scale negative if one or three + of them were negative. + FIXME - return the original values. + */ template inline vector3d CMatrix4::getScale() const { - return vector3d(M[0],M[5],M[10]); + // See http://www.robertblum.com/articles/2005/02/14/decomposing-matrices + + // Deal with the 0 rotation case first + // Prior to Irrlicht 1.6, we always returned this value. + if(core::iszero(M[1]) && core::iszero(M[2]) && + core::iszero(M[4]) && core::iszero(M[6]) && + core::iszero(M[8]) && core::iszero(M[9])) + return vector3d(M[0], M[5], M[10]); + + // We have to do the full calculation. + return vector3d(sqrtf(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]), + sqrtf(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]), + sqrtf(M[8] * M[8] + M[9] * M[9] + M[10] * M[10])); } template @@ -704,7 +833,9 @@ namespace core M[8] = (T)( crsp*cy+sr*sy ); M[9] = (T)( crsp*sy-sr*cy ); M[10] = (T)( cr*cp ); +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -717,34 +848,36 @@ namespace core inline core::vector3d CMatrix4::getRotationDegrees() const { const CMatrix4 &mat = *this; + const core::vector3d scale = getScale(); + const core::vector3d invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z)); - f64 Y = -asin(mat(0,2)); + f64 Y = -asin(mat[2]*invScale.X); const f64 C = cos(Y); Y *= RADTODEG64; f64 rotx, roty, X, Z; - if (fabs(C)>ROUNDING_ERROR_64) + if (!core::iszero(C)) { - const T invC = (T)(1.0/C); - rotx = mat(2,2) * invC; - roty = mat(1,2) * invC; + const f64 invC = core::reciprocal(C); + rotx = mat[10] * invC * invScale.Z; + roty = mat[6] * invC * invScale.Y; X = atan2( roty, rotx ) * RADTODEG64; - rotx = mat(0,0) * invC; - roty = mat(0,1) * invC; + rotx = mat[0] * invC * invScale.X; + roty = mat[1] * invC * invScale.X; Z = atan2( roty, rotx ) * RADTODEG64; } else { X = 0.0; - rotx = mat(1,1); - roty = -mat(1,0); + rotx = mat[5] * invScale.Y; + roty = -mat[4] * invScale.Y; Z = atan2( roty, rotx ) * RADTODEG64; } // fix values that get below zero // before it would set (!) values to 360 - // that where above 360: + // that were above 360: if (X < 0.0) X += 360.0; if (Y < 0.0) Y += 360.0; if (Z < 0.0) Z += 360.0; @@ -777,7 +910,9 @@ namespace core M[2] = (T)( crsp*cy+sr*sy ); M[6] = (T)( crsp*sy-sr*cy ); M[10] = (T)( cr*cp ); +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -789,7 +924,9 @@ namespace core { memset(M, 0, 16*sizeof(T)); M[0] = M[5] = M[10] = M[15] = (T)1; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=true; +#endif return *this; } @@ -801,12 +938,14 @@ namespace core template inline bool CMatrix4::isIdentity() const { +#if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix) return true; - if (!equals( M[ 0], (T)1 ) || - !equals( M[ 5], (T)1 ) || - !equals( M[10], (T)1 ) || - !equals( M[15], (T)1 )) +#endif + if (!core::equals( M[ 0], (T)1 ) || + !core::equals( M[ 5], (T)1 ) || + !core::equals( M[10], (T)1 ) || + !core::equals( M[15], (T)1 )) return false; for (s32 i=0; i<4; ++i) @@ -814,10 +953,37 @@ namespace core if ((j != i) && (!iszero((*this)(i,j)))) return false; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=true; +#endif return true; } + + /* Check orthogonality of matrix. */ + template + inline bool CMatrix4::isOrthogonal() const + { + T dp=M[0] * M[4 ] + M[1] * M[5 ] + M[2 ] * M[6 ] + M[3 ] * M[7 ]; + if (!iszero(dp)) + return false; + dp = M[0] * M[8 ] + M[1] * M[9 ] + M[2 ] * M[10] + M[3 ] * M[11]; + if (!iszero(dp)) + return false; + dp = M[0] * M[12] + M[1] * M[13] + M[2 ] * M[14] + M[3 ] * M[15]; + if (!iszero(dp)) + return false; + dp = M[4] * M[8 ] + M[5] * M[9 ] + M[6 ] * M[10] + M[7 ] * M[11]; + if (!iszero(dp)) + return false; + dp = M[4] * M[12] + M[5] * M[13] + M[6 ] * M[14] + M[7 ] * M[15]; + if (!iszero(dp)) + return false; + dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15]; + return (iszero(dp)); + } + + /* doesn't solve floating range problems.. but takes care on +/- 0 on translation because we are changing it.. @@ -827,8 +993,10 @@ namespace core template inline bool CMatrix4::isIdentity_integer_base() const { +#if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix) return true; +#endif if(IR(M[0])!=F32_VALUE_1) return false; if(IR(M[1])!=0) return false; if(IR(M[2])!=0) return false; @@ -848,7 +1016,10 @@ namespace core if(IR(M[13])!=0) return false; if(IR(M[13])!=0) return false; if(IR(M[15])!=F32_VALUE_1) return false; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=true; +#endif return true; } @@ -927,25 +1098,14 @@ namespace core inline void CMatrix4::transformPlane( core::plane3d &plane) const { vector3df member; - // Fully transform the plane member point, i.e. rotate, translate and scale it. + // Transform the plane member point, i.e. rotate, translate and scale it. transformVect(member, plane.getMemberPoint()); + // Transform the normal by the transposed inverse of the matrix + CMatrix4 transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED); vector3df normal = plane.Normal; - normal.normalize(); + transposedInverse.transformVect(normal); - // The normal needs to be rotated and inverse scaled, but not translated. - const vector3df scale = getScale(); - - if(!equals(scale.X, 0.f) && !equals(scale.Y, 0.f) && !equals(scale.Z, 0.f) - && (!equals(scale.X, 1.f) || !equals(scale.Y, 1.f) || !equals(scale.Z, 1.f))) - { - // Rotating the vector will also apply the scale, so we have to invert it twice. - normal /= (scale * scale); - } - - rotateVect(normal); - - normal.normalize(); plane.setPlane(member, normal); } @@ -961,8 +1121,10 @@ namespace core template inline void CMatrix4::transformBox(core::aabbox3d& box) const { +#if defined ( USE_MATRIX_TEST ) if (isIdentity()) return; +#endif transformVect(box.MinEdge); transformVect(box.MaxEdge); @@ -973,6 +1135,11 @@ namespace core template inline void CMatrix4::transformBoxEx(core::aabbox3d& box) const { +#if defined ( USE_MATRIX_TEST ) + if (isIdentity()) + return; +#endif + const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z}; const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z}; @@ -1062,12 +1229,13 @@ namespace core /// The inverse is calculated using Cramers rule. /// If no inverse exists then 'false' is returned. +#if defined ( USE_MATRIX_TEST ) if ( this->isIdentity() ) { out=*this; return true; } - +#endif const CMatrix4 &m = *this; f32 d = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) - @@ -1130,7 +1298,10 @@ namespace core out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) + m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) + m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))); + +#if defined ( USE_MATRIX_TEST ) out.definitelyIdentityMatrix = definitelyIdentityMatrix; +#endif return true; } @@ -1159,7 +1330,10 @@ namespace core out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]); out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]); out.M[15] = 1; + +#if defined ( USE_MATRIX_TEST ) out.definitelyIdentityMatrix = definitelyIdentityMatrix; +#endif return true; } @@ -1168,9 +1342,10 @@ namespace core template inline bool CMatrix4::makeInverse() { +#if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix) return true; - +#endif CMatrix4 temp ( EM4CONST_NOTHING ); if (getInverse(temp)) @@ -1189,7 +1364,9 @@ namespace core if (this==&other) return *this; memcpy(M, other.M, 16*sizeof(T)); +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=other.definitelyIdentityMatrix; +#endif return *this; } @@ -1199,7 +1376,10 @@ namespace core { for (s32 i = 0; i < 16; ++i) M[i]=scalar; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1207,8 +1387,10 @@ namespace core template inline bool CMatrix4::operator==(const CMatrix4 &other) const { +#if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix && other.definitelyIdentityMatrix) return true; +#endif for (s32 i = 0; i < 16; ++i) if (M[i] != other.M[i]) return false; @@ -1229,9 +1411,11 @@ namespace core inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveFovRH( f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) { - const f64 h = 1.0/tan(fieldOfViewRadians/2.0); + const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); + _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero const T w = h / aspectRatio; + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = w; M[1] = 0; M[2] = 0; @@ -1253,7 +1437,10 @@ namespace core M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version // M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1263,9 +1450,11 @@ namespace core inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveFovLH( f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) { - const f64 h = 1.0/tan(fieldOfViewRadians/2.0); + const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); + _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero const T w = (T)(h / aspectRatio); + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = w; M[1] = 0; M[2] = 0; @@ -1285,7 +1474,10 @@ namespace core M[13] = 0; M[14] = (T)(-zNear*zFar/(zFar-zNear)); M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1295,6 +1487,9 @@ namespace core inline CMatrix4& CMatrix4::buildProjectionMatrixOrthoLH( f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) { + _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = (T)(2/widthOfViewVolume); M[1] = 0; M[2] = 0; @@ -1314,7 +1509,10 @@ namespace core M[13] = 0; M[14] = (T)(zNear/(zNear-zFar)); M[15] = 1; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1324,6 +1522,9 @@ namespace core inline CMatrix4& CMatrix4::buildProjectionMatrixOrthoRH( f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) { + _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = (T)(2/widthOfViewVolume); M[1] = 0; M[2] = 0; @@ -1343,7 +1544,10 @@ namespace core M[13] = 0; M[14] = (T)(zNear/(zNear-zFar)); M[15] = -1; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1353,6 +1557,9 @@ namespace core inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveRH( f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) { + _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = (T)(2*zNear/widthOfViewVolume); M[1] = 0; M[2] = 0; @@ -1372,7 +1579,10 @@ namespace core M[13] = 0; M[14] = (T)(zNear*zFar/(zNear-zFar)); M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1382,6 +1592,9 @@ namespace core inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveLH( f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) { + _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = (T)(2*zNear/widthOfViewVolume); M[1] = 0; M[2] = 0; @@ -1401,7 +1614,9 @@ namespace core M[13] = 0; M[14] = (T)(zNear*zFar/(zNear-zFar)); M[15] = 0; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1432,7 +1647,9 @@ namespace core M[13] = (T)(-plane.D * light.Y); M[14] = (T)(-plane.D * light.Z); M[15] = (T)(-plane.D * point + d); +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1470,7 +1687,9 @@ namespace core M[13] = (T)-yaxis.dotProduct(position); M[14] = (T)-zaxis.dotProduct(position); M[15] = 1; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1509,7 +1728,9 @@ namespace core M[13] = (T)-yaxis.dotProduct(position); M[14] = (T)-zaxis.dotProduct(position); M[15] = 1; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1564,7 +1785,9 @@ namespace core o[13] = M[ 7]; o[14] = M[11]; o[15] = M[15]; +#if defined ( USE_MATRIX_TEST ) o.definitelyIdentityMatrix=definitelyIdentityMatrix; +#endif } @@ -1572,11 +1795,11 @@ namespace core template inline CMatrix4& CMatrix4::buildNDCToDCMatrix( const core::rect& viewport, f32 zScale) { - const f32 scaleX = (viewport.getWidth() - 0.75f ) / 2.0f; - const f32 scaleY = -(viewport.getHeight() - 0.75f ) / 2.0f; + const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f; + const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f; - const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) / 2.0f ); - const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) / 2.0f ); + const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f ); + const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f ); makeIdentity(); M[12] = (T)dx; @@ -1584,6 +1807,137 @@ namespace core return setScale(core::vector3d((T)scaleX, (T)scaleY, (T)zScale)); } + //! Builds a matrix that rotates from one vector to another + /** \param from: vector to rotate from + \param to: vector to rotate to + + http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm + */ + template + inline CMatrix4& CMatrix4::buildRotateFromTo(const core::vector3df& from, const core::vector3df& to) + { + // unit vectors + core::vector3df f ( from ); + core::vector3df t ( to ); + f.normalize (); + t.normalize (); + + // axis multiplication by sin + core::vector3df vs ( t.crossProduct ( f ) ); + + // axis of rotation + core::vector3df v ( vs ); + v.normalize(); + + // cosinus angle + T ca = f.dotProduct ( t ); + + core::vector3df vt ( v * ( (T) 1 - ca ) ); + + M[0] = vt.X * v.X + ca; + M[5] = vt.Y * v.Y + ca; + M[10] = vt.Z * v.Z + ca; + + vt.X *= v.Y; + vt.Z *= v.X; + vt.Y *= v.Z; + + M[1] = vt.X - vs.Z; + M[2] = vt.Z + vs.Y; + M[3] = (T) 0; + + M[4] = vt.X + vs.Z; + M[6] = vt.Y - vs.X; + M[7] = (T) 0; + + M[8] = vt.Z - vs.Y; + M[9] = vt.Y + vs.X; + M[11] = (T) 0; + + M[12] = (T) 0; + M[13] = (T) 0; + M[14] = (T) 0; + M[15] = (T) 1; + + return *this; + } + + //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis + /** \param camPos: viewer position in world coo + \param center: object position in world-coo and rotation pivot + \param translation: object final translation from center + \param axis: axis to rotate about + \param from: source vector to rotate from + */ + template + inline void CMatrix4::buildAxisAlignedBillboard( const core::vector3df& camPos, + const core::vector3df& center, + const core::vector3df& translation, + const core::vector3df& axis, + const core::vector3df& from + ) + { + // axis of rotation + core::vector3df up = axis; + up.normalize (); + + core::vector3df forward = camPos - center; + forward.normalize(); + + core::vector3df right = up.crossProduct ( forward ); + right.normalize (); + + // correct look vector + core::vector3df look = right.crossProduct ( up ); + + // rotate from to + + // axis multiplication by sin + core::vector3df vs = look.crossProduct ( from ); + + // cosinus angle + f32 ca = from.dotProduct ( look ); + + core::vector3df vt ( up * ( 1.f - ca ) ); + + M[0] = vt.X * up.X + ca; + M[5] = vt.Y * up.Y + ca; + M[10] = vt.Z * up.Z + ca; + + vt.X *= up.Y; + vt.Z *= up.X; + vt.Y *= up.Z; + + M[1] = vt.X - vs.Z; + M[2] = vt.Z + vs.Y; + M[3] = (T) 0; + + M[4] = vt.X + vs.Z; + M[6] = vt.Y - vs.X; + M[7] = (T) 0; + + M[8] = vt.Z - vs.Y; + M[9] = vt.Y + vs.X; + M[11] = (T) 0; + + setRotationCenter ( center, translation ); + + } + + + //! Builds a combined matrix which translate to a center before rotation and translate afterwards + template + inline void CMatrix4::setRotationCenter(const core::vector3df& center, const core::vector3df& translation) + { + M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X ); + M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y ); + M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z ); + M[15] = (T) 1.0; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + } + /*! Generate texture coordinates as linear functions so that: u = Ux*x + Uy*y + Uz*z + Uw @@ -1624,7 +1978,9 @@ namespace core M[13] = 0; M[14] = 0; M[15] = 1; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1643,7 +1999,10 @@ namespace core M[8] = (T)(0.5f * ( s - c) + 0.5f); M[9] = (T)(-0.5f * ( s + c) + 0.5f); + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f); +#endif return *this; } @@ -1653,7 +2012,10 @@ namespace core { M[8] = (T)x; M[9] = (T)y; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f); +#endif return *this; } @@ -1663,7 +2025,10 @@ namespace core { M[2] = (T)x; M[6] = (T)y; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ; +#endif return *this; } @@ -1672,7 +2037,9 @@ namespace core { M[0] = (T)sx; M[5] = (T)sy; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); +#endif return *this; } @@ -1684,7 +2051,10 @@ namespace core M[5] = (T)sy; M[8] = (T)(0.5f - 0.5f * sx); M[9] = (T)(0.5f - 0.5f * sy); + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); +#endif return *this; } @@ -1695,7 +2065,9 @@ namespace core { memcpy(M,data, 16*sizeof(T)); - definitelyIdentityMatrix = false; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif return *this; } @@ -1704,7 +2076,9 @@ namespace core template inline void CMatrix4::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix) { +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = isDefinitelyIdentityMatrix; +#endif } @@ -1712,7 +2086,27 @@ namespace core template inline bool CMatrix4::getDefinitelyIdentityMatrix() const { +#if defined ( USE_MATRIX_TEST ) return definitelyIdentityMatrix; +#else + return false; +#endif + } + + + //! Compare two matrices using the equal method + template + inline bool CMatrix4::equals(const core::CMatrix4& other, const T tolerance) const + { +#if defined ( USE_MATRIX_TEST ) + if (definitelyIdentityMatrix && other.definitelyIdentityMatrix) + return true; +#endif + for (s32 i = 0; i < 16; ++i) + if (!core::equals(M[i],other.M[i], tolerance)) + return false; + + return true; } @@ -1726,6 +2120,7 @@ namespace core //! Typedef for f32 matrix typedef CMatrix4 matrix4; + //! global const identity matrix IRRLICHT_API extern const matrix4 IdentityMatrix; diff --git a/src/dep/include/irrlicht/path.h b/src/dep/include/irrlicht/path.h new file mode 100644 index 0000000..b64b055 --- /dev/null +++ b/src/dep/include/irrlicht/path.h @@ -0,0 +1,88 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_PATH_H_INCLUDED__ +#define __IRR_PATH_H_INCLUDED__ + +#include "irrString.h" + +namespace irr +{ +namespace io +{ + +//! Type used for all file system related strings. +/** This type will transparently handle different file system encodings. */ +typedef core::string path; + +//! Used in places where we identify objects by a filename, but don't actually work with the real filename +/** Irrlicht is internally not case-sensitive when it comes to names. + Also this class is a first step towards support for correctly serializing renamed objects. +*/ +struct SNamedPath +{ + //! Constructor + SNamedPath() {} + + //! Constructor + SNamedPath(const path& p) : Path(p), InternalName( PathToName(p) ) + { + } + + //! Is smaller comparator + bool operator <(const SNamedPath& other) const + { + return InternalName < other.InternalName; + } + + //! Set the path. + void setPath(const path& p) + { + Path = p; + InternalName = PathToName(p); + } + + //! Get the path. + const path& getPath() const + { + return Path; + }; + + //! Get the name which is used to identify the file. + //! This string is similar to the names and filenames used before Irrlicht 1.7 + const path& getInternalName() const + { + return InternalName; + } + + //! Implicit cast to io::path + operator core::stringc() const + { + return core::stringc(getPath()); + } + //! Implicit cast to io::path + operator core::stringw() const + { + return core::stringw(getPath()); + } + +protected: + // convert the given path string to a name string. + path PathToName(const path& p) const + { + path name(p); + name.replace( '\\', '/' ); + name.make_lower(); + return name; + } + +private: + path Path; + path InternalName; +}; + +} // io +} // irr + +#endif // __IRR_PATH_H_INCLUDED__ diff --git a/src/dep/include/irrlicht/plane3d.h b/src/dep/include/irrlicht/plane3d.h index 2c5aa60..7ad9a5c 100644 --- a/src/dep/include/irrlicht/plane3d.h +++ b/src/dep/include/irrlicht/plane3d.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -131,10 +131,10 @@ class plane3d { const T d = Normal.dotProduct(point) + D; - if (d < -ROUNDING_ERROR_32) + if (d < -ROUNDING_ERROR_f32) return ISREL3D_BACK; - if (d > ROUNDING_ERROR_32) + if (d > ROUNDING_ERROR_f32) return ISREL3D_FRONT; return ISREL3D_PLANAR; @@ -157,7 +157,7 @@ class plane3d bool existsIntersection(const plane3d& other) const { vector3d cross = other.Normal.crossProduct(Normal); - return cross.getLength() > core::ROUNDING_ERROR_32; + return cross.getLength() > core::ROUNDING_ERROR_f32; } //! Intersects this plane with another. @@ -174,7 +174,7 @@ class plane3d const T fn11 = other.Normal.getLength(); const f64 det = fn00*fn11 - fn01*fn01; - if (fabs(det) < ROUNDING_ERROR_64 ) + if (fabs(det) < ROUNDING_ERROR_f64 ) return false; const f64 invdet = 1.0 / det; @@ -221,6 +221,7 @@ class plane3d //! Normal vector of the plane. vector3d Normal; + //! Distance from origin. T D; }; @@ -228,6 +229,7 @@ class plane3d //! Typedef for a f32 3d plane. typedef plane3d plane3df; + //! Typedef for an integer 3d plane. typedef plane3d plane3di; diff --git a/src/dep/include/irrlicht/position2d.h b/src/dep/include/irrlicht/position2d.h index 6e8ec8b..c78620a 100644 --- a/src/dep/include/irrlicht/position2d.h +++ b/src/dep/include/irrlicht/position2d.h @@ -1,120 +1,32 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h +//! As of Irrlicht 1.6, position2d is a synonym for vector2d. +/** You should consider position2d to be deprecated, and use vector2d by preference. */ + #ifndef __IRR_POSITION_H_INCLUDED__ #define __IRR_POSITION_H_INCLUDED__ -#include "irrTypes.h" -#include "dimension2d.h" +#include "vector2d.h" namespace irr { namespace core { - //! Simple class for holding 2d coordinates. - /** Not supposed for doing geometric calculations. - use vector2d instead for things like that. - */ - template - class position2d - { - public: - //! Default constructor for (0,0). - position2d() : X(0), Y(0) {} - position2d(T x, T y) : X(x), Y(y) {} - position2d(const position2d& other) - : X(other.X), Y(other.Y) {} +// Use typedefs where possible as they are more explicit... - bool operator == (const position2d& other) const - { - return X == other.X && Y == other.Y; - } +//! \deprecated position2d is now a synonym for vector2d, but vector2d should be used directly. +typedef vector2d position2df; - bool operator != (const position2d& other) const - { - return X != other.X || Y != other.Y; - } +//! \deprecated position2d is now a synonym for vector2d, but vector2d should be used directly. +typedef vector2d position2di; +} // namespace core +} // namespace irr - const position2d& operator+=(const position2d& other) - { - X += other.X; - Y += other.Y; - return *this; - } +// ...and use a #define to catch the rest, for (e.g.) position2d +#define position2d vector2d - const position2d& operator-=(const position2d& other) - { - X -= other.X; - Y -= other.Y; - return *this; - } - - const position2d& operator+=(const dimension2d& other) - { - X += other.Width; - Y += other.Height; - return *this; - } - - const position2d& operator-=(const dimension2d& other) - { - X -= other.Width; - Y -= other.Height; - return *this; - } - - position2d operator-(const position2d& other) const - { - return position2d(X-other.X, Y-other.Y); - } - - position2d operator+(const position2d& other) const - { - return position2d(X+other.X, Y+other.Y); - } - - position2d operator*(const position2d& other) const - { - return position2d(X*other.X, Y*other.Y); - } - - position2d operator*(const T& scalar) const - { - return position2d(X*scalar, Y*scalar); - } - - position2d operator+(const dimension2d& other) const - { - return position2d(X+other.Width, Y+other.Height); - } - - position2d operator-(const dimension2d& other) const - { - return position2d(X-other.Width, Y-other.Height); - } - - const position2d& operator=(const position2d& other) - { - X = other.X; - Y = other.Y; - return *this; - } - - //! X coordinate of the position. - T X; - //! Y coordinate of the position. - T Y; - }; - - //! Typedef for an f32 position. - typedef position2d position2df; - //! Typedef for an integer position. - typedef position2d position2di; - -} // end namespace core -} // end namespace irr - -#endif +#endif // __IRR_POSITION_H_INCLUDED__ diff --git a/src/dep/include/irrlicht/quaternion.h b/src/dep/include/irrlicht/quaternion.h index e4040b6..af4da42 100644 --- a/src/dep/include/irrlicht/quaternion.h +++ b/src/dep/include/irrlicht/quaternion.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -40,6 +40,9 @@ class quaternion //! Equalilty operator bool operator==(const quaternion& other) const; + //! inequality operator + bool operator!=(const quaternion& other) const; + //! Assignment operator inline quaternion& operator=(const quaternion& other); @@ -76,6 +79,13 @@ class quaternion //! Sets new quaternion based on euler angles (radians) inline quaternion& set(const core::vector3df& vec); + //! Sets new quaternion from other quaternion + inline quaternion& set(const core::quaternion& quat); + + //! returns if this quaternion equals the other one, taking floating point rounding errors into account + inline bool equals(const quaternion& other, + const f32 tolerance = ROUNDING_ERROR_f32 ) const; + //! Normalizes the quaternion inline quaternion& normalize(); @@ -83,7 +93,26 @@ class quaternion matrix4 getMatrix() const; //! Creates a matrix from this quaternion - void getMatrix( matrix4 &dest ) const; + void getMatrix( matrix4 &dest, const core::vector3df &translation ) const; + + /*! + Creates a matrix from this quaternion + Rotate about a center point + shortcut for + core::quaternion q; + q.rotationFromTo ( vin[i].Normal, forward ); + q.getMatrixCenter ( lookat, center, newPos ); + + core::matrix4 m2; + m2.setInverseTranslation ( center ); + lookat *= m2; + + core::matrix4 m3; + m2.setTranslation ( newPos ); + lookat *= m3; + + */ + void getMatrixCenter( matrix4 &dest, const core::vector3df ¢er, const core::vector3df &translation ) const; //! Creates a matrix from this quaternion inline void getMatrix_transposed( matrix4 &dest ) const; @@ -115,7 +144,10 @@ class quaternion quaternion& rotationFromTo(const vector3df& from, const vector3df& to); //! Quaternion elements. - f32 X, Y, Z, W; + f32 X; // vectorial (imaginary) part + f32 Y; + f32 Z; + f32 W; // real part }; @@ -149,6 +181,11 @@ inline bool quaternion::operator==(const quaternion& other) const (W == other.W)); } +// inequality operator +inline bool quaternion::operator!=(const quaternion& other) const +{ + return !(*this == other); +} // assignment operator inline quaternion& quaternion::operator=(const quaternion& other) @@ -272,28 +309,73 @@ inline matrix4 quaternion::getMatrix() const } -// Creates a matrix from this quaternion -inline void quaternion::getMatrix( matrix4 &dest ) const +/*! + Creates a matrix from this quaternion +*/ +inline void quaternion::getMatrix( matrix4 &dest, const core::vector3df ¢er ) const { - dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; - dest[1] = 2.0f*X*Y + 2.0f*Z*W; - dest[2] = 2.0f*X*Z - 2.0f*Y*W; - dest[3] = 0.0f; + f32 * m = dest.pointer(); - dest[4] = 2.0f*X*Y - 2.0f*Z*W; - dest[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; - dest[6] = 2.0f*Z*Y + 2.0f*X*W; - dest[7] = 0.0f; + m[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; + m[1] = 2.0f*X*Y + 2.0f*Z*W; + m[2] = 2.0f*X*Z - 2.0f*Y*W; + m[3] = 0.0f; - dest[8] = 2.0f*X*Z + 2.0f*Y*W; - dest[9] = 2.0f*Z*Y - 2.0f*X*W; - dest[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; - dest[11] = 0.0f; + m[4] = 2.0f*X*Y - 2.0f*Z*W; + m[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; + m[6] = 2.0f*Z*Y + 2.0f*X*W; + m[7] = 0.0f; - dest[12] = 0.f; - dest[13] = 0.f; - dest[14] = 0.f; - dest[15] = 1.f; + m[8] = 2.0f*X*Z + 2.0f*Y*W; + m[9] = 2.0f*Z*Y - 2.0f*X*W; + m[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; + m[11] = 0.0f; + + m[12] = center.X; + m[13] = center.Y; + m[14] = center.Z; + m[15] = 1.f; + + //dest.setDefinitelyIdentityMatrix ( matrix4::BIT_IS_NOT_IDENTITY ); + dest.setDefinitelyIdentityMatrix ( false ); +} + + + +/*! + Creates a matrix from this quaternion + Rotate about a center point + shortcut for + core::quaternion q; + q.rotationFromTo ( vin[i].Normal, forward ); + q.getMatrix ( lookat, center ); + + core::matrix4 m2; + m2.setInverseTranslation ( center ); + lookat *= m2; +*/ +inline void quaternion::getMatrixCenter(matrix4 &dest, + const core::vector3df ¢er, + const core::vector3df &translation) const +{ + f32 * m = dest.pointer(); + + m[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; + m[1] = 2.0f*X*Y + 2.0f*Z*W; + m[2] = 2.0f*X*Z - 2.0f*Y*W; + m[3] = 0.0f; + + m[4] = 2.0f*X*Y - 2.0f*Z*W; + m[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; + m[6] = 2.0f*Z*Y + 2.0f*X*W; + m[7] = 0.0f; + + m[8] = 2.0f*X*Z + 2.0f*Y*W; + m[9] = 2.0f*Z*Y - 2.0f*X*W; + m[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; + m[11] = 0.0f; + + dest.setRotationCenter ( center, translation ); } // Creates a matrix from this quaternion @@ -318,6 +400,8 @@ inline void quaternion::getMatrix_transposed( matrix4 &dest ) const dest[7] = 0.f; dest[11] = 0.f; dest[15] = 1.f; + //dest.setDefinitelyIdentityMatrix ( matrix4::BIT_IS_NOT_IDENTITY ); + dest.setDefinitelyIdentityMatrix ( false ); } @@ -376,6 +460,23 @@ inline quaternion& quaternion::set(const core::vector3df& vec) return set(vec.X, vec.Y, vec.Z); } +// sets new quaternion based on other quaternion +inline quaternion& quaternion::set(const core::quaternion& quat) +{ + return (*this=quat); +} + + +//! returns if this quaternion equals the other one, taking floating point rounding errors into account +inline bool quaternion::equals(const quaternion& other, const f32 tolerance) const +{ + return core::equals(X, other.X, tolerance) && + core::equals(Y, other.Y, tolerance) && + core::equals(Z, other.Z, tolerance) && + core::equals(W, other.W, tolerance); +} + + // normalizes the quaternion inline quaternion& quaternion::normalize() { @@ -527,11 +628,21 @@ inline core::quaternion& quaternion::rotationFromTo(const vector3df& from, const { return makeIdentity(); } + else if (d <= -1.0f) // exactly opposite + { + core::vector3df axis(1.0f, 0.f, 0.f); + axis = axis.crossProduct(core::vector3df(X,Y,Z)); + if (axis.getLength()==0) + { + axis.set(0.f,1.f,0.f); + axis.crossProduct(core::vector3df(X,Y,Z)); + } + return this->fromAngleAxis(core::PI, axis); + } const f32 s = sqrtf( (1+d)*2 ); // optimize inv_sqrt const f32 invs = 1.f / s; const vector3df c = v0.crossProduct(v1)*invs; - X = c.X; Y = c.Y; Z = c.Z; diff --git a/src/dep/include/irrlicht/rect.h b/src/dep/include/irrlicht/rect.h index 43847c7..7de3ead 100644 --- a/src/dep/include/irrlicht/rect.h +++ b/src/dep/include/irrlicht/rect.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -27,24 +27,30 @@ namespace core { public: + //! Default constructor creating empty rectangle at (0,0) rect() : UpperLeftCorner(0,0), LowerRightCorner(0,0) {} + //! Constructor with two corners rect(T x, T y, T x2, T y2) : UpperLeftCorner(x,y), LowerRightCorner(x2,y2) {} + //! Constructor with two corners rect(const position2d& upperLeft, const position2d& lowerRight) : UpperLeftCorner(upperLeft), LowerRightCorner(lowerRight) {} - rect(const position2d& pos, const dimension2d& size) + //! Constructor with upper left corner and dimension + template + rect(const position2d& pos, const dimension2d& size) : UpperLeftCorner(pos), LowerRightCorner(pos.X + size.Width, pos.Y + size.Height) {} - + //! move right by given numbers rect operator+(const position2d& pos) const { rect ret(*this); return ret+=pos; } + //! move right by given numbers rect& operator+=(const position2d& pos) { UpperLeftCorner += pos; @@ -52,12 +58,14 @@ namespace core return *this; } + //! move left by given numbers rect operator-(const position2d& pos) const { rect ret(*this); return ret-=pos; } + //! move left by given numbers rect& operator-=(const position2d& pos) { UpperLeftCorner -= pos; @@ -65,20 +73,21 @@ namespace core return *this; } + //! equality operator bool operator==(const rect& other) const { return (UpperLeftCorner == other.UpperLeftCorner && LowerRightCorner == other.LowerRightCorner); } - + //! inequality operator bool operator!=(const rect& other) const { return (UpperLeftCorner != other.UpperLeftCorner || LowerRightCorner != other.LowerRightCorner); } - // compares size of rectangles + //! compares size of rectangles bool operator<(const rect& other) const { return getArea() < other.getArea(); @@ -101,7 +110,9 @@ namespace core LowerRightCorner.Y >= pos.Y); } - //! Returns if the rectangle collides with another rectangle. + //! Check if the rectangle collides with another rectangle. + /** \param other Rectangle to test collision with + \return True if the rectangles collide. */ bool isRectCollided(const rect& other) const { return (LowerRightCorner.Y > other.UpperLeftCorner.Y && @@ -111,6 +122,7 @@ namespace core } //! Clips this rectangle with another one. + /** \param other Rectangle to clip with */ void clipAgainst(const rect& other) { if (other.LowerRightCorner.X < LowerRightCorner.X) @@ -168,13 +180,13 @@ namespace core return true; } - //! Returns width of rectangle. + //! Get width of rectangle. T getWidth() const { return LowerRightCorner.X - UpperLeftCorner.X; } - //! Returns height of rectangle. + //! Get height of rectangle. T getHeight() const { return LowerRightCorner.Y - UpperLeftCorner.Y; @@ -207,7 +219,7 @@ namespace core (LowerRightCorner.Y >= UpperLeftCorner.Y)); } - //! Returns the center of the rectangle + //! Get the center of the rectangle position2d getCenter() const { return position2d( @@ -215,7 +227,7 @@ namespace core (UpperLeftCorner.Y + LowerRightCorner.Y) / 2); } - //! Returns the dimensions of the rectangle + //! Get the dimensions of the rectangle dimension2d getSize() const { return dimension2d(getWidth(), getHeight()); @@ -223,18 +235,19 @@ namespace core //! Adds a point to the rectangle - /** Cause the rectangle to grow bigger, if point is outside of + /** Causes the rectangle to grow bigger if point is outside of the box - \param p Point to add into the box. */ + \param p Point to add to the box. */ void addInternalPoint(const position2d& p) { addInternalPoint(p.X, p.Y); } //! Adds a point to the bounding rectangle - /** Cause the rectangle to grow bigger, if point is outside of - \param x X Coordinate of the point to add to this box. - \param y Y Coordinate of the point to add to this box. */ + /** Causes the rectangle to grow bigger if point is outside of + the box + \param x X-Coordinate of the point to add to this box. + \param y Y-Coordinate of the point to add to this box. */ void addInternalPoint(T x, T y) { if (x>LowerRightCorner.X) @@ -248,10 +261,16 @@ namespace core UpperLeftCorner.Y = y; } + //! Upper left corner position2d UpperLeftCorner; + //! Lower right corner position2d LowerRightCorner; }; + //! Rectangle with float values + typedef rect rectf; + //! Rectangle with int values + typedef rect recti; } // end namespace core } // end namespace irr diff --git a/src/dep/include/irrlicht/triangle3d.h b/src/dep/include/irrlicht/triangle3d.h index 9559383..05ce102 100644 --- a/src/dep/include/irrlicht/triangle3d.h +++ b/src/dep/include/irrlicht/triangle3d.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -48,6 +48,20 @@ namespace core box.isPointInside(pointC)); } + //! Determines if the triangle is totally outside a bounding box. + /** \param box Box to check. + \return True if triangle is outside the box, otherwise false. */ + bool isTotalOutsideBox(const aabbox3d& box) const + { + return ((pointA.X > box.MaxEdge.X && pointB.X > box.MaxEdge.X && pointC.X > box.MaxEdge.X) || + + (pointA.Y > box.MaxEdge.Y && pointB.Y > box.MaxEdge.Y && pointC.Y > box.MaxEdge.Y) || + (pointA.Z > box.MaxEdge.Z && pointB.Z > box.MaxEdge.Z && pointC.Z > box.MaxEdge.Z) || + (pointA.X < box.MinEdge.X && pointB.X < box.MinEdge.X && pointC.X < box.MinEdge.X) || + (pointA.Y < box.MinEdge.Y && pointB.Y < box.MinEdge.Y && pointC.Y < box.MinEdge.Y) || + (pointA.Z < box.MinEdge.Z && pointB.Z < box.MinEdge.Z && pointC.Z < box.MinEdge.Z)); + } + //! Get the closest point on a triangle to a point on the same plane. /** \param p Point which must be on the same plane as the triangle. \return The closest point of the triangle */ @@ -190,7 +204,7 @@ namespace core //! Get the area of the triangle T getArea() const { - return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5; + return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5f; } diff --git a/src/dep/include/irrlicht/vector2d.h b/src/dep/include/irrlicht/vector2d.h index 9f55626..175379d 100644 --- a/src/dep/include/irrlicht/vector2d.h +++ b/src/dep/include/irrlicht/vector2d.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,7 @@ #define __IRR_POINT_2D_H_INCLUDED__ #include "irrMath.h" +#include "dimension2d.h" namespace irr { @@ -14,6 +15,8 @@ namespace core //! 2d vector template class with lots of operators and methods. +/** As of Irrlicht 1.6, this class supercedes position2d, which should + be considered deprecated. */ template class vector2d { @@ -27,21 +30,29 @@ public: //! Copy constructor vector2d(const vector2d& other) : X(other.X), Y(other.Y) {} + vector2d(const dimension2d& other) : X(other.Width), Y(other.Height) {} + // operators vector2d operator-() const { return vector2d(-X, -Y); } vector2d& operator=(const vector2d& other) { X = other.X; Y = other.Y; return *this; } + vector2d& operator=(const dimension2d& other) { X = other.Width; Y = other.Height; return *this; } + vector2d operator+(const vector2d& other) const { return vector2d(X + other.X, Y + other.Y); } + vector2d operator+(const dimension2d& other) const { return vector2d(X + other.Width, Y + other.Height); } vector2d& operator+=(const vector2d& other) { X+=other.X; Y+=other.Y; return *this; } vector2d operator+(const T v) const { return vector2d(X + v, Y + v); } vector2d& operator+=(const T v) { X+=v; Y+=v; return *this; } + vector2d& operator+=(const dimension2d& other) { X += other.Width; Y += other.Height; return *this; } vector2d operator-(const vector2d& other) const { return vector2d(X - other.X, Y - other.Y); } + vector2d operator-(const dimension2d& other) const { return vector2d(X - other.Width, Y - other.Height); } vector2d& operator-=(const vector2d& other) { X-=other.X; Y-=other.Y; return *this; } vector2d operator-(const T v) const { return vector2d(X - v, Y - v); } vector2d& operator-=(const T v) { X-=v; Y-=v; return *this; } + vector2d& operator-=(const dimension2d& other) { X -= other.Width; Y -= other.Height; return *this; } vector2d operator*(const vector2d& other) const { return vector2d(X * other.X, Y * other.Y); } vector2d& operator*=(const vector2d& other) { X*=other.X; Y*=other.Y; return *this; } @@ -53,11 +64,33 @@ public: vector2d operator/(const T v) const { return vector2d(X / v, Y / v); } vector2d& operator/=(const T v) { X/=v; Y/=v; return *this; } - bool operator<=(const vector2d&other) const { return X<=other.X && Y<=other.Y; } - bool operator>=(const vector2d&other) const { return X>=other.X && Y>=other.Y; } + //! sort in order X, Y. Equality with rounding tolerance. + bool operator<=(const vector2d&other) const + { + return (X&other) const { return X(const vector2d&other) const { return X>other.X && Y>other.Y; } + //! sort in order X, Y. Equality with rounding tolerance. + bool operator>=(const vector2d&other) const + { + return (X>other.X || core::equals(X, other.X)) || + (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))); + } + + //! sort in order X, Y. Difference must be above rounding tolerance. + bool operator<(const vector2d&other) const + { + return (X(const vector2d&other) const + { + return (X>other.X && !core::equals(X, other.X)) || + (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)); + } bool operator==(const vector2d& other) const { return equals(other); } bool operator!=(const vector2d& other) const { return !equals(other); } @@ -78,7 +111,7 @@ public: //! Gets the length of the vector. /** \return The length of the vector. */ - T getLength() const { return (T)sqrt((f64)(X*X + Y*Y)); } + T getLength() const { return core::squareroot( X*X + Y*Y ); } //! Get the squared length of this vector /** This is useful because it is much faster than getLength(). @@ -146,31 +179,31 @@ public: } //! Calculates the angle of this vector in degrees in the trigonometric sense. - /** 0 is to the left (9 o'clock), values increase clockwise. + /** 0 is to the right (3 o'clock), values increase counter-clockwise. This method has been suggested by Pr3t3nd3r. \return Returns a value between 0 and 360. */ f64 getAngleTrig() const { - if (X == 0) - return Y < 0 ? 270 : 90; - else if (Y == 0) return X < 0 ? 180 : 0; + else + if (X == 0) + return Y < 0 ? 270 : 90; if ( Y > 0) if (X > 0) - return atan(Y/X) * RADTODEG64; + return atan((irr::f64)Y/(irr::f64)X) * RADTODEG64; else - return 180.0-atan(Y/-X) * RADTODEG64; + return 180.0-atan((irr::f64)Y/-(irr::f64)X) * RADTODEG64; else if (X > 0) - return 360.0-atan(-Y/X) * RADTODEG64; + return 360.0-atan(-(irr::f64)Y/(irr::f64)X) * RADTODEG64; else - return 180.0+atan(-Y/-X) * RADTODEG64; + return 180.0+atan(-(irr::f64)Y/-(irr::f64)X) * RADTODEG64; } //! Calculates the angle of this vector in degrees in the counter trigonometric sense. - /** 0 is to the right (3 o'clock), values increase counter-clockwise. + /** 0 is to the right (3 o'clock), values increase clockwise. \return Returns a value between 0 and 360. */ inline f64 getAngle() const { @@ -179,8 +212,9 @@ public: else if (X == 0) return Y < 0 ? 90 : 270; - f64 tmp = Y / getLength(); - tmp = atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64; + // don't use getLength here to avoid precision loss with s32 vectors + f64 tmp = Y / sqrt((f64)(X*X + Y*Y)); + tmp = atan( core::squareroot(1 - tmp*tmp) / tmp) * RADTODEG64; if (X>0 && Y>0) return tmp + 270; @@ -207,7 +241,7 @@ public: if (tmp == 0.0) return 90.0; - tmp = tmp / sqrt((f64)((X*X + Y*Y) * (b.X*b.X + b.Y*b.Y))); + tmp = tmp / core::squareroot((f64)((X*X + Y*Y) * (b.X*b.X + b.Y*b.Y))); if (tmp < 0.0) tmp = -tmp; @@ -277,18 +311,27 @@ public: //! X coordinate of vector. T X; + //! Y coordinate of vector. T Y; }; //! Typedef for f32 2d vector. typedef vector2d vector2df; + //! Typedef for integer 2d vector. typedef vector2d vector2di; template vector2d operator*(const S scalar, const vector2d& vector) { return vector*scalar; } + // These methods are declared in dimension2d, but need definitions of vector2d + template + dimension2d::dimension2d(const vector2d& other) : Width(other.X), Height(other.Y) { } + + template + bool dimension2d::operator==(const vector2d& other) const { return Width == other.X && Height == other.Y; } + } // end namespace core } // end namespace irr diff --git a/src/dep/include/irrlicht/vector3d.h b/src/dep/include/irrlicht/vector3d.h index 1cc026c..0062137 100644 --- a/src/dep/include/irrlicht/vector3d.h +++ b/src/dep/include/irrlicht/vector3d.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -13,7 +13,7 @@ namespace core { //! 3d vector template class with lots of operators and methods. - /** The vector3d class is used in Irrlicht for three main purposes: + /** 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. @@ -57,10 +57,37 @@ namespace core vector3d operator/(const T v) const { T i=(T)1.0/v; return vector3d(X * i, Y * i, Z * i); } vector3d& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; } - bool operator<=(const vector3d&other) const { return X<=other.X && Y<=other.Y && Z<=other.Z;} - bool operator>=(const vector3d&other) const { return X>=other.X && Y>=other.Y && Z>=other.Z;} - bool operator<(const vector3d&other) const { return X(const vector3d&other) const { return X>other.X && Y>other.Y && Z>other.Z;} + //! sort in order X, Y, Z. Equality with rounding tolerance. + bool operator<=(const vector3d&other) const + { + return (X=(const vector3d&other) const + { + return (X>other.X || core::equals(X, other.X)) || + (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))) || + (core::equals(X, other.X) && core::equals(Y, other.Y) && (Z>other.Z || core::equals(Z, other.Z))); + } + + //! sort in order X, Y, Z. Difference must be above rounding tolerance. + bool operator<(const vector3d&other) const + { + return (X(const vector3d&other) const + { + return (X>other.X && !core::equals(X, other.X)) || + (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)) || + (core::equals(X, other.X) && core::equals(Y, other.Y) && Z>other.Z && !core::equals(Z, other.Z)); + } //! use weak float compare bool operator==(const vector3d& other) const @@ -76,7 +103,7 @@ namespace core // functions //! returns if this vector equals the other one, taking floating point rounding errors into account - bool equals(const vector3d& other, const T tolerance = (T)ROUNDING_ERROR_32 ) const + bool equals(const vector3d& other, const T tolerance = (T)ROUNDING_ERROR_f32 ) const { return core::equals(X, other.X, tolerance) && core::equals(Y, other.Y, tolerance) && @@ -87,7 +114,7 @@ namespace core vector3d& set(const vector3d& p) {X=p.X; Y=p.Y; Z=p.Z;return *this;} //! Get length of the vector. - T getLength() const { return (T) sqrt((f64)(X*X + Y*Y + Z*Z)); } + T getLength() const { return core::squareroot( X*X + Y*Y + Z*Z ); } //! Get squared length of the vector. /** This is useful because it is much faster than getLength(). @@ -140,10 +167,11 @@ namespace core \return Reference to this vector after normalization. */ vector3d& normalize() { - f32 length = (f32)(X*X + Y*Y + Z*Z); - if (core::equals(length, 0.f)) + f64 length = X*X + Y*Y + Z*Z; + if (core::equals(length, 0.0)) // this check isn't an optimization but prevents getting NAN in the sqrt. return *this; - length = core::reciprocal_squareroot ( (f32)length ); + length = core::reciprocal_squareroot(length); + X = (T)(X * length); Y = (T)(Y * length); Z = (T)(Z * length); @@ -160,9 +188,9 @@ namespace core //! Inverts the vector. vector3d& invert() { - X *= -1.0f; - Y *= -1.0f; - Z *= -1.0f; + X *= -1; + Y *= -1; + Z *= -1; return *this; } @@ -265,41 +293,66 @@ namespace core // Where target and seeker are of type ISceneNode* const vector3df toTarget(target->getAbsolutePosition() - seeker->getAbsolutePosition()); const vector3df requiredRotation = toTarget.getHorizontalAngle(); - seeker->setRotation(requiredRotation); + 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 + \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; - angle.Y = (T)(atan2(X, Z) * RADTODEG64); + const f64 tmp = (atan2((f64)X, (f64)Z) * RADTODEG64); + angle.Y = (T)tmp; - if (angle.Y < 0.0f) - angle.Y += 360.0f; - if (angle.Y >= 360.0f) - angle.Y -= 360.0f; + if (angle.Y < 0) + angle.Y += 360; + if (angle.Y >= 360) + angle.Y -= 360; - const f64 z1 = sqrt(X*X + Z*Z); + const f64 z1 = core::squareroot(X*X + Z*Z); - angle.X = (T)(atan2(z1, (f64)Y) * RADTODEG64 - 90.0); + angle.X = (T)(atan2((f64)z1, (f64)Y) * RADTODEG64 - 90.0); - if (angle.X < 0.0f) - angle.X += 360.0f; - if (angle.X >= 360.0f) - angle.X -= 360.0f; + if (angle.X < 0) + angle.X += 360; + if (angle.X >= 360) + angle.X -= 360; return angle; } + //! Get the spherical coordinate angles + /** This returns Euler degrees for the point represented by + this vector. The calculation assumes the pole at (0,1,0) and + returns the angles in X and Y. + */ + vector3d getSphericalCoordinateAngles() + { + vector3d angle; + const f64 length = X*X + Y*Y + Z*Z; + + if (length) + { + if (X!=0) + { + angle.Y = (T)(atan2((f64)Z,(f64)X) * RADTODEG64); + } + else if (Z<0) + angle.Y=180; + + angle.X = (T)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64); + } + return angle; + } + //! Builds a direction vector from (this) rotation vector. /** 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. + \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 + \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 { @@ -343,15 +396,24 @@ namespace core //! X coordinate of the vector T X; + //! Y coordinate of the vector T Y; + //! Z coordinate of the vector T Z; }; + //! partial specialization for integer vectors + // Implementor note: inline keyword needed due to template specialization for s32. Otherwise put specialization into a .cpp + template <> + inline vector3d vector3d::operator /(s32 val) const {return core::vector3d(X/val,Y/val,Z/val);} + template <> + inline vector3d& vector3d::operator /=(s32 val) {X/=val;Y/=val;Z/=val; return *this;} //! Typedef for a f32 3d vector. typedef vector3d vector3df; + //! Typedef for an integer 3d vector. typedef vector3d vector3di; diff --git a/src/dep/src/irrlicht/BuiltInFont.h b/src/dep/src/irrlicht/BuiltInFont.h index 551d1f8..68a32e4 100644 --- a/src/dep/src/irrlicht/BuiltInFont.h +++ b/src/dep/src/irrlicht/BuiltInFont.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/C3DSMeshFileLoader.cpp b/src/dep/src/irrlicht/C3DSMeshFileLoader.cpp index f5fedff..dcc3a9c 100644 --- a/src/dep/src/irrlicht/C3DSMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/C3DSMeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,97 +23,105 @@ namespace scene { -// Primary chunk -const u16 C3DS_MAIN3DS = 0x4D4D; +namespace +{ +enum e3DSChunk +{ + // Primary chunk + C3DS_MAIN3DS = 0x4D4D, -// Main Chunks -const u16 C3DS_EDIT3DS = 0x3D3D; -const u16 C3DS_KEYF3DS = 0xB000; -const u16 C3DS_VERSION = 0x0002; -const u16 C3DS_MESHVERSION = 0x3D3E; + // Main Chunks + C3DS_EDIT3DS = 0x3D3D, + C3DS_KEYF3DS = 0xB000, + C3DS_VERSION = 0x0002, + C3DS_MESHVERSION = 0x3D3E, -// sub chunks of C3DS_EDIT3DS -const u16 C3DS_EDIT_MATERIAL = 0xAFFF; -const u16 C3DS_EDIT_OBJECT = 0x4000; + // sub chunks of C3DS_EDIT3DS + C3DS_EDIT_MATERIAL = 0xAFFF, + C3DS_EDIT_OBJECT = 0x4000, -// sub chunks of C3DS_EDIT_MATERIAL -const u16 C3DS_MATNAME = 0xA000; -const u16 C3DS_MATAMBIENT = 0xA010; -const u16 C3DS_MATDIFFUSE = 0xA020; -const u16 C3DS_MATSPECULAR = 0xA030; -const u16 C3DS_MATSHININESS = 0xA040; -const u16 C3DS_MATSHIN2PCT = 0xA041; -const u16 C3DS_TRANSPARENCY = 0xA050; -const u16 C3DS_TRANSPARENCY_FALLOFF = 0xA052; -const u16 C3DS_REFL_BLUR = 0xA053; -const u16 C3DS_TWO_SIDE = 0xA081; -const u16 C3DS_WIRE = 0xA085; -const u16 C3DS_SHADING = 0xA100; -const u16 C3DS_MATTEXMAP = 0xA200; -const u16 C3DS_MATSPECMAP = 0xA204; -const u16 C3DS_MATOPACMAP = 0xA210; -const u16 C3DS_MATREFLMAP = 0xA220; -const u16 C3DS_MATBUMPMAP = 0xA230; -const u16 C3DS_MATMAPFILE = 0xA300; -const u16 C3DS_MAT_TEXTILING = 0xA351; -const u16 C3DS_MAT_USCALE = 0xA354; -const u16 C3DS_MAT_VSCALE = 0xA356; -const u16 C3DS_MAT_UOFFSET = 0xA358; -const u16 C3DS_MAT_VOFFSET = 0xA35A; + // sub chunks of C3DS_EDIT_MATERIAL + C3DS_MATNAME = 0xA000, + C3DS_MATAMBIENT = 0xA010, + C3DS_MATDIFFUSE = 0xA020, + C3DS_MATSPECULAR = 0xA030, + C3DS_MATSHININESS = 0xA040, + C3DS_MATSHIN2PCT = 0xA041, + C3DS_TRANSPARENCY = 0xA050, + C3DS_TRANSPARENCY_FALLOFF = 0xA052, + C3DS_REFL_BLUR = 0xA053, + C3DS_TWO_SIDE = 0xA081, + C3DS_WIRE = 0xA085, + C3DS_SHADING = 0xA100, + C3DS_MATTEXMAP = 0xA200, + C3DS_MATSPECMAP = 0xA204, + C3DS_MATOPACMAP = 0xA210, + C3DS_MATREFLMAP = 0xA220, + C3DS_MATBUMPMAP = 0xA230, + C3DS_MATMAPFILE = 0xA300, + C3DS_MAT_TEXTILING = 0xA351, + C3DS_MAT_USCALE = 0xA354, + C3DS_MAT_VSCALE = 0xA356, + C3DS_MAT_UOFFSET = 0xA358, + C3DS_MAT_VOFFSET = 0xA35A, -// subs of C3DS_EDIT_OBJECT -const u16 C3DS_OBJTRIMESH = 0x4100; + // subs of C3DS_EDIT_OBJECT + C3DS_OBJTRIMESH = 0x4100, -// subs of C3DS_OBJTRIMESH -const u16 C3DS_TRIVERT = 0x4110; -const u16 C3DS_POINTFLAGARRAY= 0x4111; -const u16 C3DS_TRIFACE = 0x4120; -const u16 C3DS_TRIFACEMAT = 0x4130; -const u16 C3DS_TRIUV = 0x4140; -const u16 C3DS_TRISMOOTH = 0x4150; -const u16 C3DS_TRIMATRIX = 0x4160; -const u16 C3DS_MESHCOLOR = 0x4165; -const u16 C3DS_DIRECT_LIGHT = 0x4600; -const u16 C3DS_DL_INNER_RANGE= 0x4659; -const u16 C3DS_DL_OUTER_RANGE= 0x465A; -const u16 C3DS_DL_MULTIPLIER = 0x465B; -const u16 C3DS_CAMERA = 0x4700; -const u16 C3DS_CAM_SEE_CONE = 0x4710; -const u16 C3DS_CAM_RANGES = 0x4720; + // subs of C3DS_OBJTRIMESH + C3DS_TRIVERT = 0x4110, + C3DS_POINTFLAGARRAY= 0x4111, + C3DS_TRIFACE = 0x4120, + C3DS_TRIFACEMAT = 0x4130, + C3DS_TRIUV = 0x4140, + C3DS_TRISMOOTH = 0x4150, + C3DS_TRIMATRIX = 0x4160, + C3DS_MESHCOLOR = 0x4165, + C3DS_DIRECT_LIGHT = 0x4600, + C3DS_DL_INNER_RANGE= 0x4659, + C3DS_DL_OUTER_RANGE= 0x465A, + C3DS_DL_MULTIPLIER = 0x465B, + C3DS_CAMERA = 0x4700, + C3DS_CAM_SEE_CONE = 0x4710, + C3DS_CAM_RANGES = 0x4720, -// subs of C3DS_KEYF3DS -const u16 C3DS_KF_HDR = 0xB00A; -const u16 C3DS_AMBIENT_TAG = 0xB001; -const u16 C3DS_OBJECT_TAG = 0xB002; -const u16 C3DS_CAMERA_TAG = 0xB003; -const u16 C3DS_TARGET_TAG = 0xB004; -const u16 C3DS_LIGHTNODE_TAG = 0xB005; -const u16 C3DS_KF_SEG = 0xB008; -const u16 C3DS_KF_CURTIME = 0xB009; -const u16 C3DS_KF_NODE_HDR = 0xB010; -const u16 C3DS_PIVOTPOINT = 0xB013; -const u16 C3DS_BOUNDBOX = 0xB014; -const u16 C3DS_MORPH_SMOOTH = 0xB015; -const u16 C3DS_POS_TRACK_TAG = 0xB020; -const u16 C3DS_ROT_TRACK_TAG = 0xB021; -const u16 C3DS_SCL_TRACK_TAG = 0xB022; -const u16 C3DS_NODE_ID = 0xB030; + // subs of C3DS_KEYF3DS + C3DS_KF_HDR = 0xB00A, + C3DS_AMBIENT_TAG = 0xB001, + C3DS_OBJECT_TAG = 0xB002, + C3DS_CAMERA_TAG = 0xB003, + C3DS_TARGET_TAG = 0xB004, + C3DS_LIGHTNODE_TAG = 0xB005, + C3DS_KF_SEG = 0xB008, + C3DS_KF_CURTIME = 0xB009, + C3DS_KF_NODE_HDR = 0xB010, + C3DS_PIVOTPOINT = 0xB013, + C3DS_BOUNDBOX = 0xB014, + C3DS_MORPH_SMOOTH = 0xB015, + C3DS_POS_TRACK_TAG = 0xB020, + C3DS_ROT_TRACK_TAG = 0xB021, + C3DS_SCL_TRACK_TAG = 0xB022, + C3DS_NODE_ID = 0xB030, -// Viewport definitions -const u16 C3DS_VIEWPORT_LAYOUT = 0x7001; -const u16 C3DS_VIEWPORT_DATA = 0x7011; -const u16 C3DS_VIEWPORT_DATA_3 = 0x7012; -const u16 C3DS_VIEWPORT_SIZE = 0x7020; + // Viewport definitions + C3DS_VIEWPORT_LAYOUT = 0x7001, + C3DS_VIEWPORT_DATA = 0x7011, + C3DS_VIEWPORT_DATA_3 = 0x7012, + C3DS_VIEWPORT_SIZE = 0x7020, -// different color chunk types -const u16 C3DS_COL_RGB = 0x0010; -const u16 C3DS_COL_TRU = 0x0011; -const u16 C3DS_COL_LIN_24 = 0x0012; -const u16 C3DS_COL_LIN_F = 0x0013; + // different color chunk types + C3DS_COL_RGB = 0x0010, + C3DS_COL_TRU = 0x0011, + C3DS_COL_LIN_24 = 0x0012, + C3DS_COL_LIN_F = 0x0013, -// percentage chunk types -const u16 C3DS_PERCENTAGE_I = 0x0030; -const u16 C3DS_PERCENTAGE_F = 0x0031; + // percentage chunk types + C3DS_PERCENTAGE_I = 0x0030, + C3DS_PERCENTAGE_F = 0x0031, + + C3DS_CHUNK_MAX = 0xFFFF +}; +} //! Constructor @@ -147,9 +155,9 @@ C3DSMeshFileLoader::~C3DSMeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool C3DSMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool C3DSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".3ds")!=0; + return core::hasFileExtension ( filename, "3ds" ); } @@ -296,7 +304,7 @@ bool C3DSMeshFileLoader::readColorChunk(io::IReadFile* file, ChunkData* chunk, { // read 8 bit data file->read(c, sizeof(c)); - out.set(255, c[0], c[1], c[2]); + out.set(255, c[0], c[1], c[2]); data.read += sizeof(c); } break; @@ -310,7 +318,7 @@ bool C3DSMeshFileLoader::readColorChunk(io::IReadFile* file, ChunkData* chunk, cf[1] = os::Byteswap::byteswap(cf[1]); cf[2] = os::Byteswap::byteswap(cf[2]); #endif - out.set(255, (s32)(cf[0]*255.0f), (s32)(cf[1]*255.0f), (s32)(cf[2]*255.0f)); + out.set(255, (s32)(cf[0]*255.0f), (s32)(cf[1]*255.0f), (s32)(cf[2]*255.0f)); data.read += sizeof(cf); } break; @@ -366,6 +374,7 @@ bool C3DSMeshFileLoader::readMaterialChunk(io::IReadFile* file, ChunkData* paren break; case C3DS_MATSHININESS: readPercentageChunk(file, &data, CurrentMaterial.Material.Shininess); + CurrentMaterial.Material.Shininess = (1.f-CurrentMaterial.Material.Shininess)*128.f; break; case C3DS_TRANSPARENCY: { @@ -907,7 +916,7 @@ bool C3DSMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData* parent) readObjectChunk(file, &data); break; - case C3DS_TRIVERT: + case C3DS_TRIVERT: readVertices(file, data); break; @@ -929,12 +938,12 @@ bool C3DSMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData* parent) } break; - case C3DS_TRIFACE: + case C3DS_TRIFACE: readIndices(file, data); readObjectChunk(file, &data); // read smooth and material groups break; - case C3DS_TRIFACEMAT: + case C3DS_TRIFACEMAT: readMaterialGroup(file, data); break; @@ -1059,7 +1068,7 @@ void C3DSMeshFileLoader::composeObject(io::IReadFile* file, const core::stringc& { u32 vtxCount = mb->Vertices.size(); if (vtxCount>maxPrimitives) - { + { IMeshBuffer* tmp = mb; mb = new SMeshBuffer(); Mesh->addMeshBuffer(mb); @@ -1133,13 +1142,13 @@ void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) if (Materials[i].Filename[0].size()) { video::ITexture* texture = 0; - if (FileSystem->existFile(Materials[i].Filename[0].c_str())) - texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[0].c_str()); + if (FileSystem->existFile(Materials[i].Filename[0])) + texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[0]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[0]); - if (FileSystem->existFile(fname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(fname.c_str()); + if (FileSystem->existFile(fname)) + texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) os::Printer::log("Could not load a texture for entry in 3ds file", @@ -1151,13 +1160,13 @@ void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) if (Materials[i].Filename[2].size()) { video::ITexture* texture = 0; - if (FileSystem->existFile(Materials[i].Filename[2].c_str())) - texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[2].c_str()); + if (FileSystem->existFile(Materials[i].Filename[2])) + texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[2]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[2]); - if (FileSystem->existFile(fname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(fname.c_str()); + if (FileSystem->existFile(fname)) + texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) { @@ -1174,13 +1183,13 @@ void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) if (Materials[i].Filename[3].size()) { video::ITexture* texture = 0; - if (FileSystem->existFile(Materials[i].Filename[3].c_str())) - texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[3].c_str()); + if (FileSystem->existFile(Materials[i].Filename[3])) + texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[3]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[3]); - if (FileSystem->existFile(fname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(fname.c_str()); + if (FileSystem->existFile(fname)) + texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) @@ -1199,13 +1208,13 @@ void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) if (Materials[i].Filename[4].size()) { video::ITexture* texture = 0; - if (FileSystem->existFile(Materials[i].Filename[4].c_str())) - texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[4].c_str()); + if (FileSystem->existFile(Materials[i].Filename[4])) + texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[4]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[4]); - if (FileSystem->existFile(fname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(fname.c_str()); + if (FileSystem->existFile(fname)) + texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) os::Printer::log("Could not load a texture for entry in 3ds file", @@ -1334,18 +1343,19 @@ void C3DSMeshFileLoader::readVertices(io::IReadFile* file, ChunkData& data) #endif data.read += sizeof(CountVertices); - s32 vertexBufferByteSize = CountVertices * sizeof(f32) * 3; + const s32 vertexBufferByteSize = CountVertices * sizeof(f32) * 3; if (data.header.length - data.read != vertexBufferByteSize) { - os::Printer::log("Invalid size of vertices found in 3ds file.", ELL_WARNING); + os::Printer::log("Invalid size of vertices found in 3ds file", core::stringc(CountVertices), ELL_ERROR); return; } Vertices = new f32[CountVertices * 3]; file->read(Vertices, vertexBufferByteSize); #ifdef __BIG_ENDIAN__ - for (int i=0;idrop(); } - //! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. u32 CAnimatedMeshMD2::getFrameCount() const { @@ -342,7 +262,7 @@ IMesh* CAnimatedMeshMD2::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, } -//! returns amount of mesh buffers. +//! returns amount of mesh buffers. MD2 meshes only have one buffer u32 CAnimatedMeshMD2::getMeshBufferCount() const { return 1; @@ -352,7 +272,10 @@ u32 CAnimatedMeshMD2::getMeshBufferCount() const //! returns pointer to a mesh buffer IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(u32 nr) const { - return InterpolationBuffer; + if (nr == 0) + return InterpolationBuffer; + else + return 0; } @@ -371,6 +294,7 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop, { u32 firstFrame, secondFrame; f32 div; + core::vector3df* NormalTable = (core::vector3df*)&Q2_VERTEX_NORMAL_TABLE; // TA: resolve missing ipol in loop between end-start @@ -398,16 +322,24 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop, } video::S3DVertex* target = static_cast(InterpolationBuffer->getVertices()); - video::S3DVertex* first = FrameList[firstFrame].pointer(); - video::S3DVertex* second = FrameList[secondFrame].pointer(); + SMD2Vert* first = FrameList[firstFrame].pointer(); + SMD2Vert* second = FrameList[secondFrame].pointer(); // interpolate both frames const u32 count = FrameList[firstFrame].size(); for (u32 i=0; iPos = (second->Pos - first->Pos) * div + first->Pos; - target->Normal = (second->Normal - first->Normal) * div + first->Normal; + core::vector3df one, two; + one.X = f32(first->Pos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X; + one.Y = f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y; + one.Z = f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z; + two.X = f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X; + two.Y = f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y; + two.Z = f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z; + target->Pos = (two - one) * div + one; + target->Normal = (NormalTable[second->NormalIdx] - NormalTable[first->NormalIdx]) * div + + NormalTable[first->NormalIdx]; ++target; ++first; ++second; @@ -419,259 +351,6 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop, } -//! loads an md2 file -bool CAnimatedMeshMD2::loadFile(io::IReadFile* file) -{ - if (!file) - return false; - - SMD2Header header; - - file->read(&header, sizeof(SMD2Header)); - -#ifdef __BIG_ENDIAN__ - header.magic = os::Byteswap::byteswap(header.magic); - header.version = os::Byteswap::byteswap(header.version); - header.skinWidth = os::Byteswap::byteswap(header.skinWidth); - header.skinHeight = os::Byteswap::byteswap(header.skinHeight); - header.frameSize = os::Byteswap::byteswap(header.frameSize); - header.numSkins = os::Byteswap::byteswap(header.numSkins); - header.numVertices = os::Byteswap::byteswap(header.numVertices); - header.numTexcoords = os::Byteswap::byteswap(header.numTexcoords); - header.numTriangles = os::Byteswap::byteswap(header.numTriangles); - header.numGlCommands = os::Byteswap::byteswap(header.numGlCommands); - header.numFrames = os::Byteswap::byteswap(header.numFrames); - header.offsetSkins = os::Byteswap::byteswap(header.offsetSkins); - header.offsetTexcoords = os::Byteswap::byteswap(header.offsetTexcoords); - header.offsetTriangles = os::Byteswap::byteswap(header.offsetTriangles); - header.offsetFrames = os::Byteswap::byteswap(header.offsetFrames); - header.offsetGlCommands = os::Byteswap::byteswap(header.offsetGlCommands); - header.offsetEnd = os::Byteswap::byteswap(header.offsetEnd); -#endif - - if (header.magic != MD2_MAGIC_NUMBER || header.version != MD2_VERSION) - { - os::Printer::log("MD2 Loader: Wrong file header", file->getFileName(), ELL_WARNING); - return false; - } - - // create Memory for indices and frames - - TriangleCount = header.numTriangles; - if (FrameList) - delete [] FrameList; - FrameList = new core::array[header.numFrames]; - FrameCount = header.numFrames; - - s32 i; - - for (i=0; iseek(header.offsetTexcoords); - SMD2TextureCoordinate* textureCoords = new SMD2TextureCoordinate[header.numTexcoords]; - - if (!file->read(textureCoords, sizeof(SMD2TextureCoordinate)*header.numTexcoords)) - { - os::Printer::log("MD2 Loader: Error reading TextureCoords.", file->getFileName(), ELL_ERROR); - return false; - } - -#ifdef __BIG_ENDIAN__ - for (i=0; iseek(header.offsetTriangles); - - SMD2Triangle *triangles = new SMD2Triangle[header.numTriangles]; - if (!file->read(triangles, header.numTriangles *sizeof(SMD2Triangle))) - { - os::Printer::log("MD2 Loader: Error reading triangles.", file->getFileName(), ELL_ERROR); - return false; - } - -#ifdef __BIG_ENDIAN__ - for (i=0; i* vertices = new core::array< core::vector3df >[header.numFrames]; - core::array< core::vector3df >* normals = new core::array< core::vector3df >[header.numFrames]; - - file->seek(header.offsetFrames); - - for (i = 0; iread(frame, header.frameSize); - -#ifdef __BIG_ENDIAN__ - frame->scale[0] = os::Byteswap::byteswap(frame->scale[0]); - frame->scale[1] = os::Byteswap::byteswap(frame->scale[1]); - frame->scale[2] = os::Byteswap::byteswap(frame->scale[2]); - frame->translate[0] = os::Byteswap::byteswap(frame->translate[0]); - frame->translate[1] = os::Byteswap::byteswap(frame->translate[1]); - frame->translate[2] = os::Byteswap::byteswap(frame->translate[2]); -#endif - // store frame data - - SFrameData fdata; - fdata.begin = i; - fdata.end = i; - fdata.fps = 7; - - if (frame->name[0]) - { - for (s32 s = 0; frame->name[s]!=0 && (frame->name[s] < '0' || - frame->name[s] > '9'); ++s) - fdata.name += frame->name[s]; - - if (!FrameData.empty() && FrameData[FrameData.size()-1].name == fdata.name) - ++FrameData[FrameData.size()-1].end; - else - FrameData.push_back(fdata); - } - - // add vertices - - vertices[i].reallocate(header.numVertices); - for (s32 j=0; jvertices[j].vertex[0] * frame->scale[0] + frame->translate[0]; - v.Z = frame->vertices[j].vertex[1] * frame->scale[1] + frame->translate[1]; - v.Y = frame->vertices[j].vertex[2] * frame->scale[2] + frame->translate[2]; - - vertices[i].push_back(v); - - u8 normalidx = frame->vertices[j].lightNormalIndex; - if (normalidx < Q2_VERTEX_NORMAL_TABLE_SIZE) - { - v.X = Q2_VERTEX_NORMAL_TABLE[normalidx][0]; - v.Z = Q2_VERTEX_NORMAL_TABLE[normalidx][1]; - v.Y = Q2_VERTEX_NORMAL_TABLE[normalidx][2]; - } - - normals[i].push_back(v); - } - - // calculate bounding boxes - if (header.numVertices) - { - core::aabbox3d box; - box.reset(vertices[i][0]); - - for (s32 j=1; j& vert = vertices[f]; - - for (s32 t=0; tIndices.reallocate(header.numVertices); - const u32 count = TriangleCount*3; - for (u32 n=0; nIndices.push_back(n); - InterpolationBuffer->Indices.push_back(n+1); - InterpolationBuffer->Indices.push_back(n+2); - } - - // reallocate interpolate buffer - if (header.numFrames) - { - const u32 currCount = FrameList[0].size(); - InterpolationBuffer->Vertices.set_used(currCount); - - for (u32 num=0; numVertices[num].TCoords = FrameList[0].pointer()[num].TCoords; - InterpolationBuffer->Vertices[num].Color = vtx.Color; - } - } - - // clean up - - delete [] normals; - delete [] vertices; - delete [] triangles; - delete [] textureCoords; - - // return - - calculateBoundingBox(); - - return true; -} - - -//! calculates the bounding box -void CAnimatedMeshMD2::calculateBoundingBox() -{ - InterpolationBuffer->BoundingBox.reset(0,0,0); - - if (FrameCount) - { - u32 defaultFrame = 1; - - if (defaultFrame>=FrameCount) - defaultFrame = 0; - - for (u32 j=0; jBoundingBox.addInternalPoint(FrameList[defaultFrame].pointer()[j].Pos); - } -} - - //! sets a flag of all contained materials to a new value void CAnimatedMeshMD2::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) { @@ -679,7 +358,6 @@ void CAnimatedMeshMD2::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalu } - //! set the hardware mapping hint, for driver void CAnimatedMeshMD2::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer) @@ -736,14 +414,14 @@ void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l, bool CAnimatedMeshMD2::getFrameLoop(const c8* name, s32& outBegin, s32&outEnd, s32& outFPS) const { - for (u32 i=0; i= FrameData.size()) + if ((u32)nr >= AnimationData.size()) return 0; - return FrameData[nr].name.c_str(); + return AnimationData[nr].name.c_str(); } diff --git a/src/dep/src/irrlicht/CAnimatedMeshMD2.h b/src/dep/src/irrlicht/CAnimatedMeshMD2.h index 9307f45..6876ff5 100644 --- a/src/dep/src/irrlicht/CAnimatedMeshMD2.h +++ b/src/dep/src/irrlicht/CAnimatedMeshMD2.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,9 +28,6 @@ namespace scene //! destructor virtual ~CAnimatedMeshMD2(); - //! loads an md2 file - virtual bool loadFile(io::IReadFile* file); - //! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. virtual u32 getFrameCount() const; @@ -82,19 +79,16 @@ namespace scene //! \param nr: Zero based index of animation. virtual const c8* getAnimationName(s32 nr) const; - private: - //! updates the interpolation buffer - void updateInterpolationBuffer(s32 frame, s32 startFrame, s32 endFrame); - - //! calculates the bounding box - virtual void calculateBoundingBox(); + // + // exposed for loader + // + //! the buffer that contains the most recent animation SMeshBuffer* InterpolationBuffer; - core::array *FrameList; - core::array > BoxList; - struct SFrameData + //! named animations + struct SAnimationData { core::stringc name; s32 begin; @@ -102,10 +96,40 @@ namespace scene s32 fps; }; - core::array< SFrameData > FrameData; + //! scale and translations for keyframes + struct SKeyFrameTransform + { + core::vector3df scale; + core::vector3df translate; + }; + + //! md2 vertex data + struct SMD2Vert + { + core::vector3d Pos; + u8 NormalIdx; + }; + + //! keyframe transformations + core::array FrameTransforms; + + //! keyframe vertex data + core::array *FrameList; + + //! bounding boxes for each keyframe + core::array > BoxList; + + //! named animations + core::array< SAnimationData > AnimationData; u32 FrameCount; - s32 TriangleCount; + + private: + + //! updates the interpolation buffer + void updateInterpolationBuffer(s32 frame, s32 startFrame, s32 endFrame); + + }; } // end namespace scene diff --git a/src/dep/src/irrlicht/CAnimatedMeshMD3.cpp b/src/dep/src/irrlicht/CAnimatedMeshMD3.cpp index 27e1045..aaf2302 100644 --- a/src/dep/src/irrlicht/CAnimatedMeshMD3.cpp +++ b/src/dep/src/irrlicht/CAnimatedMeshMD3.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Fabio Concas / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Fabio Concas / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -25,16 +25,18 @@ namespace scene #endif -struct SMD3Bone +//! General properties of a single animation frame. +struct SMD3Frame { - f32 Mins[3]; // bounding box per frame - f32 Maxs[3]; - f32 Position[3]; // position of bounding box - f32 scale; - c8 creator[16]; + f32 mins[3]; // bounding box per frame + f32 maxs[3]; + f32 position[3]; // position of bounding box + f32 radius; // radius of bounding sphere + c8 creator[16]; // name of frame }; +//! An attachment point for another MD3 model. struct SMD3Tag { c8 Name[64]; //name of 'tag' as it's usually called in the md3 files try to see it as a sub-mesh/seperate mesh-part. @@ -42,9 +44,11 @@ struct SMD3Tag f32 rotationMatrix[9]; //3x3 rotation direction of tag }; -struct SMD3Skin +//!Shader +struct SMD3Shader { - c8 name[68]; // name of skin + c8 name[64]; // name of shader + s32 shaderIndex; }; @@ -59,15 +63,13 @@ struct SMD3Skin //! Constructor CAnimatedMeshMD3::CAnimatedMeshMD3() -// TODO: Correct initial values needed -: Mesh(0), IPolShift(0), LoopMode(0), Scaling(1.f) +:Mesh(0), IPolShift(0), LoopMode(0), Scaling(1.f) { #ifdef _DEBUG setDebugName("CAnimatedMeshMD3"); #endif Mesh = new SMD3Mesh(); - memset( &Mesh->MD3Header, 0, sizeof ( Mesh->MD3Header ) ); setInterpolationShift ( 0, 0 ); } @@ -112,7 +114,7 @@ void CAnimatedMeshMD3::setDirty(E_BUFFER_TYPE buffer) //! Returns the animated tag list based on a detail level. 0 is the lowest, 255 the highest detail. -SMD3QuaterionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) +SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { if ( 0 == Mesh ) return 0; @@ -175,13 +177,13 @@ IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, { buildVertexArray(frameA, frameB, iPol, Mesh->Buffer[i], - (SMeshBuffer*) MeshIPol.getMeshBuffer(i) + (SMeshBufferLightMap*) MeshIPol.getMeshBuffer(i) ); } - MeshIPol.recalculateBoundingBox (); + MeshIPol.recalculateBoundingBox(); // build current tags - buildTagArray ( frameA, frameB, iPol ); + buildTagArray( frameA, frameB, iPol ); Current = candidate; return &MeshIPol; @@ -189,9 +191,10 @@ IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, //! create a Irrlicht MeshBuffer for a MD3 MeshBuffer -IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source) +IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source, + io::IFileSystem* fs, video::IVideoDriver * driver) { - SMeshBuffer * dest = new SMeshBuffer(); + SMeshBufferLightMap * dest = new SMeshBufferLightMap(); dest->Vertices.set_used( source->MeshHeader.numVertices ); dest->Indices.set_used( source->Indices.size () ); @@ -208,11 +211,22 @@ IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source) // fill in static vertex info for ( i = 0; i!= (u32)source->MeshHeader.numVertices; ++i ) { - video::S3DVertex &v = dest->Vertices[i]; + video::S3DVertex2TCoords &v = dest->Vertices[i]; v.Color = 0xFFFFFFFF; v.TCoords.X = source->Tex[i].u; v.TCoords.Y = source->Tex[i].v; + v.TCoords2.X = 0.f; + v.TCoords2.Y = 0.f; } + + // load static texture + u32 pos = 0; + quake3::tTexArray textureArray; + quake3::getTextures( textureArray, source->Shader, pos, fs, driver ); + dest->Material.MaterialType = video::EMT_SOLID; + dest->Material.setTexture ( 0, textureArray[0] ); + dest->Material.Lighting = false; + return dest; } @@ -220,7 +234,7 @@ IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source) //! build final mesh's vertices from frames frameA and frameB with linear interpolation. void CAnimatedMeshMD3::buildVertexArray ( u32 frameA, u32 frameB, f32 interpolate, const SMD3MeshBuffer * source, - SMeshBuffer * dest + SMeshBufferLightMap * dest ) { const u32 frameOffsetA = frameA * source->MeshHeader.numVertices; @@ -229,7 +243,7 @@ void CAnimatedMeshMD3::buildVertexArray ( u32 frameA, u32 frameB, f32 interpolat for (s32 i = 0; i != source->MeshHeader.numVertices; ++i) { - video::S3DVertex &v = dest->Vertices [ i ]; + video::S3DVertex2TCoords &v = dest->Vertices [ i ]; const SMD3Vertex &vA = source->Vertices [ frameOffsetA + i ]; const SMD3Vertex &vB = source->Vertices [ frameOffsetB + i ]; @@ -240,8 +254,8 @@ void CAnimatedMeshMD3::buildVertexArray ( u32 frameA, u32 frameB, f32 interpolat v.Pos.Z = scale * ( vA.position[1] + interpolate * ( vB.position[1] - vA.position[1] ) ); // normal - const core::vector3df nA(getNormal ( vA.normal[0], vA.normal[1] )); - const core::vector3df nB(getNormal ( vB.normal[0], vB.normal[1] )); + const core::vector3df nA( quake3::getMD3Normal ( vA.normal[0], vA.normal[1] )); + const core::vector3df nB( quake3::getMD3Normal ( vB.normal[0], vB.normal[1] )); v.Normal.X = nA.X + interpolate * ( nB.X - nA.X ); v.Normal.Y = nA.Z + interpolate * ( nB.Z - nA.Z ); @@ -260,10 +274,10 @@ void CAnimatedMeshMD3::buildTagArray ( u32 frameA, u32 frameB, f32 interpolate ) for ( s32 i = 0; i != Mesh->MD3Header.numTags; ++i ) { - SMD3QuaterionTag &d = TagListIPol [ i ]; + SMD3QuaternionTag &d = TagListIPol [ i ]; - const SMD3QuaterionTag &qA = Mesh->TagList.Container[ frameOffsetA + i]; - const SMD3QuaterionTag &qB = Mesh->TagList.Container[ frameOffsetB + i]; + const SMD3QuaternionTag &qA = Mesh->TagList[ frameOffsetA + i]; + const SMD3QuaternionTag &qB = Mesh->TagList[ frameOffsetB + i]; // rotation d.rotation.slerp( qA.rotation, qB.rotation, interpolate ); @@ -279,7 +293,8 @@ void CAnimatedMeshMD3::buildTagArray ( u32 frameA, u32 frameB, f32 interpolate ) /*! loads a model */ -bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file) +bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file, + io::IFileSystem* fs, video::IVideoDriver * driver) { if (!file) return false; @@ -298,19 +313,31 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file) //! store model name Mesh->Name = file->getFileName(); - //! Bone Frames Data ( ignore ) + u32 i; + + //! Frame Data ( ignore ) +#if 0 + SMD3Frame frameImport; + file->seek ( Mesh->MD3Header.frameStart ); + for (i = 0; i != Mesh->MD3Header.numFrames; ++i ) + { + file->read(&frameImport, sizeof(frameImport) ); + } +#endif + //! Tag Data const u32 totalTags = Mesh->MD3Header.numTags * Mesh->MD3Header.numFrames; SMD3Tag import; - SMD3QuaterionTag exp; - u32 i; file->seek( Mesh->MD3Header.tagStart ); + Mesh->TagList.set_used ( totalTags ); for (i = 0; i != totalTags; ++i ) { file->read(&import, sizeof(import) ); + SMD3QuaternionTag &exp = Mesh->TagList[i]; + //! tag name exp.Name = import.Name; @@ -325,14 +352,11 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file) -import.rotationMatrix[6], 1 + import.rotationMatrix[8]); exp.rotation.normalize (); - Mesh->TagList.Container.push_back ( exp ); } //! Meshes u32 offset = Mesh->MD3Header.tagEnd; - SMD3Skin skin; - for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i ) { //! construct a new mesh buffer @@ -350,13 +374,17 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file) buf->Indices.set_used ( meshHeader.numTriangles * 3 ); buf->Tex.set_used ( meshHeader.numVertices ); - - //! read skins (shaders) + //! read skins (shaders). should be 1 per meshbuffer + SMD3Shader skin; file->seek( offset + buf->MeshHeader.offset_shaders ); for ( s32 g = 0; g != buf->MeshHeader.numShader; ++g ) { file->read( &skin, sizeof(skin) ); - buf->Shader.push_back ( skin.name ); + + io::path name; + cutFilenameExtension ( name, skin.name ); + name.replace ( '\\', '/' ); + buf->Shader = name; } //! read texture coordinates @@ -380,15 +408,16 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file) // Init Mesh Interpolation for ( i = 0; i != Mesh->Buffer.size (); ++i ) { - IMeshBuffer * buffer = createMeshBuffer ( Mesh->Buffer[i] ); + IMeshBuffer * buffer = createMeshBuffer ( Mesh->Buffer[i], fs, driver ); MeshIPol.addMeshBuffer ( buffer ); buffer->drop (); } + MeshIPol.recalculateBoundingBox (); // Init Tag Interpolation for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i ) { - TagListIPol.Container.push_back ( Mesh->TagList.Container[i] ); + TagListIPol.push_back ( Mesh->TagList[i] ); } return true; diff --git a/src/dep/src/irrlicht/CAnimatedMeshMD3.h b/src/dep/src/irrlicht/CAnimatedMeshMD3.h index cafafb7..acb850f 100644 --- a/src/dep/src/irrlicht/CAnimatedMeshMD3.h +++ b/src/dep/src/irrlicht/CAnimatedMeshMD3.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,6 +12,7 @@ #include "irrString.h" #include "SMesh.h" #include "SMeshBuffer.h" +#include "IQ3Shader.h" namespace irr { @@ -23,18 +24,20 @@ namespace scene public: //! constructor - CAnimatedMeshMD3(); + CAnimatedMeshMD3( ); //! destructor virtual ~CAnimatedMeshMD3(); //! loads a quake3 md3 file - virtual bool loadModelFile( u32 modelIndex, io::IReadFile* file); + virtual bool loadModelFile( u32 modelIndex, io::IReadFile* file, + io::IFileSystem* fs, video::IVideoDriver * driver + ); // IAnimatedMeshMD3 virtual void setInterpolationShift ( u32 shift, u32 loopMode ); virtual SMD3Mesh * getOriginalMesh (); - virtual SMD3QuaterionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); + virtual SMD3QuaternionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); //IAnimatedMesh virtual u32 getFrameCount() const; @@ -42,9 +45,6 @@ namespace scene virtual const core::aabbox3d& getBoundingBox() const; virtual E_ANIMATED_MESH_TYPE getMeshType() const; - - //link? - //! returns amount of mesh buffers. virtual u32 getMeshBufferCount() const { @@ -116,29 +116,20 @@ namespace scene //! return a Mesh per frame SMesh MeshIPol; - SMD3QuaterionTagList TagListIPol; + SMD3QuaternionTagList TagListIPol; - IMeshBuffer * createMeshBuffer ( const SMD3MeshBuffer *source ); + IMeshBuffer * createMeshBuffer ( const SMD3MeshBuffer *source, io::IFileSystem* fs, video::IVideoDriver * driver ); void buildVertexArray ( u32 frameA, u32 frameB, f32 interpolate, const SMD3MeshBuffer * source, - SMeshBuffer * dest + SMeshBufferLightMap * dest ); void buildTagArray ( u32 frameA, u32 frameB, f32 interpolate ); - - core::vector3df getNormal ( u32 i, u32 j ) - { - const f32 lng = i * 2.0f * core::PI / 255.0f; - const f32 lat = j * 2.0f * core::PI / 255.0f; - return core::vector3df(cosf ( lat ) * sinf ( lng ), - sinf ( lat ) * sinf ( lng ), - cos ( lng )); - } }; + } // end namespace scene } // end namespace irr #endif - diff --git a/src/dep/src/irrlicht/CAnimatedMeshSceneNode.cpp b/src/dep/src/irrlicht/CAnimatedMeshSceneNode.cpp index aed98c6..b96823b 100644 --- a/src/dep/src/irrlicht/CAnimatedMeshSceneNode.cpp +++ b/src/dep/src/irrlicht/CAnimatedMeshSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -37,20 +37,19 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, const core::vector3df& rotation, const core::vector3df& scale) : IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), - MeshForCurrentFrame(0), - BeginFrameTime(0), StartFrame(0), EndFrame(0), FramesPerSecond(0.f), - CurrentFrameNr(0.f), FrameWhenCurrentMeshWasGenerated(0.f), - JointMode(EJUOR_NONE), JointsUsed(false), + StartFrame(0), EndFrame(0), FramesPerSecond(0.f), + CurrentFrameNr(0.f), LastTimeMs(0), TransitionTime(0), Transiting(0.f), TransitingBlend(0.f), + JointMode(EJUOR_NONE), JointsUsed(false), Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(0), - LoopCallBack(0), PassCount(0), Shadow(0) + LoopCallBack(0), PassCount(0), Shadow(0), + MD3Special ( 0 ) { #ifdef _DEBUG setDebugName("CAnimatedMeshSceneNode"); #endif - BeginFrameTime = os::Timer::getTime(); - FramesPerSecond = 25.f/100.f; + FramesPerSecond = 25.f/1000.f; setMesh(mesh); } @@ -59,6 +58,9 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, //! destructor CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode() { + if (MD3Special) + MD3Special->drop (); + if (Mesh) Mesh->drop(); @@ -80,8 +82,6 @@ void CAnimatedMeshSceneNode::setCurrentFrame(f32 frame) // if you pass an out of range value, we just clamp it CurrentFrameNr = core::clamp ( frame, (f32)StartFrame, (f32)EndFrame ); - BeginFrameTime = os::Timer::getTime() - (s32)((CurrentFrameNr - StartFrame) / FramesPerSecond); - beginTransition(); //transit to this frame if enabled } @@ -93,11 +93,11 @@ f32 CAnimatedMeshSceneNode::getFrameNr() const } -f32 CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs) +void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs) { if (Transiting!=0.f) { - TransitingBlend = (f32)(timeMs-BeginFrameTime) * Transiting; + TransitingBlend += (f32)(timeMs) * Transiting; if (TransitingBlend > 1.f) { Transiting=0.f; @@ -105,65 +105,55 @@ f32 CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs) } } - if (StartFrame==EndFrame) - return (f32)StartFrame; //Support for non animated meshes - if (FramesPerSecond==0.f) - return (f32)StartFrame; - - if (Looping) + if ((StartFrame==EndFrame)) + { + CurrentFrameNr = (f32)StartFrame; //Support for non animated meshes + } + else if (Looping) { // play animation looped + CurrentFrameNr += timeMs * FramesPerSecond; - const s32 lenInMs = abs(s32( (EndFrame - StartFrame) / FramesPerSecond)); + // We have no interpolation between EndFrame and StartFrame, + // the last frame must be identical to first one with our current solution. if (FramesPerSecond > 0.f) //forwards... { - return StartFrame + ( (timeMs - BeginFrameTime) % lenInMs) * FramesPerSecond; + if (CurrentFrameNr > EndFrame) + CurrentFrameNr = StartFrame + fmod(CurrentFrameNr - StartFrame, (f32)(EndFrame-StartFrame)); } else //backwards... { - return EndFrame - ( (timeMs - BeginFrameTime) % lenInMs)* -FramesPerSecond; + if (CurrentFrameNr < StartFrame) + CurrentFrameNr = EndFrame - fmod(EndFrame - CurrentFrameNr, (f32)(EndFrame-StartFrame)); } } else { // play animation non looped - f32 frame; - + CurrentFrameNr += timeMs * FramesPerSecond; if (FramesPerSecond > 0.f) //forwards... { - const f32 deltaFrame = ( timeMs - BeginFrameTime ) * FramesPerSecond; - - frame = StartFrame + deltaFrame; - - if (frame > (f32)EndFrame) + if (CurrentFrameNr > (f32)EndFrame) { - frame = (f32)EndFrame; + CurrentFrameNr = (f32)EndFrame; if (LoopCallBack) LoopCallBack->OnAnimationEnd(this); } } - else //backwards... (untested) + else //backwards... { - const f32 deltaFrame = ( timeMs - BeginFrameTime ) * -FramesPerSecond; - - frame = EndFrame - deltaFrame; - - if (frame < (f32)StartFrame) + if (CurrentFrameNr < (f32)StartFrame) { - frame = (f32)StartFrame; + CurrentFrameNr = (f32)StartFrame; if (LoopCallBack) LoopCallBack->OnAnimationEnd(this); } - } - - return frame; } } -//! frame void CAnimatedMeshSceneNode::OnRegisterSceneNode() { if (IsVisible) @@ -206,23 +196,22 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode() } } -IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(void) +IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame() { if(Mesh->getMeshType() != EAMT_SKINNED) { - if(!MeshForCurrentFrame || !core::equals(CurrentFrameNr, FrameWhenCurrentMeshWasGenerated)) - MeshForCurrentFrame = Mesh->getMesh((s32)getFrameNr(), 255, StartFrame, EndFrame); + return 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. + // re-animate it every frame to ensure that this node gets the mesh that it needs. CSkinnedMesh* skinnedMesh = reinterpret_cast(Mesh); if (JointMode == EJUOR_CONTROL)//write to mesh skinnedMesh->transferJointsToMesh(JointChildSceneNodes); - else + else skinnedMesh->animateMesh(getFrameNr(), 1.0f); // Update the skinned mesh for the current joint transforms. @@ -246,18 +235,24 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(void) skinnedMesh->updateBoundingBox(); } - MeshForCurrentFrame = skinnedMesh; + return skinnedMesh; } - - FrameWhenCurrentMeshWasGenerated = CurrentFrameNr; - return MeshForCurrentFrame; } //! OnAnimate() is called just before rendering the whole scene. void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs) { - CurrentFrameNr = buildFrameNr ( timeMs ); + buildFrameNr(timeMs-LastTimeMs); + + if (Mesh) + { + scene::IMesh * mesh = getMeshForCurrentFrame(); + + if (mesh) + Box = mesh->getBoundingBox(); + } + LastTimeMs = timeMs; IAnimatedMeshSceneNode::OnAnimate ( timeMs ); } @@ -303,16 +298,16 @@ void CAnimatedMeshSceneNode::render() if (DebugDataVisible && PassCount==1) { // overwrite half transparency - if ( DebugDataVisible & scene::EDS_HALF_TRANSPARENCY ) + if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) { for (u32 i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = m->getMeshBuffer(i); - mat = Materials[i]; + mat = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; if (RenderFromIdentity) - driver->setTransform(video::ETS_WORLD, core::matrix4() ); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); else if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); @@ -324,27 +319,30 @@ void CAnimatedMeshSceneNode::render() } // render original meshes - if ( renderMeshes ) + if (renderMeshes) { for (u32 i=0; igetMeshBufferCount(); ++i) { video::IMaterialRenderer* rnd = driver->getMaterialRenderer(Materials[i].MaterialType); bool transparent = (rnd && rnd->isTransparent()); + + // only render transparent buffer if this is the transparent render pass + // and solid only in solid pass + //PSEUWOW M2 RENDERING + //Render only those submeshes that are actually active bool renderSubmesh = true; if(Mesh->getMeshType() == EAMT_M2) renderSubmesh = ((CM2Mesh*)Mesh)->getGeoSetRender(i); - // only render transparent buffer if this is the transparent render pass - // and solid only in solid pass - if (transparent == isTransparentPass && renderSubmesh) + if (transparent == isTransparentPass && renderSubmesh) //PSEUWOW M2 RENDERING END { scene::IMeshBuffer* mb = m->getMeshBuffer(i); - + const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; if (RenderFromIdentity) - driver->setTransform(video::ETS_WORLD, core::matrix4() ); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); else if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); - driver->setMaterial(Materials[i]); + driver->setMaterial(material); driver->drawMeshBuffer(mb); } } @@ -357,64 +355,46 @@ void CAnimatedMeshSceneNode::render() { video::SMaterial debug_mat; debug_mat.Lighting = false; + debug_mat.AntiAliasing=0; driver->setMaterial(debug_mat); // show normals - if ( DebugDataVisible & scene::EDS_NORMALS ) + if (DebugDataVisible & scene::EDS_NORMALS) { - IAnimatedMesh * arrow = SceneManager->addArrowMesh ( - "__debugnormal", 0xFFECEC00, - 0xFF999900, 4, 8, 1.f, 0.6f, 0.05f, - 0.3f); - if ( 0 == arrow ) - { - arrow = SceneManager->getMesh ( "__debugnormal" ); - } - const IMesh *mesh = arrow->getMesh ( 0 ); - - // find a good scaling factor - - core::matrix4 m2; + core::vector3df normalizedNormal; + const f32 DebugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); + const video::SColor DebugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); // draw normals - for (u32 g=0; ggetMeshBufferCount(); ++g) + for (u32 g=0; g < m->getMeshBufferCount(); ++g) { const scene::IMeshBuffer* mb = m->getMeshBuffer(g); const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); - for ( u32 i=0; i != mb->getVertexCount(); ++i ) + const bool normalize = mb->getMaterial().NormalizeNormals; + + for (u32 i=0; i != mb->getVertexCount(); ++i) { - // Align to v->normal - core::quaternion quatRot( v->Normal.Z, 0.f, -v->Normal.X, 1 + v->Normal.Y ); - quatRot.normalize(); - quatRot.getMatrix ( m2 ); + normalizedNormal = v->Normal; + if (normalize) + normalizedNormal.normalize(); - m2.setTranslation(v->Pos); - if (Mesh->getMeshType() == EAMT_SKINNED) - { - m2 = (AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation) * m2; - } - else - m2*=AbsoluteTransformation; + driver->draw3DLine(v->Pos, v->Pos + (normalizedNormal * DebugNormalLength), DebugNormalColor); - driver->setTransform(video::ETS_WORLD, m2 ); - for ( u32 a = 0; a != mesh->getMeshBufferCount(); ++a ) - driver->drawMeshBuffer ( mesh->getMeshBuffer ( a ) ); - - v = (const video::S3DVertex*) ( (u8*) v + vSize ); + v = (const video::S3DVertex*) ( (u8*) v+vSize ); } } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); } - debug_mat.ZBuffer = false; + debug_mat.ZBuffer = video::ECFN_NEVER; debug_mat.Lighting = false; driver->setMaterial(debug_mat); - if ( DebugDataVisible & scene::EDS_BBOX ) + if (DebugDataVisible & scene::EDS_BBOX) driver->draw3DBox(Box, video::SColor(255,255,255,255)); // show bounding box - if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) + if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) { for (u32 g=0; g< m->getMeshBufferCount(); ++g) @@ -429,24 +409,28 @@ void CAnimatedMeshSceneNode::render() } // show skeleton - if ( DebugDataVisible & scene::EDS_SKELETON ) + if (DebugDataVisible & scene::EDS_SKELETON) { - if (Mesh->getMeshType() == EAMT_SKINNED || Mesh->getMeshType() == EAMT_M2) + if (Mesh->getMeshType() == EAMT_SKINNED|| Mesh->getMeshType() == EAMT_M2) { // draw skeleton - ISceneCollisionManager* Coll = SceneManager->getSceneCollisionManager(); - irr::gui::IGUIFont* Font = SceneManager->getGUIEnvironment()->getBuiltInFont(); + //PSEUWOW + ISceneCollisionManager* Coll = SceneManager->getSceneCollisionManager(); + irr::gui::IGUIFont* Font = SceneManager->getGUIEnvironment()->getBuiltInFont(); + //PSEUWOW END for (u32 g=0; g < ((ISkinnedMesh*)Mesh)->getAllJoints().size(); ++g) { ISkinnedMesh::SJoint *joint=((ISkinnedMesh*)Mesh)->getAllJoints()[g]; - core::vector3df a = joint->GlobalAnimatedMatrix.getTranslation()-core::vector3df(0.05,0.05,0.05); - core::vector3df b = joint->GlobalAnimatedMatrix.getTranslation()+core::vector3df(0.05,0.05,0.05); - core::aabbox3df marker = core::aabbox3df(a,b); - driver->draw3DBox(marker,video::SColor(255,51,66,255)); + //PSEUWOW + core::vector3df a = joint->GlobalAnimatedMatrix.getTranslation()-core::vector3df(0.05,0.05,0.05); + core::vector3df b = joint->GlobalAnimatedMatrix.getTranslation()+core::vector3df(0.05,0.05,0.05); + core::aabbox3df marker = core::aabbox3df(a,b); + driver->draw3DBox(marker,video::SColor(255,51,66,255)); - core::position2d pos = Coll->getScreenCoordinatesFrom3DPosition(a, SceneManager->getActiveCamera()); - core::rect r(pos, core::dimension2d(1,1)); - Font->draw(core::stringw(g).c_str(), r, video::SColor(255,51,255,66), true, true); + core::position2d pos = Coll->getScreenCoordinatesFrom3DPosition(a, SceneManager->getActiveCamera()); + core::rect r(pos, core::dimension2d(1,1)); + Font->draw(core::stringw(g).c_str(), r, video::SColor(255,51,255,66), true, true); + //PSEUWOW END for (u32 n=0;nChildren.size();++n) { @@ -458,7 +442,7 @@ void CAnimatedMeshSceneNode::render() } // show tag for quake3 models - if (Mesh->getMeshType() == EAMT_MD3 ) + if (Mesh->getMeshType() == EAMT_MD3) { IAnimatedMesh * arrow = SceneManager->addArrowMesh ( @@ -466,7 +450,7 @@ void CAnimatedMeshSceneNode::render() 0xFF0000FF, 0xFF000088, 4, 8, 5.f, 4.f, 0.5f, 1.f); - if ( 0 == arrow ) + if (!arrow) { arrow = SceneManager->getMesh ( "__tag_show" ); } @@ -474,10 +458,10 @@ void CAnimatedMeshSceneNode::render() core::matrix4 matr; - SMD3QuaterionTagList *taglist = ((IAnimatedMeshMD3*)Mesh)->getTagList( + SMD3QuaternionTagList *taglist = ((IAnimatedMeshMD3*)Mesh)->getTagList( (s32)getFrameNr(), 255, getStartFrame(), getEndFrame()); - if ( taglist ) + if (taglist) { for ( u32 ts = 0; ts != taglist->size(); ++ts ) { @@ -493,18 +477,18 @@ void CAnimatedMeshSceneNode::render() } // show mesh - if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) + if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) { debug_mat.Lighting = false; debug_mat.Wireframe = true; - debug_mat.ZBuffer = true; + debug_mat.ZBuffer = video::ECFN_NEVER; driver->setMaterial(debug_mat); for (u32 g=0; ggetMeshBufferCount(); ++g) { const IMeshBuffer* mb = m->getMeshBuffer(g); if (RenderFromIdentity) - driver->setTransform(video::ETS_WORLD, core::matrix4() ); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); else if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); driver->drawMeshBuffer(mb); @@ -533,7 +517,7 @@ s32 CAnimatedMeshSceneNode::getEndFrame() const bool CAnimatedMeshSceneNode::setFrameLoop(s32 begin, s32 end) { const s32 maxFrameCount = Mesh->getFrameCount() - 1; - if ( end < begin ) + if (end < begin) { StartFrame = core::s32_clamp(end, 0, maxFrameCount); EndFrame = core::s32_clamp(begin, StartFrame, maxFrameCount); @@ -543,7 +527,10 @@ bool CAnimatedMeshSceneNode::setFrameLoop(s32 begin, s32 end) StartFrame = core::s32_clamp(begin, 0, maxFrameCount); EndFrame = core::s32_clamp(end, StartFrame, maxFrameCount); } - setCurrentFrame ( (f32)StartFrame ); + if (FramesPerSecond < 0) + setCurrentFrame((f32)EndFrame); + else + setCurrentFrame((f32)StartFrame); return true; } @@ -556,6 +543,12 @@ void CAnimatedMeshSceneNode::setAnimationSpeed(f32 framesPerSecond) } +f32 CAnimatedMeshSceneNode::getAnimationSpeed() const +{ + return FramesPerSecond * 1000.f; +} + + //! returns the axis aligned bounding box of this node const core::aabbox3d& CAnimatedMeshSceneNode::getBoundingBox() const { @@ -570,7 +563,7 @@ const core::aabbox3d& CAnimatedMeshSceneNode::getBoundingBox() const //! to directly modify the material of a scene node. video::SMaterial& CAnimatedMeshSceneNode::getMaterial(u32 i) { - if ( i >= Materials.size() ) + if (i >= Materials.size()) return ISceneNode::getMaterial(i); return Materials[i]; @@ -594,10 +587,7 @@ IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(const I return 0; if (Shadow) - { - os::Printer::log("This node already has a shadow.", ELL_WARNING); - return 0; - } + return Shadow; if (!shadowMesh) shadowMesh = Mesh; // if null is given, use the mesh of node @@ -697,7 +687,6 @@ bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child) { Shadow->drop(); Shadow = 0; - return true; } if (ISceneNode::removeChild(child)) @@ -717,6 +706,7 @@ bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child) return false; } +//PSEUWOW //! Starts a M2 animation. bool CAnimatedMeshSceneNode::setM2Animation(u32 animID) { @@ -729,12 +719,12 @@ bool CAnimatedMeshSceneNode::setM2Animation(u32 animID) m->getFrameLoop(animID, begin, end); //Eventually different speeds are necessary? if(begin == -1 || end == -1) return false; - + // setAnimationSpeed( f32(speed) ); setFrameLoop(begin, end); return true; } - +//PSEUWOW END //! Starts a MD2 animation. bool CAnimatedMeshSceneNode::setMD2Animation(EMD2_ANIMATION_TYPE anim) @@ -783,6 +773,9 @@ void CAnimatedMeshSceneNode::setLoopMode(bool playAnimationLooped) //! playback has ended. Set this to 0 to disable the callback again. void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack* callback) { + if (callback == LoopCallBack) + return; + if (LoopCallBack) LoopCallBack->drop(); @@ -812,12 +805,12 @@ void CAnimatedMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttr { IAnimatedMeshSceneNode::serializeAttributes(out, options); - out->addString("Mesh", SceneManager->getMeshCache()->getMeshFilename(Mesh)); + out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str()); out->addBool("Looping", Looping); out->addBool("ReadOnlyMaterials", ReadOnlyMaterials); out->addFloat("FramesPerSecond", FramesPerSecond); - - // TODO: write animation names instead of frame begin and ends + out->addInt("StartFrame", StartFrame); + out->addInt("EndFrame", EndFrame); } @@ -826,12 +819,14 @@ void CAnimatedMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAtt { IAnimatedMeshSceneNode::deserializeAttributes(in, options); - core::stringc oldMeshStr = SceneManager->getMeshCache()->getMeshFilename(Mesh); - core::stringc newMeshStr = in->getAttributeAsString("Mesh"); + io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh); + io::path newMeshStr = in->getAttributeAsString("Mesh"); Looping = in->getAttributeAsBool("Looping"); ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials"); FramesPerSecond = in->getAttributeAsFloat("FramesPerSecond"); + StartFrame = in->getAttributeAsInt("StartFrame"); + EndFrame = in->getAttributeAsInt("EndFrame"); if (newMeshStr != "" && oldMeshStr != newMeshStr) { @@ -851,10 +846,16 @@ void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh) if (!mesh) return; // won't set null mesh - if (Mesh) - Mesh->drop(); + if (Mesh != mesh) + { + if (Mesh) + Mesh->drop(); - Mesh = mesh; + Mesh = mesh; + + // grab the mesh (it's non-null!) + Mesh->grab(); + } // get materials and bounding box Box = Mesh->getBoundingBox(); @@ -863,37 +864,28 @@ void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh) if (m) { Materials.clear(); + Materials.reallocate(m->getMeshBufferCount()); - video::SMaterial mat; for (u32 i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* mb = m->getMeshBuffer(i); if (mb) - mat = mb->getMaterial(); - - Materials.push_back(mat); + Materials.push_back(mb->getMaterial()); + else + Materials.push_back(video::SMaterial()); } } // get start and begin time setFrameLoop ( 0, Mesh->getFrameCount() ); - - // grab the mesh - if (Mesh) - Mesh->grab(); } // returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, // or the absolutetransformation if it's a normal scenenode -const SMD3QuaterionTag& CAnimatedMeshSceneNode::getMD3TagTransformation( const core::stringc & tagname) +const SMD3QuaternionTag* CAnimatedMeshSceneNode::getMD3TagTransformation( const core::stringc & tagname) { - SMD3QuaterionTag * tag = MD3Special.AbsoluteTagList.get ( tagname ); - if ( tag ) - return *tag; - - MD3Special.AbsoluteTagList.Container.push_back ( SMD3QuaterionTag ( tagname, AbsoluteTransformation ) ); - return *MD3Special.AbsoluteTagList.get ( tagname ); + return MD3Special ? MD3Special->AbsoluteTagList.get ( tagname ) : 0; } @@ -902,30 +894,40 @@ void CAnimatedMeshSceneNode::updateAbsolutePosition() { IAnimatedMeshSceneNode::updateAbsolutePosition(); - if ( 0 == Mesh || Mesh->getMeshType() != EAMT_MD3 ) + if (!Mesh || Mesh->getMeshType() != EAMT_MD3) return; - SMD3QuaterionTag parent; - if ( Parent && Parent->getType () == ESNT_ANIMATED_MESH) - { - parent = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation ( MD3Special.Tagname ); - } - - SMD3QuaterionTag relative( RelativeTranslation, RelativeRotation ); - - SMD3QuaterionTagList *taglist; + SMD3QuaternionTagList *taglist; taglist = ( (IAnimatedMeshMD3*) Mesh )->getTagList ( (s32)getFrameNr(),255,getStartFrame (),getEndFrame () ); - if ( taglist ) + if (taglist) { - MD3Special.AbsoluteTagList.Container.set_used ( taglist->size () ); + if (!MD3Special) + { + MD3Special = new SMD3Special(); + } + + SMD3QuaternionTag parent ( MD3Special->Tagname ); + if (Parent && Parent->getType() == ESNT_ANIMATED_MESH) + { + const SMD3QuaternionTag * p = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation + ( MD3Special->Tagname ); + + if (p) + parent = *p; + } + + SMD3QuaternionTag relative( RelativeTranslation, RelativeRotation ); + + MD3Special->AbsoluteTagList.set_used ( taglist->size () ); for ( u32 i=0; i!= taglist->size (); ++i ) { - MD3Special.AbsoluteTagList[i].position = parent.position + (*taglist)[i].position + relative.position; - MD3Special.AbsoluteTagList[i].rotation = parent.rotation * (*taglist)[i].rotation * relative.rotation; + MD3Special->AbsoluteTagList[i].position = parent.position + (*taglist)[i].position + relative.position; + MD3Special->AbsoluteTagList[i].rotation = parent.rotation * (*taglist)[i].rotation * relative.rotation; } } } + //! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set) void CAnimatedMeshSceneNode::setJointMode(E_JOINT_UPDATE_ON_RENDER mode) { @@ -950,6 +952,7 @@ void CAnimatedMeshSceneNode::setTransitionTime(f32 time) } } + //! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected) void CAnimatedMeshSceneNode::setRenderFromIdentity( bool On ) { @@ -957,7 +960,6 @@ void CAnimatedMeshSceneNode::setRenderFromIdentity( bool On ) } - //! updates the joint positions of this mesh void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions) { @@ -1025,8 +1027,6 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions) } } - - if (CalculateAbsolutePositions) { //---slow--- @@ -1043,6 +1043,8 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions) } +/*! +*/ void CAnimatedMeshSceneNode::checkJoints() { if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) @@ -1061,6 +1063,8 @@ void CAnimatedMeshSceneNode::checkJoints() } +/*! +*/ void CAnimatedMeshSceneNode::beginTransition() { if (!JointsUsed) @@ -1085,21 +1089,29 @@ void CAnimatedMeshSceneNode::beginTransition() TransitingBlend = 0.f; } + +/*! +*/ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CAnimatedMeshSceneNode * newNode = - new CAnimatedMeshSceneNode(Mesh, newParent, newManager, ID, RelativeTranslation, + new CAnimatedMeshSceneNode(Mesh, NULL, newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale); + if ( newParent ) + { + newNode->setParent(newParent); // not in constructor because virtual overload for updateAbsolutePosition won't be called + newNode->drop(); + } + newNode->cloneMembers(this, newManager); newNode->Materials = Materials; newNode->Box = Box; newNode->Mesh = Mesh; - newNode->BeginFrameTime = BeginFrameTime; newNode->StartFrame = StartFrame; newNode->EndFrame = EndFrame; newNode->FramesPerSecond = FramesPerSecond; @@ -1119,12 +1131,10 @@ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newNode->RenderFromIdentity = RenderFromIdentity; newNode->MD3Special = MD3Special; - (void)newNode->drop(); return newNode; } - } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CAnimatedMeshSceneNode.h b/src/dep/src/irrlicht/CAnimatedMeshSceneNode.h index 8fba544..5065dc1 100644 --- a/src/dep/src/irrlicht/CAnimatedMeshSceneNode.h +++ b/src/dep/src/irrlicht/CAnimatedMeshSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -57,9 +57,12 @@ namespace scene //! playback has ended. Set this to 0 to disable the callback again. virtual void setAnimationEndCallback(IAnimationEndCallBack* callback=0); - //! sets the speed with witch the animation is played + //! sets the speed with which the animation is played virtual void setAnimationSpeed(f32 framesPerSecond); + //! gets the speed with which the animation is played + virtual f32 getAnimationSpeed() const; + //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a @@ -96,8 +99,10 @@ namespace scene //! or to remove attached childs. virtual bool removeChild(ISceneNode* child); + //PSEUWOW //! Starts a M2 animation. virtual bool setM2Animation(u32 anim); + //PSEUWOW //! Starts a MD2 animation. virtual bool setMD2Animation(EMD2_ANIMATION_TYPE anim); @@ -137,7 +142,7 @@ namespace scene // returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, // or the absolutetransformation if it's a normal scenenode - const SMD3QuaterionTag& getMD3TagTransformation( const core::stringc & tagname); + const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname); //! updates the absolute position based on the relative and the parents position virtual void updateAbsolutePosition(); @@ -165,32 +170,30 @@ namespace scene private: //! Get a static mesh for the current frame of this animated mesh - IMesh* getMeshForCurrentFrame(void); + IMesh* getMeshForCurrentFrame(); - f32 buildFrameNr( u32 timeMs); + void buildFrameNr(u32 timeMs); void checkJoints(); void beginTransition(); core::array Materials; core::aabbox3d Box; IAnimatedMesh* Mesh; - IMesh* MeshForCurrentFrame; - u32 BeginFrameTime; s32 StartFrame; s32 EndFrame; f32 FramesPerSecond; f32 CurrentFrameNr; - f32 FrameWhenCurrentMeshWasGenerated; + + u32 LastTimeMs; + u32 TransitionTime; //Transition time in millisecs + f32 Transiting; //is mesh transiting (plus cache of TransitionTime) + f32 TransitingBlend; //0-1, calculated on buildFrameNr //0-unused, 1-get joints only, 2-set joints only, 3-move and set E_JOINT_UPDATE_ON_RENDER JointMode; bool JointsUsed; - u32 TransitionTime; //Transition time in millisecs - f32 Transiting; //is mesh transiting (plus cache of TransitionTime) - f32 TransitingBlend; //0-1, calculated on buildFrameNr - bool Looping; bool ReadOnlyMaterials; bool RenderFromIdentity; @@ -203,10 +206,11 @@ namespace scene core::array JointChildSceneNodes; core::array PretransitingSave; - struct SMD3Special + // Quake3 Model + struct SMD3Special : public virtual IReferenceCounted { core::stringc Tagname; - SMD3QuaterionTagList AbsoluteTagList; + SMD3QuaternionTagList AbsoluteTagList; SMD3Special & operator = (const SMD3Special & copyMe) { @@ -215,7 +219,7 @@ namespace scene return *this; } }; - SMD3Special MD3Special; + SMD3Special *MD3Special; }; } // end namespace scene diff --git a/src/dep/src/irrlicht/CAttributeImpl.h b/src/dep/src/irrlicht/CAttributeImpl.h index 9654e83..4fee892 100644 --- a/src/dep/src/irrlicht/CAttributeImpl.h +++ b/src/dep/src/irrlicht/CAttributeImpl.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -186,7 +186,7 @@ public: Value = core::fast_atof(text); } - virtual E_ATTRIBUTE_TYPE getType() const + virtual E_ATTRIBUTE_TYPE getType() const { return EAT_FLOAT; } @@ -212,7 +212,7 @@ class CNumbersAttribute : public IAttribute { public: - CNumbersAttribute(const char* name, video::SColorf value) : + CNumbersAttribute(const char* name, video::SColorf value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; @@ -233,7 +233,7 @@ public: } - CNumbersAttribute(const char* name, core::vector3df value) : + CNumbersAttribute(const char* name, core::vector3df value) : ValueI(), ValueF(), Count(3), IsFloat(true) { Name = name; @@ -242,23 +242,7 @@ public: ValueF.push_back(value.Z); } - CNumbersAttribute(const char* name, core::position2df value) : - ValueI(), ValueF(), Count(2), IsFloat(true) - { - Name = name; - ValueF.push_back(value.X); - ValueF.push_back(value.Y); - } - - CNumbersAttribute(const char* name, core::position2di value) : - ValueI(), ValueF(), Count(2), IsFloat(false) - { - Name = name; - ValueI.push_back(value.X); - ValueI.push_back(value.Y); - } - - CNumbersAttribute(const char* name, core::rect value) : + CNumbersAttribute(const char* name, core::rect value) : ValueI(), ValueF(), Count(4), IsFloat(false) { Name = name; @@ -268,7 +252,7 @@ public: ValueI.push_back(value.LowerRightCorner.Y); } - CNumbersAttribute(const char* name, core::rect value) : + CNumbersAttribute(const char* name, core::rect value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; @@ -278,7 +262,7 @@ public: ValueF.push_back(value.LowerRightCorner.Y); } - CNumbersAttribute(const char* name, core::matrix4 value) : + CNumbersAttribute(const char* name, core::matrix4 value) : ValueI(), ValueF(), Count(16), IsFloat(true) { Name = name; @@ -287,7 +271,7 @@ public: ValueF.push_back(value(r,c)); } - CNumbersAttribute(const char* name, core::quaternion value) : + CNumbersAttribute(const char* name, core::quaternion value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; @@ -297,7 +281,7 @@ public: ValueF.push_back(value.W); } - CNumbersAttribute(const char* name, core::aabbox3d value) : + CNumbersAttribute(const char* name, core::aabbox3d value) : ValueI(), ValueF(), Count(6), IsFloat(true) { Name = name; @@ -309,7 +293,7 @@ public: ValueF.push_back(value.MaxEdge.Z); } - CNumbersAttribute(const char* name, core::plane3df value) : + CNumbersAttribute(const char* name, core::plane3df value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; @@ -319,7 +303,7 @@ public: ValueF.push_back(value.D); } - CNumbersAttribute(const char* name, core::triangle3df value) : + CNumbersAttribute(const char* name, core::triangle3df value) : ValueI(), ValueF(), Count(9), IsFloat(true) { Name = name; @@ -334,7 +318,7 @@ public: ValueF.push_back(value.pointC.Z); } - CNumbersAttribute(const char* name, core::vector2df value) : + CNumbersAttribute(const char* name, core::vector2df value) : ValueI(), ValueF(), Count(2), IsFloat(true) { Name = name; @@ -342,7 +326,7 @@ public: ValueF.push_back(value.Y); } - CNumbersAttribute(const char* name, core::vector2di value) : + CNumbersAttribute(const char* name, core::vector2di value) : ValueI(), ValueF(), Count(2), IsFloat(false) { Name = name; @@ -350,7 +334,7 @@ public: ValueI.push_back(value.Y); } - CNumbersAttribute(const char* name, core::line2di value) : + CNumbersAttribute(const char* name, core::line2di value) : ValueI(), ValueF(), Count(4), IsFloat(false) { Name = name; @@ -360,7 +344,7 @@ public: ValueI.push_back(value.end.Y); } - CNumbersAttribute(const char* name, core::line2df value) : + CNumbersAttribute(const char* name, core::line2df value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; @@ -370,7 +354,7 @@ public: ValueF.push_back(value.end.Y); } - CNumbersAttribute(const char* name, core::line3df value) : + CNumbersAttribute(const char* name, core::line3df value) : ValueI(), ValueF(), Count(6), IsFloat(true) { Name = name; @@ -382,7 +366,7 @@ public: ValueF.push_back(value.end.Z); } - CNumbersAttribute(const char* name, core::dimension2di value) : + CNumbersAttribute(const char* name, core::dimension2du value) : ValueI(), ValueF(), Count(2), IsFloat(false) { Name = name; @@ -391,7 +375,7 @@ public: } - CNumbersAttribute(const char* name, core::dimension2df value) : + CNumbersAttribute(const char* name, core::dimension2df value) : ValueI(), ValueF(), Count(2), IsFloat(true) { Name = name; @@ -400,7 +384,7 @@ public: } - + // getting values virtual s32 getInt() { @@ -415,20 +399,20 @@ public: virtual f32 getFloat() { - if (Count==0) + if (Count==0) return 0.0f; if (IsFloat) return ValueF[0]; else - return (f32)ValueI[0]; + return (f32)ValueI[0]; } virtual bool getBool() { // return true if any number is nonzero bool ret=false; - + for (u32 i=0; i < Count; ++i) if ( IsFloat ? (ValueF[i] != 0) : (ValueI[i] != 0) ) { @@ -437,14 +421,14 @@ public: } return ret; - + } virtual core::stringc getString() { core::stringc outstr; - + for (u32 i=0; i c+r*4) + if (Count > c+r*4) ret(r,c) = ValueF[c+r*4]; } else { for (u32 r=0; r<4; ++r) for (u32 c=0; c<4; ++c) - if (Count > c+r*4) + if (Count > c+r*4) ret(r,c) = (f32)ValueI[c+r*4]; } return ret; @@ -747,7 +731,7 @@ public: return ValueI; } - + // setting values virtual void setInt(s32 intValue) { @@ -804,14 +788,14 @@ public: f32 c = 0; P = core::fast_atof_move(P, c); ValueI[i] = (s32)c; - + } } } // todo: warning message //if (i < Count-1) //{ - // + // //} } @@ -912,14 +896,14 @@ public: { for (u32 r=0; r<4; ++r) for (u32 c=0; c<4; ++c) - if (Count > c+r*4) + if (Count > c+r*4) ValueF[c+r*4] = value(r,c); } else { for (u32 r=0; r<4; ++r) for (u32 c=0; c<4; ++c) - if (Count > c+r*4) + if (Count > c+r*4) ValueI[c+r*4] = (s32)value(r,c); } } @@ -1082,7 +1066,7 @@ public: } } - virtual void setDimension2d(core::dimension2di v) + virtual void setDimension2d(core::dimension2du v) { reset(); if (IsFloat) @@ -1205,12 +1189,11 @@ public: setInt((s32)floatValue); } - virtual E_ATTRIBUTE_TYPE getType() const + virtual E_ATTRIBUTE_TYPE getType() const { return EAT_COLORF; } - virtual const wchar_t* getTypeString() const { return L"colorf"; @@ -1224,7 +1207,9 @@ class CColorAttribute : public CNumbersAttribute { public: - CColorAttribute(const char* name, video::SColorf value) : CNumbersAttribute(name, value) {} + CColorAttribute(const char* name, const video::SColorf& value) : CNumbersAttribute(name, value) {} + + CColorAttribute(const char* name, const video::SColor& value) : CNumbersAttribute(name, value) {} virtual s32 getInt() { @@ -1253,16 +1238,20 @@ public: virtual core::stringw getStringW() { char tmp[10]; - video::SColor c = getColor(); - sprintf(tmp, "%08x", c.color); + const video::SColor c = getColor(); + sprintf(tmp, "%02x%02x%02x%02x", c.getAlpha(), c.getRed(), c.getGreen(), c.getBlue()); return core::stringw(tmp); } virtual void setString(const char* text) { - video::SColor c; - sscanf(text, "%08x", &c.color); - setColor(c); + u32 c; + if (sscanf(text, "%08x", &c)!=1) + { + CNumbersAttribute::setString(text); + } + else + setColor(c); } virtual E_ATTRIBUTE_TYPE getType() const @@ -1488,9 +1477,9 @@ public: // vector2df -// dimension2di +// dimension2du -/* +/* Special attributes */ @@ -1607,7 +1596,7 @@ public: Name = name; setString(value); } - + CStringAttribute(const char* name, const wchar_t* value) { IsStringW = true; @@ -1626,7 +1615,7 @@ public: { if (IsStringW) return atoi(core::stringc(ValueW.c_str()).c_str()); - else + else return atoi(Value.c_str()); } @@ -1641,7 +1630,7 @@ public: virtual bool getBool() { if (IsStringW) - return Value.equals_ignore_case(L"true"); + return ValueW.equals_ignore_case(L"true"); else return Value.equals_ignore_case("true"); } @@ -1708,9 +1697,9 @@ public: return L"string"; } - virtual void getBinary(void* outdata, s32 maxLenght) + virtual void getBinary(void* outdata, s32 maxLength) { - s32 dataSize = maxLenght; + s32 dataSize = maxLength; c8* datac8 = (c8*)(outdata); s32 p = 0; const c8* dataString = Value.c_str(); @@ -1730,9 +1719,9 @@ public: } }; - virtual void setBinary(void* data, s32 maxLenght) + virtual void setBinary(void* data, s32 maxLength) { - s32 dataSize = maxLenght; + s32 dataSize = maxLength; c8* datac8 = (c8*)(data); char tmp[3]; tmp[2] = 0; @@ -1839,20 +1828,13 @@ public: virtual core::stringw getStringW() { - return core::stringw(Value ? Value->getName().c_str() : 0); + return core::stringw(Value ? Value->getName().getPath().c_str() : 0); } virtual core::stringc getString() { - return Value ? Value->getName() : core::stringc(); - } - - virtual void getString(char* target) - { - if (Value) - strcpy(target, Value->getName().c_str()); - else - target[0] = 0x0; + // since texture names can be stringw we are careful with the types + return core::stringc(Value ? Value->getName().getPath().c_str() : 0); } virtual void setString(const char* text) @@ -1868,6 +1850,9 @@ public: virtual void setTexture(video::ITexture* value) { + if ( value == Value ) + return; + if (Value) Value->drop(); @@ -1899,7 +1884,7 @@ class CStringWArrayAttribute : public IAttribute { public: - CStringWArrayAttribute(const char* name, core::array value) + CStringWArrayAttribute(const char* name, const core::array& value) { Name = name; setArray(value); @@ -1910,7 +1895,7 @@ public: return Value; } - virtual void setArray(core::array value) + virtual void setArray(const core::array& value) { Value = value; } @@ -1940,22 +1925,25 @@ public: Value = value; } - virtual s32 getInt() - { - return *(s32*)(&Value); + virtual s32 getInt() + { + return *static_cast(Value); } virtual bool getBool() - { + { return (Value != 0); } - virtual void getString(char* target) + virtual core::stringw getStringW() { - sprintf(target, "0x%x", *(int*)(&Value)); + wchar_t buf[32]; + swprintf(buf, 32, L"%p", Value); + + return core::stringw(buf); } - virtual void setString(const char* text) + virtual void setString(const char* text) { sscanf(text, "0x%x", (unsigned int*)(&Value)); } @@ -1975,7 +1963,7 @@ public: return Value; } - + virtual const wchar_t* getTypeString() const { return L"userPointer"; diff --git a/src/dep/src/irrlicht/CAttributes.cpp b/src/dep/src/irrlicht/CAttributes.cpp index 21443ef..66530d1 100644 --- a/src/dep/src/irrlicht/CAttributes.cpp +++ b/src/dep/src/irrlicht/CAttributes.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -181,13 +181,13 @@ core::stringw CAttributes::getAttributeAsStringW(s32 index) //! Adds an attribute as an array of wide strings -void CAttributes::addArray(const c8* attributeName, core::array value) +void CAttributes::addArray(const c8* attributeName, const core::array& value) { Attributes.push_back(new CStringWArrayAttribute(attributeName, value)); } //! Sets an attribute value as an array of wide strings. -void CAttributes::setAttribute(const c8* attributeName, const core::array value) +void CAttributes::setAttribute(const c8* attributeName, const core::array& value) { IAttribute* att = getAttributeP(attributeName); if (att) @@ -220,7 +220,7 @@ core::array CAttributes::getAttributeAsArray(s32 index) } //! Sets an attribute as an array of wide strings -void CAttributes::setAttribute(s32 index, core::array value) +void CAttributes::setAttribute(s32 index, const core::array& value) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setArray(value); @@ -1366,6 +1366,12 @@ void CAttributes::readAttributeFromXML(io::IXMLReader* reader) Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else + if (element == L"binary") + { + addBinary(name.c_str(), 0, 0); + Attributes.getLast()->setString(reader->getAttributeValue(L"value")); + } + else if (element == L"color") { addColor(name.c_str(), video::SColor()); @@ -1398,7 +1404,7 @@ void CAttributes::readAttributeFromXML(io::IXMLReader* reader) else if (element == L"string") { - addString(name.c_str(), ""); + addString(name.c_str(), L""); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else @@ -1481,6 +1487,12 @@ void CAttributes::readAttributeFromXML(io::IXMLReader* reader) } addArray(name.c_str(),tmpArray); } + else + if (element == L"userPointer") + { + // It's debatable if a pointer should be set or not, but it's more likely that adding it now would wreck user-applications. + // Also it probably doesn't makes sense setting this to a value when it comes from file. + } } //! Write these attributes into a xml file diff --git a/src/dep/src/irrlicht/CAttributes.h b/src/dep/src/irrlicht/CAttributes.h index c001a88..160ab25 100644 --- a/src/dep/src/irrlicht/CAttributes.h +++ b/src/dep/src/irrlicht/CAttributes.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,7 @@ #define __C_ATTRIBUTES_H_INCLUDED__ #include "IAttributes.h" +#include "IAttribute.h" namespace irr { @@ -17,7 +18,6 @@ namespace video namespace io { -class IAttribute; //! Implementation of the IAttributes interface class CAttributes : public IAttributes @@ -30,7 +30,7 @@ public: //! Returns amount of attributes in this collection of attributes. virtual u32 getAttributeCount() const; - //! Returns attribute name by index. + //! Returns attribute name by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual const c8* getAttributeName(s32 index); @@ -38,7 +38,7 @@ public: //! \param attributeName: Name for the attribute virtual E_ATTRIBUTE_TYPE getAttributeType(const c8* attributeName); - //! Returns attribute type by index. + //! Returns attribute type by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual E_ATTRIBUTE_TYPE getAttributeType(s32 index); @@ -46,7 +46,7 @@ public: //! \param attributeName: String for the attribute type virtual const wchar_t* getAttributeTypeString(const c8* attributeName); - //! Returns the type string of the attribute by index. + //! Returns the type string of the attribute by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual const wchar_t* getAttributeTypeString(s32 index); @@ -126,14 +126,14 @@ public: //! Adds an attribute as string virtual void addString(const c8* attributeName, const c8* value); - //! Sets an attribute value as string. + //! Sets an attribute value as string. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute virtual void setAttribute(const c8* attributeName, const c8* value); //! Gets an attribute as string. //! \param attributeName: Name of the attribute to get. - //! \return Returns value of the attribute previously set by setAttribute() + //! \return Returns value of the attribute previously set by setAttribute() //! or 0 if attribute is not set. virtual core::stringc getAttributeAsString(const c8* attributeName); @@ -142,11 +142,11 @@ public: //! \param target: Buffer where the string is copied to. virtual void getAttributeAsString(const c8* attributeName, c8* target); - //! Returns attribute value as string by index. + //! Returns attribute value as string by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::stringc getAttributeAsString(s32 index); - //! Sets an attribute value as string. + //! Sets an attribute value as string. //! \param attributeName: Name for the attribute virtual void setAttribute(s32 index, const c8* value); @@ -155,14 +155,14 @@ public: //! Adds an attribute as string virtual void addString(const c8* attributeName, const wchar_t* value); - //! Sets an attribute value as string. + //! Sets an attribute value as string. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute virtual void setAttribute(const c8* attributeName, const wchar_t* value); //! Gets an attribute as string. //! \param attributeName: Name of the attribute to get. - //! \return Returns value of the attribute previously set by setAttribute() + //! \return Returns value of the attribute previously set by setAttribute() //! or 0 if attribute is not set. virtual core::stringw getAttributeAsStringW(const c8* attributeName); @@ -171,11 +171,11 @@ public: //! \param target: Buffer where the string is copied to. virtual void getAttributeAsStringW(const c8* attributeName, wchar_t* target); - //! Returns attribute value as string by index. + //! Returns attribute value as string by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::stringw getAttributeAsStringW(s32 index); - //! Sets an attribute value as string. + //! Sets an attribute value as string. //! \param attributeName: Name for the attribute virtual void setAttribute(s32 index, const wchar_t* value); @@ -210,25 +210,25 @@ public: */ //! Adds an attribute as wide string array - virtual void addArray(const c8* attributeName, core::array value); + virtual void addArray(const c8* attributeName, const core::array& value); - //! Sets an attribute value as a wide string array. + //! Sets an attribute value as a wide string array. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute - virtual void setAttribute(const c8* attributeName, const core::array value); + virtual void setAttribute(const c8* attributeName, const core::array& value); //! Gets an attribute as an array of wide strings. //! \param attributeName: Name of the attribute to get. - //! \return Returns value of the attribute previously set by setAttribute() + //! \return Returns value of the attribute previously set by setAttribute() //! or 0 if attribute is not set. virtual core::array getAttributeAsArray(const c8* attributeName); - //! Returns attribute value as an array of wide strings by index. + //! Returns attribute value as an array of wide strings by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::array getAttributeAsArray(s32 index); //! Sets an attribute as an array of wide strings - virtual void setAttribute(s32 index, core::array value); + virtual void setAttribute(s32 index, const core::array& value); /* @@ -244,7 +244,7 @@ public: //! Gets an attribute as boolean value //! \param attributeName: Name of the attribute to get. - //! \return Returns value of the attribute previously set by setAttribute() + //! \return Returns value of the attribute previously set by setAttribute() virtual bool getAttributeAsBool(const c8* attributeName); //! Gets an attribute as boolean value @@ -290,11 +290,11 @@ public: //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual const c8* getAttributeAsEnumeration(s32 index); - //! Gets the list of enumeration literals of an enumeration attribute + //! Gets the list of enumeration literals of an enumeration attribute //! \param attributeName: Name of the attribute to get. virtual void getAttributeEnumerationLiteralsOfEnumeration(const c8* attributeName, core::array& outLiterals); - //! Gets the list of enumeration literals of an enumeration attribute + //! Gets the list of enumeration literals of an enumeration attribute //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual void getAttributeEnumerationLiteralsOfEnumeration(s32 index, core::array& outLiterals); @@ -371,7 +371,7 @@ public: //! Gets an attribute as 3d vector //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::vector3df getAttributeAsVector3d(s32 index); - + //! Sets an attribute as vector virtual void setAttribute(s32 index, core::vector3df v); @@ -428,7 +428,7 @@ public: matrix attribute - */ + */ //! Adds an attribute as matrix virtual void addMatrix(const c8* attributeName, const core::matrix4& v); @@ -619,7 +619,7 @@ public: virtual void setAttribute(s32 index, video::ITexture* texture); - + /* User Pointer Attribute @@ -654,77 +654,6 @@ protected: video::IVideoDriver* Driver; }; - -class IAttribute : public virtual IReferenceCounted -{ -public: - - virtual ~IAttribute() {}; - - virtual s32 getInt() { return 0; } - virtual f32 getFloat() { return 0; } - virtual video::SColorf getColorf() { return video::SColorf(1.0f,1.0f,1.0f,1.0f); } - virtual video::SColor getColor() { return video::SColor(255,255,255,255); } - virtual core::stringc getString() { return core::stringc(getStringW().c_str()); } - virtual core::stringw getStringW() { return core::stringw(); } - virtual core::array getArray() { return core::array(); }; - virtual bool getBool() { return false; } - virtual void getBinary(void* outdata, s32 maxLength) {}; - virtual core::vector3df getVector() { return core::vector3df(); } - virtual core::position2di getPosition() { return core::position2di(); } - virtual core::rect getRect() { return core::rect(); } - virtual core::quaternion getQuaternion(){ return core::quaternion(); } - virtual core::matrix4 getMatrix() { return core::matrix4(); } - virtual core::triangle3df getTriangle() { return core::triangle3df(); } - virtual core::vector2df getVector2d() { return core::vector2df(); } - virtual core::vector2di getVector2di() { return core::vector2di(); } - virtual core::line2df getLine2d() { return core::line2df(); } - virtual core::line2di getLine2di() { return core::line2di(); } - virtual core::line3df getLine3d() { return core::line3df(); } - virtual core::line3di getLine3di() { return core::line3di(); } - virtual core::dimension2di getDimension2d() { return core::dimension2di(); } - virtual core::aabbox3d getBBox() { return core::aabbox3d(); } - virtual core::plane3df getPlane() { return core::plane3df(); } - - virtual video::ITexture* getTexture() { return 0; } - virtual const char* getEnum() { return 0; } - virtual void* getUserPointer() { return 0; } - - virtual void setInt(s32 intValue) {}; - virtual void setFloat(f32 floatValue) {}; - virtual void setString(const char* text) {}; - virtual void setString(const wchar_t* text){ setString(core::stringc(text).c_str()); }; - virtual void setArray( core::array arr ) {}; - virtual void setColor(video::SColorf color) {}; - virtual void setColor(video::SColor color) {}; - virtual void setBool(bool boolValue) {}; - virtual void setBinary(void* data, s32 maxLenght) {}; - virtual void setVector(core::vector3df v) {}; - virtual void setPosition(core::position2di v) {}; - virtual void setRect(core::rect v) {}; - virtual void setQuaternion(core::quaternion v) {}; - virtual void setMatrix(core::matrix4 v) {}; - virtual void setTriangle(core::triangle3df v) {}; - virtual void setVector2d(core::vector2df v) {}; - virtual void setVector2d(core::vector2di v) {}; - virtual void setLine2d(core::line2df v) {}; - virtual void setLine2d(core::line2di v) {}; - virtual void setLine3d(core::line3df v) {}; - virtual void setLine3d(core::line3di v) {}; - virtual void setDimension2d(core::dimension2di v) {}; - virtual void setBBox(core::aabbox3d v) {}; - virtual void setPlane(core::plane3df v) {}; - virtual void setUserPointer(void* v) {}; - - virtual void setEnum(const char* enumValue, const char* const* enumerationLiterals) {}; - virtual void setTexture(video::ITexture*) {}; - - core::stringc Name; - - virtual E_ATTRIBUTE_TYPE getType() const = 0; - virtual const wchar_t* getTypeString() const = 0; -}; - } // end namespace io } // end namespace irr diff --git a/src/dep/src/irrlicht/CB3DMeshFileLoader.cpp b/src/dep/src/irrlicht/CB3DMeshFileLoader.cpp index 1fd7422..1713cbe 100644 --- a/src/dep/src/irrlicht/CB3DMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CB3DMeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2006-2008 Luke Hoschke +// Copyright (C) 2006-2010 Luke Hoschke // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,6 +12,7 @@ #include "CB3DMeshFileLoader.h" #include "IVideoDriver.h" +#include "IFileSystem.h" #include "os.h" #ifdef _DEBUG @@ -26,7 +27,7 @@ namespace scene //! Constructor CB3DMeshFileLoader::CB3DMeshFileLoader(scene::ISceneManager* smgr) : SceneManager(smgr), AnimatedMesh(0), B3DFile(0), NormalsInFile(false), - ShowWarning(true) + HasVertexColors(false), ShowWarning(true) { #ifdef _DEBUG setDebugName("CB3DMeshFileLoader"); @@ -36,9 +37,9 @@ CB3DMeshFileLoader::CB3DMeshFileLoader(scene::ISceneManager* smgr) //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CB3DMeshFileLoader::isALoadableFileExtension(const c8* fileName) const +bool CB3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(fileName, ".b3d") != 0; + return core::hasFileExtension ( filename, "b3d" ); } @@ -55,9 +56,6 @@ IAnimatedMesh* CB3DMeshFileLoader::createMesh(io::IReadFile* f) AnimatedMesh = new scene::CSkinnedMesh(); ShowWarning = true; // If true a warning is issued if too many textures are used - Buffers = &AnimatedMesh->getMeshBuffers(); - AllJoints = &AnimatedMesh->getAllJoints(); - if ( load() ) { AnimatedMesh->finalize(); @@ -77,6 +75,7 @@ bool CB3DMeshFileLoader::load() B3dStack.clear(); NormalsInFile=false; + HasVertexColors=false; //------ Get header ------ @@ -144,19 +143,17 @@ bool CB3DMeshFileLoader::load() Materials.clear(); Textures.clear(); - Buffers=0; - AllJoints=0; - return true; } -bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *InJoint) +bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *inJoint) { - const core::stringc JointName = readString(); + CSkinnedMesh::SJoint *joint = AnimatedMesh->addJoint(inJoint); + readString(joint->Name); #ifdef _B3D_READER_DEBUG - os::Printer::log("read ChunkNODE", JointName.c_str()); + os::Printer::log("read ChunkNODE", joint->Name.c_str()); #endif f32 position[3], scale[3], rotation[4]; @@ -165,27 +162,24 @@ bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *InJoint) readFloats(scale, 3); readFloats(rotation, 4); - CSkinnedMesh::SJoint *Joint = AnimatedMesh->createJoint(InJoint); - - Joint->Name = JointName; - Joint->Animatedposition = core::vector3df(position[0],position[1],position[2]) ; - Joint->Animatedscale = core::vector3df(scale[0],scale[1],scale[2]); - Joint->Animatedrotation = core::quaternion(rotation[1], rotation[2], rotation[3], rotation[0]); + joint->Animatedposition = core::vector3df(position[0],position[1],position[2]) ; + joint->Animatedscale = core::vector3df(scale[0],scale[1],scale[2]); + joint->Animatedrotation = core::quaternion(rotation[1], rotation[2], rotation[3], rotation[0]); //Build LocalMatrix: core::matrix4 positionMatrix; - positionMatrix.setTranslation( Joint->Animatedposition ); + positionMatrix.setTranslation( joint->Animatedposition ); core::matrix4 scaleMatrix; - scaleMatrix.setScale( Joint->Animatedscale ); - core::matrix4 rotationMatrix = Joint->Animatedrotation.getMatrix(); + scaleMatrix.setScale( joint->Animatedscale ); + core::matrix4 rotationMatrix = joint->Animatedrotation.getMatrix(); - Joint->LocalMatrix = positionMatrix * rotationMatrix * scaleMatrix; + joint->LocalMatrix = positionMatrix * rotationMatrix * scaleMatrix; - if (InJoint) - Joint->GlobalMatrix = InJoint->GlobalMatrix * Joint->LocalMatrix; + if (inJoint) + joint->GlobalMatrix = inJoint->GlobalMatrix * joint->LocalMatrix; else - Joint->GlobalMatrix = Joint->LocalMatrix; + joint->GlobalMatrix = joint->LocalMatrix; while(B3dStack.getLast().startposition + B3dStack.getLast().length > B3DFile->getPos()) // this chunk repeats { @@ -199,22 +193,22 @@ bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *InJoint) if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 ) { - if (!readChunkNODE(Joint)) + if (!readChunkNODE(joint)) return false; } else if ( strncmp( B3dStack.getLast().name, "MESH", 4 ) == 0 ) { - if (!readChunkMESH(Joint)) + if (!readChunkMESH(joint)) return false; } else if ( strncmp( B3dStack.getLast().name, "BONE", 4 ) == 0 ) { - if (!readChunkBONE(Joint)) + if (!readChunkBONE(joint)) return false; } else if ( strncmp( B3dStack.getLast().name, "KEYS", 4 ) == 0 ) { - if(!readChunkKEYS(Joint)) + if(!readChunkKEYS(joint)) return false; } else if ( strncmp( B3dStack.getLast().name, "ANIM", 4 ) == 0 ) @@ -236,7 +230,7 @@ bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *InJoint) } -bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint) +bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *inJoint) { #ifdef _B3D_READER_DEBUG os::Printer::log("read ChunkMESH"); @@ -251,6 +245,7 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint) #endif NormalsInFile=false; + HasVertexColors=false; while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats { @@ -264,41 +259,41 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint) if ( strncmp( B3dStack.getLast().name, "VRTS", 4 ) == 0 ) { - if (!readChunkVRTS(InJoint)) + if (!readChunkVRTS(inJoint)) return false; } else if ( strncmp( B3dStack.getLast().name, "TRIS", 4 ) == 0 ) { - scene::SSkinMeshBuffer *MeshBuffer = AnimatedMesh->createBuffer(); + scene::SSkinMeshBuffer *meshBuffer = AnimatedMesh->addMeshBuffer(); if (brush_id!=-1) { loadTextures(Materials[brush_id]); - MeshBuffer->Material=Materials[brush_id].Material; + meshBuffer->Material=Materials[brush_id].Material; } - if(readChunkTRIS(MeshBuffer,AnimatedMesh->getMeshBuffers().size()-1, vertices_Start)==false) + if(readChunkTRIS(meshBuffer,AnimatedMesh->getMeshBuffers().size()-1, vertices_Start)==false) return false; if (!NormalsInFile) { s32 i; - for ( i=0; i<(s32)MeshBuffer->Indices.size(); i+=3) + for ( i=0; i<(s32)meshBuffer->Indices.size(); i+=3) { - core::plane3df p(MeshBuffer->getVertex(MeshBuffer->Indices[i+0])->Pos, - MeshBuffer->getVertex(MeshBuffer->Indices[i+1])->Pos, - MeshBuffer->getVertex(MeshBuffer->Indices[i+2])->Pos); + core::plane3df p(meshBuffer->getVertex(meshBuffer->Indices[i+0])->Pos, + meshBuffer->getVertex(meshBuffer->Indices[i+1])->Pos, + meshBuffer->getVertex(meshBuffer->Indices[i+2])->Pos); - MeshBuffer->getVertex(MeshBuffer->Indices[i+0])->Normal += p.Normal; - MeshBuffer->getVertex(MeshBuffer->Indices[i+1])->Normal += p.Normal; - MeshBuffer->getVertex(MeshBuffer->Indices[i+2])->Normal += p.Normal; + meshBuffer->getVertex(meshBuffer->Indices[i+0])->Normal += p.Normal; + meshBuffer->getVertex(meshBuffer->Indices[i+1])->Normal += p.Normal; + meshBuffer->getVertex(meshBuffer->Indices[i+2])->Normal += p.Normal; } - for ( i = 0; i<(s32)MeshBuffer->getVertexCount(); ++i ) + for ( i = 0; i<(s32)meshBuffer->getVertexCount(); ++i ) { - MeshBuffer->getVertex(i)->Normal.normalize(); - BaseVertices[vertices_Start+i].Normal=MeshBuffer->getVertex(i)->Normal; + meshBuffer->getVertex(i)->Normal.normalize(); + BaseVertices[vertices_Start+i].Normal=meshBuffer->getVertex(i)->Normal; } } } @@ -329,7 +324,7 @@ VRTS: float tex_coords[tex_coord_sets][tex_coord_set_size] ;tex coords } */ -bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint) +bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *inJoint) { #ifdef _B3D_READER_DEBUG os::Printer::log("read ChunkVRTS"); @@ -355,16 +350,22 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint) //------ Allocate Memory, for speed -----------// - s32 NumberOfReads = 3; + s32 numberOfReads = 3; if (flags & 1) - NumberOfReads += 3; + { + NormalsInFile = true; + numberOfReads += 3; + } if (flags & 2) - NumberOfReads += 4; + { + numberOfReads += 4; + HasVertexColors=true; + } - NumberOfReads += tex_coord_sets*tex_coord_set_size; + numberOfReads += tex_coord_sets*tex_coord_set_size; - const s32 memoryNeeded = (B3dStack.getLast().length / sizeof(f32)) / NumberOfReads; + const s32 memoryNeeded = (B3dStack.getLast().length / sizeof(f32)) / numberOfReads; BaseVertices.reallocate(memoryNeeded + BaseVertices.size() + 1); AnimatedVertices_VertexID.reallocate(memoryNeeded + AnimatedVertices_VertexID.size() + 1); @@ -381,11 +382,7 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint) readFloats(position, 3); if (flags & 1) - { - NormalsInFile = true; readFloats(normal, 3); - } - if (flags & 2) readFloats(color, 4); @@ -413,8 +410,8 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint) tu, tv, tu2, tv2); // Transform the Vertex position by nested node... - InJoint->GlobalMatrix.transformVect(Vertex.Pos); - InJoint->GlobalMatrix.rotateVect(Vertex.Normal); + inJoint->GlobalMatrix.transformVect(Vertex.Pos); + inJoint->GlobalMatrix.rotateVect(Vertex.Normal); //Add it... BaseVertices.push_back(Vertex); @@ -429,7 +426,7 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint) } -bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 MeshBufferID, s32 vertices_Start) +bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *meshBuffer, u32 meshBufferID, s32 vertices_Start) { #ifdef _B3D_READER_DEBUG os::Printer::log("read ChunkTRIS"); @@ -449,13 +446,13 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M { loadTextures(Materials[triangle_brush_id]); B3dMaterial = &Materials[triangle_brush_id]; - MeshBuffer->Material = B3dMaterial->Material; + meshBuffer->Material = B3dMaterial->Material; } else B3dMaterial = 0; const s32 memoryNeeded = B3dStack.getLast().length / sizeof(s32); - MeshBuffer->Indices.reallocate(memoryNeeded + MeshBuffer->Indices.size() + 1); + meshBuffer->Indices.reallocate(memoryNeeded + meshBuffer->Indices.size() + 1); while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats { @@ -483,7 +480,7 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M if (AnimatedVertices_VertexID[ vertex_id[i] ] != -1) { - if ( AnimatedVertices_BufferID[ vertex_id[i] ] != (s32)MeshBufferID ) //If this vertex is linked in a different meshbuffer + if ( AnimatedVertices_BufferID[ vertex_id[i] ] != (s32)meshBufferID ) //If this vertex is linked in a different meshbuffer { AnimatedVertices_VertexID[ vertex_id[i] ] = -1; AnimatedVertices_BufferID[ vertex_id[i] ] = -1; @@ -494,24 +491,26 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M { //Check for lightmapping: if (BaseVertices[ vertex_id[i] ].TCoords2 != core::vector2df(0.f,0.f)) - MeshBuffer->MoveTo_2TCoords(); //Will only affect the meshbuffer the first time this is called + meshBuffer->convertTo2TCoords(); //Will only affect the meshbuffer the first time this is called //Add the vertex to the meshbuffer: - if (MeshBuffer->VertexType == video::EVT_STANDARD) - MeshBuffer->Vertices_Standard.push_back( BaseVertices[ vertex_id[i] ] ); + if (meshBuffer->VertexType == video::EVT_STANDARD) + meshBuffer->Vertices_Standard.push_back( BaseVertices[ vertex_id[i] ] ); else - MeshBuffer->Vertices_2TCoords.push_back(BaseVertices[ vertex_id[i] ] ); + meshBuffer->Vertices_2TCoords.push_back(BaseVertices[ vertex_id[i] ] ); //create vertex id to meshbuffer index link: - AnimatedVertices_VertexID[ vertex_id[i] ] = MeshBuffer->getVertexCount()-1; - AnimatedVertices_BufferID[ vertex_id[i] ] = MeshBufferID; + AnimatedVertices_VertexID[ vertex_id[i] ] = meshBuffer->getVertexCount()-1; + AnimatedVertices_BufferID[ vertex_id[i] ] = meshBufferID; if (B3dMaterial) { - // Apply Material/Colour/etc... - video::S3DVertex *Vertex=MeshBuffer->getVertex(MeshBuffer->getVertexCount()-1); + // Apply Material/Color/etc... + video::S3DVertex *Vertex=meshBuffer->getVertex(meshBuffer->getVertexCount()-1); - if (Vertex->Color.getAlpha() == 255) + if (!HasVertexColors) + Vertex->Color=B3dMaterial->Material.DiffuseColor; + else if (Vertex->Color.getAlpha() == 255) Vertex->Color.setAlpha( (s32)(B3dMaterial->alpha * 255.0f) ); // Use texture's scale @@ -531,9 +530,9 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M } } - MeshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[0] ] ); - MeshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[1] ] ); - MeshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[2] ] ); + meshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[0] ] ); + meshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[1] ] ); + meshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[2] ] ); } B3dStack.erase(B3dStack.size()-1); @@ -545,7 +544,7 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M } -bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *InJoint) +bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *inJoint) { #ifdef _B3D_READER_DEBUG os::Printer::log("read ChunkBONE"); @@ -555,25 +554,24 @@ bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *InJoint) { while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats { - CSkinnedMesh::SWeight *weight=AnimatedMesh->createWeight(InJoint); - u32 globalVertexID; - + f32 strength; B3DFile->read(&globalVertexID, sizeof(globalVertexID)); - B3DFile->read(&weight->strength, sizeof(weight->strength)); + B3DFile->read(&strength, sizeof(strength)); #ifdef __BIG_ENDIAN__ globalVertexID = os::Byteswap::byteswap(globalVertexID); - weight->strength = os::Byteswap::byteswap(weight->strength); + strength = os::Byteswap::byteswap(strength); #endif if (AnimatedVertices_VertexID[globalVertexID]==-1) { os::Printer::log("B3dMeshLoader: Weight has bad vertex id (no link to meshbuffer index found)"); - weight->vertex_id = weight->buffer_id = 0; } - else + else if (strength >0) { - //Find the MeshBuffer and Vertex index from the Global Vertex ID: + CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(inJoint); + weight->strength=strength; + //Find the meshbuffer and Vertex index from the Global Vertex ID: weight->vertex_id = AnimatedVertices_VertexID[globalVertexID]; weight->buffer_id = AnimatedVertices_BufferID[globalVertexID]; } @@ -585,7 +583,7 @@ bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *InJoint) } -bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *InJoint) +bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *inJoint) { #ifdef _B3D_READER_DEBUG // os::Printer::log("read ChunkKEYS"); @@ -597,6 +595,13 @@ bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *InJoint) flags = os::Byteswap::byteswap(flags); #endif + CSkinnedMesh::SPositionKey *oldPosKey=0; + core::vector3df oldPos[2]; + CSkinnedMesh::SScaleKey *oldScaleKey=0; + core::vector3df oldScale[2]; + CSkinnedMesh::SRotationKey *oldRotKey=0; + core::quaternion oldRot[2]; + bool isFirst[3]={true,true,true}; while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats { s32 frame; @@ -606,29 +611,109 @@ bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *InJoint) frame = os::Byteswap::byteswap(frame); #endif - // Add key frames + // Add key frames, frames in Irrlicht are zero-based f32 data[4]; if (flags & 1) { readFloats(data, 3); - CSkinnedMesh::SPositionKey *Key=AnimatedMesh->createPositionKey(InJoint); - Key->frame = (f32)frame; - Key->position.set(data[0], data[1], data[2]); + if ((oldPosKey!=0) && (oldPos[0]==oldPos[1])) + { + const core::vector3df pos(data[0], data[1], data[2]); + if (oldPos[1]==pos) + oldPosKey->frame = (f32)frame-1; + else + { + oldPos[0]=oldPos[1]; + oldPosKey=AnimatedMesh->addPositionKey(inJoint); + oldPosKey->frame = (f32)frame-1; + oldPos[1].set(oldPosKey->position.set(pos)); + } + } + else if (oldPosKey==0 && isFirst[0]) + { + oldPosKey=AnimatedMesh->addPositionKey(inJoint); + oldPosKey->frame = (f32)frame-1; + oldPos[0].set(oldPosKey->position.set(data[0], data[1], data[2])); + oldPosKey=0; + isFirst[0]=false; + } + else + { + if (oldPosKey!=0) + oldPos[0]=oldPos[1]; + oldPosKey=AnimatedMesh->addPositionKey(inJoint); + oldPosKey->frame = (f32)frame-1; + oldPos[1].set(oldPosKey->position.set(data[0], data[1], data[2])); + } } if (flags & 2) { readFloats(data, 3); - CSkinnedMesh::SScaleKey *Key=AnimatedMesh->createScaleKey(InJoint); - Key->frame = (f32)frame; - Key->scale.set(data[0], data[1], data[2]); + if ((oldScaleKey!=0) && (oldScale[0]==oldScale[1])) + { + const core::vector3df scale(data[0], data[1], data[2]); + if (oldScale[1]==scale) + oldScaleKey->frame = (f32)frame-1; + else + { + oldScale[0]=oldScale[1]; + oldScaleKey=AnimatedMesh->addScaleKey(inJoint); + oldScaleKey->frame = (f32)frame-1; + oldScale[1].set(oldScaleKey->scale.set(scale)); + } + } + else if (oldScaleKey==0 && isFirst[1]) + { + oldScaleKey=AnimatedMesh->addScaleKey(inJoint); + oldScaleKey->frame = (f32)frame-1; + oldScale[0].set(oldScaleKey->scale.set(data[0], data[1], data[2])); + oldScaleKey=0; + isFirst[1]=false; + } + else + { + if (oldScaleKey!=0) + oldScale[0]=oldScale[1]; + oldScaleKey=AnimatedMesh->addScaleKey(inJoint); + oldScaleKey->frame = (f32)frame-1; + oldScale[1].set(oldScaleKey->scale.set(data[0], data[1], data[2])); + } } if (flags & 4) { readFloats(data, 4); - CSkinnedMesh::SRotationKey *Key=AnimatedMesh->createRotationKey(InJoint); - Key->frame = (f32)frame; - // meant to be in this order since b3d stores W first - Key->rotation.set(data[1], data[2], data[3], data[0]); + if ((oldRotKey!=0) && (oldRot[0]==oldRot[1])) + { + // meant to be in this order since b3d stores W first + const core::quaternion rot(data[1], data[2], data[3], data[0]); + if (oldRot[1]==rot) + oldRotKey->frame = (f32)frame-1; + else + { + oldRot[0]=oldRot[1]; + oldRotKey=AnimatedMesh->addRotationKey(inJoint); + oldRotKey->frame = (f32)frame-1; + oldRot[1].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0])); + } + } + else if (oldRotKey==0 && isFirst[2]) + { + oldRotKey=AnimatedMesh->addRotationKey(inJoint); + oldRotKey->frame = (f32)frame-1; + // meant to be in this order since b3d stores W first + oldRot[0].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0])); + oldRotKey=0; + isFirst[2]=false; + } + else + { + if (oldRotKey!=0) + oldRot[0]=oldRot[1]; + oldRotKey=AnimatedMesh->addRotationKey(inJoint); + oldRotKey->frame = (f32)frame-1; + // meant to be in this order since b3d stores W first + oldRot[1].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0])); + } } } @@ -672,8 +757,8 @@ bool CB3DMeshFileLoader::readChunkTEXS() Textures.push_back(SB3dTexture()); SB3dTexture& B3dTexture = Textures.getLast(); - B3dTexture.TextureName=readString(); - B3dTexture.TextureName=stripPathFromString(B3DFile->getFileName(),true) + stripPathFromString(B3dTexture.TextureName,false); + readString(B3dTexture.TextureName); + B3dTexture.TextureName.replace('\\','/'); #ifdef _B3D_READER_DEBUG os::Printer::log("read Texture", B3dTexture.TextureName.c_str()); #endif @@ -722,9 +807,10 @@ bool CB3DMeshFileLoader::readChunkBRUS() { // This is what blitz basic calls a brush, like a Irrlicht Material - const core::stringc name = readString(); + core::stringc name; + readString(name); #ifdef _B3D_READER_DEBUG - os::Printer::log("read Material", name.c_str()); + os::Printer::log("read Material", name); #endif Materials.push_back(SB3dMaterial()); SB3dMaterial& B3dMaterial=Materials.getLast(); @@ -859,6 +945,7 @@ bool CB3DMeshFileLoader::readChunkBRUS() } B3dMaterial.Material.DiffuseColor = video::SColorf(B3dMaterial.red, B3dMaterial.green, B3dMaterial.blue, B3dMaterial.alpha).toSColor(); + B3dMaterial.Material.ColorMaterial=video::ECM_NONE; //------ Material fx ------ @@ -870,7 +957,8 @@ bool CB3DMeshFileLoader::readChunkBRUS() else B3dMaterial.Material.AmbientColor = B3dMaterial.Material.DiffuseColor; - //if (B3dMaterial.fx & 2) //use vertex colors instead of brush color + if (B3dMaterial.fx & 2) //use vertex colors instead of brush color + B3dMaterial.Material.ColorMaterial=video::ECM_DIFFUSE_AND_AMBIENT; if (B3dMaterial.fx & 4) //flatshaded B3dMaterial.Material.GouraudShading = false; @@ -878,11 +966,11 @@ bool CB3DMeshFileLoader::readChunkBRUS() if (B3dMaterial.fx & 16) //disable backface culling B3dMaterial.Material.BackfaceCulling = false; -// if (B3dMaterial.fx & 32) //force vertex alpha-blending -// { -// B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; -// B3dMaterial.Material.ZWriteEnable = false; -// } + if (B3dMaterial.fx & 32) //force vertex alpha-blending + { + B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; + B3dMaterial.Material.ZWriteEnable = false; + } B3dMaterial.Material.Shininess = B3dMaterial.shininess; } @@ -907,12 +995,32 @@ void CB3DMeshFileLoader::loadTextures(SB3dMaterial& material) const SB3dTexture* B3dTexture = material.Textures[i]; if (B3dTexture && B3dTexture->TextureName.size() && !material.Material.getTexture(i)) { - SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, (B3dTexture->Flags & 0x8) ? true:false); - material.Material.setTexture(i, SceneManager->getVideoDriver()->getTexture( B3dTexture->TextureName.c_str() )); + if (!SceneManager->getParameters()->getAttributeAsBool(B3D_LOADER_IGNORE_MIPMAP_FLAG)) + SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, (B3dTexture->Flags & 0x8) ? true:false); + { + video::ITexture* tex = 0; + io::IFileSystem* fs = SceneManager->getFileSystem(); + io::path texnameWithUserPath( SceneManager->getParameters()->getAttributeAsString(B3D_TEXTURE_PATH) ); + if ( texnameWithUserPath.size() ) + { + texnameWithUserPath += '/'; + texnameWithUserPath += B3dTexture->TextureName; + } + if (fs->existFile(texnameWithUserPath)) + tex = SceneManager->getVideoDriver()->getTexture(texnameWithUserPath); + else if (fs->existFile(B3dTexture->TextureName)) + tex = SceneManager->getVideoDriver()->getTexture(B3dTexture->TextureName); + else if (fs->existFile(fs->getFileDir(B3DFile->getFileName()) +"/"+ fs->getFileBasename(B3dTexture->TextureName))) + tex = SceneManager->getVideoDriver()->getTexture(fs->getFileDir(B3DFile->getFileName()) +"/"+ fs->getFileBasename(B3dTexture->TextureName)); + else + tex = SceneManager->getVideoDriver()->getTexture(fs->getFileBasename(B3dTexture->TextureName)); + + material.Material.setTexture(i, tex); + } if (material.Textures[i]->Flags & 0x10) // Clamp U - material.Material.TextureLayer[i].TextureWrap=video::ETC_CLAMP; + material.Material.TextureLayer[i].TextureWrapU=video::ETC_CLAMP; if (material.Textures[i]->Flags & 0x20) // Clamp V - material.Material.TextureLayer[i].TextureWrap=video::ETC_CLAMP; + material.Material.TextureLayer[i].TextureWrapV=video::ETC_CLAMP; } } @@ -921,42 +1029,20 @@ void CB3DMeshFileLoader::loadTextures(SB3dMaterial& material) const } -core::stringc CB3DMeshFileLoader::readString() +void CB3DMeshFileLoader::readString(core::stringc& newstring) { - core::stringc newstring; + newstring=""; while (B3DFile->getPos() <= B3DFile->getSize()) { c8 character; B3DFile->read(&character, sizeof(character)); if (character==0) - break; + return; newstring.append(character); } - return newstring; } -core::stringc CB3DMeshFileLoader::stripPathFromString(const core::stringc& string, bool returnPath) const -{ - s32 slashIndex=string.findLast('/'); // forward slash - s32 backSlash=string.findLast('\\'); // back slash - - if (backSlash>slashIndex) slashIndex=backSlash; - - if (slashIndex==-1)//no slashes found - { - if (returnPath) - return core::stringc(); //no path to return - else - return string; - } - - if (returnPath) - return string.subString(0, slashIndex + 1); - else - return string.subString(slashIndex+1, string.size() - (slashIndex+1)); -} - void CB3DMeshFileLoader::readFloats(f32* vec, u32 count) { B3DFile->read(vec, count*sizeof(f32)); diff --git a/src/dep/src/irrlicht/CB3DMeshFileLoader.h b/src/dep/src/irrlicht/CB3DMeshFileLoader.h index 151ea1c..6da02a9 100644 --- a/src/dep/src/irrlicht/CB3DMeshFileLoader.h +++ b/src/dep/src/irrlicht/CB3DMeshFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2006-2008 Luke Hoschke +// Copyright (C) 2006-2010 Luke Hoschke // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -32,7 +32,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -105,8 +105,7 @@ private: void loadTextures(SB3dMaterial& material) const; - core::stringc readString(); - core::stringc stripPathFromString(const core::stringc& string, bool returnPath=false) const; + void readString(core::stringc& newstring); void readFloats(f32* vec, u32 count); core::array B3dStack; @@ -120,14 +119,12 @@ private: core::array BaseVertices; - core::array *Buffers; - core::array *AllJoints; - ISceneManager* SceneManager; CSkinnedMesh* AnimatedMesh; io::IReadFile* B3DFile; bool NormalsInFile; + bool HasVertexColors; bool ShowWarning; }; diff --git a/src/dep/src/irrlicht/CBSPMeshFileLoader.cpp b/src/dep/src/irrlicht/CBSPMeshFileLoader.cpp index 11553fc..1a53873 100644 --- a/src/dep/src/irrlicht/CBSPMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CBSPMeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -38,9 +38,9 @@ CBSPMeshFileLoader::~CBSPMeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CBSPMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CBSPMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".bsp") || strstr(filename, ".shader"); + return core::hasFileExtension ( filename, "bsp", "shader", "cfg" ); } @@ -50,27 +50,51 @@ bool CBSPMeshFileLoader::isALoadableFileExtension(const c8* filename) const //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CBSPMeshFileLoader::createMesh(io::IReadFile* file) { - // load quake 3 bsp - if (strstr(file->getFileName(), ".bsp")) + s32 type = core::isFileExtension ( file->getFileName(), "bsp", "shader", "cfg" ); + CQ3LevelMesh* q = 0; + + switch ( type ) { - CQ3LevelMesh* q = new CQ3LevelMesh(FileSystem, SceneManager); + case 1: + q = new CQ3LevelMesh(FileSystem, SceneManager, LoadParam); - q->getShader("scripts/models.shader"); - q->getShader("scripts/liquid.shader"); - //q->getShader("scripts/sky.shader"); + // determine real shaders in LoadParam + if ( 0 == LoadParam.loadAllShaders ) + { + q->getShader("scripts/common.shader"); + q->getShader("scripts/sfx.shader"); + q->getShader("scripts/gfx.shader"); + q->getShader("scripts/liquid.shader"); + q->getShader("scripts/models.shader"); + q->getShader("scripts/walls.shader"); + //q->getShader("scripts/sky.shader"); + } - if ( q->loadFile(file) ) + if ( q->loadFile(file) ) + return q; + + q->drop(); + break; + + case 2: + q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam); + q->getShader( file ); return q; + break; - q->drop(); - } - - // load quake 3 shader container - if (strstr(file->getFileName(), ".shader")) - { - CQ3LevelMesh* q = new CQ3LevelMesh(FileSystem, SceneManager); - q->getShader(file->getFileName()); - return q; + case 3: + // load quake 3 loading parameter + if ( file->getFileName() == "levelparameter.cfg" ) + { + file->read ( &LoadParam, sizeof ( LoadParam ) ); + } + else + { + q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam); + q->getConfiguration( file ); + return q; + } + break; } return 0; diff --git a/src/dep/src/irrlicht/CBSPMeshFileLoader.h b/src/dep/src/irrlicht/CBSPMeshFileLoader.h index 88e3612..4f96a3e 100644 --- a/src/dep/src/irrlicht/CBSPMeshFileLoader.h +++ b/src/dep/src/irrlicht/CBSPMeshFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,6 +9,7 @@ #include "IFileSystem.h" #include "IVideoDriver.h" #include "ISceneManager.h" +#include "IQ3Shader.h" namespace irr { @@ -28,7 +29,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -40,6 +41,8 @@ private: io::IFileSystem* FileSystem; scene::ISceneManager* SceneManager; + + quake3::Q3LevelLoadParameter LoadParam; }; } // end namespace scene diff --git a/src/dep/src/irrlicht/CBillboardSceneNode.cpp b/src/dep/src/irrlicht/CBillboardSceneNode.cpp index 86cd70d..56a9116 100644 --- a/src/dep/src/irrlicht/CBillboardSceneNode.cpp +++ b/src/dep/src/irrlicht/CBillboardSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -225,13 +225,14 @@ ISceneNode* CBillboardSceneNode::clone(ISceneNode* newParent, ISceneManager* new if (!newManager) newManager = SceneManager; - CBillboardSceneNode* nb = new CBillboardSceneNode(newParent, + CBillboardSceneNode* nb = new CBillboardSceneNode(newParent, newManager, ID, RelativeTranslation, Size); nb->cloneMembers(this, newManager); nb->Material = Material; - nb->drop(); + if ( newParent ) + nb->drop(); return nb; } diff --git a/src/dep/src/irrlicht/CBillboardSceneNode.h b/src/dep/src/irrlicht/CBillboardSceneNode.h index d4f96a9..8d6d23f 100644 --- a/src/dep/src/irrlicht/CBillboardSceneNode.h +++ b/src/dep/src/irrlicht/CBillboardSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CBlit.h b/src/dep/src/irrlicht/CBlit.h new file mode 100644 index 0000000..973b973 --- /dev/null +++ b/src/dep/src/irrlicht/CBlit.h @@ -0,0 +1,969 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef _C_BLIT_H_INCLUDED_ +#define _C_BLIT_H_INCLUDED_ + +#include "SoftwareDriver2_helper.h" + +namespace irr +{ + + struct SBlitJob + { + AbsRectangle Dest; + AbsRectangle Source; + + u32 argb; + + void * src; + void * dst; + + s32 width; + s32 height; + + u32 srcPitch; + u32 dstPitch; + + u32 srcPixelMul; + u32 dstPixelMul; + }; + + + // Bitfields Cohen Sutherland + enum eClipCode + { + CLIPCODE_EMPTY = 0, + CLIPCODE_BOTTOM = 1, + CLIPCODE_TOP = 2, + CLIPCODE_LEFT = 4, + CLIPCODE_RIGHT = 8 + }; + +inline u32 GetClipCode( const AbsRectangle &r, const core::position2d &p ) +{ + u32 code = CLIPCODE_EMPTY; + + if ( p.X < r.x0 ) + code = CLIPCODE_LEFT; + else + if ( p.X > r.x1 ) + code = CLIPCODE_RIGHT; + + if ( p.Y < r.y0 ) + code |= CLIPCODE_TOP; + else + if ( p.Y > r.y1 ) + code |= CLIPCODE_BOTTOM; + + return code; +} + + +/*! + Cohen Sutherland clipping + @return: 1 if valid +*/ + +static int ClipLine(const AbsRectangle &clipping, + core::position2d &p0, + core::position2d &p1, + const core::position2d& p0_in, + const core::position2d& p1_in) +{ + u32 code0; + u32 code1; + u32 code; + + p0 = p0_in; + p1 = p1_in; + + code0 = GetClipCode( clipping, p0 ); + code1 = GetClipCode( clipping, p1 ); + + // trivial accepted + while ( code0 | code1 ) + { + s32 x=0; + s32 y=0; + + // trivial reject + if ( code0 & code1 ) + return 0; + + if ( code0 ) + { + // clip first point + code = code0; + } + else + { + // clip last point + code = code1; + } + + if ( (code & CLIPCODE_BOTTOM) == CLIPCODE_BOTTOM ) + { + // clip bottom viewport + y = clipping.y1; + x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); + } + else + if ( (code & CLIPCODE_TOP) == CLIPCODE_TOP ) + { + // clip to viewport + y = clipping.y0; + x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); + } + else + if ( (code & CLIPCODE_RIGHT) == CLIPCODE_RIGHT ) + { + // clip right viewport + x = clipping.x1; + y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); + } + else + if ( (code & CLIPCODE_LEFT) == CLIPCODE_LEFT ) + { + // clip left viewport + x = clipping.x0; + y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); + } + + if ( code == code0 ) + { + // modify first point + p0.X = x; + p0.Y = y; + code0 = GetClipCode( clipping, p0 ); + } + else + { + // modify second point + p1.X = x; + p1.Y = y; + code1 = GetClipCode( clipping, p1 ); + } + } + + return 1; +} + +/* +*/ +inline void GetClip(AbsRectangle &clipping, video::IImage * t) +{ + clipping.x0 = 0; + clipping.y0 = 0; + clipping.x1 = t->getDimension().Width - 1; + clipping.y1 = t->getDimension().Height - 1; +} + +/* + return alpha in [0;256] Granularity from 32-Bit ARGB + add highbit alpha ( alpha > 127 ? + 1 ) +*/ +static inline u32 extractAlpha ( const u32 c ) +{ + return ( c >> 24 ) + ( c >> 31 ); +} + +/* + return alpha in [0;255] Granularity and 32-Bit ARGB + add highbit alpha ( alpha > 127 ? + 1 ) +*/ +static inline u32 packAlpha ( const u32 c ) +{ + return (c > 127 ? c - 1 : c) << 24; +} + + +/*! + Scale Color by (1/value) + value 0 - 256 ( alpha ) +*/ +inline u32 PixelLerp32 ( const u32 source, const u32 value ) +{ + u32 srcRB = source & 0x00FF00FF; + u32 srcXG = (source & 0xFF00FF00) >> 8; + + srcRB *= value; + srcXG *= value; + + srcRB >>= 8; + //srcXG >>= 8; + + srcXG &= 0xFF00FF00; + srcRB &= 0x00FF00FF; + + return srcRB | srcXG; +} + + +/* +*/ +static void RenderLine32_Decal(video::IImage *t, + const core::position2d &p0, + const core::position2d &p1, + u32 argb ) +{ + s32 dx = p1.X - p0.X; + s32 dy = p1.Y - p0.Y; + + s32 c; + s32 m; + s32 d = 0; + s32 run; + + s32 xInc = 4; + s32 yInc = (s32) t->getPitch(); + + if ( dx < 0 ) + { + xInc = -xInc; + dx = -dx; + } + + if ( dy < 0 ) + { + yInc = -yInc; + dy = -dy; + } + + u32 *dst; + dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); + + if ( dy > dx ) + { + s32 tmp; + tmp = dx; + dx = dy; + dy = tmp; + tmp = xInc; + xInc = yInc; + yInc = tmp; + } + + c = dx << 1; + m = dy << 1; + + run = dx; + while ( run ) + { + *dst = argb; + + dst = (u32*) ( (u8*) dst + xInc ); // x += xInc + d += m; + if ( d > dx ) + { + dst = (u32*) ( (u8*) dst + yInc ); // y += yInc + d -= c; + } + run -= 1; + } + + t->unlock(); +} + + +/* +*/ +static void RenderLine32_Blend(video::IImage *t, + const core::position2d &p0, + const core::position2d &p1, + u32 argb, u32 alpha) +{ + s32 dx = p1.X - p0.X; + s32 dy = p1.Y - p0.Y; + + s32 c; + s32 m; + s32 d = 0; + s32 run; + + s32 xInc = 4; + s32 yInc = (s32) t->getPitch(); + + if ( dx < 0 ) + { + xInc = -xInc; + dx = -dx; + } + + if ( dy < 0 ) + { + yInc = -yInc; + dy = -dy; + } + + u32 *dst; + dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); + + if ( dy > dx ) + { + s32 tmp; + tmp = dx; + dx = dy; + dy = tmp; + tmp = xInc; + xInc = yInc; + yInc = tmp; + } + + c = dx << 1; + m = dy << 1; + + run = dx; + const u32 packA = packAlpha ( alpha ); + while ( run ) + { + *dst = packA | PixelBlend32( *dst, argb, alpha ); + + dst = (u32*) ( (u8*) dst + xInc ); // x += xInc + d += m; + if ( d > dx ) + { + dst = (u32*) ( (u8*) dst + yInc ); // y += yInc + d -= c; + } + run -= 1; + } + + t->unlock(); +} + +/* +*/ +static void RenderLine16_Decal(video::IImage *t, + const core::position2d &p0, + const core::position2d &p1, + u32 argb ) +{ + s32 dx = p1.X - p0.X; + s32 dy = p1.Y - p0.Y; + + s32 c; + s32 m; + s32 d = 0; + s32 run; + + s32 xInc = 2; + s32 yInc = (s32) t->getPitch(); + + if ( dx < 0 ) + { + xInc = -xInc; + dx = -dx; + } + + if ( dy < 0 ) + { + yInc = -yInc; + dy = -dy; + } + + u16 *dst; + dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); + + if ( dy > dx ) + { + s32 tmp; + tmp = dx; + dx = dy; + dy = tmp; + tmp = xInc; + xInc = yInc; + yInc = tmp; + } + + c = dx << 1; + m = dy << 1; + + run = dx; + while ( run ) + { + *dst = (u16)argb; + + dst = (u16*) ( (u8*) dst + xInc ); // x += xInc + d += m; + if ( d > dx ) + { + dst = (u16*) ( (u8*) dst + yInc ); // y += yInc + d -= c; + } + run -= 1; + } + + t->unlock(); +} + +/* +*/ +static void RenderLine16_Blend(video::IImage *t, + const core::position2d &p0, + const core::position2d &p1, + u16 argb, + u16 alpha) +{ + s32 dx = p1.X - p0.X; + s32 dy = p1.Y - p0.Y; + + s32 c; + s32 m; + s32 d = 0; + s32 run; + + s32 xInc = 2; + s32 yInc = (s32) t->getPitch(); + + if ( dx < 0 ) + { + xInc = -xInc; + dx = -dx; + } + + if ( dy < 0 ) + { + yInc = -yInc; + dy = -dy; + } + + u16 *dst; + dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); + + if ( dy > dx ) + { + s32 tmp; + tmp = dx; + dx = dy; + dy = tmp; + tmp = xInc; + xInc = yInc; + yInc = tmp; + } + + c = dx << 1; + m = dy << 1; + + run = dx; + const u16 packA = alpha ? 0x8000 : 0; + while ( run ) + { + *dst = packA | PixelBlend16( *dst, argb, alpha ); + + dst = (u16*) ( (u8*) dst + xInc ); // x += xInc + d += m; + if ( d > dx ) + { + dst = (u16*) ( (u8*) dst + yInc ); // y += yInc + d -= c; + } + run -= 1; + } + + t->unlock(); +} + + +/*! +*/ +static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job ) +{ + const void *src = (void*) job->src; + void *dst = (void*) job->dst; + + const u32 widthPitch = job->width * job->dstPixelMul; + for ( s32 dy = 0; dy != job->height; ++dy ) + { + memcpy( dst, src, widthPitch ); + + src = (void*) ( (u8*) (src) + job->srcPitch ); + dst = (void*) ( (u8*) (dst) + job->dstPitch ); + } +} + + +/*! +*/ +static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job ) +{ + const u32 *src = static_cast(job->src); + u16 *dst = static_cast(job->dst); + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + //16 bit Blitter depends on pre-multiplied color + const u32 s = PixelLerp32( src[dx] | 0xFF000000, extractAlpha( src[dx] ) ); + dst[dx] = video::A8R8G8B8toA1R5G5B5( s ); + } + + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job ) +{ + const void *src = (void*) job->src; + u16 *dst = (u16*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + u8 * s = (u8*) src; + + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = video::RGBA16(s[0], s[1], s[2]); + s += 3; + } + + src = (void*) ( (u8*) (src) + job->srcPitch ); + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } +} + + +/*! +*/ +static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job ) +{ + const u16 *src = (u16*) job->src; + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = video::A1R5G5B5toA8R8G8B8( src[dx] ); + } + + src = (u16*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +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 ) +{ + void *src = (void*) job->src; + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + u8 * s = (u8*) src; + + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2]; + s += 3; + } + + src = (void*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +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 ; + } + +} + + +/*! +*/ +static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job ) +{ + u32 dx; + s32 dy; + + u32 *src = (u32*) job->src; + u32 *dst = (u32*) job->dst; + + + const u32 rdx = job->width >> 1; + const u32 off = core::if_c_a_else_b( job->width & 1 ,job->width - 1, 0 ); + + + for ( dy = 0; dy != job->height; ++dy ) + { + for ( dx = 0; dx != rdx; ++dx ) + { + dst[dx] = PixelBlend16_simd( dst[dx], src[dx] ); + } + + if ( off ) + { + ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] ); + } + + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job ) +{ + u32 *src = (u32*) job->src; + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = PixelBlend32( dst[dx], src[dx] ); + } + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job ) +{ + u16 *src = (u16*) job->src; + u16 *dst = (u16*) job->dst; + + u16 blend = video::A8R8G8B8toA1R5G5B5 ( job->argb ); + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + if ( 0 == (src[dx] & 0x8000) ) + continue; + + dst[dx] = PixelMul16_2( src[dx], blend ); + } + src = (u16*) ( (u8*) (src) + job->srcPitch ); + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } +} + + +/*! +*/ +static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job ) +{ + u32 *src = (u32*) job->src; + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = PixelBlend32( dst[dx], PixelMul32_2( src[dx], job->argb ) ); + } + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_Color_16_to_16( const SBlitJob * job ) +{ + u16 *dst = (u16*) job->dst; + + u16 c0 = video::A8R8G8B8toA1R5G5B5( job->argb ); + u32 c = c0 | c0 << 16; + + if ( 0 == (job->srcPitch & 3 ) ) + { + for ( s32 dy = 0; dy != job->height; ++dy ) + { + memset32( dst, c, job->srcPitch ); + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } + } + else + { + s32 dx = job->width - 1; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + memset32( dst, c, job->srcPitch ); + dst[dx] = c0; + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } + + } +} + +/*! +*/ +static void executeBlit_Color_32_to_32( const SBlitJob * job ) +{ + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + memset32( dst, job->argb, job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job ) +{ + u16 *dst = (u16*) job->dst; + + const u16 alpha = extractAlpha( job->argb ) >> 3; + if ( 0 == alpha ) + return; + const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb ); + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = 0x8000 | PixelBlend16( dst[dx], src, alpha ); + } + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job ) +{ + u32 *dst = (u32*) job->dst; + + const u32 alpha = extractAlpha( job->argb ); + const u32 src = job->argb; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = (job->argb & 0xFF000000 ) | PixelBlend32( dst[dx], src, alpha ); + } + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +// Blitter Operation +enum eBlitter +{ + BLITTER_INVALID = 0, + BLITTER_COLOR, + BLITTER_COLOR_ALPHA, + BLITTER_TEXTURE, + BLITTER_TEXTURE_ALPHA_BLEND, + BLITTER_TEXTURE_ALPHA_COLOR_BLEND +}; + +typedef void (*tExecuteBlit) ( const SBlitJob * job ); + + +/*! +*/ +struct blitterTable +{ + eBlitter operation; + s32 destFormat; + s32 sourceFormat; + tExecuteBlit func; +}; + +static const blitterTable blitTable[] = +{ + { BLITTER_TEXTURE, -2, -2, executeBlit_TextureCopy_x_to_x }, + { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_16 }, + { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 }, + { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_32 }, + { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_32 }, + { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_24 }, + { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_24 }, + { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlend_16_to_16 }, + { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlend_32_to_32 }, + { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlendColor_16_to_16 }, + { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlendColor_32_to_32 }, + { BLITTER_COLOR, video::ECF_A1R5G5B5, -1, executeBlit_Color_16_to_16 }, + { BLITTER_COLOR, video::ECF_A8R8G8B8, -1, executeBlit_Color_32_to_32 }, + { BLITTER_COLOR_ALPHA, video::ECF_A1R5G5B5, -1, executeBlit_ColorAlpha_16_to_16 }, + { BLITTER_COLOR_ALPHA, video::ECF_A8R8G8B8, -1, executeBlit_ColorAlpha_32_to_32 }, + { BLITTER_INVALID, -1, -1, 0 } +}; + + +static inline tExecuteBlit getBlitter2( eBlitter operation,const video::IImage * dest,const video::IImage * source ) +{ + video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) ( source ? source->getColorFormat() : -1 ); + video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) ( dest ? dest->getColorFormat() : -1 ); + + const blitterTable * b = blitTable; + + while ( b->operation != BLITTER_INVALID ) + { + if ( b->operation == operation ) + { + if (( b->destFormat == -1 || b->destFormat == destFormat ) && + ( b->sourceFormat == -1 || b->sourceFormat == sourceFormat ) ) + return b->func; + else + if ( b->destFormat == -2 && ( sourceFormat == destFormat ) ) + return b->func; + } + b += 1; + } + return 0; +} + + +// bounce clipping to texture +inline void setClip ( AbsRectangle &out, const core::rect *clip, + const video::IImage * tex, s32 passnative ) +{ + if ( clip && 0 == tex && passnative ) + { + out.x0 = clip->UpperLeftCorner.X; + out.x1 = clip->LowerRightCorner.X; + out.y0 = clip->UpperLeftCorner.Y; + out.y1 = clip->LowerRightCorner.Y; + return; + } + + const s32 w = tex ? tex->getDimension().Width : 0; + const s32 h = tex ? tex->getDimension().Height : 0; + if ( clip ) + { + out.x0 = core::s32_clamp ( clip->UpperLeftCorner.X, 0, w ); + out.x1 = core::s32_clamp ( clip->LowerRightCorner.X, out.x0, w ); + out.y0 = core::s32_clamp ( clip->UpperLeftCorner.Y, 0, h ); + out.y1 = core::s32_clamp ( clip->LowerRightCorner.Y, out.y0, h ); + } + else + { + out.x0 = 0; + out.y0 = 0; + out.x1 = w; + out.y1 = h; + } + +} + +/*! + a generic 2D Blitter +*/ +static s32 Blit(eBlitter operation, + video::IImage * dest, + const core::rect *destClipping, + const core::position2d *destPos, + video::IImage * const source, + const core::rect *sourceClipping, + u32 argb) +{ + tExecuteBlit blitter = getBlitter2( operation, dest, source ); + if ( 0 == blitter ) + { + return 0; + } + + // Clipping + AbsRectangle sourceClip; + AbsRectangle destClip; + AbsRectangle v; + + SBlitJob job; + + setClip ( sourceClip, sourceClipping, source, 1 ); + setClip ( destClip, destClipping, dest, 0 ); + + v.x0 = destPos ? destPos->X : 0; + v.y0 = destPos ? destPos->Y : 0; + v.x1 = v.x0 + ( sourceClip.x1 - sourceClip.x0 ); + v.y1 = v.y0 + ( sourceClip.y1 - sourceClip.y0 ); + + if ( !intersect( job.Dest, destClip, v ) ) + return 0; + + job.width = job.Dest.x1 - job.Dest.x0; + job.height = job.Dest.y1 - job.Dest.y0; + + + job.Source.x0 = sourceClip.x0 + ( job.Dest.x0 - v.x0 ); + job.Source.x1 = job.Source.x0 + job.width; + + job.Source.y0 = sourceClip.y0 + ( job.Dest.y0 - v.y0 ); + job.Source.y1 = job.Source.y0 + job.height; + + job.argb = argb; + + if ( source ) + { + job.srcPitch = source->getPitch(); + job.srcPixelMul = source->getBytesPerPixel(); + job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) ); + } + else + { + // use srcPitch for color operation on dest + job.srcPitch = job.width * dest->getBytesPerPixel(); + } + + job.dstPitch = dest->getPitch(); + job.dstPixelMul = dest->getBytesPerPixel(); + job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) ); + + blitter( &job ); + + if ( source ) + source->unlock(); + + if ( dest ) + dest->unlock(); + + return 1; +} + +} + +#endif + diff --git a/src/dep/src/irrlicht/CBoneSceneNode.cpp b/src/dep/src/irrlicht/CBoneSceneNode.cpp index a12563d..6e0107d 100644 --- a/src/dep/src/irrlicht/CBoneSceneNode.cpp +++ b/src/dep/src/irrlicht/CBoneSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -69,7 +69,7 @@ void CBoneSceneNode::OnAnimate(u32 timeMs) { // animate this node with all animators - core::list::Iterator ait = Animators.begin(); + ISceneNodeAnimatorList::Iterator ait = Animators.begin(); for (; ait != Animators.end(); ++ait) (*ait)->animateNode(this, timeMs); @@ -77,7 +77,7 @@ void CBoneSceneNode::OnAnimate(u32 timeMs) //updateAbsolutePosition(); // perform the post render process on all children - core::list::Iterator it = Children.begin(); + ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnAnimate(timeMs); } @@ -88,7 +88,7 @@ void CBoneSceneNode::helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node { Node->updateAbsolutePosition(); - core::list::ConstIterator it = Node->getChildren().begin(); + ISceneNodeList::ConstIterator it = Node->getChildren().begin(); for (; it != Node->getChildren().end(); ++it) { helper_updateAbsolutePositionOfAllChildren( (*it) ); diff --git a/src/dep/src/irrlicht/CBoneSceneNode.h b/src/dep/src/irrlicht/CBoneSceneNode.h index 263e91f..d2bd07b 100644 --- a/src/dep/src/irrlicht/CBoneSceneNode.h +++ b/src/dep/src/irrlicht/CBoneSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CBurningShader_Raster_Reference.cpp b/src/dep/src/irrlicht/CBurningShader_Raster_Reference.cpp index 3706f47..2ad9384 100644 --- a/src/dep/src/irrlicht/CBurningShader_Raster_Reference.cpp +++ b/src/dep/src/irrlicht/CBurningShader_Raster_Reference.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -554,8 +554,8 @@ void CBurningShader_Raster_Reference::pShader_EMT_LIGHTMAP_M4 () f32 inversew = fix_inverse32 ( line.w[0] ); - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); pShader.dst[pShader.i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), @@ -574,8 +574,8 @@ void CBurningShader_Raster_Reference::pShader_1 () const f32 inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x, inversew ); - ty0 = f32_to_fixPoint ( line.t[0][0].y, inversew ); + tx0 = tofix ( line.t[0][0].x, inversew ); + ty0 = tofix ( line.t[0][0].y, inversew ); getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); pShader.dst[pShader.i] = fix_to_color ( r0, g0, b0 ); @@ -622,16 +622,40 @@ void CBurningShader_Raster_Reference::setMaterial ( const SBurningShaderMaterial enable = F32_LOWER_EQUAL_0 ( m.Shininess ); ShaderParam.SetRenderState( BD3DRS_SPECULARENABLE, enable); ShaderParam.SetRenderState( BD3DRS_NORMALIZENORMALS, enable); - ShaderParam.SetRenderState( BD3DRS_SPECULARMATERIALSOURCE, BD3DMCS_MATERIAL); + ShaderParam.SetRenderState( BD3DRS_SPECULARMATERIALSOURCE, (m.ColorMaterial==ECM_SPECULAR)?BD3DMCS_COLOR1:BD3DMCS_MATERIAL); // depth buffer enable and compare - ShaderParam.SetRenderState( BD3DRS_ZENABLE, material.org.ZBuffer ? BD3DZB_USEW : BD3DZB_FALSE); - ShaderParam.SetRenderState( BD3DRS_ZFUNC, material.org.ZBuffer == 2 ? BD3DCMP_EQUAL : BD3DCMP_LESSEQUAL ); + ShaderParam.SetRenderState( BD3DRS_ZENABLE, (material.org.ZBuffer==video::ECFN_NEVER) ? BD3DZB_FALSE : BD3DZB_USEW); + switch (material.org.ZBuffer) + { + case ECFN_NEVER: + ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_NEVER); + break; + case ECFN_LESSEQUAL: + ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_LESSEQUAL); + break; + case ECFN_EQUAL: + ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_EQUAL); + break; + case ECFN_LESS: + ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_LESSEQUAL); + break; + case ECFN_NOTEQUAL: + ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_NOTEQUAL); + break; + case ECFN_GREATEREQUAL: + ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_GREATEREQUAL); + break; + case ECFN_GREATER: + ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_GREATER); + break; + case ECFN_ALWAYS: + ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_ALWAYS); + break; + } // depth buffer write ShaderParam.SetRenderState( BD3DRS_ZWRITEENABLE, m.ZWriteEnable ); - - } /*! @@ -832,8 +856,8 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges diff --git a/src/dep/src/irrlicht/CCSMLoader.cpp b/src/dep/src/irrlicht/CCSMLoader.cpp index 8ec2aed..3ecb7fc 100644 --- a/src/dep/src/irrlicht/CCSMLoader.cpp +++ b/src/dep/src/irrlicht/CCSMLoader.cpp @@ -1,11 +1,11 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This file was written by Saurav Mohapatra and modified by Nikolaus Gebhardt. // See CCSMLoader.h for details. -#include "IrrCompileConfig.h" +#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_CSM_LOADER_ #include "CCSMLoader.h" @@ -19,6 +19,10 @@ #include "SAnimatedMesh.h" #include "SMeshBufferLightMap.h" +#ifdef _DEBUG +#define _IRR_DEBUG_CSM_LOADER_ +#endif + namespace irr { namespace scene @@ -32,15 +36,34 @@ namespace scene s32 green; s32 blue; - void clear() - { - red = 0; - green = 0; - blue = 0; - } + color_rgb_t() : red(0), green(0), blue(0) {} + void clear() { red=0; green=0; blue=0; } + video::SColor toSColor() const { return video::SColor(255, red, green, blue); } }; - class BinaryFileReader; + + // + // A Binary File Reader + // + struct BinaryFileReader + { + BinaryFileReader(io::IReadFile* pFile) : file(pFile) { } + + s32 readBuffer(void* buffer, s32 len) + { + return file->read(buffer,len); + } + + s32 readLong(); + f32 readFloat(); + + void readString(core::stringc &str); + void readVec3f(core::vector3df* v); + void readVec2f(core::vector2df* v); + void readColorRGB(color_rgb_t* color); + + io::IReadFile *file; + }; // // The file header @@ -49,15 +72,20 @@ namespace scene { public: - static const s32 VERSION_4; - static const s32 VERSION_4_1; + enum E_CSM_VERSION + { + VERSION_4 = 4, + VERSION_4_1 = 5 + }; Header(){ clear(); } - virtual ~Header(){ clear(); } - s32 getVersion() const{ return version; } + s32 getVersion() const { return version; } void clear(){ version = 0; } - void load(BinaryFileReader* pReader); + void load(BinaryFileReader* pReader) + { + version = pReader->readLong(); + } private: @@ -73,7 +101,7 @@ namespace scene public: Group(){ clear(); } - virtual ~Group(){ clear(); } + ~Group(){ clear(); } void clear(); void load(BinaryFileReader* pReader); @@ -81,7 +109,7 @@ namespace scene s32 getFlags() const { return flags; } s32 getParentGroupID() const { return parentGroup; } const core::stringc& getProperties() const { return props; } - const color_rgb_t* getColor() const { return &color; } + video::SColor getColor() const { return color.toSColor(); } private: @@ -100,13 +128,13 @@ namespace scene public: VisGroup(){ clear(); } - virtual ~VisGroup(){ clear(); } + ~VisGroup(){ clear(); } void clear(); void load(BinaryFileReader* pReader); s32 getFlags() const{ return flags; } const core::stringc& getName() const{ return name; } - const color_rgb_t* getColor() const{ return &color; } + video::SColor getColor() const{ return color.toSColor(); } private: @@ -124,12 +152,12 @@ namespace scene public: LightMap() : pixelData(0){ clear(); } - virtual ~LightMap(){ clear(); } + ~LightMap(){ clear(); } void clear(); void load(BinaryFileReader* pReader); s32 getWidth() const{ return width; } s32 getHeight() const{ return height; } - const s32* getPixelData() const{ return pixelData; } + s32* getPixelData() const{ return pixelData; } private: @@ -155,15 +183,15 @@ namespace scene public: Vertex(){ clear(); } - virtual ~Vertex(){ clear(); } + ~Vertex(){ clear(); } void clear(); void load(BinaryFileReader* pReader); - const core::vector3df* getPosition() const { return &position; } - const core::vector3df* getNormal() const { return &normal; } - const color_rgb_t* getColor() const { return &color; } - const core::vector3df* getTextureCoordinates() const { return &texCoords; } - const core::vector3df* getLightMapCoordinates() const { return &lmapCoords; } + const core::vector3df& getPosition() const { return position; } + const core::vector3df& getNormal() const { return normal; } + video::SColor getColor() const { return color.toSColor(); } + const core::vector3df& getTextureCoordinates() const { return texCoords; } + const core::vector3df& getLightMapCoordinates() const { return lmapCoords; } private: @@ -180,7 +208,7 @@ namespace scene public: Surface() { clear(); } - virtual ~Surface(){ clear(); } + ~Surface(){ clear(); } void clear(); void load(BinaryFileReader *pReader); @@ -193,9 +221,9 @@ namespace scene f32 getUVRotation() const{ return uvRotation; } u32 getVertexCount() const{ return vertices.size(); } - const Vertex* getVertexAt(const s32 index) const{ return vertices[index]; } + const Vertex& getVertexAt(const s32 index) const{ return vertices[index]; } - s32 getTriangleCount() const{ return triangles.size(); } + u32 getTriangleCount() const{ return triangles.size(); } const Triangle& getTriangleAt(const s32 index) const{ return triangles[index]; } private: @@ -206,7 +234,7 @@ namespace scene core::vector2df uvOffset; core::vector2df uvScale; f32 uvRotation; - core::array vertices; + core::array vertices; core::array triangles; core::array lines; }; @@ -216,7 +244,7 @@ namespace scene public: Mesh(){ clear(); } - virtual ~Mesh(){ clear(); } + ~Mesh(){ clear(); } void clear(); void load(BinaryFileReader* pReader, bool bReadVisGroups); @@ -224,7 +252,7 @@ namespace scene s32 getFlags() const { return flags; } s32 getGroupID() const { return groupId; } const core::stringc& getProperties() const { return props; } - const color_rgb_t* getColor() const { return &color; } + video::SColor getColor() const { return color.toSColor(); } const core::vector3df* getPosition() const { return &position; } s32 getVisgroupID() const { return visgroupId; } s32 getSurfaceCount() const { return surfaces.size(); } @@ -247,7 +275,7 @@ namespace scene public: Entity() { clear(); } - virtual ~Entity() { clear(); } + ~Entity() { clear(); } void clear(); void load(BinaryFileReader* pReader); @@ -270,7 +298,7 @@ namespace scene public: CameraData(){ clear(); } - virtual ~CameraData(){ clear(); } + ~CameraData(){ clear(); } void clear(); void load(BinaryFileReader* pReader); @@ -294,25 +322,25 @@ namespace scene public: CSMFile(){ clear(); } - virtual ~CSMFile(){ clear(); } + ~CSMFile(){ clear(); } void clear(); void load(BinaryFileReader* pReader); const Header* getHeader() const{ return &header; } - s32 getGroupCount() const{ return groups.size(); } + u32 getGroupCount() const{ return groups.size(); } const Group* getGroupAt(const s32 index) const{ return groups[index]; } - s32 getVisGroupCount() const{ return visgroups.size(); } + u32 getVisGroupCount() const{ return visgroups.size(); } const VisGroup* getVisGroupAt(const s32 index) const{ return visgroups[index]; } - s32 getLightMapCount() const{ return lightmaps.size(); } + u32 getLightMapCount() const{ return lightmaps.size(); } const LightMap* getLightMapAt(const s32 index) const { return lightmaps[index]; } - s32 getMeshCount() const{ return meshes.size(); } + u32 getMeshCount() const{ return meshes.size(); } const Mesh* getMeshAt(const s32 index) const{ return meshes[index]; } - s32 getEntityCount() const{ return entities.size(); } + u32 getEntityCount() const{ return entities.size(); } const Entity* getEntityAt(const s32 index) const{ return entities[index]; } const CameraData* getCameraData() const{ return &cameraData; } @@ -328,35 +356,6 @@ namespace scene CameraData cameraData; }; - - // - // A Binary File Reader - // - class BinaryFileReader - { - public: - - BinaryFileReader(io::IReadFile* pFile, bool closeWhenDone=true); - virtual ~BinaryFileReader(); - - virtual s32 readBuffer(void* buffer, s32 len); - - s32 readLong(); - f32 readFloat(); - u8 readByte(); - - core::stringc readString(); - void readVec3f(core::vector3df* v); - void readVec2f(core::vector2df* v); - void readColorRGB(color_rgb_t* color); - - private: - - io::IReadFile *file; - bool autoClose; - - }; - CCSMLoader::CCSMLoader(scene::ISceneManager* manager, io::IFileSystem* fs) : FileSystem(fs), SceneManager(manager) { @@ -366,22 +365,18 @@ namespace scene #endif } - CCSMLoader::~CCSMLoader() - { - } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - bool CCSMLoader::isALoadableFileExtension(const c8* fileName) const + bool CCSMLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(fileName, ".csm")!=0; + return core::hasFileExtension ( filename, "csm" ); } + //! creates/loads an animated mesh from the file. IAnimatedMesh* CCSMLoader::createMesh(io::IReadFile* file) { - file->grab(); // originally, this loader created the file on its own. - scene::IMesh* m = createCSMMesh(file); if (!m) @@ -401,47 +396,41 @@ namespace scene if (!file) return 0; - if(file) - { - BinaryFileReader reader(file, true); - CSMFile csmFile; - csmFile.load(&reader); + BinaryFileReader reader(file); + CSMFile csmFile; + csmFile.load(&reader); - scene::IMesh* pMesh = createIrrlichtMesh(&csmFile, - SceneManager->getParameters()->getAttributeAsString(CSM_TEXTURE_PATH), - file->getFileName()); - return pMesh; - } - - return 0; + return createIrrlichtMesh(&csmFile, + SceneManager->getParameters()->getAttributeAsString(CSM_TEXTURE_PATH), + file->getFileName()); } + scene::IMesh* CCSMLoader::createIrrlichtMesh(const CSMFile* csmFile, - core::stringc textureRoot, const c8* lmprefix) + const core::stringc& textureRoot, const io::path& lmprefix) { scene::SMesh *pMesh = new scene::SMesh(); video::IVideoDriver* driver = SceneManager->getVideoDriver(); - for(s32 l = 0; lgetLightMapCount(); l++) + for(u32 l = 0; lgetLightMapCount(); l++) { const LightMap* lmap = csmFile->getLightMapAt(l); - core::stringc lmapName = lmprefix; + io::path lmapName = lmprefix; lmapName += "LMAP_"; - lmapName += (int)(l+1); + lmapName += io::path(l+1); os::Printer::log("CCSMLoader loading light map", lmapName.c_str()); video::IImage* lmapImg = driver->createImageFromData( video::ECF_A8R8G8B8, - core::dimension2d(lmap->getWidth(),lmap->getHeight()), - (void *)(lmap->getPixelData())); + core::dimension2d(lmap->getWidth(),lmap->getHeight()), + lmap->getPixelData()); driver->addTexture(lmapName.c_str(), lmapImg); lmapImg->drop(); - } - for(s32 m = 0; mgetMeshCount(); m++) + for(u32 m = 0; mgetMeshCount(); m++) { const Mesh* mshPtr = csmFile->getMeshAt(m); @@ -449,42 +438,64 @@ namespace scene { const Surface* surface = mshPtr->getSurfaceAt(s); - core::stringc texName = textureRoot; - texName+= "/"; + core::stringc texName; + if (textureRoot.size()) + { + texName += textureRoot; + texName += "/"; + } texName+= surface->getTextureName(); - video::ITexture* texture = driver->getTexture(texName.c_str()); - scene::SMeshBufferLightMap *buffer = new scene::SMeshBufferLightMap(); + video::ITexture* texture = 0; + if (texName.size()) + { + if (FileSystem->existFile(texName)) + texture = driver->getTexture(texName); + else if (FileSystem->existFile(surface->getTextureName())) + texture = driver->getTexture(surface->getTextureName()); + else if (FileSystem->existFile(FileSystem->getFileBasename(surface->getTextureName()))) + texture = driver->getTexture(FileSystem->getFileBasename(surface->getTextureName())); + else if (FileSystem->existFile(FileSystem->getFileDir(lmprefix)+"/"+surface->getTextureName())) + texture = driver->getTexture(FileSystem->getFileDir(lmprefix)+"/"+surface->getTextureName()); + else + texture = driver->getTexture(FileSystem->getFileDir(lmprefix)+"/"+FileSystem->getFileBasename(surface->getTextureName())); + } //material - core::stringc lmapName = lmprefix; + io::path lmapName = lmprefix; lmapName += "LMAP_"; - lmapName += (int)surface->getLightMapId(); + lmapName += io::path(surface->getLightMapId()); + scene::SMeshBufferLightMap *buffer = new scene::SMeshBufferLightMap(); buffer->Material.setTexture(0, texture); - buffer->Material.setTexture(1, driver->getTexture(lmapName.c_str())); - buffer->Material.Lighting = false; - buffer->Material.MaterialType = video::EMT_LIGHTMAP_M4; - - for(u32 v = 0; v < surface->getVertexCount(); v++) + if (surface->getLightMapId()) { - const Vertex *vtxPtr = surface->getVertexAt(v); + buffer->Material.setTexture(1, driver->getTexture(lmapName)); + buffer->Material.Lighting = false; + buffer->Material.MaterialType = video::EMT_LIGHTMAP_ADD; + } + + buffer->Vertices.reallocate(surface->getVertexCount()); + for(u32 v = 0; v < surface->getVertexCount(); ++v) + { + const Vertex& vtxPtr = surface->getVertexAt(v); video::S3DVertex2TCoords vtx; - vtx.Pos = *(vtxPtr->getPosition()); - vtx.Normal = *(vtxPtr->getPosition()); - vtx.Color.set(255,vtxPtr->getColor()->red,vtxPtr->getColor()->green,vtxPtr->getColor()->blue); - vtx.TCoords.set(vtxPtr->getTextureCoordinates()->X,vtxPtr->getTextureCoordinates()->Y); - vtx.TCoords2.set(vtxPtr->getLightMapCoordinates()->X,0.0f - vtxPtr->getLightMapCoordinates()->Y); + vtx.Pos = vtxPtr.getPosition(); + vtx.Normal = vtxPtr.getPosition(); + vtx.Color=vtxPtr.getColor(); + vtx.TCoords.set(vtxPtr.getTextureCoordinates().X, 1.f-vtxPtr.getTextureCoordinates().Y); + vtx.TCoords2.set(vtxPtr.getLightMapCoordinates().X, 1.f-vtxPtr.getLightMapCoordinates().Y); buffer->Vertices.push_back(vtx); } - for(s32 t = 0; t < surface->getTriangleCount(); t++) + buffer->Indices.reallocate(surface->getTriangleCount()*3); + for(u32 t = 0; t < surface->getTriangleCount(); ++t) { const Triangle& tri = surface->getTriangleAt(t); - buffer->Indices.push_back(tri.a); buffer->Indices.push_back(tri.c); buffer->Indices.push_back(tri.b); + buffer->Indices.push_back(tri.a); } buffer->recalculateBoundingBox(); @@ -497,14 +508,6 @@ namespace scene return pMesh; } - const s32 Header::VERSION_4 = 4; - const s32 Header::VERSION_4_1 = 5; - - void Header::load(BinaryFileReader* pReader) - { - version = pReader->readLong(); - } - void Group::clear() { color.clear(); @@ -517,7 +520,7 @@ namespace scene { flags = pReader->readLong(); parentGroup = pReader->readLong(); - props = pReader->readString(); + pReader->readString(props); pReader->readColorRGB(&color); } @@ -526,23 +529,19 @@ namespace scene color.clear(); flags = 0; name = ""; - } void VisGroup::load(BinaryFileReader* pReader) { - name = pReader->readString(); + pReader->readString(name); flags = pReader->readLong(); pReader->readColorRGB(&color); } void LightMap::clear() { - if(pixelData) - { - delete[] pixelData; - pixelData = 0; - } + delete[] pixelData; + pixelData = 0; width = height = 0; } @@ -565,10 +564,7 @@ namespace scene for(u32 s = 0; s < surfaces.size(); s++) { - if(surfaces[s]) - { - delete surfaces[s]; - } + delete surfaces[s]; } surfaces.clear(); } @@ -577,7 +573,7 @@ namespace scene { flags = pReader->readLong(); groupId = pReader->readLong(); - props = pReader->readString(); + pReader->readString(props); pReader->readColorRGB(&color); pReader->readVec3f(&position); if(bReadVisGroups) @@ -605,17 +601,14 @@ namespace scene uvRotation = 0.0f; triangles.clear(); lines.clear(); - - for(u32 v = 0; v < vertices.size(); v++) - delete vertices[v]; - vertices.clear(); } void Surface::load(BinaryFileReader* pReader) { flags = pReader->readLong(); - textureName = pReader->readString(); + pReader->readString(textureName); + textureName.replace('\\', '/'); lightMapId = pReader->readLong(); pReader->readVec2f(&uvOffset); @@ -627,9 +620,8 @@ namespace scene for(s32 v = 0; v < vtxCount; v++) { - Vertex *vtx = new Vertex(); - vtx->load(pReader); - vertices.push_back(vtx); + vertices.push_back(Vertex()); + vertices.getLast().load(pReader); } for(s32 t = 0; t < triCount; t++) @@ -678,7 +670,7 @@ namespace scene { visgroupId = pReader->readLong(); groupId = pReader->readLong(); - props = pReader->readString(); + pReader->readString(props); pReader->readVec3f(&position); } @@ -736,8 +728,13 @@ namespace scene //groups { - s32 count = pReader->readLong(); + const s32 count = pReader->readLong(); +#ifdef _IRR_DEBUG_CSM_LOADER_ + os::Printer::log("CSM Version", core::stringc(header.getVersion()).c_str()); + os::Printer::log("Loading groups. Count", core::stringc(count)); +#endif + groups.reallocate(count); for (s32 i = 0; i < count; i++) { Group* grp = new Group(); @@ -745,13 +742,17 @@ namespace scene groups.push_back(grp); } } - bool bHasVGroups = (header.getVersion() == Header::VERSION_4_1); + const bool bHasVGroups = (header.getVersion() == Header::VERSION_4_1); if (bHasVGroups) { //visgroups - s32 count = pReader->readLong(); + const s32 count = pReader->readLong(); +#ifdef _IRR_DEBUG_CSM_LOADER_ + os::Printer::log("Loading visgroups. Count", core::stringc(count)); +#endif + visgroups.reallocate(count); for (s32 i = 0; i < count; i++) { VisGroup* grp = new VisGroup(); @@ -762,99 +763,89 @@ namespace scene //lightmaps { - s32 count = pReader->readLong(); + const s32 count = pReader->readLong(); +#ifdef _IRR_DEBUG_CSM_LOADER_ + os::Printer::log("Loading lightmaps. Count", core::stringc(count)); +#endif + lightmaps.reallocate(count); for(s32 i = 0; i < count; i++) { - LightMap* grp = new LightMap(); - grp->load(pReader); - lightmaps.push_back(grp); + LightMap* lm = new LightMap(); + lm->load(pReader); + lightmaps.push_back(lm); } } //meshes { - s32 count = pReader->readLong(); + const s32 count = pReader->readLong(); +#ifdef _IRR_DEBUG_CSM_LOADER_ + os::Printer::log("Loading meshes. Count", core::stringc(count)); +#endif + meshes.reallocate(count); for(s32 i = 0; i < count; i++) { - Mesh* grp = new Mesh(); - grp->load(pReader,bHasVGroups); - meshes.push_back(grp); + Mesh* mesh = new Mesh(); + mesh->load(pReader,bHasVGroups); + meshes.push_back(mesh); } } //entities { - s32 count = pReader->readLong(); + const s32 count = pReader->readLong(); +#ifdef _IRR_DEBUG_CSM_LOADER_ + os::Printer::log("Loading entitites. Count", core::stringc(count)); +#endif + entities.reallocate(count); for(s32 i = 0; i < count; i++) { - Entity* grp = new Entity(); - grp->load(pReader); - entities.push_back(grp); + Entity* ent = new Entity(); + ent->load(pReader); + entities.push_back(ent); } } //camera data +#ifdef _IRR_DEBUG_CSM_LOADER_ + os::Printer::log("Loading camera data."); +#endif cameraData.load(pReader); - - - } - - BinaryFileReader::BinaryFileReader(io::IReadFile* pFile, - bool closeWhenDone) - : file(pFile), autoClose(closeWhenDone) - { - } - - BinaryFileReader::~BinaryFileReader() - { - if(autoClose && file) - { - file->drop(); - file = 0; - - } - } - - s32 BinaryFileReader::readBuffer(void* buffer, s32 len) - { - return file->read(buffer,len); - } s32 BinaryFileReader::readLong() { int ret = 0; readBuffer(&ret,sizeof(int)); - return (s32)ret; +#ifdef __BIG_ENDIAN__ + ret = os::Byteswap::byteswap(ret); +#endif + return ret; } f32 BinaryFileReader::readFloat() { float ret = 0; readBuffer(&ret,sizeof(float)); - return (f32)ret; +#ifdef __BIG_ENDIAN__ + ret = os::Byteswap::byteswap(ret); +#endif + return ret; } - u8 BinaryFileReader::readByte() + void BinaryFileReader::readString(core::stringc &str) { - char ret = 0; - readBuffer(&ret,sizeof(char)); - return (u8)ret; - } - - core::stringc BinaryFileReader::readString() - { - core::stringc str = ""; - c8 c = (c8)readByte(); + str = ""; + c8 c; + readBuffer(&c,sizeof(char)); while(c != 0) { str += c; - c = (c8)readByte(); + readBuffer(&c,sizeof(char)); } - return str; } void BinaryFileReader::readVec3f(core::vector3df* v) diff --git a/src/dep/src/irrlicht/CCSMLoader.h b/src/dep/src/irrlicht/CCSMLoader.h index cb87167..2265fad 100644 --- a/src/dep/src/irrlicht/CCSMLoader.h +++ b/src/dep/src/irrlicht/CCSMLoader.h @@ -1,11 +1,11 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This Loader has been originally written by Saurav Mohapatra. I (Nikolaus Gebhardt) -// modified some minor things and integrated it into Irrlicht 0.9. Thanks a lot +// modified some minor things and integrated it into Irrlicht 0.9. Thanks a lot // to Saurav Mohapatra for his work on this and that he gave me his permission to -// add it into Irrlicht. +// add it into Irrlicht. // I did some changes to Saurav Mohapatra's loader, so I'm writing this down here: // - Replaced all dependencies to STL and stdio with irr:: methods/constructs. // - Moved everything into namespace irr::scene @@ -20,7 +20,7 @@ // // The original readme of this file looks like this: // -// This component provides a loader for the Cartography shop 4.x .csm maps for Irrlicht Engine. +// This component provides a loader for the Cartography shop 4.x .csm maps for Irrlicht Engine. // This is a part of the M_TRIX Project. // This is licensed under the ZLib/LibPNG license // The IrrCSM library is written by Saurav Mohapatra. @@ -30,7 +30,7 @@ // The IrrCSM library features the following capabilities // // * Loads the .csm 4.0 and 4.1 files transparently -// * Presents the loaded file as irr::scene::IAnimatedMesh for easy creation of IOctTreeSceneNode +// * Presents the loaded file as irr::scene::IAnimatedMesh for easy creation of IOctreeSceneNode // * Loads the textures given the correct texture root. hence map and textures can be in separate directories // // For more informations go to http://www.geocities.com/standard_template/irrcsm/downloads.html @@ -56,11 +56,10 @@ namespace scene public: CCSMLoader(ISceneManager* manager, io::IFileSystem* fs); - virtual ~CCSMLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. virtual IAnimatedMesh* createMesh(io::IReadFile* file); @@ -70,14 +69,14 @@ namespace scene scene::IMesh* createCSMMesh(io::IReadFile* file); scene::IMesh* createIrrlichtMesh(const CSMFile* csmFile, - core::stringc textureRoot, const c8* lmprefix); + const core::stringc& textureRoot, const io::path& lmprefix); io::IFileSystem* FileSystem; scene::ISceneManager* SceneManager; }; } // end namespace -} // end namespace +} // end namespace #endif diff --git a/src/dep/src/irrlicht/CCameraFPSSceneNode.cpp b/src/dep/src/irrlicht/CCameraFPSSceneNode.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/dep/src/irrlicht/CCameraFPSSceneNode.h b/src/dep/src/irrlicht/CCameraFPSSceneNode.h deleted file mode 100644 index e69de29..0000000 diff --git a/src/dep/src/irrlicht/CCameraMayaSceneNode.cpp b/src/dep/src/irrlicht/CCameraMayaSceneNode.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/dep/src/irrlicht/CCameraMayaSceneNode.h b/src/dep/src/irrlicht/CCameraMayaSceneNode.h deleted file mode 100644 index e69de29..0000000 diff --git a/src/dep/src/irrlicht/CCameraSceneNode.cpp b/src/dep/src/irrlicht/CCameraSceneNode.cpp index 93545b8..b4228d0 100644 --- a/src/dep/src/irrlicht/CCameraSceneNode.cpp +++ b/src/dep/src/irrlicht/CCameraSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -14,7 +14,7 @@ namespace scene //! constructor -CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, +CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& lookat) : ICameraSceneNode(parent, mgr, id, position), Target(lookat), UpVector(0.0f, 1.0f, 0.0f), ZNear(1.0f), ZFar(3000.0f), @@ -25,14 +25,14 @@ CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 i #endif // set default projection - Fovy = core::PI / 2.5f; // Field of view, in radians. + Fovy = core::PI / 2.5f; // Field of view, in radians. const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0; if (d) Aspect = (f32)d->getCurrentRenderTargetSize().Width / (f32)d->getCurrentRenderTargetSize().Height; else - Aspect = 4.0f / 3.0f; // Aspect ratio. + Aspect = 4.0f / 3.0f; // Aspect ratio. recalculateProjectionMatrix(); recalculateViewArea(); @@ -61,8 +61,7 @@ to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspecti void CCameraSceneNode::setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal) { IsOrthogonal = isOrthogonal; - ViewArea.Matrices [ video::ETS_PROJECTION ] = projection; - ViewArea.setTransformState ( video::ETS_PROJECTION ); + ViewArea.getTransform ( video::ETS_PROJECTION ) = projection; } @@ -70,7 +69,7 @@ void CCameraSceneNode::setProjectionMatrix(const core::matrix4& projection, bool //! \return Returns the current projection matrix of the camera. const core::matrix4& CCameraSceneNode::getProjectionMatrix() const { - return ViewArea.Matrices [ video::ETS_PROJECTION ]; + return ViewArea.getTransform ( video::ETS_PROJECTION ); } @@ -78,15 +77,32 @@ const core::matrix4& CCameraSceneNode::getProjectionMatrix() const //! \return Returns the current view matrix of the camera. const core::matrix4& CCameraSceneNode::getViewMatrix() const { - return ViewArea.Matrices [ video::ETS_VIEW ]; + return ViewArea.getTransform ( video::ETS_VIEW ); +} + + +//! Sets a custom view matrix affector. The matrix passed here, will be +//! multiplied with the view matrix when it gets updated. +//! This allows for custom camera setups like, for example, a reflection camera. +/** \param affector: The affector matrix. */ +void CCameraSceneNode::setViewMatrixAffector(const core::matrix4& affector) +{ + Affector = affector; +} + + +//! Gets the custom view matrix affector. +const core::matrix4& CCameraSceneNode::getViewMatrixAffector() const +{ + return Affector; } //! 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::addFPSCameraSceneNode, may want to get this input -//! for changing their position, look at target or whatever. +//! for changing their position, look at target or whatever. bool CCameraSceneNode::OnEvent(const SEvent& event) { if (!InputReceiverEnabled) @@ -94,8 +110,8 @@ bool CCameraSceneNode::OnEvent(const SEvent& event) // send events to event receiving animators - core::list::Iterator ait = Animators.begin(); - + ISceneNodeAnimatorList::Iterator ait = Animators.begin(); + for (; ait != Animators.end(); ++ait) if ((*ait)->isEventReceiverEnabled() && (*ait)->OnEvent(event)) return true; @@ -157,25 +173,25 @@ const core::vector3df& CCameraSceneNode::getUpVector() const } -f32 CCameraSceneNode::getNearValue() const +f32 CCameraSceneNode::getNearValue() const { return ZNear; } -f32 CCameraSceneNode::getFarValue() const +f32 CCameraSceneNode::getFarValue() const { return ZFar; } -f32 CCameraSceneNode::getAspectRatio() const +f32 CCameraSceneNode::getAspectRatio() const { return Aspect; } -f32 CCameraSceneNode::getFOV() const +f32 CCameraSceneNode::getFOV() const { return Fovy; } @@ -211,13 +227,22 @@ void CCameraSceneNode::setFOV(f32 f) void CCameraSceneNode::recalculateProjectionMatrix() { - ViewArea.Matrices [ video::ETS_PROJECTION ].buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar); - ViewArea.setTransformState ( video::ETS_PROJECTION ); + ViewArea.getTransform ( video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar); } //! prerender void CCameraSceneNode::OnRegisterSceneNode() +{ + if ( SceneManager->getActiveCamera () == this ) + SceneManager->registerNodeForRendering(this, ESNRP_CAMERA); + + ISceneNode::OnRegisterSceneNode(); +} + + +//! render +void CCameraSceneNode::render() { core::vector3df pos = getAbsolutePosition(); core::vector3df tgtv = Target - pos; @@ -230,30 +255,20 @@ void CCameraSceneNode::OnRegisterSceneNode() f32 dp = tgtv.dotProduct(up); - if ( core::equals(fabsf(dp), 1.f) ) + if ( core::equals(core::abs_(dp), 1.f) ) { up.X += 0.5f; } - ViewArea.Matrices[video::ETS_VIEW].buildCameraLookAtMatrixLH(pos, Target, up); - ViewArea.setTransformState(video::ETS_VIEW); + ViewArea.getTransform(video::ETS_VIEW).buildCameraLookAtMatrixLH(pos, Target, up); + ViewArea.getTransform(video::ETS_VIEW) *= Affector; recalculateViewArea(); - if ( SceneManager->getActiveCamera () == this ) - SceneManager->registerNodeForRendering(this, ESNRP_CAMERA); - - ISceneNode::OnRegisterSceneNode(); -} - - -//! render -void CCameraSceneNode::render() -{ video::IVideoDriver* driver = SceneManager->getVideoDriver(); if ( driver) { - driver->setTransform(video::ETS_PROJECTION, ViewArea.Matrices [ video::ETS_PROJECTION ] ); - driver->setTransform(video::ETS_VIEW, ViewArea.Matrices [ video::ETS_VIEW ] ); + driver->setTransform(video::ETS_PROJECTION, ViewArea.getTransform ( video::ETS_PROJECTION) ); + driver->setTransform(video::ETS_VIEW, ViewArea.getTransform ( video::ETS_VIEW) ); } } @@ -275,7 +290,11 @@ const SViewFrustum* CCameraSceneNode::getViewFrustum() const void CCameraSceneNode::recalculateViewArea() { ViewArea.cameraPosition = getAbsolutePosition(); - ViewArea.setFrom(ViewArea.Matrices[SViewFrustum::ETS_VIEW_PROJECTION_3]); + + core::matrix4 m(core::matrix4::EM4CONST_NOTHING); + m.setbyproduct_nocheck(ViewArea.getTransform(video::ETS_PROJECTION), + ViewArea.getTransform(video::ETS_VIEW)); + ViewArea.setFrom(m); } @@ -308,7 +327,7 @@ void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribute TargetAndRotationAreBound = in->getAttributeAsBool("Binding"); recalculateProjectionMatrix(); - recalculateViewArea(); + recalculateViewArea(); } @@ -326,6 +345,25 @@ bool CCameraSceneNode::getTargetAndRotationBinding(void) const } +//! Creates a clone of this scene node and its children. +ISceneNode* CCameraSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) +{ + if (!newParent) + newParent = Parent; + if (!newManager) + newManager = SceneManager; + + CCameraSceneNode* nb = new CCameraSceneNode(newParent, + newManager, ID, RelativeTranslation, Target); + + nb->cloneMembers(this, newManager); + + if ( newParent ) + nb->drop(); + return nb; +} + + } // end namespace } // end namespace diff --git a/src/dep/src/irrlicht/CCameraSceneNode.h b/src/dep/src/irrlicht/CCameraSceneNode.h index d4bdd46..9ea9c13 100644 --- a/src/dep/src/irrlicht/CCameraSceneNode.h +++ b/src/dep/src/irrlicht/CCameraSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -40,6 +40,13 @@ namespace scene //! \return Returns the current view matrix of the camera. virtual const core::matrix4& getViewMatrix() const; + //! Sets a custom view matrix affector. + /** \param affector: The affector matrix. */ + virtual void setViewMatrixAffector(const core::matrix4& affector); + + //! Gets the custom view matrix affector. + virtual const core::matrix4& getViewMatrixAffector() const; + //! 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 scene::ISceneManager::addMayaCameraSceneNode or @@ -135,6 +142,9 @@ namespace scene //! Queries if the camera scene node's rotation and its target position are bound together. virtual bool getTargetAndRotationBinding(void) const; + //! Creates a clone of this scene node and its children. + virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); + protected: void recalculateProjectionMatrix(); @@ -149,9 +159,9 @@ namespace scene f32 ZFar; // Z-value of the far view-plane. SViewFrustum ViewArea; + core::matrix4 Affector; bool InputReceiverEnabled; - bool TargetAndRotationAreBound; }; diff --git a/src/dep/src/irrlicht/CColladaFileLoader.cpp b/src/dep/src/irrlicht/CColladaFileLoader.cpp index 0ba5b89..4117682 100644 --- a/src/dep/src/irrlicht/CColladaFileLoader.cpp +++ b/src/dep/src/irrlicht/CColladaFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,9 +28,10 @@ namespace irr { namespace scene +{ +namespace { // currently supported COLLADA tag names - const core::stringc colladaSectionName = "COLLADA"; const core::stringc librarySectionName = "library"; const core::stringc libraryNodesSectionName = "library_nodes"; @@ -118,9 +119,11 @@ namespace scene const core::stringc falloffExponentNodeName = "falloff_exponent"; const core::stringc profileCOMMONSectionName = "profile_COMMON"; + const core::stringc profileCOMMONAttributeName = "COMMON"; const char* const inputSemanticNames[] = {"POSITION", "VERTEX", "NORMAL", "TEXCOORD", "UV", "TANGENT", "IMAGE", "TEXTURE", 0}; +} //! following class is for holding and creating instances of library //! objects, named prefabs in this loader. @@ -328,9 +331,9 @@ CColladaFileLoader::~CColladaFileLoader() //! Returns true if the file maybe is able to be loaded by this class. /** This decision should be based only on the file extension (e.g. ".cob") */ -bool CColladaFileLoader::isALoadableFileExtension(const c8* fileName) const +bool CColladaFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(fileName, ".xml") || strstr(fileName, ".dae"); + return core::hasFileExtension ( filename, "xml", "dae" ); } @@ -367,7 +370,6 @@ IAnimatedMesh* CColladaFileLoader::createMesh(io::IReadFile* file) if (!Version) return 0; - // because this loader loads and creates a complete scene instead of // a single mesh, return an empty dummy mesh to make the scene manager // know that everything went well. @@ -375,6 +377,9 @@ IAnimatedMesh* CColladaFileLoader::createMesh(io::IReadFile* file) DummyMesh = new SAnimatedMesh(); scene::IAnimatedMesh* returnMesh = DummyMesh; + if (Version < 10400) + instantiateNode(SceneManager->getRootSceneNode()); + // add the first loaded mesh into the mesh cache too, if more than one // meshes have been loaded from the file if (LoadedMeshCount>1 && FirstLoadedMesh) @@ -422,7 +427,7 @@ void CColladaFileLoader::skipSection(io::IXMLReaderUTF8* reader, bool reportSkip { #ifdef COLLADA_READER_DEBUG if (reportSkipping) - os::Printer::log("Skipping COLLADA unknown element:", core::stringc(reader->getNodeName()).c_str()); + os::Printer::log("Skipping COLLADA unknown element", core::stringc(reader->getNodeName()).c_str()); #endif // COLLADA_READER_DEBUG ++tagCounter; @@ -441,7 +446,7 @@ void CColladaFileLoader::readColladaSection(io::IXMLReaderUTF8* reader) return; const f32 version = core::fast_atof(core::stringc(reader->getAttributeValue("version")).c_str()); - Version = core::floor32(version)*10000+core::ceil32(core::fract(version)*1000.0f); + Version = core::floor32(version)*10000+core::round32(core::fract(version)*1000.0f); // Version 1.4 can be checked for by if (Version >= 10400) while(reader->read()) @@ -774,7 +779,7 @@ void CColladaFileLoader::readNodeSection(io::IXMLReaderUTF8* reader, scene::ISce if (node && newnode) { // move children from dummy to new node - core::list::ConstIterator it = node->getChildren().begin(); + ISceneNodeList::ConstIterator it = node->getChildren().begin(); for (; it != node->getChildren().end(); it = node->getChildren().begin()) (*it)->setParent(newnode); @@ -1074,9 +1079,9 @@ core::matrix4 CColladaFileLoader::readTranslateNode(io::IXMLReaderUTF8* reader) } -//! reads any kind of node and creates a scene node from it -void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, - scene::ISceneNode** outNode, CScenePrefab* p) +//! reads any kind of node +void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader, + scene::ISceneNode* parent, scene::ISceneNode** outNode, CScenePrefab* p) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading instance"); @@ -1103,10 +1108,20 @@ void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader, scene::ISc break; } } + instantiateNode(parent, outNode, p, url); +} + + +void CColladaFileLoader::instantiateNode(scene::ISceneNode* parent, + scene::ISceneNode** outNode, CScenePrefab* p, const core::stringc& url) +{ + #ifdef COLLADA_READER_DEBUG + os::Printer::log("COLLADA instantiate node"); + #endif for (u32 i=0; igetId()) + if (url == "" || url == Prefabs[i]->getId()) { if (p) p->Childs.push_back(Prefabs[i]); @@ -1119,7 +1134,7 @@ void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader, scene::ISc { *outNode = newNode; if (*outNode) - (*outNode)->setName(readId(reader)); + (*outNode)->setName(url); } } return; @@ -1474,6 +1489,10 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * readIntsInsideElement(reader,&doubleSided,1); if (doubleSided) { + #ifdef COLLADA_READER_DEBUG + os::Printer::log("Setting double sided flag for effect."); + #endif + effect->Mat.setFlag(irr::video::EMF_BACK_FACE_CULLING,false); } } @@ -1724,12 +1743,26 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader) } else // trifans, and tristrips missing - if (extraNodeName == reader->getNodeName()) - skipSection(reader, false); - else - if (techniqueCommonSectionName != nodeName) // techniqueCommon must not be skipped + if (doubleSidedNodeName == reader->getNodeName()) { -// os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); + // read the extra flag for double sided polys + s32 doubleSided = 0; + readIntsInsideElement(reader,&doubleSided,1); + if (doubleSided) + { + #ifdef COLLADA_READER_DEBUG + os::Printer::log("Setting double sided flag for mesh."); + #endif + amesh->setMaterialFlag(irr::video::EMF_BACK_FACE_CULLING,false); + } + } + else + // techniqueCommon or 'technique profile=common' must not be skipped + if ((techniqueCommonSectionName != nodeName) // Collada 1.2/1.3 + && (techniqueNodeName != nodeName) // Collada 1.4+ + && (extraNodeName != nodeName)) + { + os::Printer::log("COLLADA loader warning: Wrong tag usage found in geometry", reader->getNodeName(), ELL_WARNING); skipSection(reader, true); // ignore all other sections } } // end if node type is element @@ -1774,7 +1807,7 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader) amesh->recalculateBoundingBox(); // create virtual file name - core::stringc filename = CurrentlyLoadingMesh; + io::path filename = CurrentlyLoadingMesh; filename += '#'; filename += id; @@ -1828,6 +1861,8 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, core::stringc polygonType = reader->getNodeName(); const int polygonCount = reader->getAttributeValueAsInt("count"); // Not useful because it only determines the number of primitives, which have arbitrary vertices in case of polygon core::array polygons; + if (polygonType == polygonsSectionName) + polygons.reallocate(polygonCount); core::array vCounts; bool parsePolygonOK = false; bool parseVcountOK = false; @@ -1945,7 +1980,10 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, data.trim(); const c8* p = &data[0]; SPolygon& poly = polygons.getLast(); - poly.Indices.reallocate(polygonCount*(maxOffset+1)*3); + if (polygonType == polygonsSectionName) + poly.Indices.reallocate((maxOffset+1)*3); + else + poly.Indices.reallocate(polygonCount*(maxOffset+1)*3); if (vCounts.empty()) { @@ -1957,10 +1995,9 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, } else { - for (u32 i = 0; i < vCounts.size(); i++) { - int polyVCount = vCounts[i]; + const int polyVCount = vCounts[i]; core::array polyCorners; @@ -2395,7 +2432,10 @@ void CColladaFileLoader::readColladaInput(io::IXMLReaderUTF8* reader) // get source p.Source = reader->getAttributeValue("source"); - p.Offset = (u32)reader->getAttributeValueAsInt("offset"); + if (reader->getAttributeValue("offset")) // Collada 1.4+ + p.Offset = (u32)reader->getAttributeValueAsInt("offset"); + else // Collada 1.2/1.3 + p.Offset = (u32)reader->getAttributeValueAsInt("idx"); p.Set = (u32)reader->getAttributeValueAsInt("set"); // add input @@ -2696,9 +2736,9 @@ video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri) { if (Images[i].Source.size() && Images[i].SourceIsFilename) { - if (FileSystem->existFile(Images[i].Source.c_str())) - return driver->getTexture(Images[i].Source.c_str()); - return driver->getTexture((FileSystem->getFileDir(CurrentlyLoadingMesh)+"/"+Images[i].Source).c_str()); + if (FileSystem->existFile(Images[i].Source)) + return driver->getTexture(Images[i].Source); + return driver->getTexture((FileSystem->getFileDir(CurrentlyLoadingMesh)+"/"+Images[i].Source)); } else if (Images[i].Source.size()) diff --git a/src/dep/src/irrlicht/CColladaFileLoader.h b/src/dep/src/irrlicht/CColladaFileLoader.h index 84db175..000fc1c 100644 --- a/src/dep/src/irrlicht/CColladaFileLoader.h +++ b/src/dep/src/irrlicht/CColladaFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -101,7 +101,7 @@ struct SColladaImage { core::stringc Id; core::stringc Source; - core::dimension2di Dimension; + core::dimension2du Dimension; bool SourceIsFilename; }; @@ -121,7 +121,7 @@ struct SColladaMaterial core::stringc Id; core::stringc InstanceEffectId; f32 Transparency; - + inline bool operator< (const SColladaMaterial & other) const { return Id < other.Id; @@ -134,7 +134,7 @@ struct SColladaEffect video::SMaterial Mat; core::stringc Id; f32 Transparency; - + inline bool operator< (const SColladaEffect & other) const { return Id < other.Id; @@ -184,7 +184,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -246,10 +246,14 @@ private: //! reads a element f32 readFloatNode(io::IXMLReaderUTF8* reader); - //! reads a node and creates a scene node from it + //! reads a node void readInstanceNode(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, scene::ISceneNode** outNode, CScenePrefab* p=0); + //! creates a scene node from Prefabs (with name given in 'url') + void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0, + CScenePrefab* p=0, const core::stringc& url=""); + //! reads a element and stores it as prefab void readLightPrefab(io::IXMLReaderUTF8* reader); @@ -317,10 +321,10 @@ private: void readPolygonSection(io::IXMLReaderUTF8* reader, const core::stringc& vertexPositionSource, core::array& sources, scene::SMesh* mesh, const core::stringc& geometryId); - + //! finds a material, possible instancing it const SColladaMaterial * findMaterial(const core::stringc & materialName); - + //! reads and bind materials as given by the symbol->target bind mapping void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id); @@ -337,7 +341,7 @@ private: core::stringc CurrentlyLoadingMesh; scene::IAnimatedMesh* FirstLoadedMesh; - core::stringc FirstLoadedMeshName; + io::path FirstLoadedMeshName; s32 LoadedMeshCount; u32 Version; bool FlipAxis; diff --git a/src/dep/src/irrlicht/CColladaMeshWriter.cpp b/src/dep/src/irrlicht/CColladaMeshWriter.cpp index f8b230f..ded3096 100644 --- a/src/dep/src/irrlicht/CColladaMeshWriter.cpp +++ b/src/dep/src/irrlicht/CColladaMeshWriter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CColladaMeshWriter.h b/src/dep/src/irrlicht/CColladaMeshWriter.h index a0dc99b..1b8d372 100644 --- a/src/dep/src/irrlicht/CColladaMeshWriter.h +++ b/src/dep/src/irrlicht/CColladaMeshWriter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CColorConverter.cpp b/src/dep/src/irrlicht/CColorConverter.cpp index e2573af..30eb129 100644 --- a/src/dep/src/irrlicht/CColorConverter.cpp +++ b/src/dep/src/irrlicht/CColorConverter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -415,6 +415,38 @@ void CColorConverter::convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP) } } +void CColorConverter::convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP) +{ + u8* sB = (u8* )sP; + u32* dB = (u32*)dP; + + for (s32 x = 0; x < sN; ++x) + { + *dB = 0xff000000 | (sB[2]<<16) | (sB[1]<<8) | sB[0]; + + sB += 3; + ++dB; + } +} + +void CColorConverter::convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP) +{ + u8* sB = (u8*)sP; + u8* dB = (u8*)dP; + + for (s32 x = 0; x < sN; ++x) + { + dB[0] = sB[3]; + dB[1] = sB[2]; + dB[2] = sB[1]; + dB[3] = sB[0]; + + sB += 4; + dB += 4; + } + +} + void CColorConverter::convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP) { u8 * sB = (u8 *)sP; diff --git a/src/dep/src/irrlicht/CColorConverter.h b/src/dep/src/irrlicht/CColorConverter.h index e457e6b..6882af6 100644 --- a/src/dep/src/irrlicht/CColorConverter.h +++ b/src/dep/src/irrlicht/CColorConverter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -66,6 +66,8 @@ public: static void convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP); static void convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP); + static void convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP); + static void convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP); static void convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP); diff --git a/src/dep/src/irrlicht/CCubeSceneNode.cpp b/src/dep/src/irrlicht/CCubeSceneNode.cpp index 29ee1e8..59ef0be 100644 --- a/src/dep/src/irrlicht/CCubeSceneNode.cpp +++ b/src/dep/src/irrlicht/CCubeSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,68 +24,36 @@ namespace scene | / | / |/ | / 0------11,1/ - 000 100 + 000 100 */ //! constructor CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) - : IMeshSceneNode(parent, mgr, id, position, rotation, scale), Size(size) + : IMeshSceneNode(parent, mgr, id, position, rotation, scale), + Mesh(0), Size(size) { #ifdef _DEBUG setDebugName("CCubeSceneNode"); #endif - const u16 u[36] = { 0,2,1, 0,3,2, 1,5,4, 1,2,5, 4,6,7, 4,5,6, - 7,3,0, 7,6,3, 9,5,2, 9,8,5, 0,11,10, 0,10,7}; - - SMeshBuffer* buf = new SMeshBuffer(); - Mesh.addMeshBuffer(buf); - buf->Indices.set_used(36); - for (u32 i=0; i<36; ++i) - buf->Indices[i] = u[i]; - buf->drop(); - setSize(); } +CCubeSceneNode::~CCubeSceneNode() +{ + if (Mesh) + Mesh->drop(); +} + + void CCubeSceneNode::setSize() { - // we are creating the cube mesh here. - - // nicer texture mapping sent in by Dr Andros C Bragianos - // .. and then improved by jox. - - video::SColor clr(255,255,255,255); - - SMeshBuffer* buf = (SMeshBuffer*)Mesh.getMeshBuffer(0); - - buf->Vertices.reallocate(12); - // Start setting vertices from index 0 to deal with this method being called multiple times. - buf->Vertices.set_used(0); - buf->Vertices.push_back(video::S3DVertex(0,0,0, -1,-1,-1, clr, 0, 1)); - buf->Vertices.push_back(video::S3DVertex(1,0,0, 1,-1,-1, clr, 1, 1)); - buf->Vertices.push_back(video::S3DVertex(1,1,0, 1, 1,-1, clr, 1, 0)); - buf->Vertices.push_back(video::S3DVertex(0,1,0, -1, 1,-1, clr, 0, 0)); - buf->Vertices.push_back(video::S3DVertex(1,0,1, 1,-1, 1, clr, 0, 1)); - buf->Vertices.push_back(video::S3DVertex(1,1,1, 1, 1, 1, clr, 0, 0)); - buf->Vertices.push_back(video::S3DVertex(0,1,1, -1, 1, 1, clr, 1, 0)); - buf->Vertices.push_back(video::S3DVertex(0,0,1, -1,-1, 1, clr, 1, 1)); - buf->Vertices.push_back(video::S3DVertex(0,1,1, -1, 1, 1, clr, 0, 1)); - buf->Vertices.push_back(video::S3DVertex(0,1,0, -1, 1,-1, clr, 1, 1)); - buf->Vertices.push_back(video::S3DVertex(1,0,1, 1,-1, 1, clr, 1, 0)); - buf->Vertices.push_back(video::S3DVertex(1,0,0, 1,-1,-1, clr, 0, 0)); - - buf->BoundingBox.reset(0,0,0); - - for (u32 i=0; i<12; ++i) - { - buf->Vertices[i].Pos -= core::vector3df(0.5f, 0.5f, 0.5f); - buf->Vertices[i].Pos *= Size; - buf->BoundingBox.addInternalPoint(buf->Vertices[i].Pos); - } + if (Mesh) + Mesh->drop(); + Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size)); } @@ -93,16 +61,78 @@ void CCubeSceneNode::setSize() void CCubeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); - driver->setMaterial(Mesh.getMeshBuffer(0)->getMaterial()); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); - driver->drawMeshBuffer(Mesh.getMeshBuffer(0)); + + // for debug purposes only: + bool renderMeshes = true; + video::SMaterial mat = Mesh->getMeshBuffer(0)->getMaterial(); + + // overwrite half transparency + if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) + mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; + else + driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); + driver->setMaterial(mat); + driver->drawMeshBuffer(Mesh->getMeshBuffer(0)); + + // for debug purposes only: + if (DebugDataVisible) + { + video::SMaterial m; + m.Lighting = false; + m.AntiAliasing=0; + driver->setMaterial(m); + + if (DebugDataVisible & scene::EDS_BBOX) + { + driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,255,255,255)); + } + if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) + { + driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), + video::SColor(255,190,128,128)); + } + if (DebugDataVisible & scene::EDS_NORMALS) + { + // draw normals + core::vector3df normalizedNormal; + const f32 DebugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); + const video::SColor DebugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); + + const scene::IMeshBuffer* mb = Mesh->getMeshBuffer(0); + const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); + const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); + const bool normalize = mb->getMaterial().NormalizeNormals; + + for (u32 i=0; i != mb->getVertexCount(); ++i) + { + normalizedNormal = v->Normal; + if (normalize) + normalizedNormal.normalize(); + + driver->draw3DLine(v->Pos, v->Pos + (normalizedNormal * DebugNormalLength), DebugNormalColor); + + v = (const video::S3DVertex*) ( (u8*) v+vSize ); + } + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + } + + // show mesh + if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) + { + m.Wireframe = true; + driver->setMaterial(m); + + driver->drawMeshBuffer( Mesh->getMeshBuffer(0) ); + } + } } //! returns the axis aligned bounding box of this node const core::aabbox3d& CCubeSceneNode::getBoundingBox() const { - return Mesh.getMeshBuffer(0)->getBoundingBox(); + return Mesh->getMeshBuffer(0)->getBoundingBox(); } @@ -114,14 +144,10 @@ void CCubeSceneNode::OnRegisterSceneNode() } -//! returns the material based on the zero based index i. To get the amount -//! of materials used by this scene node, use getMaterialCount(). -//! This function is needed for inserting the node into the scene hirachy on a -//! optimal position for minimizing renderstate changes, but can also be used -//! to directly modify the material of a scene node. +//! returns the material based on the zero based index i. video::SMaterial& CCubeSceneNode::getMaterial(u32 i) { - return Mesh.getMeshBuffer(0)->getMaterial(); + return Mesh->getMeshBuffer(0)->getMaterial(); } @@ -144,9 +170,13 @@ void CCubeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeRea //! Reads attributes of the scene node. void CCubeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - Size = in->getAttributeAsFloat("Size"); - Size = core::max_(Size, 0.0001f); - setSize(); + f32 newSize = in->getAttributeAsFloat("Size"); + newSize = core::max_(newSize, 0.0001f); + if (newSize != Size) + { + Size = newSize; + setSize(); + } ISceneNode::deserializeAttributes(in, options); } @@ -155,16 +185,19 @@ void CCubeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeRe //! Creates a clone of this scene node and its children. ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { - if (!newParent) newParent = Parent; - if (!newManager) newManager = SceneManager; + if (!newParent) + newParent = Parent; + if (!newManager) + newManager = SceneManager; - CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent, + CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent, newManager, ID, RelativeTranslation); nb->cloneMembers(this, newManager); nb->getMaterial(0) = getMaterial(0); - nb->drop(); + if ( newParent ) + nb->drop(); return nb; } diff --git a/src/dep/src/irrlicht/CCubeSceneNode.h b/src/dep/src/irrlicht/CCubeSceneNode.h index 658b061..2d97879 100644 --- a/src/dep/src/irrlicht/CCubeSceneNode.h +++ b/src/dep/src/irrlicht/CCubeSceneNode.h @@ -1,9 +1,9 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#ifndef __C_TEST_SCENE_NODE_H_INCLUDED__ -#define __C_TEST_SCENE_NODE_H_INCLUDED__ +#ifndef __C_CUBE_SCENE_NODE_H_INCLUDED__ +#define __C_CUBE_SCENE_NODE_H_INCLUDED__ #include "IMeshSceneNode.h" #include "SMesh.h" @@ -22,6 +22,8 @@ namespace scene const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); + virtual ~CCubeSceneNode(); + virtual void OnRegisterSceneNode(); //! renders the node. @@ -56,7 +58,7 @@ namespace scene virtual void setMesh(IMesh* mesh) {} //! Returns the current mesh - virtual IMesh* getMesh(void) { return &Mesh; } + virtual IMesh* getMesh(void) { return Mesh; } //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. /* In this way it is possible to change the materials a mesh causing all mesh scene nodes @@ -69,7 +71,7 @@ namespace scene private: void setSize(); - SMesh Mesh; + IMesh* Mesh; f32 Size; }; diff --git a/src/dep/src/irrlicht/CD3D8Driver.cpp b/src/dep/src/irrlicht/CD3D8Driver.cpp index cc6371a..4c8ec5e 100644 --- a/src/dep/src/irrlicht/CD3D8Driver.cpp +++ b/src/dep/src/irrlicht/CD3D8Driver.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -25,7 +25,7 @@ namespace video //! constructor -CD3D8Driver::CD3D8Driver(const core::dimension2d& screenSize, HWND window, +CD3D8Driver::CD3D8Driver(const core::dimension2d& screenSize, HWND window, bool fullscreen, bool stencilbuffer, io::IFileSystem* io, bool pureSoftware, bool vsync) : CNullDriver(io, screenSize), CurrentRenderMode(ERM_NONE), @@ -33,7 +33,7 @@ CD3D8Driver::CD3D8Driver(const core::dimension2d& screenSize, HWND window, D3DLibrary(0), pID3D(0), pID3DDevice(0), PrevRenderTarget(0), WindowId(0), SceneSourceRect(0), LastVertexType((video::E_VERTEX_TYPE)-1), MaxTextureUnits(0), MaxUserClipPlanes(0), - MaxLightDistance(sqrtf(FLT_MAX)), LastSetLight(-1), DeviceLost(false), + MaxLightDistance(0), LastSetLight(-1), DeviceLost(false), DriverWasReset(true) { #ifdef _DEBUG @@ -44,7 +44,7 @@ CD3D8Driver::CD3D8Driver(const core::dimension2d& screenSize, HWND window, for (u32 i=0; i& screenSize, HWND window, SphereMapMatrixD3D8._41 = 0.5f; SphereMapMatrixD3D8._42 = 0.5f; SphereMapMatrixD3D8._43 = 0.0f; SphereMapMatrixD3D8._44 = 1.0f; - core::matrix4 mat; - UnitMatrixD3D8 = *(D3DMATRIX*)((void*)mat.pointer()); + UnitMatrixD3D8 = *(D3DMATRIX*)((void*)core::IdentityMatrix.pointer()); // init direct 3d is done in the factory function } @@ -138,17 +137,21 @@ void CD3D8Driver::createMaterialRenderers() // add basic 1 texture blending addAndDropMaterialRenderer(new CD3D8MaterialRenderer_ONETEXTURE_BLEND(pID3DDevice, this)); - } //! initialises the Direct3D API -bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, +bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, HWND hwnd, u32 bits, bool fullScreen, bool pureSoftware, - bool highPrecisionFPU, bool vsync, bool antiAlias) + bool highPrecisionFPU, bool vsync, u8 antiAlias) { HRESULT hr; - D3DLibrary = LoadLibrary( "d3d8.dll" ); + typedef IDirect3D8 * (__stdcall *D3DCREATETYPE)(UINT); + +#if defined( _IRR_XBOX_PLATFORM_) + D3DCREATETYPE d3dCreate = (D3DCREATETYPE) &Direct3DCreate8; +#else + D3DLibrary = LoadLibrary( __TEXT("d3d8.dll") ); if (!D3DLibrary) { @@ -156,7 +159,6 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, return false; } - typedef IDirect3D8 * (__stdcall *D3DCREATETYPE)(UINT); D3DCREATETYPE d3dCreate = (D3DCREATETYPE) GetProcAddress(D3DLibrary, "Direct3DCreate8"); if (!d3dCreate) @@ -164,6 +166,7 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, os::Printer::log("Error, could not get proc adress of Direct3DCreate8.", ELL_ERROR); return false; } +#endif //just like pID3D = Direct3DCreate8(D3D_SDK_VERSION); pID3D = (*d3dCreate)(D3D_SDK_VERSION); @@ -190,8 +193,6 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, os::Printer::log(tmp, ELL_INFORMATION); } - - D3DDISPLAYMODE d3ddm; hr = pID3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm); if (FAILED(hr)) @@ -200,13 +201,12 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, return false; } - ZeroMemory(&present, sizeof(present)); - present.SwapEffect = D3DSWAPEFFECT_COPY; - present.Windowed = TRUE; - present.BackBufferFormat = d3ddm.Format; - present.EnableAutoDepthStencil = TRUE; + present.SwapEffect = D3DSWAPEFFECT_DISCARD; + present.Windowed = TRUE; + present.BackBufferFormat = d3ddm.Format; + present.EnableAutoDepthStencil = TRUE; if (fullScreen) { @@ -229,21 +229,26 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, #endif // enable anti alias if possible and whished - if (antiAlias) + if (antiAlias > 0) { - if (!FAILED(pID3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, + if(antiAlias > 16) + antiAlias = 16; + + while(antiAlias > 0) + { + if(!FAILED(pID3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, devtype , present.BackBufferFormat, !fullScreen, - D3DMULTISAMPLE_2_SAMPLES))) - { - // enable multi sampling - present.SwapEffect = D3DSWAPEFFECT_DISCARD; - present.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES; + (D3DMULTISAMPLE_TYPE)antiAlias))) + { + present.MultiSampleType = (D3DMULTISAMPLE_TYPE)antiAlias; + present.SwapEffect = D3DSWAPEFFECT_DISCARD; + break; + } + --antiAlias; } - else - { + + if(antiAlias==0) os::Printer::log("Anti aliasing disabled because hardware/driver lacks necessary caps.", ELL_WARNING); - antiAlias = false; - } } // check stencil buffer compatibility @@ -254,6 +259,7 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { +#if !defined( _IRR_XBOX_PLATFORM_) present.AutoDepthStencilFormat = D3DFMT_D24X4S4; if(FAILED(pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, @@ -268,6 +274,7 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, StencilBuffer = false; } } +#endif } else if(FAILED(pID3D->CheckDepthStencilMatch(D3DADAPTER_DEFAULT, devtype, @@ -280,6 +287,7 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, // do not use else here to cope with flag change in previous block if (!StencilBuffer) { +#if !defined( _IRR_XBOX_PLATFORM_) present.AutoDepthStencilFormat = D3DFMT_D32; if(FAILED(pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, @@ -300,11 +308,24 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, } } } +#else + present.AutoDepthStencilFormat = D3DFMT_D16; + if(FAILED(pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, devtype, + present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, + D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) + { + os::Printer::log("Device does not support required depth buffer.", ELL_WARNING); + return false; + } +#endif } // create device - +#if defined( _IRR_XBOX_PLATFORM_) + DWORD fpuPrecision = 0; +#else DWORD fpuPrecision = highPrecisionFPU ? D3DCREATE_FPU_PRESERVE : 0; +#endif if (pureSoftware) { hr = pID3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hwnd, @@ -350,11 +371,11 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, setVertexShader(EVT_STANDARD); // enable antialiasing - if (antiAlias) + if (antiAlias>0) pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); // set fog mode - setFog(FogColor, LinearFog, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); + setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); // set exposed data ExposedData.D3D8.D3D8 = pID3D; @@ -372,12 +393,6 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, // set the renderstates setRenderStates3DMode(); - // set max anisotropy - pID3DDevice->SetTextureStageState(0, D3DTSS_MAXANISOTROPY, core::min_( (DWORD) 16, Caps.MaxAnisotropy)); - pID3DDevice->SetTextureStageState(1, D3DTSS_MAXANISOTROPY, core::min_( (DWORD) 16, Caps.MaxAnisotropy)); - pID3DDevice->SetTextureStageState(2, D3DTSS_MAXANISOTROPY, core::min_( (DWORD) 16, Caps.MaxAnisotropy)); - pID3DDevice->SetTextureStageState(3, D3DTSS_MAXANISOTROPY, core::min_( (DWORD) 16, Caps.MaxAnisotropy)); - // so far so good. return true; } @@ -385,10 +400,10 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, //! applications must call this method before performing any rendering. returns false if failed. bool CD3D8Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, - void* windowId, core::rect* sourceRect) + const SExposedVideoData& videoData, core::rect* sourceRect) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); - WindowId = windowId; + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + WindowId = (HWND)videoData.D3D8.HWnd; SceneSourceRect = sourceRect; if (!pID3DDevice) @@ -397,6 +412,7 @@ bool CD3D8Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, HRESULT hr; if (DeviceLost) { +#ifndef _IRR_XBOX_PLATFORM_ if(FAILED(hr = pID3DDevice->TestCooperativeLevel())) { if (hr == D3DERR_DEVICELOST) @@ -410,6 +426,7 @@ bool CD3D8Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, if ((hr == D3DERR_DEVICENOTRESET) && !reset()) return false; } +#endif } DWORD flags = 0; @@ -423,9 +440,12 @@ bool CD3D8Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, if (StencilBuffer) flags |= D3DCLEAR_STENCIL; - hr = pID3DDevice->Clear( 0, NULL, flags, color.color, 1.0, 0); - if (FAILED(hr)) - os::Printer::log("Direct3D8 clear failed.", ELL_WARNING); + if (flags) + { + hr = pID3DDevice->Clear( 0, NULL, flags, color.color, 1.0, 0); + if (FAILED(hr)) + os::Printer::log("Direct3D8 clear failed.", ELL_WARNING); + } hr = pID3DDevice->BeginScene(); if (FAILED(hr)) @@ -462,7 +482,7 @@ bool CD3D8Driver::endScene() sourceRectData.bottom = SceneSourceRect->LowerRightCorner.Y; } - hr = pID3DDevice->Present(srcRct, NULL, (HWND)WindowId, NULL); + hr = pID3DDevice->Present(srcRct, NULL, WindowId, NULL); if (SUCCEEDED(hr)) return true; @@ -519,12 +539,12 @@ bool CD3D8Driver::reset() ResetRenderStates = true; LastVertexType = (E_VERTEX_TYPE)-1; - for (u32 i=0; i= D3DVS_VERSION(1,1); case EVDF_VERTEX_SHADER_2_0: @@ -571,6 +591,8 @@ bool CD3D8Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const return (Caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) == 0; case EVDF_TEXTURE_NPOT: return (Caps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0; + case EVDF_COLOR_MASK: + return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0; default: return false; }; @@ -595,15 +617,15 @@ void CD3D8Driver::setTransform(E_TRANSFORMATION_STATE state, pID3DDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)((void*)mat.pointer())); Transformation3DChanged = true; break; - case ETS_TEXTURE_0: - case ETS_TEXTURE_1: - case ETS_TEXTURE_2: - case ETS_TEXTURE_3: - pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); - pID3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+ ( state - ETS_TEXTURE_0 )), - (D3DMATRIX*)((void*)mat.pointer())); - break; case ETS_COUNT: + return; + default: + if (state-ETS_TEXTURE_0 < MATERIAL_MAX_TEXTURES) + { + pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); + pID3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+ ( state - ETS_TEXTURE_0 )), + (D3DMATRIX*)((void*)mat.pointer())); + } break; } @@ -612,12 +634,12 @@ void CD3D8Driver::setTransform(E_TRANSFORMATION_STATE state, //! sets the current Texture -bool CD3D8Driver::setTexture(s32 stage, const video::ITexture* texture) +bool CD3D8Driver::setActiveTexture(u32 stage, const video::ITexture* texture) { if (CurrentTexture[stage] == texture) return true; - if (texture && texture->getDriverType() != EDT_DIRECT3D8) + if (texture && (texture->getDriverType() != EDT_DIRECT3D8)) { os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; @@ -642,22 +664,21 @@ bool CD3D8Driver::setTexture(s32 stage, const video::ITexture* texture) void CD3D8Driver::setMaterial(const SMaterial& material) { Material = material; + OverrideMaterial.apply(Material); for (u32 i=0; iRelease(); - CurrentRendertargetSize = core::dimension2d(0,0); + CurrentRendertargetSize = core::dimension2d(0,0); PrevRenderTarget->Release(); PrevRenderTarget = 0; } @@ -733,12 +753,11 @@ bool CD3D8Driver::setRenderTarget(video::ITexture* texture, // store previous target - if (!PrevRenderTarget) - if (FAILED(pID3DDevice->GetRenderTarget(&PrevRenderTarget))) - { - os::Printer::log("Could not get previous render target.", ELL_ERROR); - return false; - } + if (!PrevRenderTarget && (FAILED(pID3DDevice->GetRenderTarget(&PrevRenderTarget)))) + { + os::Printer::log("Could not get previous render target.", ELL_ERROR); + return false; + } // set new render target @@ -775,11 +794,10 @@ bool CD3D8Driver::setRenderTarget(video::ITexture* texture, //! Creates a render target texture. -ITexture* CD3D8Driver::addRenderTargetTexture( - const core::dimension2d& size, const c8* name) +ITexture* CD3D8Driver::addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, + const ECOLOR_FORMAT format) { - if (!name) - name="rt"; ITexture* tex = new CD3D8Texture(this, size, name); addTexture(tex); tex->drop(); @@ -834,64 +852,126 @@ void CD3D8Driver::drawVertexPrimitiveList(const void* vertices, if (!vertexCount || !primitiveCount) return; + draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, + vType, pType, iType, true); +} + + +//! draws a vertex primitive list in 2d +void CD3D8Driver::draw2DVertexPrimitiveList(const void* vertices, + u32 vertexCount, const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType) +{ + if (!checkPrimitiveCount(primitiveCount)) + return; + + CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType); + + if (!vertexCount || !primitiveCount) + return; + + draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, + vType, pType, iType, false); +} + + +void CD3D8Driver::draw2D3DVertexPrimitiveList(const void* vertices, + u32 vertexCount, const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType, bool is3D) +{ setVertexShader(vType); const u32 stride = getVertexPitchFromType(vType); - if (setRenderStates3DMode()) + D3DFORMAT indexType=D3DFMT_UNKNOWN; + switch (iType) { - switch (pType) + case (EIT_16BIT): { - case scene::EPT_POINT_SPRITES: - case scene::EPT_POINTS: - { - if (pType==scene::EPT_POINT_SPRITES) - pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_POINTSIZE, *(DWORD*)(&Material.Thickness)); - f32 tmp=1.0f; - pID3DDevice->SetRenderState(D3DRS_POINTSCALE_C, *(DWORD*)(&tmp)); - tmp=0.0f; - pID3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, *(DWORD*)(&tmp)); - pID3DDevice->SetRenderState(D3DRS_POINTSCALE_A, *(DWORD*)(&tmp)); - pID3DDevice->SetRenderState(D3DRS_POINTSCALE_B, *(DWORD*)(&tmp)); - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount, - primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride); - pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); - if (pType==scene::EPT_POINT_SPRITES) - pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); - } - break; - case scene::EPT_LINE_STRIP: - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, - primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride); - break; - case scene::EPT_LINE_LOOP: - { - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, - primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride); - u16 tmpIndices[] = {0, primitiveCount}; - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, - 1, tmpIndices, D3DFMT_INDEX16, vertices, stride); - } - break; - case scene::EPT_LINES: - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, - primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride); - break; - case scene::EPT_TRIANGLE_STRIP: - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount, - primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride); - break; - case scene::EPT_TRIANGLE_FAN: - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount, - primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride); - break; - case scene::EPT_TRIANGLES: - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount, - primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride); + indexType=D3DFMT_INDEX16; break; } + case (EIT_32BIT): + { + indexType=D3DFMT_INDEX32; + break; + } + } + + if (is3D) + { + if (!setRenderStates3DMode()) + return; + } + else + { + if (Material.MaterialType==EMT_ONETEXTURE_BLEND) + { + E_BLEND_FACTOR srcFact; + E_BLEND_FACTOR dstFact; + E_MODULATE_FUNC modulo; + u32 alphaSource; + unpack_texureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam); + setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0); + } + else + setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL); + } + + switch (pType) + { + case scene::EPT_POINT_SPRITES: + case scene::EPT_POINTS: + { + f32 tmp=Material.Thickness/getScreenSize().Height; + if (pType==scene::EPT_POINT_SPRITES) + pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_POINTSIZE, *(DWORD*)(&tmp)); + tmp=1.0f; + pID3DDevice->SetRenderState(D3DRS_POINTSCALE_A, *(DWORD*)(&tmp)); + pID3DDevice->SetRenderState(D3DRS_POINTSCALE_B, *(DWORD*)(&tmp)); + pID3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, *(DWORD*)(&tmp)); + tmp=0.0f; + pID3DDevice->SetRenderState(D3DRS_POINTSCALE_C, *(DWORD*)(&tmp)); + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); + if (pType==scene::EPT_POINT_SPRITES) + pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); + } + break; + case scene::EPT_LINE_STRIP: + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + break; + case scene::EPT_LINE_LOOP: + { + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, + primitiveCount - 1, indexList, indexType, vertices, stride); + u16 tmpIndices[] = {primitiveCount - 1, 0}; + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, + 1, tmpIndices, indexType, vertices, stride); + } + break; + case scene::EPT_LINES: + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + break; + case scene::EPT_TRIANGLE_STRIP: + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + break; + case scene::EPT_TRIANGLE_FAN: + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + break; + case scene::EPT_TRIANGLES: + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + break; } } @@ -909,13 +989,14 @@ void CD3D8Driver::draw2DImage(const video::ITexture* texture, if (!sourceRect.isValid()) return; - if (!setTexture(0, texture)) + if (!setActiveTexture(0, texture)) return; core::position2d targetPos = pos; core::position2d sourcePos = sourceRect.UpperLeftCorner; + // This needs to be signed as it may go negative. core::dimension2d sourceSize(sourceRect.getSize()); - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); if (clipRect) { @@ -929,7 +1010,7 @@ void CD3D8Driver::draw2DImage(const video::ITexture* texture, targetPos.X = clipRect->UpperLeftCorner.X; } - if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) + if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; if (sourceSize.Width <= 0) @@ -946,7 +1027,7 @@ void CD3D8Driver::draw2DImage(const video::ITexture* texture, targetPos.Y = clipRect->UpperLeftCorner.Y; } - if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) + if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; if (sourceSize.Height <= 0) @@ -966,7 +1047,7 @@ void CD3D8Driver::draw2DImage(const video::ITexture* texture, targetPos.X = 0; } - if (targetPos.X + sourceSize.Width > renderTargetSize.Width) + if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; if (sourceSize.Width <= 0) @@ -983,7 +1064,7 @@ void CD3D8Driver::draw2DImage(const video::ITexture* texture, targetPos.Y = 0; } - if (targetPos.Y + sourceSize.Height > renderTargetSize.Height) + if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; if (sourceSize.Height <= 0) @@ -993,47 +1074,40 @@ void CD3D8Driver::draw2DImage(const video::ITexture* texture, // ok, we've clipped everything. // now draw it. - s32 xPlus = -(renderTargetSize.Width>>1); - f32 xFact = 1.0f / (renderTargetSize.Width>>1); - - s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1); - f32 yFact = 1.0f / (renderTargetSize.Height>>1); - - const core::dimension2d sourceSurfaceSize = texture->getOriginalSize(); core::rect tcoords; - tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)+0.5f) / texture->getOriginalSize().Width ; - tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)+0.5f) / texture->getOriginalSize().Height; - tcoords.LowerRightCorner.X = (((f32)sourcePos.X +0.5f + (f32)sourceSize.Width)) / texture->getOriginalSize().Width; - tcoords.LowerRightCorner.Y = (((f32)sourcePos.Y +0.5f + (f32)sourceSize.Height)) / texture->getOriginalSize().Height; + tcoords.UpperLeftCorner.X = (f32)sourcePos.X / texture->getOriginalSize().Width ; + tcoords.UpperLeftCorner.Y = (f32)sourcePos.Y / texture->getOriginalSize().Height; + tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + (f32)sourceSize.Width / texture->getOriginalSize().Width; + tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + (f32)sourceSize.Height / texture->getOriginalSize().Height; - core::rect poss(targetPos, sourceSize); + const core::rect poss(targetPos, sourceSize); setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); S3DVertex vtx[4]; - vtx[0] = S3DVertex((f32)(poss.UpperLeftCorner.X+xPlus) * xFact, - (f32)(yPlus-poss.UpperLeftCorner.Y ) * yFact, 0.0f, + vtx[0] = S3DVertex((f32)poss.UpperLeftCorner.X, + (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); - vtx[1] = S3DVertex((f32)(poss.LowerRightCorner.X+xPlus) * xFact, - (f32)(yPlus- poss.UpperLeftCorner.Y) * yFact, 0.0f, + vtx[1] = S3DVertex((f32)poss.LowerRightCorner.X, + (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); - vtx[2] = S3DVertex((f32)(poss.LowerRightCorner.X+xPlus) * xFact, - (f32)(yPlus-poss.LowerRightCorner.Y) * yFact, 0.0f, + vtx[2] = S3DVertex((f32)poss.LowerRightCorner.X, + (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); - vtx[3] = S3DVertex((f32)(poss.UpperLeftCorner.X+xPlus) * xFact, - (f32)(yPlus-poss.LowerRightCorner.Y) * yFact, 0.0f, + vtx[3] = S3DVertex((f32)poss.UpperLeftCorner.X, + (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); - s16 indices[6] = {0,1,2,0,2,3}; + const s16 indices[6] = {0,1,2,0,2,3}; setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], - D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex)); + D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); } @@ -1047,7 +1121,7 @@ void CD3D8Driver::draw2DImage(const video::ITexture* texture, if(!texture) return; - const core::dimension2d& ss = texture->getOriginalSize(); + const core::dimension2d& ss = texture->getOriginalSize(); core::rect tcoords; tcoords.UpperLeftCorner.X = (f32)sourceRect.UpperLeftCorner.X / (f32)ss.Width; tcoords.UpperLeftCorner.Y = (f32)sourceRect.UpperLeftCorner.Y / (f32)ss.Height; @@ -1076,15 +1150,6 @@ void CD3D8Driver::draw2DImage(const video::ITexture* texture, tcoords.LowerRightCorner.Y -= scale * tcHeight; } - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - core::rect npos; - f32 xFact = 2.0f / ( renderTargetSize.Width ); - f32 yFact = 2.0f / ( renderTargetSize.Height ); - npos.UpperLeftCorner.X = ( clippedRect.UpperLeftCorner.X * xFact ) - 1.0f; - npos.UpperLeftCorner.Y = 1.0f - ( clippedRect.UpperLeftCorner.Y * yFact ); - npos.LowerRightCorner.X = ( clippedRect.LowerRightCorner.X * xFact ) - 1.0f; - npos.LowerRightCorner.Y = 1.0f - ( clippedRect.LowerRightCorner.Y * yFact ); - const video::SColor temp[4] = { 0xFFFFFFFF, @@ -1096,31 +1161,31 @@ void CD3D8Driver::draw2DImage(const video::ITexture* texture, const video::SColor* const useColor = colors ? colors : temp; S3DVertex vtx[4]; // clock wise - vtx[0] = S3DVertex(npos.UpperLeftCorner.X, npos.UpperLeftCorner.Y, 0.0f, + vtx[0] = S3DVertex((f32)clippedRect.UpperLeftCorner.X, (f32)clippedRect.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); - vtx[1] = S3DVertex(npos.LowerRightCorner.X, npos.UpperLeftCorner.Y, 0.0f, + vtx[1] = S3DVertex((f32)clippedRect.LowerRightCorner.X, (f32)clippedRect.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[3], tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); - vtx[2] = S3DVertex(npos.LowerRightCorner.X, npos.LowerRightCorner.Y, 0.0f, + vtx[2] = S3DVertex((f32)clippedRect.LowerRightCorner.X, (f32)clippedRect.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); - vtx[3] = S3DVertex(npos.UpperLeftCorner.X, npos.LowerRightCorner.Y, 0.0f, + vtx[3] = S3DVertex((f32)clippedRect.UpperLeftCorner.X, (f32)clippedRect.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); - s16 indices[6] = {0,1,2,0,2,3}; + const s16 indices[6] = {0,1,2,0,2,3}; setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 || useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255, true, useAlphaChannelOfTexture); - setTexture(0, texture); + setActiveTexture(0, texture); setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], - D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex)); + D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); } @@ -1137,24 +1202,17 @@ void CD3D8Driver::draw2DRectangle(const core::rect& position, if (!pos.isValid()) return; - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - s32 xPlus = -(renderTargetSize.Width>>1); - f32 xFact = 1.0f / (renderTargetSize.Width>>1); - - s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1); - f32 yFact = 1.0f / (renderTargetSize.Height>>1); - S3DVertex vtx[4]; - vtx[0] = S3DVertex((f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.UpperLeftCorner.Y) * yFact , 0.0f, + vtx[0] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorLeftUp, 0.0f, 0.0f); - vtx[1] = S3DVertex((f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus- pos.UpperLeftCorner.Y) * yFact, 0.0f, + vtx[1] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorRightUp, 0.0f, 1.0f); - vtx[2] = S3DVertex((f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.0f, + vtx[2] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorRightDown, 1.0f, 0.0f); - vtx[3] = S3DVertex((f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.0f, + vtx[3] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorLeftDown, 1.0f, 1.0f); - s16 indices[6] = {0,1,2,0,2,3}; + const s16 indices[6] = {0,1,2,0,2,3}; setRenderStates2DMode( colorLeftUp.getAlpha() < 255 || @@ -1162,80 +1220,57 @@ void CD3D8Driver::draw2DRectangle(const core::rect& position, colorLeftDown.getAlpha() < 255 || colorRightDown.getAlpha() < 255, false, false); - setTexture(0,0); + setActiveTexture(0,0); setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); - } - //! Draws a 2d line. void CD3D8Driver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { // thanks to Vash TheStampede who sent in his implementation - - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - const s32 xPlus = -(renderTargetSize.Width>>1); - const f32 xFact = 1.0f / (renderTargetSize.Width>>1); - - const s32 yPlus = - renderTargetSize.Height-(renderTargetSize.Height>>1); - const f32 yFact = 1.0f / (renderTargetSize.Height>>1); - S3DVertex vtx[2]; - vtx[0] = S3DVertex((f32)(start.X + xPlus) * xFact, - (f32)(yPlus - start.Y) * yFact, - 0.0f, // z + vtx[0] = S3DVertex((f32)start.X, (f32)start.Y, 0.0f, 0.0f, 0.0f, 0.0f, // normal - color, - 0.0f, 0.0f); // texture + color, 0.0f, 0.0f); // texture - vtx[1] = S3DVertex((f32)(end.X+xPlus) * xFact, - (f32)(yPlus- end.Y) * yFact, - 0.0f, + vtx[1] = S3DVertex((f32)end.X, (f32)end.Y, 0.0f, 0.0f, 0.0f, 0.0f, - color, - 0.0f, 0.0f); + color, 0.0f, 0.0f); setRenderStates2DMode(color.getAlpha() < 255, false, false); - setTexture(0,0); + setActiveTexture(0,0); setVertexShader(EVT_STANDARD); pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, &vtx[0], sizeof(S3DVertex)); } + //! Draws a pixel void CD3D8Driver::drawPixel(u32 x, u32 y, const SColor & color) { - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - if(x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) return; setRenderStates2DMode(color.getAlpha() < 255, false, false); - setTexture(0,0); + setActiveTexture(0,0); setVertexShader(EVT_STANDARD); - const s32 xPlus = -renderTargetSize.Width / 2; - const f32 xFact = 2.0f / renderTargetSize.Width; - const s32 yPlus = renderTargetSize.Height / 2; - const f32 yFact = 2.0f / renderTargetSize.Height; - S3DVertex vertex((f32)((s32)x + xPlus) * xFact, - (f32)(yPlus - (s32)y) * yFact, - 0.f, 0.f, 0.f, 0.f, color, 0.f, 0.f); + S3DVertex vertex((f32)x, (f32)y, 0.f, 0.f, 0.f, 0.f, color, 0.f, 0.f); pID3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &vertex, sizeof(vertex)); } - //! sets right vertex shader void CD3D8Driver::setVertexShader(E_VERTEX_TYPE newType) { @@ -1321,6 +1356,39 @@ bool CD3D8Driver::setRenderStates3DMode() } +//! Map Irrlicht texture wrap mode to native values +D3DTEXTUREADDRESS CD3D8Driver::getTextureWrapMode(const u8 clamp) +{ + switch (clamp) + { + case ETC_REPEAT: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP) + return D3DTADDRESS_WRAP; + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP) + return D3DTADDRESS_CLAMP; + case ETC_MIRROR: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR) + return D3DTADDRESS_MIRROR; + case ETC_CLAMP_TO_BORDER: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER) + return D3DTADDRESS_BORDER; + else + return D3DTADDRESS_CLAMP; + case ETC_MIRROR_CLAMP: + case ETC_MIRROR_CLAMP_TO_EDGE: + case ETC_MIRROR_CLAMP_TO_BORDER: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE) + return D3DTADDRESS_MIRRORONCE; + else + return D3DTADDRESS_CLAMP; + default: + return D3DTADDRESS_WRAP; + } +} + + //! Can be called by an IMaterialRenderer to make its work easier. void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates) @@ -1341,6 +1409,21 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria pID3DDevice->SetMaterial(&mat); } + if (lastmaterial.ColorMaterial != material.ColorMaterial) + { + pID3DDevice->SetRenderState(D3DRS_COLORVERTEX, (material.ColorMaterial != ECM_NONE)); + pID3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, + ((material.ColorMaterial == ECM_DIFFUSE)|| + (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL); + pID3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, + ((material.ColorMaterial == ECM_AMBIENT)|| + (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL); + pID3DDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, + (material.ColorMaterial == ECM_EMISSIVE)?D3DMCS_COLOR1:D3DMCS_MATERIAL); + pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, + (material.ColorMaterial == ECM_SPECULAR)?D3DMCS_COLOR1:D3DMCS_MATERIAL); + } + // fillmode if (resetAllRenderstates || lastmaterial.Wireframe != material.Wireframe || lastmaterial.PointCloud != material.PointCloud) { @@ -1354,7 +1437,6 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria } // shademode - if (resetAllRenderstates || lastmaterial.GouraudShading != material.GouraudShading) { if (material.GouraudShading) @@ -1364,7 +1446,6 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria } // lighting - if (resetAllRenderstates || lastmaterial.Lighting != material.Lighting) { if (material.Lighting) @@ -1373,28 +1454,45 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); } - // zbuffer - if (resetAllRenderstates || lastmaterial.ZBuffer != material.ZBuffer) { switch (material.ZBuffer) { - case 0: - pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - break; - case 1: - pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - break; - case 2: - pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL); - break; + case ECFN_NEVER: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + break; + case ECFN_LESSEQUAL: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + break; + case ECFN_EQUAL: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL); + break; + case ECFN_LESS: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); + break; + case ECFN_NOTEQUAL: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_NOTEQUAL); + break; + case ECFN_GREATEREQUAL: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL); + break; + case ECFN_GREATER: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER); + break; + case ECFN_ALWAYS: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + break; } } - // zwrite // if (resetAllRenderstates || lastmaterial.ZWriteEnable != material.ZWriteEnable) { @@ -1405,8 +1503,6 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria } // back face culling - - if (resetAllRenderstates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling)) { // if (material.FrontfaceCulling && material.BackfaceCulling) @@ -1439,56 +1535,60 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria // normalization if (resetAllRenderstates || lastmaterial.NormalizeNormals != material.NormalizeNormals) { - pID3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, material.NormalizeNormals); + pID3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, material.NormalizeNormals); + } + + // Color Mask + if (queryFeature(EVDF_COLOR_MASK) && + (resetAllRenderstates || lastmaterial.ColorMask != material.ColorMask)) + { + const DWORD flag = + ((material.ColorMask & ECP_RED)?D3DCOLORWRITEENABLE_RED:0) | + ((material.ColorMask & ECP_GREEN)?D3DCOLORWRITEENABLE_GREEN:0) | + ((material.ColorMask & ECP_BLUE)?D3DCOLORWRITEENABLE_BLUE:0) | + ((material.ColorMask & ECP_ALPHA)?D3DCOLORWRITEENABLE_ALPHA:0); + pID3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, flag); } // thickness if (resetAllRenderstates || lastmaterial.Thickness != material.Thickness) { - pID3DDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&material.Thickness)); + pID3DDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&material.Thickness)); } // texture address mode for (u32 st=0; stSetTextureStageState(st, D3DTSS_ADDRESSU, mode ); - pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSV, mode ); + const float tmp = material.TextureLayer[st].LODBias * 0.125f; + pID3DDevice->SetTextureStageState(st, D3DTSS_MIPMAPLODBIAS, *(DWORD*)(&tmp)); } + if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapU != material.TextureLayer[st].TextureWrapU) + pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSU, getTextureWrapMode(material.TextureLayer[st].TextureWrapU)); + // If separate UV not supported reuse U for V + if (!(Caps.TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV)) + pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapU)); + else if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapV != material.TextureLayer[st].TextureWrapV) + pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapV)); + // Bilinear and/or trilinear if (resetAllRenderstates || lastmaterial.TextureLayer[st].BilinearFilter != material.TextureLayer[st].BilinearFilter || lastmaterial.TextureLayer[st].TrilinearFilter != material.TextureLayer[st].TrilinearFilter || lastmaterial.TextureLayer[st].AnisotropicFilter != material.TextureLayer[st].AnisotropicFilter ) { - if (material.TextureLayer[st].BilinearFilter || material.TextureLayer[st].TrilinearFilter || material.TextureLayer[st].AnisotropicFilter) + if (material.TextureLayer[st].BilinearFilter || material.TextureLayer[st].TrilinearFilter || material.TextureLayer[st].AnisotropicFilter>1) { - D3DTEXTUREFILTERTYPE tftMag = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) && + const D3DTEXTUREFILTERTYPE tftMag = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) && material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR; - D3DTEXTUREFILTERTYPE tftMin = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) && + const D3DTEXTUREFILTERTYPE tftMin = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) && material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR; - D3DTEXTUREFILTERTYPE tftMip = material.TextureLayer[st].TrilinearFilter ? D3DTEXF_LINEAR : D3DTEXF_POINT; + const D3DTEXTUREFILTERTYPE tftMip = material.TextureLayer[st].TrilinearFilter ? D3DTEXF_LINEAR : D3DTEXF_POINT; + if (tftMag==D3DTEXF_ANISOTROPIC || tftMin == D3DTEXF_ANISOTROPIC) + pID3DDevice->SetTextureStageState(st, D3DTSS_MAXANISOTROPY, core::min_((DWORD)material.TextureLayer[st].AnisotropicFilter, Caps.MaxAnisotropy)); pID3DDevice->SetTextureStageState(st, D3DTSS_MAGFILTER, tftMag); pID3DDevice->SetTextureStageState(st, D3DTSS_MINFILTER, tftMin); pID3DDevice->SetTextureStageState(st, D3DTSS_MIPFILTER, tftMip); @@ -1504,7 +1604,6 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria } - //! sets the needed renderstates void CD3D8Driver::setRenderStatesStencilShadowMode(bool zfail) { @@ -1519,10 +1618,10 @@ void CD3D8Driver::setRenderStatesStencilShadowMode(bool zfail) Transformation3DChanged = false; - setTexture(0,0); - setTexture(1,0); - setTexture(2,0); - setTexture(3,0); + setActiveTexture(0,0); + setActiveTexture(1,0); + setActiveTexture(2,0); + setActiveTexture(3,0); pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); @@ -1536,7 +1635,7 @@ void CD3D8Driver::setRenderStatesStencilShadowMode(bool zfail) pID3DDevice->SetVertexShader(D3DFVF_XYZ); LastVertexType = (video::E_VERTEX_TYPE)(-1); - pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE ); + pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE ); pID3DDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE ); pID3DDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT); @@ -1588,7 +1687,6 @@ void CD3D8Driver::setRenderStatesStencilShadowMode(bool zfail) } - //! sets the needed renderstates void CD3D8Driver::setRenderStatesStencilFillMode(bool alpha) { @@ -1646,7 +1744,6 @@ void CD3D8Driver::setRenderStatesStencilFillMode(bool alpha) } - //! sets the needed renderstates void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) { @@ -1655,82 +1752,79 @@ void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan if (CurrentRenderMode != ERM_2D || Transformation3DChanged) { - pID3DDevice->SetTransform(D3DTS_VIEW, &UnitMatrixD3D8); + // unset last 3d material + if (CurrentRenderMode == ERM_3D) + { + if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) + MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); + } + if (!OverrideMaterial2DEnabled) + { + setBasicRenderStates(InitMaterial2D, LastMaterial, true); + LastMaterial=InitMaterial2D; + + // fix everything that is wrongly set by SMaterial default + pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); + pID3DDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); + pID3DDevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); + pID3DDevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE); + pID3DDevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); + + pID3DDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE ); + + } pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D8); - pID3DDevice->SetTransform(D3DTS_PROJECTION, &UnitMatrixD3D8); + core::matrix4 m; + m.setTranslation(core::vector3df(-0.5f,-0.5f,0)); + pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)m.pointer())); - pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - //pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); - pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); - pID3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); - - pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); - pID3DDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); - pID3DDevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); - pID3DDevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE); - pID3DDevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); - - pID3DDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE ); - - pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); - - pID3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP ); - pID3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP ); - pID3DDevice->SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP ); - pID3DDevice->SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP ); - pID3DDevice->SetTextureStageState(2, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP ); - pID3DDevice->SetTextureStageState(2, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP ); - pID3DDevice->SetTextureStageState(3, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP ); - pID3DDevice->SetTextureStageState(3, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP ); - - pID3DDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); - pID3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); - pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D8 ); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0); + m.setTranslation(core::vector3df(-1,1,0)); + pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)m.pointer())); Transformation3DChanged = false; - - // unset last 3d material - if (CurrentRenderMode == ERM_3D && - Material.MaterialType >= 0 && LastMaterial.MaterialType < (s32)MaterialRenderers.size()) - MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); + } + if (OverrideMaterial2DEnabled) + { + OverrideMaterial2D.Lighting=false; + OverrideMaterial2D.ZBuffer=ECFN_NEVER; + OverrideMaterial2D.ZWriteEnable=false; + setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); + LastMaterial = OverrideMaterial2D; } if (texture) { - pID3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_POINT); - pID3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE); - pID3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT); - + setTransform(ETS_TEXTURE_0, core::IdentityMatrix); if (alphaChannel) { pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); if (alpha) { pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); - pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); } else { pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); } pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } else { + pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); if (alpha) { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); - pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); @@ -1739,7 +1833,6 @@ void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan { pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } @@ -1747,11 +1840,11 @@ void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan } else { + pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); if (alpha) { - pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); @@ -1760,9 +1853,6 @@ void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan } else { - pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } @@ -1784,13 +1874,9 @@ void CD3D8Driver::deleteAllDynamicLights() } - //! adds a dynamic light -void CD3D8Driver::addDynamicLight(const SLight& dl) +s32 CD3D8Driver::addDynamicLight(const SLight& dl) { - if ((u32)LastSetLight == Caps.MaxActiveLights-1) - return; - CNullDriver::addDynamicLight(dl); D3DLIGHT8 light; @@ -1826,11 +1912,26 @@ void CD3D8Driver::addDynamicLight(const SLight& dl) light.Phi = dl.OuterCone * 2.0f * core::DEGTORAD; ++LastSetLight; - pID3DDevice->SetLight(LastSetLight, &light); - pID3DDevice->LightEnable(LastSetLight, true); + + if(D3D_OK == pID3DDevice->SetLight(LastSetLight, &light)) + { + // I don't care if this succeeds + (void)pID3DDevice->LightEnable(LastSetLight, true); + return LastSetLight; + } + + return -1; } +void CD3D8Driver::turnLightOn(s32 lightIndex, bool turnOn) +{ + if(lightIndex < 0 || lightIndex > LastSetLight) + return; + + (void)pID3DDevice->LightEnable(lightIndex, turnOn); +} + //! returns the maximal amount of dynamic lights the device can handle u32 CD3D8Driver::getMaximalDynamicLightAmount() const @@ -1839,7 +1940,6 @@ u32 CD3D8Driver::getMaximalDynamicLightAmount() const } - //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. @@ -1854,7 +1954,6 @@ void CD3D8Driver::setAmbientLight(const SColorf& color) } - //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8.1". const wchar_t* CD3D8Driver::getName() const @@ -1863,7 +1962,6 @@ const wchar_t* CD3D8Driver::getName() const } - //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: Frist, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. @@ -1884,7 +1982,7 @@ void CD3D8Driver::drawStencilShadowVolume(const core::vector3df* triangles, s32 pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles, sizeof(core::vector3df)); // Now reverse cull order so front sides of shadow volume are written. - pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW ); + pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW ); pID3DDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_DECRSAT); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles, sizeof(core::vector3df)); } @@ -1898,14 +1996,13 @@ void CD3D8Driver::drawStencilShadowVolume(const core::vector3df* triangles, s32 pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles, sizeof(core::vector3df)); // Now reverse cull order so front sides of shadow volume are written. - pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); - pID3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECRSAT ); + pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); + pID3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECRSAT ); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles, sizeof(core::vector3df)); } } - //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. @@ -1921,7 +2018,7 @@ void CD3D8Driver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftU vtx[2] = S3DVertex(-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, leftDownEdge, 1.0f, 0.0f); vtx[3] = S3DVertex(-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, rightDownEdge, 1.0f, 1.0f); - s16 indices[6] = {0,1,2,1,3,2}; + const s16 indices[6] = {0,1,2,1,3,2}; setRenderStatesStencilFillMode( leftUpEdge.getAlpha() < 255 || @@ -1929,7 +2026,7 @@ void CD3D8Driver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftU leftDownEdge.getAlpha() < 255 || rightDownEdge.getAlpha() < 255); - setTexture(0,0); + setActiveTexture(0,0); setVertexShader(EVT_STANDARD); @@ -1937,11 +2034,10 @@ void CD3D8Driver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftU D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); if (clearStencilBuffer) - pID3DDevice->Clear( 0, NULL, D3DCLEAR_STENCIL,0, 1.0, 0); + pID3DDevice->Clear(0, NULL, D3DCLEAR_STENCIL,0, 1.0, 0); } - //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. @@ -1952,10 +2048,10 @@ u32 CD3D8Driver::getMaximalPrimitiveCount() const //! Sets the fog mode. -void CD3D8Driver::setFog(SColor color, bool linearFog, f32 start, +void CD3D8Driver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { - CNullDriver::setFog(color, linearFog, start, end, density, pixelFog, rangeFog); + CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog); if (!pID3DDevice) return; @@ -1963,21 +2059,26 @@ void CD3D8Driver::setFog(SColor color, bool linearFog, f32 start, pID3DDevice->SetRenderState(D3DRS_FOGCOLOR, color.color); pID3DDevice->SetRenderState( - pixelFog ? D3DRS_FOGTABLEMODE : D3DRS_FOGVERTEXMODE, - linearFog ? D3DFOG_LINEAR : D3DFOG_EXP); +#if defined( _IRR_XBOX_PLATFORM_) + D3DRS_FOGTABLEMODE, +#else + pixelFog ? D3DRS_FOGTABLEMODE : D3DRS_FOGVERTEXMODE, +#endif + (fogType==EFT_FOG_LINEAR)? D3DFOG_LINEAR : (fogType==EFT_FOG_EXP)?D3DFOG_EXP:D3DFOG_EXP2); - if(linearFog) + if (fogType==EFT_FOG_LINEAR) { pID3DDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD*)(&start)); - pID3DDevice->SetRenderState(D3DRS_FOGEND, *(DWORD*)(&end)); + pID3DDevice->SetRenderState(D3DRS_FOGEND, *(DWORD*)(&end)); } else pID3DDevice->SetRenderState(D3DRS_FOGDENSITY, *(DWORD*)(&density)); if(!pixelFog) - pID3DDevice->SetRenderState (D3DRS_RANGEFOGENABLE, rangeFog); + pID3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, rangeFog); } + //! Draws a 3d line. void CD3D8Driver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) @@ -1994,7 +2095,7 @@ void CD3D8Driver::draw3DLine(const core::vector3df& start, } -void CD3D8Driver::OnResize(const core::dimension2d& size) +void CD3D8Driver::OnResize(const core::dimension2d& size) { if (!pID3DDevice) return; @@ -2003,18 +2104,21 @@ void CD3D8Driver::OnResize(const core::dimension2d& size) reset(); } + //! Returns type of video driver E_DRIVER_TYPE CD3D8Driver::getDriverType() const { return EDT_DIRECT3D8; } + //! Returns the transformation set by setTransform const core::matrix4& CD3D8Driver::getTransform(E_TRANSFORMATION_STATE state) const { return Matrices[state]; } + //! Sets a vertex shader constant. void CD3D8Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { @@ -2022,6 +2126,7 @@ void CD3D8Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s3 pID3DDevice->SetVertexShaderConstant(startRegister, data, constantAmount); } + //! Sets a pixel shader constant. void CD3D8Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { @@ -2029,6 +2134,7 @@ void CD3D8Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 pID3DDevice->SetPixelShaderConstant(startRegister, data, constantAmount); } + //! Sets a constant for the vertex shader based on a name. bool CD3D8Driver::setVertexShaderConstant(const c8* name, const f32* floats, int count) { @@ -2036,6 +2142,7 @@ bool CD3D8Driver::setVertexShaderConstant(const c8* name, const f32* floats, int return false; } + //! Sets a constant for the pixel shader based on a name. bool CD3D8Driver::setPixelShaderConstant(const c8* name, const f32* floats, int count) { @@ -2043,12 +2150,6 @@ bool CD3D8Driver::setPixelShaderConstant(const c8* name, const f32* floats, int return false; } -//! Returns pointer to the IGPUProgrammingServices interface. -IGPUProgrammingServices* CD3D8Driver::getGPUProgrammingServices() -{ - return this; -} - //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. @@ -2075,19 +2176,22 @@ IVideoDriver* CD3D8Driver::getVideoDriver() } - //! Clears the ZBuffer. void CD3D8Driver::clearZBuffer() { - HRESULT hr = pID3DDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0, 0); + const HRESULT hr = pID3DDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0, 0); if (FAILED(hr)) os::Printer::log("CD3D8Driver clearZBuffer() failed.", ELL_WARNING); } + //! Returns an image created from the last rendered frame. IImage* CD3D8Driver::createScreenShot() { +#if defined( _IRR_XBOX_PLATFORM_) + return 0; +#else HRESULT hr; // query the screen dimensions of the current adapter @@ -2118,6 +2222,12 @@ IImage* CD3D8Driver::createScreenShot() clientRect.top = clientPoint.y; clientRect.right = clientRect.left + ScreenSize.Width; clientRect.bottom = clientRect.top + ScreenSize.Height; + + // window can be off-screen partly, we can't take screenshots from that + clientRect.left = core::max_(clientRect.left, 0l); + clientRect.top = core::max_(clientRect.top, 0l); + clientRect.right = core::min_(clientRect.right, (long)displayMode.Width); + clientRect.bottom = core::min_(clientRect.bottom, (long)displayMode.Height ); } // lock our area of the surface @@ -2128,38 +2238,42 @@ IImage* CD3D8Driver::createScreenShot() return 0; } + irr::core::dimension2d shotSize; + shotSize.Width = core::min_( ScreenSize.Width, (u32)(clientRect.right-clientRect.left) ); + shotSize.Height = core::min_( ScreenSize.Height, (u32)(clientRect.bottom-clientRect.top) ); + // this could throw, but we aren't going to worry about that case very much - IImage* newImage = new CImage(ECF_A8R8G8B8, ScreenSize); + IImage* newImage = new CImage(ECF_A8R8G8B8, shotSize); // d3d pads the image, so we need to copy the correct number of bytes u32* dP = (u32*)newImage->lock(); u8 * sP = (u8 *)lockedRect.pBits; // If the display mode format doesn't promise anything about the Alpha value - // and it appears that it's not presenting 255, then we should manually + // and it appears that it's not presenting 255, then we should manually // set each pixel alpha value to 255. if(D3DFMT_X8R8G8B8 == displayMode.Format && (0xFF000000 != (*dP & 0xFF000000))) { - for (s32 y = 0; y < ScreenSize.Height; ++y) + for (u32 y = 0; y < shotSize.Height; ++y) { - for(s32 x = 0; x < ScreenSize.Width; ++x) + for(u32 x = 0; x < shotSize.Width; ++x) { *dP = *((u32*)sP) | 0xFF000000; dP++; sP += 4; } - sP += lockedRect.Pitch - (4 * ScreenSize.Width); + sP += lockedRect.Pitch - (4 * shotSize.Width); } } else { - for (s32 y = 0; y < ScreenSize.Height; ++y) + for (u32 y = 0; y < shotSize.Height; ++y) { - memcpy(dP, sP, ScreenSize.Width * 4); + memcpy(dP, sP, shotSize.Width * 4); sP += lockedRect.Pitch; - dP += ScreenSize.Width; + dP += shotSize.Width; } } @@ -2173,12 +2287,12 @@ IImage* CD3D8Driver::createScreenShot() // return status of save operation to caller return newImage; +#endif } - // returns the current size of the screen or rendertarget -const core::dimension2d& CD3D8Driver::getCurrentRenderTargetSize() const +const core::dimension2d& CD3D8Driver::getCurrentRenderTargetSize() const { if ( CurrentRendertargetSize.Width == 0 ) return ScreenSize; @@ -2187,22 +2301,27 @@ const core::dimension2d& CD3D8Driver::getCurrentRenderTargetSize() const } - // Set/unset a clipping plane. bool CD3D8Driver::setClipPlane(u32 index, const core::plane3df& plane, bool enable) { +#if defined( _IRR_XBOX_PLATFORM_) + return false; +#else if (index >= MaxUserClipPlanes) return false; - pID3DDevice->SetClipPlane(index, (const float*)&plane); enableClipPlane(index, enable); return true; +#endif } // Enable/disable a clipping plane. void CD3D8Driver::enableClipPlane(u32 index, bool enable) { +#if defined( _IRR_XBOX_PLATFORM_) + return; +#else if (index >= MaxUserClipPlanes) return; DWORD renderstate; @@ -2212,6 +2331,13 @@ void CD3D8Driver::enableClipPlane(u32 index, bool enable) else renderstate &= ~(1 << index); pID3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, renderstate); +#endif +} + + +core::dimension2du CD3D8Driver::getMaxTextureSize() const +{ + return core::dimension2du(Caps.MaxTextureWidth, Caps.MaxTextureHeight); } @@ -2228,12 +2354,12 @@ namespace video #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ //! creates a video driver -IVideoDriver* createDirectX8Driver(const core::dimension2d& screenSize, HWND window, - u32 bits, bool fullscreen, bool stencilbuffer, - io::IFileSystem* io, bool pureSoftware, bool highPrecisionFPU, - bool vsync, bool antiAlias) +IVideoDriver* createDirectX8Driver(const core::dimension2d& screenSize, + HWND window, u32 bits, bool fullscreen, bool stencilbuffer, + io::IFileSystem* io, bool pureSoftware, bool highPrecisionFPU, + bool vsync, u8 antiAlias) { - CD3D8Driver* dx8 = new CD3D8Driver(screenSize, window, fullscreen, + CD3D8Driver* dx8 = new CD3D8Driver(screenSize, window, fullscreen, stencilbuffer, io, pureSoftware); if (!dx8->initDriver(screenSize, window, bits, fullscreen, @@ -2249,5 +2375,3 @@ IVideoDriver* createDirectX8Driver(const core::dimension2d& screenSize, HWN } // end namespace video } // end namespace irr - - diff --git a/src/dep/src/irrlicht/CD3D8Driver.h b/src/dep/src/irrlicht/CD3D8Driver.h index 21b1042..6d6bfd0 100644 --- a/src/dep/src/irrlicht/CD3D8Driver.h +++ b/src/dep/src/irrlicht/CD3D8Driver.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -14,15 +14,11 @@ #include #endif -#ifdef _IRR_XBOX_PLATFORM_ - #include -#endif - // always included for static createDriver function #include "CNullDriver.h" #include "IMaterialRendererServices.h" -#include "d3d8.h" +#include namespace irr { @@ -30,10 +26,12 @@ namespace video { class CD3D8Driver : public CNullDriver, IMaterialRendererServices { + friend class CD3D8Texture; + public: //! constructor - CD3D8Driver(const core::dimension2d& screenSize, HWND window, bool fullscreen, + CD3D8Driver(const core::dimension2d& screenSize, HWND window, bool fullscreen, bool stencibuffer, io::IFileSystem* io, bool pureSoftware=false, bool vsync=false); //! destructor @@ -42,7 +40,7 @@ namespace video //! applications must call this method before performing any rendering. returns false if failed. virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! applications must call this method after performing any rendering. returns false if failed. @@ -59,7 +57,7 @@ namespace video //! sets a render target virtual bool setRenderTarget(video::ITexture* texture, - bool clearBackBuffer=false, bool clearZBuffer=false, + bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)); //! sets a viewport @@ -69,9 +67,16 @@ namespace video virtual const core::rect& getViewPort() const; //! draws a vertex primitive list - void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, - const void* indexList, u32 primitiveCount, - E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); + virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType); + + //! draws a vertex primitive list in 2d + virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType); //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, @@ -101,9 +106,9 @@ namespace video const core::vector3df& end, SColor color = SColor(255,255,255,255)); //! initialises the Direct3D API - bool initDriver(const core::dimension2d& screenSize, HWND hwnd, + bool initDriver(const core::dimension2d& screenSize, HWND hwnd, u32 bits, bool fullScreen, bool pureSoftware, - bool highPrecisionFPU, bool vsync, bool antiAlias); + bool highPrecisionFPU, bool vsync, u8 antiAlias); //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8.1". @@ -112,8 +117,15 @@ namespace video //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); - //! adds a dynamic light - virtual void addDynamicLight(const SLight& light); + //! adds a dynamic light, returning an index to the light + //! \param light: the light data to use to create the light + //! \return An index to the light, or -1 if an error occurs + virtual s32 addDynamicLight(const SLight& light); + + //! Turns a dynamic light on or off + //! \param lightIndex: the index returned by addDynamicLight + //! \param turnOn: true to turn the light on, false to turn it off + virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; @@ -146,12 +158,12 @@ namespace video virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled); //! Sets the fog mode. - virtual void setFog(SColor color, bool linearFog, f32 start, + virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog); //! Only used by the internal engine. Used to notify the driver that //! the window was resized. - virtual void OnResize(const core::dimension2d& size); + virtual void OnResize(const core::dimension2d& size); //! Returns type of video driver virtual E_DRIVER_TYPE getDriverType() const; @@ -175,16 +187,13 @@ namespace video //! Sets a constant for the pixel shader based on a name. virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); - //! Returns pointer to the IGPUProgrammingServices interface. - virtual IGPUProgrammingServices* getGPUProgrammingServices(); - //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) virtual IVideoDriver* getVideoDriver(); //! Creates a render target texture. - virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Clears the ZBuffer. virtual void clearZBuffer(); @@ -205,6 +214,9 @@ namespace video //! \param enable: If true, enable the clipping plane else disable it. virtual void enableClipPlane(u32 index, bool enable); + //! Returns the maximum texture size supported. + virtual core::dimension2du getMaxTextureSize() const; + virtual bool checkDriverReset() {return DriverWasReset;} private: @@ -235,17 +247,17 @@ namespace video void setRenderStatesStencilShadowMode(bool zfail); //! sets the current Texture - bool setTexture(s32 stage, const video::ITexture* texture); + bool setActiveTexture(u32 stage, const video::ITexture* texture); //! resets the device bool reset(); //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); // returns the current size of the screen or rendertarget - virtual const core::dimension2d& getCurrentRenderTargetSize() const; + virtual const core::dimension2d& getCurrentRenderTargetSize() const; //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. @@ -255,6 +267,13 @@ namespace video void createMaterialRenderers(); + void draw2D3DVertexPrimitiveList(const void* vertices, + u32 vertexCount, const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType, bool is3D); + + D3DTEXTUREADDRESS getTextureWrapMode(const u8 clamp); + inline D3DCOLORVALUE colorToD3D(const SColor& col) { const f32 f = 1.0f / 255.0f; @@ -281,9 +300,9 @@ namespace video IDirect3DDevice8* pID3DDevice; IDirect3DSurface8* PrevRenderTarget; - core::dimension2d CurrentRendertargetSize; + core::dimension2d CurrentRendertargetSize; - void* WindowId; + HWND WindowId; core::rect* SceneSourceRect; D3DCAPS8 Caps; diff --git a/src/dep/src/irrlicht/CD3D8MaterialRenderer.h b/src/dep/src/irrlicht/CD3D8MaterialRenderer.h index fb1bfb4..9eb5200 100644 --- a/src/dep/src/irrlicht/CD3D8MaterialRenderer.h +++ b/src/dep/src/irrlicht/CD3D8MaterialRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,7 @@ #ifdef _IRR_WINDOWS_API_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ -#include "d3d8.h" +#include #include "IMaterialRenderer.h" @@ -83,7 +83,8 @@ public: E_BLEND_FACTOR srcFact,dstFact; E_MODULATE_FUNC modulate; - unpack_texureBlendFunc ( srcFact, dstFact, modulate, material.MaterialTypeParam ); + u32 alphaSource; + unpack_texureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam ); if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO) pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); @@ -98,10 +99,24 @@ public: pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - if ( getTexelAlpha ( srcFact ) + getTexelAlpha ( dstFact ) ) + if ( alphaSource && (textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) )) { - pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + if (alphaSource==EAS_VERTEX_COLOR) + { + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + } + else if (alphaSource==EAS_TEXTURE) + { + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + } + else + { + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + } } else { @@ -116,6 +131,12 @@ public: } + //! Returns if the material is transparent. + virtual bool isTransparent() const + { + return true; + } + private: u32 getD3DBlend ( E_BLEND_FACTOR factor ) const @@ -138,20 +159,6 @@ public: return r; } - u32 getTexelAlpha ( E_BLEND_FACTOR factor ) const - { - u32 r = 0; - switch ( factor ) - { - case EBF_SRC_ALPHA: r = 1; break; - case EBF_ONE_MINUS_SRC_ALPHA: r = 1; break; - case EBF_DST_ALPHA: r = 1; break; - case EBF_ONE_MINUS_DST_ALPHA: r = 1; break; - case EBF_SRC_ALPHA_SATURATE: r = 1; break; - } - return r; - } - u32 getD3DModulate ( E_MODULATE_FUNC func ) const { u32 r = D3DTOP_MODULATE; @@ -338,7 +345,8 @@ public: pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255.f)); + // 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF + pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127); pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); } @@ -393,10 +401,10 @@ public: if (material.MaterialType == EMT_LIGHTMAP_ADD) pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); else - if (material.MaterialType == EMT_LIGHTMAP_M4) + if (material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4) pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE4X); else - if (material.MaterialType == EMT_LIGHTMAP_M2) + if (material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2) pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE2X); else pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); diff --git a/src/dep/src/irrlicht/CD3D8NormalMapRenderer.cpp b/src/dep/src/irrlicht/CD3D8NormalMapRenderer.cpp index f924962..e8af3e0 100644 --- a/src/dep/src/irrlicht/CD3D8NormalMapRenderer.cpp +++ b/src/dep/src/irrlicht/CD3D8NormalMapRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CD3D8NormalMapRenderer.h b/src/dep/src/irrlicht/CD3D8NormalMapRenderer.h index 4df4c62..48df6bb 100644 --- a/src/dep/src/irrlicht/CD3D8NormalMapRenderer.h +++ b/src/dep/src/irrlicht/CD3D8NormalMapRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,7 @@ #ifdef _IRR_WINDOWS_API_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ -#include "d3d8.h" +#include #include "CD3D8ShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" diff --git a/src/dep/src/irrlicht/CD3D8ParallaxMapRenderer.cpp b/src/dep/src/irrlicht/CD3D8ParallaxMapRenderer.cpp index d892232..774ed5f 100644 --- a/src/dep/src/irrlicht/CD3D8ParallaxMapRenderer.cpp +++ b/src/dep/src/irrlicht/CD3D8ParallaxMapRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CD3D8ParallaxMapRenderer.h b/src/dep/src/irrlicht/CD3D8ParallaxMapRenderer.h index 11a173f..b80cf4a 100644 --- a/src/dep/src/irrlicht/CD3D8ParallaxMapRenderer.h +++ b/src/dep/src/irrlicht/CD3D8ParallaxMapRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,7 @@ #ifdef _IRR_WINDOWS_API_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ -#include "d3d8.h" +#include #include "CD3D8ShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" @@ -33,9 +33,10 @@ public: //! material renderer should be set. virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData); - bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); + virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); - void OnSetMaterial(const video::SMaterial& material, + virtual void OnSetMaterial(const SMaterial& material) { } + virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); diff --git a/src/dep/src/irrlicht/CD3D8ShaderMaterialRenderer.cpp b/src/dep/src/irrlicht/CD3D8ShaderMaterialRenderer.cpp index e581708..3044aab 100644 --- a/src/dep/src/irrlicht/CD3D8ShaderMaterialRenderer.cpp +++ b/src/dep/src/irrlicht/CD3D8ShaderMaterialRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,7 +6,7 @@ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ -#include "d3d8.h" +#include #include #pragma comment (lib, "d3dx8.lib") @@ -123,14 +123,14 @@ void CD3D8ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material // set new vertex shader if (FAILED(pID3DDevice->SetVertexShader(VertexShader))) - os::Printer::log("Could not set vertex shader."); + os::Printer::log("Could not set vertex shader.", ELL_ERROR); } // set new pixel shader if (PixelShader) { if (FAILED(pID3DDevice->SetPixelShader(PixelShader))) - os::Printer::log("Could not set pixel shader."); + os::Printer::log("Could not set pixel shader.", ELL_ERROR); } if (BaseMaterial) @@ -172,6 +172,9 @@ bool CD3D8ShaderMaterialRenderer::createPixelShader(const c8* pxsh) if (!pxsh) return true; +#if defined( _IRR_XBOX_PLATFORM_) + return false; +#else // compile shader LPD3DXBUFFER code = 0; @@ -180,7 +183,7 @@ bool CD3D8ShaderMaterialRenderer::createPixelShader(const c8* pxsh) #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile shader without debug info - D3DXAssembleShader(pxsh, strlen(pxsh), 0, 0, &code, &errors); + D3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, &code, &errors); #else @@ -198,14 +201,12 @@ bool CD3D8ShaderMaterialRenderer::createPixelShader(const c8* pxsh) fclose(f); D3DXAssembleShaderFromFile(tmp, D3DXASM_DEBUG, 0, &code, &errors); - #endif - if (errors) { // print out compilation errors. - os::Printer::log("Pixel shader compilation failed:"); - os::Printer::log((c8*)errors->GetBufferPointer()); + os::Printer::log("Pixel shader compilation failed:", ELL_ERROR); + os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); if (code) code->Release(); @@ -216,13 +217,15 @@ bool CD3D8ShaderMaterialRenderer::createPixelShader(const c8* pxsh) if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader))) { - os::Printer::log("Could not create pixel shader."); + os::Printer::log("Could not create pixel shader.", ELL_ERROR); code->Release(); return false; } code->Release(); return true; +#endif + } @@ -233,6 +236,9 @@ bool CD3D8ShaderMaterialRenderer::createVertexShader(const char* vtxsh, E_VERTEX return true; // compile shader +#if defined( _IRR_XBOX_PLATFORM_) + return false; +#else LPD3DXBUFFER code = 0; LPD3DXBUFFER errors = 0; @@ -240,7 +246,7 @@ bool CD3D8ShaderMaterialRenderer::createVertexShader(const char* vtxsh, E_VERTEX #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile shader without debug info - D3DXAssembleShader(vtxsh, strlen(vtxsh), 0, 0, &code, &errors); + D3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, &code, &errors); #else @@ -264,8 +270,8 @@ bool CD3D8ShaderMaterialRenderer::createVertexShader(const char* vtxsh, E_VERTEX if (errors) { // print out compilation errors. - os::Printer::log("Vertex shader compilation failed:"); - os::Printer::log((c8*)errors->GetBufferPointer()); + os::Printer::log("Vertex shader compilation failed:", ELL_ERROR); + os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); if (code) code->Release(); @@ -307,13 +313,14 @@ bool CD3D8ShaderMaterialRenderer::createVertexShader(const char* vtxsh, E_VERTEX if (FAILED(pID3DDevice->CreateVertexShader(decl, (DWORD*)code->GetBufferPointer(), &VertexShader, 0))) { - os::Printer::log("Could not create vertex shader."); + os::Printer::log("Could not create vertex shader.", ELL_ERROR); code->Release(); return false; } code->Release(); return true; +#endif } diff --git a/src/dep/src/irrlicht/CD3D8ShaderMaterialRenderer.h b/src/dep/src/irrlicht/CD3D8ShaderMaterialRenderer.h index fe7e59c..349469d 100644 --- a/src/dep/src/irrlicht/CD3D8ShaderMaterialRenderer.h +++ b/src/dep/src/irrlicht/CD3D8ShaderMaterialRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,7 @@ #ifdef _IRR_WINDOWS_API_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ -#include "d3d8.h" +#include #include #include "IMaterialRenderer.h" diff --git a/src/dep/src/irrlicht/CD3D8Texture.cpp b/src/dep/src/irrlicht/CD3D8Texture.cpp index e87b61b..b08c717 100644 --- a/src/dep/src/irrlicht/CD3D8Texture.cpp +++ b/src/dep/src/irrlicht/CD3D8Texture.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -31,7 +31,7 @@ namespace video { //! rendertarget constructor -CD3D8Texture::CD3D8Texture(CD3D8Driver* driver, core::dimension2d size, const char* name) +CD3D8Texture::CD3D8Texture(CD3D8Driver* driver, const core::dimension2d& size, const io::path& name) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), TextureSize(size), ImageSize(size), Pitch(0), HasMipMaps(false), IsRenderTarget(true) @@ -50,7 +50,7 @@ CD3D8Texture::CD3D8Texture(CD3D8Driver* driver, core::dimension2d size, con //! constructor CD3D8Texture::CD3D8Texture(IImage* image, CD3D8Driver* driver, - u32 flags, const char* name) + u32 flags, const io::path& name, void* mipmapData) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), TextureSize(0,0), ImageSize(0,0), Pitch(0), HasMipMaps(false), IsRenderTarget(false) @@ -59,7 +59,7 @@ HasMipMaps(false), IsRenderTarget(false) setDebugName("CD3D8Texture"); #endif - const bool generateMipLevels = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); Device=driver->getExposedVideoData().D3D8.D3DDev8; if (Device) @@ -67,26 +67,11 @@ HasMipMaps(false), IsRenderTarget(false) if (image) { - if (createTexture(image, flags)) + if (createTexture(flags, image)) { - if (copyTexture(image) && generateMipLevels) + if (copyTexture(image)) { - // create mip maps. - - #ifndef _IRR_USE_D3DXFilterTexture_ - // The D3DXFilterTexture function seems to get linked wrong when - // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. - // So mipmapgeneration is replaced with my own bad generation in d3d 8 when - // compiling with both D3D 8 and 9. - HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT , D3DX_DEFAULT ); - if (FAILED(hr)) - os::Printer::log("Could not create direct3d mip map levels.", ELL_WARNING); - else - HasMipMaps = true; - #else - createMipMaps(); - HasMipMaps = true; - #endif + regenerateMipMapLevels(mipmapData); } } else @@ -110,22 +95,13 @@ CD3D8Texture::~CD3D8Texture() //! creates the hardware texture -bool CD3D8Texture::createTexture(video::IImage* image, u32 flags) +bool CD3D8Texture::createTexture(u32 flags, video::IImage* image) { - core::dimension2d optSize; ImageSize = image->getDimension(); - if (Driver->queryFeature(EVDF_TEXTURE_NPOT)) - optSize=ImageSize; - else - { - optSize.Width = getTextureSizeFromSurfaceSize(ImageSize.Width); - optSize.Height = getTextureSizeFromSurfaceSize(ImageSize.Height); - } + core::dimension2d optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); - HRESULT hr; D3DFORMAT format = D3DFMT_A1R5G5B5; - switch(getTextureFormatFromFlags(flags)) { case ETCF_ALWAYS_16_BIT: @@ -148,17 +124,24 @@ bool CD3D8Texture::createTexture(video::IImage* image, u32 flags) case ETCF_OPTIMIZED_FOR_SPEED: format = D3DFMT_A1R5G5B5; break; } + if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL)) { if (format == D3DFMT_A8R8G8B8) + +#ifdef _IRR_XBOX_PLATFORM_ + format = D3DFMT_X8R8G8B8; +#else format = D3DFMT_R8G8B8; +#endif + else if (format == D3DFMT_A1R5G5B5) format = D3DFMT_R5G6B5; } const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); - hr = Device->CreateTexture(optSize.Width, optSize.Height, + HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height, mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all) 0, format, D3DPOOL_MANAGED, &Texture); @@ -167,8 +150,13 @@ bool CD3D8Texture::createTexture(video::IImage* image, u32 flags) // try brute force 16 bit if (format == D3DFMT_A8R8G8B8) format = D3DFMT_A1R5G5B5; +#ifdef _IRR_XBOX_PLATFORM_ + else if (format == D3DFMT_X8R8G8B8) + format = D3DFMT_R5G6B5; +#else else if (format == D3DFMT_R8G8B8) format = D3DFMT_R5G6B5; +#endif else return false; @@ -217,23 +205,30 @@ bool CD3D8Texture::copyTexture(video::IImage* image) //! lock function -void* CD3D8Texture::lock(bool readOnly) +void* CD3D8Texture::lock(bool readOnly, u32 mipmapLevel) { if (!Texture) return 0; + MipLevelLocked=mipmapLevel; HRESULT hr; D3DLOCKED_RECT rect; if(!IsRenderTarget) { - hr = Texture->LockRect(0, &rect, 0, readOnly?D3DLOCK_READONLY:0); + hr = Texture->LockRect(mipmapLevel, &rect, 0, readOnly?D3DLOCK_READONLY:0); + if (FAILED(hr)) + { + os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); + return 0; + } } else { - D3DSURFACE_DESC desc; - Texture->GetLevelDesc(0, &desc); if (!RTTSurface) { + // Make RTT surface large enough for all miplevels (including 0) + D3DSURFACE_DESC desc; + Texture->GetLevelDesc(0, &desc); hr = Device->CreateImageSurface(desc.Width, desc.Height, desc.Format, &RTTSurface); if (FAILED(hr)) { @@ -243,33 +238,26 @@ void* CD3D8Texture::lock(bool readOnly) } IDirect3DSurface8 *surface = 0; - hr = Texture->GetSurfaceLevel(0, &surface); + hr = Texture->GetSurfaceLevel(mipmapLevel, &surface); if (FAILED(hr)) { - os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D8 Texture.", "Could not get surface.", ELL_ERROR); return 0; } hr = Device->CopyRects(surface, 0, 0, RTTSurface, 0); surface->Release(); if(FAILED(hr)) { - os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D8 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 DIRECT3D8 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D8 Texture.", "LockRect failed.", ELL_ERROR); return 0; } - return rect.pBits; } - if (FAILED(hr)) - { - os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); - return 0; - } - return rect.pBits; } @@ -281,38 +269,26 @@ void CD3D8Texture::unlock() return; if (!IsRenderTarget) - Texture->UnlockRect(0); + Texture->UnlockRect(MipLevelLocked); else if (RTTSurface) RTTSurface->UnlockRect(); } //! Returns original size of the texture. -const core::dimension2d& CD3D8Texture::getOriginalSize() const +const core::dimension2d& CD3D8Texture::getOriginalSize() const { return ImageSize; } //! Returns (=size) of the texture. -const core::dimension2d& CD3D8Texture::getSize() const +const core::dimension2d& CD3D8Texture::getSize() const { return TextureSize; } -//! returns the size of a texture which would be the optimize size for rendering it -inline s32 CD3D8Texture::getTextureSizeFromSurfaceSize(s32 size) const -{ - s32 ts = 0x01; - - while(ts < size) - ts <<= 1; - - return ts; -} - - //! returns driver type of texture (=the driver, who created the texture) E_DRIVER_TYPE CD3D8Texture::getDriverType() const { @@ -320,7 +296,6 @@ E_DRIVER_TYPE CD3D8Texture::getDriverType() const } - //! returns color format of texture ECOLOR_FORMAT CD3D8Texture::getColorFormat() const { @@ -328,7 +303,6 @@ ECOLOR_FORMAT CD3D8Texture::getColorFormat() const } - //! returns pitch of texture (in bytes) u32 CD3D8Texture::getPitch() const { @@ -336,7 +310,6 @@ u32 CD3D8Texture::getPitch() const } - //! returns the DIRECT3D8 Texture IDirect3DTexture8* CD3D8Texture::getDX8Texture() const { @@ -549,11 +522,9 @@ void CD3D8Texture::copy32BitMipMap(char* src, char* tgt, } - void CD3D8Texture::createRenderTarget() { - TextureSize.Width = getTextureSizeFromSurfaceSize(TextureSize.Width); - TextureSize.Height = getTextureSizeFromSurfaceSize(TextureSize.Height); + TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); // get backbuffer format to create the render target in the // same format @@ -599,13 +570,61 @@ void CD3D8Texture::createRenderTarget() } - //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void CD3D8Texture::regenerateMipMapLevels() +void CD3D8Texture::regenerateMipMapLevels(void* mipmapData) { - if (HasMipMaps) + if (mipmapData) + { + core::dimension2du size = TextureSize; + u32 level=0; + do + { + if (size.Width>1) + size.Width /=2; + if (size.Height>1) + size.Height /=2; + ++level; + IDirect3DSurface8* mipSurface = 0; + HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); + if (FAILED(hr) || !mipSurface) + { + os::Printer::log("Could not get mipmap level", ELL_WARNING); + return; + } + D3DSURFACE_DESC mipDesc; + mipSurface->GetDesc(&mipDesc); + D3DLOCKED_RECT miplr; + + // lock mipmap surface + if (FAILED(mipSurface->LockRect(&miplr, NULL, 0))) + { + mipSurface->Release(); + os::Printer::log("Could not lock texture", ELL_WARNING); + return; + } + + memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); + mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; + // unlock + mipSurface->UnlockRect(); + // release + mipSurface->Release(); + } while (size.Width != 1 || size.Height != 1); + } + else if (HasMipMaps) + { + // create mip maps. +#ifndef _IRR_USE_D3DXFilterTexture_ + // The D3DXFilterTexture function seems to get linked wrong when + // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. + // So mipmapgeneration is replaced with my own bad generation in d3d 8 when + // compiling with both D3D 8 and 9. + HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT , D3DX_DEFAULT ); + if (FAILED(hr)) +#endif createMipMaps(); + } } @@ -615,6 +634,7 @@ bool CD3D8Texture::isRenderTarget() const return IsRenderTarget; } + //! Returns pointer to the render target surface IDirect3DSurface8* CD3D8Texture::getRenderTargetSurface() { diff --git a/src/dep/src/irrlicht/CD3D8Texture.h b/src/dep/src/irrlicht/CD3D8Texture.h index 3947377..eccda5e 100644 --- a/src/dep/src/irrlicht/CD3D8Texture.h +++ b/src/dep/src/irrlicht/CD3D8Texture.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -10,7 +10,8 @@ #include "ITexture.h" #include "IImage.h" -#include "d3d8.h" + +#include namespace irr { @@ -28,25 +29,25 @@ public: //! constructor CD3D8Texture(IImage* image, CD3D8Driver* driver, - u32 flags, const char* name); + u32 flags, const io::path& name, void* mipmapData=0); //! rendertarget constructor - CD3D8Texture(CD3D8Driver* driver, core::dimension2d size, const char* name); + CD3D8Texture(CD3D8Driver* driver, const core::dimension2d& size, const io::path& name); //! destructor virtual ~CD3D8Texture(); //! lock function - virtual void* lock(bool readOnly = false); + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0); //! unlock function virtual void unlock(); //! Returns original size of the texture. - virtual const core::dimension2d& getOriginalSize() const; + virtual const core::dimension2d& getOriginalSize() const; //! Returns (=size) of the texture. - virtual const core::dimension2d& getSize() const; + virtual const core::dimension2d& getSize() const; //! returns driver type of texture (=the driver, who created the texture) virtual E_DRIVER_TYPE getDriverType() const; @@ -65,7 +66,7 @@ public: //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture - virtual void regenerateMipMapLevels(); + virtual void regenerateMipMapLevels(void* mipmapData=0); //! returns if it is a render target virtual bool isRenderTarget() const; @@ -78,11 +79,8 @@ private: void createRenderTarget(); - //! returns the size of a texture which would be the optimize size for rendering it - inline s32 getTextureSizeFromSurfaceSize(s32 size) const; - //! creates the hardware texture - bool createTexture(IImage* Image, u32 flags); + bool createTexture(u32 flags, IImage* Image); //! copies the image to the texture bool copyTexture(IImage* Image); @@ -102,10 +100,12 @@ private: IDirect3DTexture8* Texture; IDirect3DSurface8* RTTSurface; CD3D8Driver* Driver; - core::dimension2d TextureSize; - core::dimension2d ImageSize; + core::dimension2d TextureSize; + core::dimension2d ImageSize; s32 Pitch; + u32 MipLevelLocked; ECOLOR_FORMAT ColorFormat; + bool HasMipMaps; bool IsRenderTarget; }; diff --git a/src/dep/src/irrlicht/CD3D9Driver.cpp b/src/dep/src/irrlicht/CD3D9Driver.cpp index 0d29705..11306dc 100644 --- a/src/dep/src/irrlicht/CD3D9Driver.cpp +++ b/src/dep/src/irrlicht/CD3D9Driver.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -16,7 +16,6 @@ #include "CD3D9NormalMapRenderer.h" #include "CD3D9ParallaxMapRenderer.h" #include "CD3D9HLSLMaterialRenderer.h" -#include namespace irr { @@ -24,16 +23,19 @@ namespace video { //! constructor -CD3D9Driver::CD3D9Driver(const core::dimension2d& screenSize, HWND window, +CD3D9Driver::CD3D9Driver(const core::dimension2d& screenSize, HWND window, bool fullscreen, bool stencilbuffer, io::IFileSystem* io, bool pureSoftware) : CNullDriver(io, screenSize), CurrentRenderMode(ERM_NONE), - ResetRenderStates(true), Transformation3DChanged(false), StencilBuffer(stencilbuffer), + ResetRenderStates(true), Transformation3DChanged(false), + StencilBuffer(stencilbuffer), AntiAliasing(0), D3DLibrary(0), pID3D(0), pID3DDevice(0), PrevRenderTarget(0), WindowId(0), SceneSourceRect(0), - LastVertexType((video::E_VERTEX_TYPE)-1), MaxTextureUnits(0), MaxUserClipPlanes(0), - MaxLightDistance(sqrtf(FLT_MAX)), LastSetLight(-1), ColorFormat(ECF_A8R8G8B8), DeviceLost(false), - Fullscreen(fullscreen), DriverWasReset(true) + LastVertexType((video::E_VERTEX_TYPE)-1), VendorID(0), + MaxTextureUnits(0), MaxUserClipPlanes(0), + MaxLightDistance(0.f), LastSetLight(-1), Cached2DModeSignature(0), + ColorFormat(ECF_A8R8G8B8), DeviceLost(false), + Fullscreen(fullscreen), DriverWasReset(true), AlphaToCoverageSupport(false) { #ifdef _DEBUG setDebugName("CD3D9Driver"); @@ -46,7 +48,7 @@ CD3D9Driver::CD3D9Driver(const core::dimension2d& screenSize, HWND window, CurrentTexture[i] = 0; LastTextureMipMapsAvailable[i] = false; } - + MaxLightDistance = sqrtf(FLT_MAX); // create sphere map matrix SphereMapMatrixD3D9._11 = 0.5f; SphereMapMatrixD3D9._12 = 0.0f; @@ -69,9 +71,11 @@ CD3D9Driver::CD3D9Driver(const core::dimension2d& screenSize, HWND window, CD3D9Driver::~CD3D9Driver() { deleteMaterialRenders(); + deleteAllTextures(); // drop the main depth buffer - DepthBuffers[0]->drop(); + if (DepthBuffers.size()) + DepthBuffers[0]->drop(); // drop d3d9 @@ -130,7 +134,6 @@ void CD3D9Driver::createMaterialRenderers() MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); renderer->drop(); - // add parallax map renderers renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp, @@ -145,17 +148,15 @@ void CD3D9Driver::createMaterialRenderers() MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); renderer->drop(); - // add basic 1 texture blending addAndDropMaterialRenderer(new CD3D9MaterialRenderer_ONETEXTURE_BLEND(pID3DDevice, this)); - } //! initialises the Direct3D API -bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, +bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, HWND hwnd, u32 bits, bool fullScreen, bool pureSoftware, - bool highPrecisionFPU, bool vsync, bool antiAlias) + bool highPrecisionFPU, bool vsync, u8 antiAlias) { HRESULT hr; Fullscreen = fullScreen; @@ -163,7 +164,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, if (!pID3D) { - D3DLibrary = LoadLibrary( "d3d9.dll" ); + D3DLibrary = LoadLibrary( __TEXT("d3d9.dll") ); if (!D3DLibrary) { @@ -206,15 +207,16 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, os::Printer::log(tmp, ELL_INFORMATION); // Assign vendor name based on vendor id. + VendorID= static_cast(dai.VendorId); switch(dai.VendorId) { - case 0x1002 : vendorName = "ATI Technologies Inc."; break; - case 0x10DE : vendorName = "NVIDIA Corporation"; break; - case 0x102B : vendorName = "Matrox Electronic Systems Ltd."; break; - case 0x121A : vendorName = "3dfx Interactive Inc"; break; - case 0x5333 : vendorName = "S3 Graphics Co., Ltd."; break; - case 0x8086 : vendorName = "Intel Corporation"; break; - default: vendorName = "Unknown VendorId: ";vendorName += (u32)dai.VendorId; break; + case 0x1002 : VendorName = "ATI Technologies Inc."; break; + case 0x10DE : VendorName = "NVIDIA Corporation"; break; + case 0x102B : VendorName = "Matrox Electronic Systems Ltd."; break; + case 0x121A : VendorName = "3dfx Interactive Inc"; break; + case 0x5333 : VendorName = "S3 Graphics Co., Ltd."; break; + case 0x8086 : VendorName = "Intel Corporation"; break; + default: VendorName = "Unknown VendorId: ";VendorName += (u32)dai.VendorId; break; } } @@ -251,7 +253,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, else { present.BackBufferFormat = d3ddm.Format; - present.SwapEffect = D3DSWAPEFFECT_COPY; + present.SwapEffect = D3DSWAPEFFECT_DISCARD; present.Windowed = TRUE; } @@ -274,45 +276,33 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, #endif // enable anti alias if possible and desired - if (antiAlias) + if (antiAlias > 0) { + if(antiAlias > 16) + antiAlias = 16; + DWORD qualityLevels = 0; - if (SUCCEEDED(pID3D->CheckDeviceMultiSampleType(adapter, + while(antiAlias > 0) + { + if(SUCCEEDED(pID3D->CheckDeviceMultiSampleType(adapter, devtype, present.BackBufferFormat, !fullScreen, - D3DMULTISAMPLE_4_SAMPLES, &qualityLevels))) - { - // enable multi sampling - present.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES; - present.MultiSampleQuality = qualityLevels-1; - present.SwapEffect = D3DSWAPEFFECT_DISCARD; + (D3DMULTISAMPLE_TYPE)antiAlias, &qualityLevels))) + { + present.MultiSampleType = (D3DMULTISAMPLE_TYPE)antiAlias; + present.MultiSampleQuality = qualityLevels-1; + present.SwapEffect = D3DSWAPEFFECT_DISCARD; + break; + } + --antiAlias; } - else - if (SUCCEEDED(pID3D->CheckDeviceMultiSampleType(adapter, - devtype, present.BackBufferFormat, !fullScreen, - D3DMULTISAMPLE_2_SAMPLES, &qualityLevels))) - { - // enable multi sampling - present.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES; - present.MultiSampleQuality = qualityLevels-1; - present.SwapEffect = D3DSWAPEFFECT_DISCARD; - } - else - if (SUCCEEDED(pID3D->CheckDeviceMultiSampleType(adapter, - devtype, present.BackBufferFormat, !fullScreen, - D3DMULTISAMPLE_NONMASKABLE, &qualityLevels))) - { - // enable non maskable multi sampling - present.SwapEffect = D3DSWAPEFFECT_DISCARD; - present.MultiSampleType = D3DMULTISAMPLE_NONMASKABLE; - present.MultiSampleQuality = qualityLevels-1; - } - else + + if(antiAlias==0) { os::Printer::log("Anti aliasing disabled because hardware/driver lacks necessary caps.", ELL_WARNING); - antiAlias = false; } } + AntiAliasing = antiAlias; // check stencil buffer compatibility if (StencilBuffer) @@ -420,12 +410,8 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, // set default vertex shader setVertexShader(EVT_STANDARD); - // enable antialiasing - if (antiAlias) - pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - // set fog mode - setFog(FogColor, LinearFog, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); + setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); // set exposed data ExposedData.D3D9.D3D9 = pID3D; @@ -440,19 +426,33 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, MaxTextureUnits = core::min_((u32)Caps.MaxSimultaneousTextures, MATERIAL_MAX_TEXTURES); MaxUserClipPlanes = (u32)Caps.MaxUserClipPlanes; + if (VendorID==0x10DE)//NVidia + AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE, + (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK); + else if (VendorID==0x1002)//ATI + AlphaToCoverageSupport = true; // TODO: Check unknown +#if 0 + AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE, + (D3DFORMAT)MAKEFOURCC('A','2','M','1')) == S_OK); +#endif // set the renderstates setRenderStates3DMode(); - // set maximal anisotropy - pID3DDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, min(16ul, Caps.MaxAnisotropy)); - pID3DDevice->SetSamplerState(1, D3DSAMP_MAXANISOTROPY, min(16ul, Caps.MaxAnisotropy)); - pID3DDevice->SetSamplerState(2, D3DSAMP_MAXANISOTROPY, min(16ul, Caps.MaxAnisotropy)); - pID3DDevice->SetSamplerState(3, D3DSAMP_MAXANISOTROPY, min(16ul, Caps.MaxAnisotropy)); - // store the screen's depth buffer DepthBuffers.push_back(new SDepthSurface()); - pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface)); - DepthBuffers[0]->Size=ScreenSize; + if (SUCCEEDED(pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface)))) + { + D3DSURFACE_DESC desc; + DepthBuffers[0]->Surface->GetDesc(&desc); + DepthBuffers[0]->Size.set(desc.Width, desc.Height); + } + else + { + os::Printer::log("Was not able to get main depth buffer.", ELL_ERROR); + return false; + } D3DColorFormat = D3DFMT_A8R8G8B8; IDirect3DSurface9* bb=0; @@ -476,10 +476,10 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, //! applications must call this method before performing any rendering. returns false if failed. bool CD3D9Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, - void* windowId, core::rect* sourceRect) + const SExposedVideoData& videoData, core::rect* sourceRect) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); - WindowId = windowId; + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + WindowId = (HWND)videoData.D3D9.HWnd; SceneSourceRect = sourceRect; if (!pID3DDevice) @@ -514,9 +514,12 @@ bool CD3D9Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, if (StencilBuffer) flags |= D3DCLEAR_STENCIL; - hr = pID3DDevice->Clear( 0, NULL, flags, color.color, 1.0, 0); - if (FAILED(hr)) - os::Printer::log("DIRECT3D9 clear failed.", ELL_WARNING); + if (flags) + { + hr = pID3DDevice->Clear( 0, NULL, flags, color.color, 1.0, 0); + if (FAILED(hr)) + os::Printer::log("DIRECT3D9 clear failed.", ELL_WARNING); + } hr = pID3DDevice->BeginScene(); if (FAILED(hr)) @@ -553,7 +556,7 @@ bool CD3D9Driver::endScene() sourceRectData.bottom = SceneSourceRect->LowerRightCorner.Y; } - hr = pID3DDevice->Present(srcRct, NULL, (HWND)WindowId, NULL); + hr = pID3DDevice->Present(srcRct, NULL, WindowId, NULL); if (SUCCEEDED(hr)) return true; @@ -626,6 +629,14 @@ bool CD3D9Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const return (Caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) == 0; case EVDF_TEXTURE_NPOT: return (Caps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0; + case EVDF_COLOR_MASK: + return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0; + case EVDF_MULTIPLE_RENDER_TARGETS: + return Caps.NumSimultaneousRTs > 1; + case EVDF_MRT_COLOR_MASK: + return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_INDEPENDENTWRITEMASKS) != 0; + case EVDF_MRT_BLEND: + return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING) != 0; default: return false; }; @@ -649,15 +660,20 @@ void CD3D9Driver::setTransform(E_TRANSFORMATION_STATE state, case ETS_PROJECTION: pID3DDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)((void*)mat.pointer())); break; - case ETS_TEXTURE_0: - case ETS_TEXTURE_1: - case ETS_TEXTURE_2: - case ETS_TEXTURE_3: - pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); - pID3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+ ( state - ETS_TEXTURE_0 )), - (D3DMATRIX*)((void*)mat.pointer())); - break; case ETS_COUNT: + return; + default: + if (state-ETS_TEXTURE_0 < MATERIAL_MAX_TEXTURES) + { + if (mat.isIdentity()) + pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); + else + { + pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); + pID3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+ ( state - ETS_TEXTURE_0 )), + (D3DMATRIX*)((void*)mat.pointer())); + } + } break; } @@ -666,7 +682,7 @@ void CD3D9Driver::setTransform(E_TRANSFORMATION_STATE state, //! sets the current Texture -bool CD3D9Driver::setTexture(s32 stage, const video::ITexture* texture) +bool CD3D9Driver::setActiveTexture(u32 stage, const video::ITexture* texture) { if (CurrentTexture[stage] == texture) return true; @@ -696,10 +712,11 @@ bool CD3D9Driver::setTexture(s32 stage, const video::ITexture* texture) void CD3D9Driver::setMaterial(const SMaterial& material) { Material = material; + OverrideMaterial.apply(Material); for (u32 i=0; i(0,0); + CurrentRendertargetSize = core::dimension2d(0,0); PrevRenderTarget->Release(); PrevRenderTarget = 0; } @@ -817,6 +833,120 @@ bool CD3D9Driver::setRenderTarget(video::ITexture* texture, } +//! Sets multiple render targets +bool CD3D9Driver::setRenderTarget(const core::array& targets, + bool clearBackBuffer, bool clearZBuffer, SColor color) +{ + if (targets.size()==0) + return setRenderTarget(0, clearBackBuffer, clearZBuffer, color); + + u32 maxMultipleRTTs = core::min_(4u, targets.size()); + + for (u32 i = 0; i < maxMultipleRTTs; ++i) + { + if (targets[i].TargetType != ERT_RENDER_TEXTURE || !targets[i].RenderTexture) + { + maxMultipleRTTs = i; + os::Printer::log("Missing texture for MRT.", ELL_WARNING); + break; + } + + // check for right driver type + + if (targets[i].RenderTexture->getDriverType() != EDT_DIRECT3D9) + { + maxMultipleRTTs = i; + os::Printer::log("Tried to set a texture not owned by this driver.", ELL_WARNING); + break; + } + + // check for valid render target + + if (!targets[i].RenderTexture->isRenderTarget()) + { + maxMultipleRTTs = i; + os::Printer::log("Tried to set a non render target texture as render target.", ELL_WARNING); + break; + } + + // check for valid size + + if (targets[0].RenderTexture->getSize() != targets[i].RenderTexture->getSize()) + { + maxMultipleRTTs = i; + os::Printer::log("Render target texture has wrong size.", ELL_WARNING); + break; + } + } + if (maxMultipleRTTs==0) + { + os::Printer::log("Fatal Error: No valid MRT found.", ELL_ERROR); + return false; + } + + CD3D9Texture* tex = static_cast(targets[0].RenderTexture); + + // check if we should set the previous RT back + + bool ret = true; + + // we want to set a new target. so do this. + // store previous target + + if (!PrevRenderTarget) + { + if (FAILED(pID3DDevice->GetRenderTarget(0, &PrevRenderTarget))) + { + os::Printer::log("Could not get previous render target.", ELL_ERROR); + return false; + } + } + + // set new render target + + D3DRENDERSTATETYPE colorWrite[4]={D3DRS_COLORWRITEENABLE, D3DRS_COLORWRITEENABLE1, D3DRS_COLORWRITEENABLE2, D3DRS_COLORWRITEENABLE3}; + for (u32 i = 0; i < maxMultipleRTTs; ++i) + { + if (FAILED(pID3DDevice->SetRenderTarget(i, static_cast(targets[i].RenderTexture)->getRenderTargetSurface()))) + { + os::Printer::log("Error: Could not set render target.", ELL_ERROR); + return false; + } + if (i<4 && (i==0 || queryFeature(EVDF_MRT_COLOR_MASK))) + { + const DWORD flag = + ((targets[i].ColorMask & ECP_RED)?D3DCOLORWRITEENABLE_RED:0) | + ((targets[i].ColorMask & ECP_GREEN)?D3DCOLORWRITEENABLE_GREEN:0) | + ((targets[i].ColorMask & ECP_BLUE)?D3DCOLORWRITEENABLE_BLUE:0) | + ((targets[i].ColorMask & ECP_ALPHA)?D3DCOLORWRITEENABLE_ALPHA:0); + pID3DDevice->SetRenderState(colorWrite[i], flag); + } + } + + CurrentRendertargetSize = tex->getSize(); + + if (FAILED(pID3DDevice->SetDepthStencilSurface(tex->DepthSurface->Surface))) + { + os::Printer::log("Error: Could not set new depth buffer.", ELL_ERROR); + } + + if (clearBackBuffer || clearZBuffer) + { + DWORD flags = 0; + + if (clearBackBuffer) + flags |= D3DCLEAR_TARGET; + + if (clearZBuffer) + flags |= D3DCLEAR_ZBUFFER; + + pID3DDevice->Clear(0, NULL, flags, color.color, 1.0f, 0); + } + + return ret; +} + + //! sets a viewport void CD3D9Driver::setViewPort(const core::rect& area) { @@ -850,12 +980,12 @@ const core::rect& CD3D9Driver::getViewPort() const } -bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) +bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer) { - if (!HWBuffer) + if (!hwBuffer) return false; - const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; + const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer; const void* vertices=mb->getVertices(); const u32 vertexCount=mb->getVertexCount(); const E_VERTEX_TYPE vType=mb->getVertexType(); @@ -863,7 +993,7 @@ bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) void* pLockedBuffer = 0; - if (!HWBuffer->vertexBuffer || vertexSize * vertexCount > HWBuffer->vertexBufferSize) + if (!hwBuffer->vertexBuffer || vertexSize * vertexCount > hwBuffer->vertexBufferSize) { DWORD flags = 0; @@ -890,41 +1020,41 @@ bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) } flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY - if(HWBuffer->Mapped_Vertex != scene::EHM_STATIC) + if(hwBuffer->Mapped_Vertex != scene::EHM_STATIC) flags |= D3DUSAGE_DYNAMIC; - pID3DDevice->CreateVertexBuffer(vertexCount * vertexSize, flags, FVF, D3DPOOL_DEFAULT, &HWBuffer->vertexBuffer, NULL); + pID3DDevice->CreateVertexBuffer(vertexCount * vertexSize, flags, FVF, D3DPOOL_DEFAULT, &hwBuffer->vertexBuffer, NULL); - if(!HWBuffer->vertexBuffer) + if(!hwBuffer->vertexBuffer) return false; flags = 0; // SIO2: Reset flags before Lock - if(HWBuffer->Mapped_Vertex != scene::EHM_STATIC) + if(hwBuffer->Mapped_Vertex != scene::EHM_STATIC) flags = D3DLOCK_DISCARD; - HWBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, flags); + hwBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, flags); memcpy(pLockedBuffer, vertices, vertexCount * vertexSize); - HWBuffer->vertexBuffer->Unlock(); + hwBuffer->vertexBuffer->Unlock(); - HWBuffer->vertexBufferSize = vertexCount * vertexSize; + hwBuffer->vertexBufferSize = vertexCount * vertexSize; } else { - HWBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, D3DLOCK_DISCARD); + hwBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, D3DLOCK_DISCARD); memcpy(pLockedBuffer, vertices, vertexCount * vertexSize); - HWBuffer->vertexBuffer->Unlock(); + hwBuffer->vertexBuffer->Unlock(); } return true; } -bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) +bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer) { - if (!HWBuffer) + if (!hwBuffer) return false; - const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; + const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer; const u16* indices=mb->getIndices(); const u32 indexCount=mb->getIndexCount(); u32 indexSize = 2; @@ -945,38 +1075,38 @@ bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) } } - if (!HWBuffer->indexBuffer || indexSize * indexCount > HWBuffer->indexBufferSize) + if (!hwBuffer->indexBuffer || indexSize * indexCount > hwBuffer->indexBufferSize) { DWORD flags = 0; flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY - if(HWBuffer->Mapped_Index != scene::EHM_STATIC) + if(hwBuffer->Mapped_Index != scene::EHM_STATIC) flags |= D3DUSAGE_DYNAMIC; // SIO2: Add DYNAMIC flag for dynamic buffer data - if(FAILED(pID3DDevice->CreateIndexBuffer( indexCount * indexSize, flags, indexType, D3DPOOL_DEFAULT, &HWBuffer->indexBuffer, NULL))) + if(FAILED(pID3DDevice->CreateIndexBuffer( indexCount * indexSize, flags, indexType, D3DPOOL_DEFAULT, &hwBuffer->indexBuffer, NULL))) return false; void* pIndices = 0; flags = 0; // SIO2: Reset flags before Lock - if(HWBuffer->Mapped_Index != scene::EHM_STATIC) + if(hwBuffer->Mapped_Index != scene::EHM_STATIC) flags = D3DLOCK_DISCARD; - if(FAILED(HWBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, flags))) + if(FAILED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, flags))) return false; memcpy(pIndices, indices, indexCount * indexSize); - HWBuffer->indexBuffer->Unlock(); + hwBuffer->indexBuffer->Unlock(); - HWBuffer->indexBufferSize = indexCount * indexSize; + hwBuffer->indexBufferSize = indexCount * indexSize; } else { void* pIndices = 0; - if( SUCCEEDED(HWBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, D3DLOCK_DISCARD))) + if( SUCCEEDED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, D3DLOCK_DISCARD))) { memcpy(pIndices, indices, indexCount * indexSize); - HWBuffer->indexBuffer->Unlock(); + hwBuffer->indexBuffer->Unlock(); } } @@ -985,33 +1115,33 @@ bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) //! updates hardware buffer if needed -bool CD3D9Driver::updateHardwareBuffer(SHWBufferLink *HWBuffer) +bool CD3D9Driver::updateHardwareBuffer(SHWBufferLink *hwBuffer) { - if (!HWBuffer) + if (!hwBuffer) return false; - if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) + if (hwBuffer->Mapped_Vertex!=scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() - || !((SHWBufferLink_d3d9*)HWBuffer)->vertexBuffer) + if (hwBuffer->ChangedID_Vertex != hwBuffer->MeshBuffer->getChangedID_Vertex() + || !((SHWBufferLink_d3d9*)hwBuffer)->vertexBuffer) { - HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); + hwBuffer->ChangedID_Vertex = hwBuffer->MeshBuffer->getChangedID_Vertex(); - if (!updateVertexHardwareBuffer((SHWBufferLink_d3d9*)HWBuffer)) + if (!updateVertexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer)) return false; } } - if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) + if (hwBuffer->Mapped_Index!=scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() - || !((SHWBufferLink_d3d9*)HWBuffer)->indexBuffer) + if (hwBuffer->ChangedID_Index != hwBuffer->MeshBuffer->getChangedID_Index() + || !((SHWBufferLink_d3d9*)hwBuffer)->indexBuffer) { - HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); + hwBuffer->ChangedID_Index = hwBuffer->MeshBuffer->getChangedID_Index(); - if (!updateIndexHardwareBuffer((SHWBufferLink_d3d9*)HWBuffer)) + if (!updateIndexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer)) return false; } } @@ -1026,28 +1156,28 @@ CD3D9Driver::SHWBufferLink *CD3D9Driver::createHardwareBuffer(const scene::IMesh if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER)) return 0; - SHWBufferLink_d3d9 *HWBuffer=new SHWBufferLink_d3d9(mb); + SHWBufferLink_d3d9 *hwBuffer=new SHWBufferLink_d3d9(mb); //add to map - HWBufferMap.insert(HWBuffer->MeshBuffer, HWBuffer); + HWBufferMap.insert(hwBuffer->MeshBuffer, hwBuffer); - HWBuffer->ChangedID_Vertex=HWBuffer->MeshBuffer->getChangedID_Vertex(); - HWBuffer->ChangedID_Index=HWBuffer->MeshBuffer->getChangedID_Index(); - HWBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex(); - HWBuffer->Mapped_Index=mb->getHardwareMappingHint_Index(); - HWBuffer->LastUsed=0; - HWBuffer->vertexBuffer=0; - HWBuffer->indexBuffer=0; - HWBuffer->vertexBufferSize=0; - HWBuffer->indexBufferSize=0; + hwBuffer->ChangedID_Vertex=hwBuffer->MeshBuffer->getChangedID_Vertex(); + hwBuffer->ChangedID_Index=hwBuffer->MeshBuffer->getChangedID_Index(); + hwBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex(); + hwBuffer->Mapped_Index=mb->getHardwareMappingHint_Index(); + hwBuffer->LastUsed=0; + hwBuffer->vertexBuffer=0; + hwBuffer->indexBuffer=0; + hwBuffer->vertexBufferSize=0; + hwBuffer->indexBufferSize=0; - if (!updateHardwareBuffer(HWBuffer)) + if (!updateHardwareBuffer(hwBuffer)) { - deleteHardwareBuffer(HWBuffer); + deleteHardwareBuffer(hwBuffer); return 0; } - return HWBuffer; + return hwBuffer; } @@ -1113,15 +1243,40 @@ void CD3D9Driver::drawVertexPrimitiveList(const void* vertices, if (!vertexCount || !primitiveCount) return; + draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, + vType, pType, iType, true); +} + + +//! draws a vertex primitive list +void CD3D9Driver::draw2DVertexPrimitiveList(const void* vertices, + u32 vertexCount, const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType) +{ + if (!checkPrimitiveCount(primitiveCount)) + return; + + CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType); + + if (!vertexCount || !primitiveCount) + return; + + draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, + vType, pType, iType, false); +} + + +void CD3D9Driver::draw2D3DVertexPrimitiveList(const void* vertices, + u32 vertexCount, const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType, bool is3D) +{ setVertexShader(vType); const u32 stride = getVertexPitchFromType(vType); - D3DFORMAT indexType=D3DFMT_UNKNOWN; - - - switch (iType) { case (EIT_16BIT): @@ -1136,100 +1291,118 @@ void CD3D9Driver::drawVertexPrimitiveList(const void* vertices, } } - if (setRenderStates3DMode()) + if (is3D) { - switch (pType) + if (!setRenderStates3DMode()) + return; + } + else + { + if (Material.MaterialType==EMT_ONETEXTURE_BLEND) { - case scene::EPT_POINT_SPRITES: - case scene::EPT_POINTS: - { - if (pType==scene::EPT_POINT_SPRITES) - pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_POINTSIZE, *(DWORD*)(&Material.Thickness)); - f32 tmp=1.0f; - pID3DDevice->SetRenderState(D3DRS_POINTSCALE_C, *(DWORD*)(&tmp)); - tmp=0.0f; - pID3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, *(DWORD*)(&tmp)); - pID3DDevice->SetRenderState(D3DRS_POINTSCALE_A, *(DWORD*)(&tmp)); - pID3DDevice->SetRenderState(D3DRS_POINTSCALE_B, *(DWORD*)(&tmp)); - - if (!vertices) - { - pID3DDevice->DrawIndexedPrimitive(D3DPT_POINTLIST, 0, 0, vertexCount, 0, primitiveCount); - } - else - { - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount, - primitiveCount, indexList, indexType, vertices, stride); - } - - pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); - if (pType==scene::EPT_POINT_SPRITES) - pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); - } - break; - case scene::EPT_LINE_STRIP: - if(!vertices) - pID3DDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 0, vertexCount, 0, primitiveCount); - else - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, - primitiveCount, indexList, indexType, vertices, stride); - break; - case scene::EPT_LINE_LOOP: - if(!vertices) - { - // TODO: Implement proper hardware support for this primitive type. - // (No looping occurs currently because this would require a way to - // draw the hardware buffer with a custom set of indices. We may even - // need to create a new mini index buffer specifically for this - // primitive type.) - pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount); - } - else - { - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, - primitiveCount, indexList, indexType, vertices, stride); - - u16 tmpIndices[] = {0, primitiveCount}; - - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, - 1, tmpIndices, indexType, vertices, stride); - } - break; - case scene::EPT_LINES: - if(!vertices) - pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount); - else - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, - primitiveCount, indexList, indexType, vertices, stride); - break; - case scene::EPT_TRIANGLE_STRIP: - if(!vertices) - pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, vertexCount, 0, primitiveCount); - else - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount, primitiveCount, - indexList, indexType, vertices, stride); - break; - case scene::EPT_TRIANGLE_FAN: - if(!vertices) - pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, 0, vertexCount, 0, primitiveCount); - else - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount, primitiveCount, - indexList, indexType, vertices, stride); - break; - case scene::EPT_TRIANGLES: - if(!vertices) - { - pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vertexCount, 0, primitiveCount); - } - else - { - pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount, - primitiveCount, indexList, indexType, vertices, stride); - } - break; + E_BLEND_FACTOR srcFact; + E_BLEND_FACTOR dstFact; + E_MODULATE_FUNC modulo; + u32 alphaSource; + unpack_texureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam); + setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0); } + else + setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL); + } + + switch (pType) + { + case scene::EPT_POINT_SPRITES: + case scene::EPT_POINTS: + { + f32 tmp=Material.Thickness/getScreenSize().Height; + if (pType==scene::EPT_POINT_SPRITES) + pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_POINTSIZE, *(DWORD*)(&tmp)); + tmp=1.0f; + pID3DDevice->SetRenderState(D3DRS_POINTSCALE_A, *(DWORD*)(&tmp)); + pID3DDevice->SetRenderState(D3DRS_POINTSCALE_B, *(DWORD*)(&tmp)); + pID3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, *(DWORD*)(&tmp)); + tmp=0.0f; + pID3DDevice->SetRenderState(D3DRS_POINTSCALE_C, *(DWORD*)(&tmp)); + + if (!vertices) + { + pID3DDevice->DrawIndexedPrimitive(D3DPT_POINTLIST, 0, 0, vertexCount, 0, primitiveCount); + } + else + { + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + } + + pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); + if (pType==scene::EPT_POINT_SPRITES) + pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); + } + break; + case scene::EPT_LINE_STRIP: + if(!vertices) + pID3DDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 0, vertexCount, 0, primitiveCount); + else + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + break; + case scene::EPT_LINE_LOOP: + if(!vertices) + { + // TODO: Implement proper hardware support for this primitive type. + // (No looping occurs currently because this would require a way to + // draw the hardware buffer with a custom set of indices. We may even + // need to create a new mini index buffer specifically for this + // primitive type.) + pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount); + } + else + { + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, + primitiveCount - 1, indexList, indexType, vertices, stride); + + u16 tmpIndices[] = {primitiveCount - 1, 0}; + + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, + 1, tmpIndices, indexType, vertices, stride); + } + break; + case scene::EPT_LINES: + if(!vertices) + pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount); + else + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + break; + case scene::EPT_TRIANGLE_STRIP: + if(!vertices) + pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, vertexCount, 0, primitiveCount); + else + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount, primitiveCount, + indexList, indexType, vertices, stride); + break; + case scene::EPT_TRIANGLE_FAN: + if(!vertices) + pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, 0, vertexCount, 0, primitiveCount); + else + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount, primitiveCount, + indexList, indexType, vertices, stride); + break; + case scene::EPT_TRIANGLES: + if(!vertices) + { + pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vertexCount, 0, primitiveCount); + } + else + { + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount, + primitiveCount, indexList, indexType, vertices, stride); + } + break; } } @@ -1244,21 +1417,14 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, if(!texture) return; - const core::dimension2d& ss = texture->getOriginalSize(); + const core::dimension2d& ss = texture->getOriginalSize(); core::rect tcoords; tcoords.UpperLeftCorner.X = (f32)sourceRect.UpperLeftCorner.X / (f32)ss.Width; tcoords.UpperLeftCorner.Y = (f32)sourceRect.UpperLeftCorner.Y / (f32)ss.Height; tcoords.LowerRightCorner.X = (f32)sourceRect.LowerRightCorner.X / (f32)ss.Width; tcoords.LowerRightCorner.Y = (f32)sourceRect.LowerRightCorner.Y / (f32)ss.Height; - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - core::rect npos; - f32 xFact = 2.0f / ( renderTargetSize.Width ); - f32 yFact = 2.0f / ( renderTargetSize.Height ); - npos.UpperLeftCorner.X = ( destRect.UpperLeftCorner.X * xFact ) - 1.0f; - npos.UpperLeftCorner.Y = 1.0f - ( destRect.UpperLeftCorner.Y * yFact ); - npos.LowerRightCorner.X = ( destRect.LowerRightCorner.X * xFact ) - 1.0f; - npos.LowerRightCorner.Y = 1.0f - ( destRect.LowerRightCorner.Y * yFact ); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); const video::SColor temp[4] = { @@ -1271,16 +1437,16 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, const video::SColor* const useColor = colors ? colors : temp; S3DVertex vtx[4]; // clock wise - vtx[0] = S3DVertex(npos.UpperLeftCorner.X, npos.UpperLeftCorner.Y, 0.0f, + vtx[0] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); - vtx[1] = S3DVertex(npos.LowerRightCorner.X, npos.UpperLeftCorner.Y, 0.0f, + vtx[1] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[3], tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); - vtx[2] = S3DVertex(npos.LowerRightCorner.X, npos.LowerRightCorner.Y, 0.0f, + vtx[2] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); - vtx[3] = S3DVertex(npos.UpperLeftCorner.X, npos.LowerRightCorner.Y, 0.0f, + vtx[3] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); @@ -1290,7 +1456,7 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255, true, useAlphaChannelOfTexture); - setTexture(0, const_cast(texture)); + setActiveTexture(0, const_cast(texture)); setVertexShader(EVT_STANDARD); @@ -1313,6 +1479,152 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, } +void CD3D9Driver::draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect, + SColor color, + bool useAlphaChannelOfTexture) +{ + if (!texture) + return; + + if (!setActiveTexture(0, const_cast(texture))) + return; + + const irr::u32 drawCount = core::min_(positions.size(), sourceRects.size()); + + core::array vtx(drawCount * 4); + core::array indices(drawCount * 6); + + for(u32 i = 0;i < drawCount;i++) + { + core::position2d targetPos = positions[i]; + core::position2d sourcePos = sourceRects[i].UpperLeftCorner; + // This needs to be signed as it may go negative. + core::dimension2d sourceSize(sourceRects[i].getSize()); + + if (clipRect) + { + if (targetPos.X < clipRect->UpperLeftCorner.X) + { + sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; + if (sourceSize.Width <= 0) + continue; + + sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; + targetPos.X = clipRect->UpperLeftCorner.X; + } + + if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X) + { + sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; + if (sourceSize.Width <= 0) + continue; + } + + if (targetPos.Y < clipRect->UpperLeftCorner.Y) + { + sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; + if (sourceSize.Height <= 0) + continue; + + sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; + targetPos.Y = clipRect->UpperLeftCorner.Y; + } + + if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y) + { + sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; + if (sourceSize.Height <= 0) + continue; + } + } + + // clip these coordinates + + if (targetPos.X<0) + { + sourceSize.Width += targetPos.X; + if (sourceSize.Width <= 0) + continue; + + sourcePos.X -= targetPos.X; + targetPos.X = 0; + } + + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + + if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) + { + sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; + if (sourceSize.Width <= 0) + continue; + } + + if (targetPos.Y<0) + { + sourceSize.Height += targetPos.Y; + if (sourceSize.Height <= 0) + continue; + + sourcePos.Y -= targetPos.Y; + targetPos.Y = 0; + } + + if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) + { + sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; + if (sourceSize.Height <= 0) + continue; + } + + // ok, we've clipped everything. + // now draw it. + + core::rect tcoords; + tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ; + tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height; + tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width); + tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height); + + const core::rect poss(targetPos, sourceSize); + + setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); + + vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, + 0.0f, 0.0f, 0.0f, color, + tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y)); + vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, + 0.0f, 0.0f, 0.0f, color, + tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y)); + vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, + 0.0f, 0.0f, 0.0f, color, + tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y)); + vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, + 0.0f, 0.0f, 0.0f, color, + tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y)); + + const u32 curPos = vtx.size()-4; + indices.push_back(0+curPos); + indices.push_back(1+curPos); + indices.push_back(2+curPos); + + indices.push_back(0+curPos); + indices.push_back(2+curPos); + indices.push_back(3+curPos); + } + + if (vtx.size()) + { + setVertexShader(EVT_STANDARD); + + pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vtx.size(), indices.size() / 3, indices.pointer(), + D3DFMT_INDEX16,vtx.pointer(), sizeof(S3DVertex)); + } +} + + //! draws a 2d image, using a color and the alpha channel of the texture if //! desired. The image is drawn at pos and clipped against clipRect (if != 0). void CD3D9Driver::draw2DImage(const video::ITexture* texture, @@ -1327,11 +1639,12 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, if (!sourceRect.isValid()) return; - if (!setTexture(0, const_cast(texture))) + if (!setActiveTexture(0, const_cast(texture))) return; core::position2d targetPos = pos; core::position2d sourcePos = sourceRect.UpperLeftCorner; + // This needs to be signed as it may go negative. core::dimension2d sourceSize(sourceRect.getSize()); if (clipRect) @@ -1346,7 +1659,7 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, targetPos.X = clipRect->UpperLeftCorner.X; } - if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) + if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; if (sourceSize.Width <= 0) @@ -1363,7 +1676,7 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, targetPos.Y = clipRect->UpperLeftCorner.Y; } - if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) + if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; if (sourceSize.Height <= 0) @@ -1383,9 +1696,9 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, targetPos.X = 0; } - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - if (targetPos.X + sourceSize.Width > renderTargetSize.Width) + if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; if (sourceSize.Width <= 0) @@ -1402,7 +1715,7 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, targetPos.Y = 0; } - if (targetPos.Y + sourceSize.Height > renderTargetSize.Height) + if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; if (sourceSize.Height <= 0) @@ -1412,33 +1725,27 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture, // ok, we've clipped everything. // now draw it. - s32 xPlus = -renderTargetSize.Width / 2; - f32 xFact = 2.0f / renderTargetSize.Width; - - s32 yPlus = renderTargetSize.Height / 2; - f32 yFact = 2.0f / renderTargetSize.Height; - core::rect tcoords; - tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)+0.5f) / texture->getOriginalSize().Width ; - tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)+0.5f) / texture->getOriginalSize().Height; - tcoords.LowerRightCorner.X = (((f32)sourcePos.X +0.5f + (f32)sourceSize.Width)) / texture->getOriginalSize().Width; - tcoords.LowerRightCorner.Y = (((f32)sourcePos.Y +0.5f + (f32)sourceSize.Height)) / texture->getOriginalSize().Height; + tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ; + tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height; + tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width); + tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height); - core::rect poss(targetPos, sourceSize); + const core::rect poss(targetPos, sourceSize); setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); S3DVertex vtx[4]; - vtx[0] = S3DVertex((f32)(poss.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-poss.UpperLeftCorner.Y ) * yFact, 0.0f, + vtx[0] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); - vtx[1] = S3DVertex((f32)(poss.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus- poss.UpperLeftCorner.Y) * yFact, 0.0f, + vtx[1] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); - vtx[2] = S3DVertex((f32)(poss.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus-poss.LowerRightCorner.Y) * yFact, 0.0f, + vtx[2] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); - vtx[3] = S3DVertex((f32)(poss.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-poss.LowerRightCorner.Y) * yFact, 0.0f, + vtx[3] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); @@ -1464,22 +1771,14 @@ void CD3D9Driver::draw2DRectangle(const core::rect& position, if (!pos.isValid()) return; - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - - s32 xPlus = -renderTargetSize.Width / 2; - f32 xFact = 2.0f / renderTargetSize.Width; - - s32 yPlus = renderTargetSize.Height / 2; - f32 yFact = 2.0f / renderTargetSize.Height; - S3DVertex vtx[4]; - vtx[0] = S3DVertex((f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.UpperLeftCorner.Y) * yFact, 0.0f, + vtx[0] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorLeftUp, 0.0f, 0.0f); - vtx[1] = S3DVertex((f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus- pos.UpperLeftCorner.Y) * yFact, 0.0f, + vtx[1] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorRightUp, 0.0f, 1.0f); - vtx[2] = S3DVertex((f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.0f, + vtx[2] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorRightDown, 1.0f, 0.0f); - vtx[3] = S3DVertex((f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.0f, + vtx[3] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorLeftDown, 1.0f, 1.0f); s16 indices[6] = {0,1,2,0,2,3}; @@ -1490,48 +1789,32 @@ void CD3D9Driver::draw2DRectangle(const core::rect& position, colorLeftDown.getAlpha() < 255 || colorRightDown.getAlpha() < 255, false, false); - setTexture(0,0); + setActiveTexture(0,0); setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); - } - //! Draws a 2d line. void CD3D9Driver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { // thanks to Vash TheStampede who sent in his implementation - - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - const s32 xPlus = -renderTargetSize.Width / 2; - const f32 xFact = 2.0f / renderTargetSize.Width; - - const s32 yPlus = renderTargetSize.Height / 2; - const f32 yFact = 2.0f / renderTargetSize.Height; - S3DVertex vtx[2]; - vtx[0] = S3DVertex((f32)(start.X + xPlus) * xFact, - (f32)(yPlus - start.Y) * yFact, - 0.0f, // z + vtx[0] = S3DVertex((f32)start.X, (f32)start.Y, 0.0f, 0.0f, 0.0f, 0.0f, // normal - color, - 0.0f, 0.0f); // texture + color, 0.0f, 0.0f); // texture - vtx[1] = S3DVertex((f32)(end.X+xPlus) * xFact, - (f32)(yPlus- end.Y) * yFact, - 0.0f, + vtx[1] = S3DVertex((f32)end.X, (f32)end.Y, 0.0f, 0.0f, 0.0f, 0.0f, - color, - 0.0f, 0.0f); + color, 0.0f, 0.0f); setRenderStates2DMode(color.getAlpha() < 255, false, false); - setTexture(0,0); + setActiveTexture(0,0); setVertexShader(EVT_STANDARD); @@ -1539,25 +1822,20 @@ void CD3D9Driver::draw2DLine(const core::position2d& start, &vtx[0], sizeof(S3DVertex) ); } + //! Draws a pixel void CD3D9Driver::drawPixel(u32 x, u32 y, const SColor & color) { - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); if(x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) return; setRenderStates2DMode(color.getAlpha() < 255, false, false); - setTexture(0,0); + setActiveTexture(0,0); setVertexShader(EVT_STANDARD); - const s32 xPlus = -renderTargetSize.Width / 2; - const f32 xFact = 2.0f / renderTargetSize.Width; - const s32 yPlus = renderTargetSize.Height / 2; - const f32 yFact = 2.0f / renderTargetSize.Height; - S3DVertex vertex((f32)((s32)x + xPlus) * xFact, - (f32)(yPlus - (s32)y) * yFact, - 0.f, 0.f, 0.f, 0.f, color, 0.f, 0.f); + S3DVertex vertex((f32)x, (f32)y, 0.f, 0.f, 0.f, 0.f, color, 0.f, 0.f); pID3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &vertex, sizeof(vertex)); } @@ -1597,7 +1875,6 @@ void CD3D9Driver::setVertexShader(E_VERTEX_TYPE newType) } - //! sets the needed renderstates bool CD3D9Driver::setRenderStates3DMode() { @@ -1646,6 +1923,39 @@ bool CD3D9Driver::setRenderStates3DMode() } +//! Map Irrlicht texture wrap mode to native values +D3DTEXTUREADDRESS CD3D9Driver::getTextureWrapMode(const u8 clamp) +{ + switch (clamp) + { + case ETC_REPEAT: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP) + return D3DTADDRESS_WRAP; + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP) + return D3DTADDRESS_CLAMP; + case ETC_MIRROR: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR) + return D3DTADDRESS_MIRROR; + case ETC_CLAMP_TO_BORDER: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER) + return D3DTADDRESS_BORDER; + else + return D3DTADDRESS_CLAMP; + case ETC_MIRROR_CLAMP: + case ETC_MIRROR_CLAMP_TO_EDGE: + case ETC_MIRROR_CLAMP_TO_BORDER: + if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE) + return D3DTADDRESS_MIRRORONCE; + else + return D3DTADDRESS_CLAMP; + default: + return D3DTADDRESS_WRAP; + } +} + + //! Can be called by an IMaterialRenderer to make its work easier. void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates) @@ -1666,6 +1976,21 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria pID3DDevice->SetMaterial(&mat); } + if (lastmaterial.ColorMaterial != material.ColorMaterial) + { + pID3DDevice->SetRenderState(D3DRS_COLORVERTEX, (material.ColorMaterial != ECM_NONE)); + pID3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, + ((material.ColorMaterial == ECM_DIFFUSE)|| + (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL); + pID3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, + ((material.ColorMaterial == ECM_AMBIENT)|| + (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL); + pID3DDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, + (material.ColorMaterial == ECM_EMISSIVE)?D3DMCS_COLOR1:D3DMCS_MATERIAL); + pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, + (material.ColorMaterial == ECM_SPECULAR)?D3DMCS_COLOR1:D3DMCS_MATERIAL); + } + // fillmode if (resetAllRenderstates || lastmaterial.Wireframe != material.Wireframe || lastmaterial.PointCloud != material.PointCloud) { @@ -1704,17 +2029,37 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria { switch (material.ZBuffer) { - case 0: - pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - break; - case 1: - pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - break; - case 2: - pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL); - break; + case ECFN_NEVER: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + break; + case ECFN_LESSEQUAL: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + break; + case ECFN_EQUAL: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL); + break; + case ECFN_LESS: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); + break; + case ECFN_NOTEQUAL: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_NOTEQUAL); + break; + case ECFN_GREATEREQUAL: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL); + break; + case ECFN_GREATER: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER); + break; + case ECFN_ALWAYS: + pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + break; } } @@ -1752,7 +2097,7 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria // specular highlights if (resetAllRenderstates || !core::equals(lastmaterial.Shininess,material.Shininess)) { - bool enable = (material.Shininess!=0.0f); + const bool enable = (material.Shininess!=0.0f); pID3DDevice->SetRenderState(D3DRS_SPECULARENABLE, enable); pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL); } @@ -1763,6 +2108,51 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria pID3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, material.NormalizeNormals); } + // Color Mask + if (queryFeature(EVDF_COLOR_MASK) && + (resetAllRenderstates || lastmaterial.ColorMask != material.ColorMask)) + { + const DWORD flag = + ((material.ColorMask & ECP_RED)?D3DCOLORWRITEENABLE_RED:0) | + ((material.ColorMask & ECP_GREEN)?D3DCOLORWRITEENABLE_GREEN:0) | + ((material.ColorMask & ECP_BLUE)?D3DCOLORWRITEENABLE_BLUE:0) | + ((material.ColorMask & ECP_ALPHA)?D3DCOLORWRITEENABLE_ALPHA:0); + pID3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, flag); + } + + // Anti Aliasing + if (resetAllRenderstates || lastmaterial.AntiAliasing != material.AntiAliasing) + { + if (AlphaToCoverageSupport && (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)) + { + if (VendorID==0x10DE)//NVidia + pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, MAKEFOURCC('A','T','O','C')); + // SSAA could give better results on NVidia cards + else if (VendorID==0x1002)//ATI + pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','1')); + } + else if (AlphaToCoverageSupport && (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)) + { + if (VendorID==0x10DE) + pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, D3DFMT_UNKNOWN); + else if (VendorID==0x1002) + pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','0')); + } + + // enable antialiasing + if (AntiAliasing) + { + if (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY)) + pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); + else if (lastmaterial.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY)) + pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE); + if (material.AntiAliasing & (EAAM_LINE_SMOOTH)) + pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE); + else if (lastmaterial.AntiAliasing & (EAAM_LINE_SMOOTH)) + pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE); + } + } + // thickness if (resetAllRenderstates || lastmaterial.Thickness != material.Thickness) { @@ -1772,30 +2162,20 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria // texture address mode for (u32 st=0; stSetSamplerState(st, D3DSAMP_ADDRESSU, mode ); - pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, mode ); + const float tmp = material.TextureLayer[st].LODBias * 0.125f; + pID3DDevice->SetSamplerState(st, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)(&tmp)); } + if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapU != material.TextureLayer[st].TextureWrapU) + pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSU, getTextureWrapMode(material.TextureLayer[st].TextureWrapU)); + // If separate UV not supported reuse U for V + if (!(Caps.TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV)) + pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapU)); + else if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapV != material.TextureLayer[st].TextureWrapV) + pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapV)); + // Bilinear, trilinear, and anisotropic filter if (resetAllRenderstates || lastmaterial.TextureLayer[st].BilinearFilter != material.TextureLayer[st].BilinearFilter || @@ -1810,6 +2190,8 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR; D3DTEXTUREFILTERTYPE tftMip = material.TextureLayer[st].TrilinearFilter ? D3DTEXF_LINEAR : D3DTEXF_POINT; + if (tftMag==D3DTEXF_ANISOTROPIC || tftMin == D3DTEXF_ANISOTROPIC) + pID3DDevice->SetSamplerState(st, D3DSAMP_MAXANISOTROPY, core::min_((DWORD)material.TextureLayer[st].AnisotropicFilter, Caps.MaxAnisotropy)); pID3DDevice->SetSamplerState(st, D3DSAMP_MAGFILTER, tftMag); pID3DDevice->SetSamplerState(st, D3DSAMP_MINFILTER, tftMin); pID3DDevice->SetSamplerState(st, D3DSAMP_MIPFILTER, tftMip); @@ -1839,10 +2221,10 @@ void CD3D9Driver::setRenderStatesStencilShadowMode(bool zfail) Transformation3DChanged = false; - setTexture(0,0); - setTexture(1,0); - setTexture(2,0); - setTexture(3,0); + setActiveTexture(0,0); + setActiveTexture(1,0); + setActiveTexture(2,0); + setActiveTexture(3,0); pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); @@ -1966,6 +2348,15 @@ void CD3D9Driver::setRenderStatesStencilFillMode(bool alpha) } +//! Enable the 2d override material +void CD3D9Driver::enableMaterial2D(bool enable) +{ + if (!enable) + CurrentRenderMode = ERM_NONE; + CNullDriver::enableMaterial2D(enable); +} + + //! sets the needed renderstates void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) { @@ -1975,15 +2366,17 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan if (CurrentRenderMode != ERM_2D || Transformation3DChanged) { // unset last 3d material - if (CurrentRenderMode != ERM_2D) + if (CurrentRenderMode == ERM_3D) { if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); - setBasicRenderStates(SMaterial(), SMaterial(), true); - // everything that is wrongly set by SMaterial default - pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); + } + if (!OverrideMaterial2DEnabled) + { + setBasicRenderStates(InitMaterial2D, LastMaterial, true); + LastMaterial=InitMaterial2D; + // fix everything that is wrongly set by InitMaterial2D default pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); @@ -1992,96 +2385,102 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan pID3DDevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE ); - - pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); - - pID3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP ); - pID3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP ); - - pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0); - pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D9 ); } - - pID3DDevice->SetTransform(D3DTS_VIEW, &UnitMatrixD3D9); pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D9); - pID3DDevice->SetTransform(D3DTS_PROJECTION, &UnitMatrixD3D9); + + core::matrix4 m; + m.setTranslation(core::vector3df(-0.5f,-0.5f,0)); + pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)m.pointer())); + + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0); + m.setTranslation(core::vector3df(-1,1,0)); + pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)m.pointer())); Transformation3DChanged = false; } - - if (texture) + if (OverrideMaterial2DEnabled) { - pID3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - pID3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); - pID3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + OverrideMaterial2D.Lighting=false; + OverrideMaterial2D.ZBuffer=ECFN_NEVER; + OverrideMaterial2D.ZWriteEnable=false; + setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); + LastMaterial = OverrideMaterial2D; + } - if (alphaChannel) + u32 current2DSignature = 0; + current2DSignature |= alpha ? EC2D_ALPHA : 0; + current2DSignature |= texture ? EC2D_TEXTURE : 0; + current2DSignature |= alphaChannel ? EC2D_ALPHA_CHANNEL : 0; + + if(CurrentRenderMode != ERM_2D || current2DSignature != Cached2DModeSignature) + { + if (texture) { - pID3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - - if (alpha) + setTransform(ETS_TEXTURE_0, core::IdentityMatrix); + if (alphaChannel) { - pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); - } - else - { - pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - } - pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); - } - else - { - if (alpha) - { - pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); - pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + if (alpha) + { + pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + } + else + { + pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + } + pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); } else { - pID3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + if (alpha) + { + pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); + pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); + } + else + { + pID3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } } } - } - else - { - if (alpha) - { - pID3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); - pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); - } else { pID3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + if (alpha) + { + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); + } + else + { + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } } } CurrentRenderMode = ERM_2D; + Cached2DModeSignature = current2DSignature; } @@ -2098,11 +2497,8 @@ void CD3D9Driver::deleteAllDynamicLights() //! adds a dynamic light -void CD3D9Driver::addDynamicLight(const SLight& dl) +s32 CD3D9Driver::addDynamicLight(const SLight& dl) { - if ((u32)LastSetLight == Caps.MaxActiveLights-1) - return; - CNullDriver::addDynamicLight(dl); D3DLIGHT9 light; @@ -2138,8 +2534,26 @@ void CD3D9Driver::addDynamicLight(const SLight& dl) light.Phi = dl.OuterCone * 2.0f * core::DEGTORAD; ++LastSetLight; - pID3DDevice->SetLight(LastSetLight, &light); - pID3DDevice->LightEnable(LastSetLight, true); + + if(D3D_OK == pID3DDevice->SetLight(LastSetLight, &light)) + { + // I don't care if this succeeds + (void)pID3DDevice->LightEnable(LastSetLight, true); + return LastSetLight; + } + + return -1; +} + +//! Turns a dynamic light on or off +//! \param lightIndex: the index returned by addDynamicLight +//! \param turnOn: true to turn the light on, false to turn it off +void CD3D9Driver::turnLightOn(s32 lightIndex, bool turnOn) +{ + if(lightIndex < 0 || lightIndex > LastSetLight) + return; + + (void)pID3DDevice->LightEnable(lightIndex, turnOn); } @@ -2236,7 +2650,7 @@ void CD3D9Driver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftU leftDownEdge.getAlpha() < 255 || rightDownEdge.getAlpha() < 255); - setTexture(0,0); + setActiveTexture(0,0); setVertexShader(EVT_STANDARD); @@ -2258,10 +2672,10 @@ u32 CD3D9Driver::getMaximalPrimitiveCount() const //! Sets the fog mode. -void CD3D9Driver::setFog(SColor color, bool linearFog, f32 start, +void CD3D9Driver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { - CNullDriver::setFog(color, linearFog, start, end, density, pixelFog, rangeFog); + CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog); if (!pID3DDevice) return; @@ -2270,9 +2684,9 @@ void CD3D9Driver::setFog(SColor color, bool linearFog, f32 start, pID3DDevice->SetRenderState( pixelFog ? D3DRS_FOGTABLEMODE : D3DRS_FOGVERTEXMODE, - linearFog ? D3DFOG_LINEAR : D3DFOG_EXP); + (fogType==EFT_FOG_LINEAR)? D3DFOG_LINEAR : (fogType==EFT_FOG_EXP)?D3DFOG_EXP:D3DFOG_EXP2); - if(linearFog) + if (fogType==EFT_FOG_LINEAR) { pID3DDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD*)(&start)); pID3DDevice->SetRenderState(D3DRS_FOGEND, *(DWORD*)(&end)); @@ -2321,28 +2735,14 @@ bool CD3D9Driver::reset() if(DepthBuffers[i]->Surface) DepthBuffers[i]->Surface->Release(); } + // this does not require a restore in the reset method, it's updated + // automatically in the next render cycle. + removeAllHardwareBuffers(); DriverWasReset=true; HRESULT hr = pID3DDevice->Reset(&present); - // restore screen depthbuffer - pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface)); - D3DSURFACE_DESC desc; - DepthBuffers[0]->Surface->GetDesc(&desc); - // restore other depth buffers - for (i=1; iCreateDepthStencilSurface(DepthBuffers[i]->Size.Width, - DepthBuffers[i]->Size.Height, - desc.Format, - desc.MultiSampleType, - desc.MultiSampleQuality, - TRUE, - &(DepthBuffers[i]->Surface), - NULL); - } - // restore RTTs for (i=0; icreateRenderTarget(); } + // restore screen depthbuffer + pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface)); + D3DSURFACE_DESC desc; + // restore other depth buffers + // depth format is taken from main depth buffer + DepthBuffers[0]->Surface->GetDesc(&desc); + // multisampling is taken from rendertarget + D3DSURFACE_DESC desc2; + for (i=1; iDepthSurface==DepthBuffers[i]) + { + ((CD3D9Texture*)(Textures[j].Surface))->Texture->GetLevelDesc(0,&desc2); + break; + } + } + + pID3DDevice->CreateDepthStencilSurface(DepthBuffers[i]->Size.Width, + DepthBuffers[i]->Size.Height, + desc.Format, + desc2.MultiSampleType, + desc2.MultiSampleQuality, + TRUE, + &(DepthBuffers[i]->Surface), + NULL); + } + if (FAILED(hr)) { if (hr == D3DERR_DEVICELOST) @@ -2395,14 +2826,14 @@ bool CD3D9Driver::reset() setVertexShader(EVT_STANDARD); setRenderStates3DMode(); - setFog(FogColor, LinearFog, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); + setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); setAmbientLight(AmbientLight); return true; } -void CD3D9Driver::OnResize(const core::dimension2d& size) +void CD3D9Driver::OnResize(const core::dimension2d& size) { if (!pID3DDevice) return; @@ -2471,13 +2902,6 @@ bool CD3D9Driver::setPixelShaderConstant(const c8* name, const f32* floats, int } -//! Returns pointer to the IGPUProgrammingServices interface. -IGPUProgrammingServices* CD3D9Driver::getGPUProgrammingServices() -{ - return this; -} - - //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 CD3D9Driver::addShaderMaterial(const c8* vertexShaderProgram, @@ -2504,6 +2928,11 @@ s32 CD3D9Driver::addHighLevelShaderMaterial( const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) { @@ -2535,13 +2964,11 @@ IVideoDriver* CD3D9Driver::getVideoDriver() //! Creates a render target texture. -ITexture* CD3D9Driver::addRenderTargetTexture( - const core::dimension2d& size, - const c8* name) +ITexture* CD3D9Driver::addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, + const ECOLOR_FORMAT format) { - if (!name) - name="rt"; - ITexture* tex = new CD3D9Texture(this, size, name); + ITexture* tex = new CD3D9Texture(this, size, name, format); if (tex) { checkDepthBuffer(tex); @@ -2595,6 +3022,12 @@ IImage* CD3D9Driver::createScreenShot() clientRect.top = clientPoint.y; clientRect.right = clientRect.left + ScreenSize.Width; clientRect.bottom = clientRect.top + ScreenSize.Height; + + // window can be off-screen partly, we can't take screenshots from that + clientRect.left = core::max_(clientRect.left, 0l); + clientRect.top = core::max_(clientRect.top, 0l); + clientRect.right = core::min_(clientRect.right, (long)displayMode.Width); + clientRect.bottom = core::min_(clientRect.bottom, (long)displayMode.Height ); } // lock our area of the surface @@ -2605,38 +3038,42 @@ IImage* CD3D9Driver::createScreenShot() return 0; } + irr::core::dimension2d shotSize; + shotSize.Width = core::min_( ScreenSize.Width, (u32)(clientRect.right-clientRect.left) ); + shotSize.Height = core::min_( ScreenSize.Height, (u32)(clientRect.bottom-clientRect.top) ); + // this could throw, but we aren't going to worry about that case very much - IImage* newImage = new CImage(ECF_A8R8G8B8, ScreenSize); + IImage* newImage = new CImage(ECF_A8R8G8B8, shotSize); // d3d pads the image, so we need to copy the correct number of bytes u32* dP = (u32*)newImage->lock(); u8 * sP = (u8 *)lockedRect.pBits; // If the display mode format doesn't promise anything about the Alpha value - // and it appears that it's not presenting 255, then we should manually + // and it appears that it's not presenting 255, then we should manually // set each pixel alpha value to 255. if(D3DFMT_X8R8G8B8 == displayMode.Format && (0xFF000000 != (*dP & 0xFF000000))) { - for (s32 y = 0; y < ScreenSize.Height; ++y) + for (u32 y = 0; y < shotSize.Height; ++y) { - for(s32 x = 0; x < ScreenSize.Width; ++x) + for(u32 x = 0; x < shotSize.Width; ++x) { *dP = *((u32*)sP) | 0xFF000000; dP++; sP += 4; } - sP += lockedRect.Pitch - (4 * ScreenSize.Width); + sP += lockedRect.Pitch - (4 * shotSize.Width); } } else { - for (s32 y = 0; y < ScreenSize.Height; ++y) + for (u32 y = 0; y < shotSize.Height; ++y) { - memcpy(dP, sP, ScreenSize.Width * 4); + memcpy(dP, sP, shotSize.Width * 4); sP += lockedRect.Pitch; - dP += ScreenSize.Width; + dP += shotSize.Width; } } @@ -2668,7 +3105,7 @@ D3DFORMAT CD3D9Driver::getD3DColorFormat() const // returns the current size of the screen or rendertarget -const core::dimension2d& CD3D9Driver::getCurrentRenderTargetSize() const +const core::dimension2d& CD3D9Driver::getCurrentRenderTargetSize() const { if ( CurrentRendertargetSize.Width == 0 ) return ScreenSize; @@ -2716,6 +3153,20 @@ D3DFORMAT CD3D9Driver::getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const return D3DFMT_R8G8B8; case ECF_A8R8G8B8: return D3DFMT_A8R8G8B8; + + // Floating Point formats. Thanks to Patryk "Nadro" Nadrowski. + case ECF_R16F: + return D3DFMT_R16F; + case ECF_G16R16F: + return D3DFMT_G16R16F; + case ECF_A16B16G16R16F: + return D3DFMT_A16B16G16R16F; + case ECF_R32F: + return D3DFMT_R32F; + case ECF_G32R32F: + return D3DFMT_G32R32F; + case ECF_A32B32G32R32F: + return D3DFMT_A32B32G32R32F; } return D3DFMT_UNKNOWN; } @@ -2725,19 +3176,33 @@ ECOLOR_FORMAT CD3D9Driver::getColorFormatFromD3DFormat(D3DFORMAT format) const { switch(format) { - case D3DFMT_X1R5G5B5: - case D3DFMT_A1R5G5B5: - return ECF_A1R5G5B5; - case D3DFMT_A8B8G8R8: - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - return ECF_A8R8G8B8; - case D3DFMT_R5G6B5: - return ECF_R5G6B5; - case D3DFMT_R8G8B8: - return ECF_R8G8B8; - default: - return (ECOLOR_FORMAT)0; + case D3DFMT_X1R5G5B5: + case D3DFMT_A1R5G5B5: + return ECF_A1R5G5B5; + case D3DFMT_A8B8G8R8: + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + return ECF_A8R8G8B8; + case D3DFMT_R5G6B5: + return ECF_R5G6B5; + case D3DFMT_R8G8B8: + return ECF_R8G8B8; + + // Floating Point formats. Thanks to Patryk "Nadro" Nadrowski. + case D3DFMT_R16F: + return ECF_R16F; + case D3DFMT_G16R16F: + return ECF_G16R16F; + case D3DFMT_A16B16G16R16F: + return ECF_A16B16G16R16F; + case D3DFMT_R32F: + return ECF_R32F; + case D3DFMT_G32R32F: + return ECF_G32R32F; + case D3DFMT_A32B32G32R32F: + return ECF_A32B32G32R32F; + default: + return (ECOLOR_FORMAT)0; }; } @@ -2746,11 +3211,11 @@ void CD3D9Driver::checkDepthBuffer(ITexture* tex) { if (!tex) return; - const core::dimension2di optSize = tex->getSize().getOptimalSize( + const core::dimension2du optSize = tex->getSize().getOptimalSize( !queryFeature(EVDF_TEXTURE_NPOT), !queryFeature(EVDF_TEXTURE_NSQUARE), true); SDepthSurface* depth=0; - core::dimension2di destSize(0x7fffffff, 0x7fffffff); + core::dimension2du destSize(0x7fffffff, 0x7fffffff); for (u32 i=0; iSize.Width>=optSize.Width) && @@ -2768,19 +3233,23 @@ void CD3D9Driver::checkDepthBuffer(ITexture* tex) { D3DSURFACE_DESC desc; DepthBuffers[0]->Surface->GetDesc(&desc); + // the multisampling needs to match the RTT + D3DSURFACE_DESC desc2; + ((CD3D9Texture*)tex)->Texture->GetLevelDesc(0,&desc2); DepthBuffers.push_back(new SDepthSurface()); HRESULT hr=pID3DDevice->CreateDepthStencilSurface(optSize.Width, optSize.Height, desc.Format, - desc.MultiSampleType, - desc.MultiSampleQuality, + desc2.MultiSampleType, + desc2.MultiSampleQuality, TRUE, &(DepthBuffers.getLast()->Surface), - NULL); + NULL); if (SUCCEEDED(hr)) { depth=DepthBuffers.getLast(); - depth->Size=optSize; + depth->Surface->GetDesc(&desc); + depth->Size.set(desc.Width, desc.Height); } else { @@ -2791,9 +3260,9 @@ void CD3D9Driver::checkDepthBuffer(ITexture* tex) else { char buffer[128]; - sprintf(buffer,"Could not create DepthBuffer of %ix%i",destSize.Width,destSize.Height); + sprintf(buffer,"Could not create DepthBuffer of %ix%i",optSize.Width,optSize.Height); os::Printer::log(buffer,ELL_ERROR); - } + } DepthBuffers.erase(DepthBuffers.size()-1); } } @@ -2817,6 +3286,12 @@ void CD3D9Driver::removeDepthSurface(SDepthSurface* depth) } +core::dimension2du CD3D9Driver::getMaxTextureSize() const +{ + return core::dimension2du(Caps.MaxTextureWidth, Caps.MaxTextureHeight); +} + + } // end namespace video } // end namespace irr @@ -2831,10 +3306,10 @@ namespace video #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ //! creates a video driver -IVideoDriver* createDirectX9Driver(const core::dimension2d& screenSize, +IVideoDriver* createDirectX9Driver(const core::dimension2d& screenSize, HWND window, u32 bits, bool fullscreen, bool stencilbuffer, io::IFileSystem* io, bool pureSoftware, bool highPrecisionFPU, - bool vsync, bool antiAlias) + bool vsync, u8 antiAlias) { CD3D9Driver* dx9 = new CD3D9Driver(screenSize, window, fullscreen, stencilbuffer, io, pureSoftware); if (!dx9->initDriver(screenSize, window, bits, fullscreen, pureSoftware, highPrecisionFPU, vsync, antiAlias)) diff --git a/src/dep/src/irrlicht/CD3D9Driver.h b/src/dep/src/irrlicht/CD3D9Driver.h index 545a685..98ccd99 100644 --- a/src/dep/src/irrlicht/CD3D9Driver.h +++ b/src/dep/src/irrlicht/CD3D9Driver.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -16,7 +16,10 @@ #include "CNullDriver.h" #include "IMaterialRendererServices.h" -#include "d3d9.h" +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#include "irrMath.h" // needed by borland for sqrtf define +#endif +#include namespace irr { @@ -24,23 +27,30 @@ namespace video { struct SDepthSurface : public IReferenceCounted { - SDepthSurface() : Surface(0) {} - ~SDepthSurface() + SDepthSurface() : Surface(0) + { + #ifdef _DEBUG + setDebugName("SDepthSurface"); + #endif + } + virtual ~SDepthSurface() { if (Surface) Surface->Release(); } IDirect3DSurface9* Surface; - core::dimension2di Size; + core::dimension2du Size; }; class CD3D9Driver : public CNullDriver, IMaterialRendererServices { public: + friend class CD3D9Texture; + //! constructor - CD3D9Driver(const core::dimension2d& screenSize, HWND window, bool fullscreen, + CD3D9Driver(const core::dimension2d& screenSize, HWND window, bool fullscreen, bool stencibuffer, io::IFileSystem* io, bool pureSoftware=false); //! destructor @@ -49,7 +59,7 @@ namespace video //! applications must call this method before performing any rendering. returns false if failed. virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! applications must call this method after performing any rendering. returns false if failed. @@ -66,7 +76,12 @@ namespace video //! sets a render target virtual bool setRenderTarget(video::ITexture* texture, - bool clearBackBuffer=false, bool clearZBuffer=false, + bool clearBackBuffer=true, bool clearZBuffer=true, + SColor color=video::SColor(0,0,0,0)); + + //! Sets multiple render targets + virtual bool setRenderTarget(const core::array& texture, + bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)); //! sets a viewport @@ -77,7 +92,10 @@ namespace video struct SHWBufferLink_d3d9 : public SHWBufferLink { - SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer): SHWBufferLink(_MeshBuffer), vertexBuffer(0), indexBuffer(0){} + SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer): + SHWBufferLink(_MeshBuffer), + vertexBuffer(0), indexBuffer(0), + vertexBufferSize(0), indexBufferSize(0) {} IDirect3DVertexBuffer9* vertexBuffer; IDirect3DIndexBuffer9* indexBuffer; @@ -104,7 +122,14 @@ namespace video //! draws a vertex primitive list virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, - E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType); + + //! draws a vertex primitive list in 2d + virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType); //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, @@ -116,6 +141,14 @@ namespace video const core::rect& sourceRect, const core::rect* clipRect = 0, const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false); + //! Draws a set of 2d images, using a color and the alpha channel of the texture. + virtual void draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect=0, + SColor color=SColor(255,255,255,255), + bool useAlphaChannelOfTexture=false); + //!Draws an 2d rectangle with a gradient. virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, @@ -134,9 +167,9 @@ namespace video const core::vector3df& end, SColor color = SColor(255,255,255,255)); //! initialises the Direct3D API - bool initDriver(const core::dimension2d& screenSize, HWND hwnd, + bool initDriver(const core::dimension2d& screenSize, HWND hwnd, u32 bits, bool fullScreen, bool pureSoftware, - bool highPrecisionFPU, bool vsync, bool antiAlias); + bool highPrecisionFPU, bool vsync, u8 antiAlias); //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8.1". @@ -145,8 +178,15 @@ namespace video //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); - //! adds a dynamic light - virtual void addDynamicLight(const SLight& light); + //! adds a dynamic light, returning an index to the light + //! \param light: the light data to use to create the light + //! \return An index to the light, or -1 if an error occurs + virtual s32 addDynamicLight(const SLight& light); + + //! Turns a dynamic light on or off + //! \param lightIndex: the index returned by addDynamicLight + //! \param turnOn: true to turn the light on, false to turn it off + virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; @@ -175,12 +215,12 @@ namespace video virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled); //! Sets the fog mode. - virtual void setFog(SColor color, bool linearFog, f32 start, + virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog); //! Only used by the internal engine. Used to notify the driver that //! the window was resized. - virtual void OnResize(const core::dimension2d& size); + virtual void OnResize(const core::dimension2d& size); //! Can be called by an IMaterialRenderer to make its work easier. virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, @@ -204,16 +244,13 @@ namespace video //! Sets a constant for the pixel shader based on a name. virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); - //! Returns pointer to the IGPUProgrammingServices interface. - virtual IGPUProgrammingServices* getGPUProgrammingServices(); - //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) virtual IVideoDriver* getVideoDriver(); //! Creates a render target texture. - virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Clears the ZBuffer. virtual void clearZBuffer(); @@ -228,7 +265,10 @@ namespace video virtual void enableClipPlane(u32 index, bool enable); //! Returns the graphics card vendor name. - virtual core::stringc getVendorInfo() {return vendorName;} + virtual core::stringc getVendorInfo() {return VendorName;} + + //! Enable the 2d override material + virtual void enableMaterial2D(bool enable=true); //! Check if the driver was recently reset. virtual bool checkDriverReset() {return DriverWasReset;} @@ -240,6 +280,9 @@ namespace video /** \return Color format of the color buffer. */ virtual ECOLOR_FORMAT getColorFormat() const; + //! Returns the maximum texture size supported. + virtual core::dimension2du getMaxTextureSize() const; + //! Get the current color format of the color buffer /** \return Color format of the color buffer as D3D color value. */ D3DFORMAT getD3DColorFormat() const; @@ -279,21 +322,21 @@ namespace video void setRenderStatesStencilShadowMode(bool zfail); //! sets the current Texture - bool setTexture(s32 stage, const video::ITexture* texture); + bool setActiveTexture(u32 stage, const video::ITexture* texture); //! resets the device bool reset(); //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); //! returns the current size of the screen or rendertarget - virtual const core::dimension2d& getCurrentRenderTargetSize() const; + virtual const core::dimension2d& getCurrentRenderTargetSize() const; //! Check if a proper depth buffer for the RTT is available, otherwise create it. void checkDepthBuffer(ITexture* tex); - + //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, @@ -304,17 +347,30 @@ namespace video //! language. virtual s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, - const c8* vertexShaderEntryPointName = "main", - E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, - const c8* pixelShaderProgram = 0, - const c8* pixelShaderEntryPointName = "main", - E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const c8* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); void createMaterialRenderers(); + void draw2D3DVertexPrimitiveList(const void* vertices, + u32 vertexCount, const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType, bool is3D); + + D3DTEXTUREADDRESS getTextureWrapMode(const u8 clamp); + inline D3DCOLORVALUE colorToD3D(const SColor& col) { const f32 f = 1.0f / 255.0f; @@ -333,6 +389,7 @@ namespace video bool ResetRenderStates; // bool to make all renderstates be reseted if set. bool Transformation3DChanged; bool StencilBuffer; + u8 AntiAliasing; const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES]; bool LastTextureMipMapsAvailable[MATERIAL_MAX_TEXTURES]; core::matrix4 Matrices[ETS_COUNT]; // matrizes of the 3d mode we need to restore when we switch back from the 2d mode. @@ -342,10 +399,10 @@ namespace video IDirect3DDevice9* pID3DDevice; IDirect3DSurface9* PrevRenderTarget; - core::dimension2d CurrentRendertargetSize; - core::dimension2d CurrentDepthBufferSize; + core::dimension2d CurrentRendertargetSize; + core::dimension2d CurrentDepthBufferSize; - void* WindowId; + HWND WindowId; core::rect* SceneSourceRect; D3DCAPS9 Caps; @@ -354,7 +411,8 @@ namespace video SColorf AmbientLight; - core::stringc vendorName; + core::stringc VendorName; + u16 VendorID; core::array DepthBuffers; @@ -363,11 +421,21 @@ namespace video f32 MaxLightDistance; s32 LastSetLight; + enum E_CACHE_2D_ATTRIBUTES + { + EC2D_ALPHA = 0x1, + EC2D_TEXTURE = 0x2, + EC2D_ALPHA_CHANNEL = 0x4 + }; + + u32 Cached2DModeSignature; + ECOLOR_FORMAT ColorFormat; D3DFORMAT D3DColorFormat; bool DeviceLost; bool Fullscreen; bool DriverWasReset; + bool AlphaToCoverageSupport; }; diff --git a/src/dep/src/irrlicht/CD3D9HLSLMaterialRenderer.cpp b/src/dep/src/irrlicht/CD3D9HLSLMaterialRenderer.cpp index 46cdeaf..63a94ba 100644 --- a/src/dep/src/irrlicht/CD3D9HLSLMaterialRenderer.cpp +++ b/src/dep/src/irrlicht/CD3D9HLSLMaterialRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,20 +18,20 @@ namespace irr { -namespace video +namespace video { //! Public constructor CD3D9HLSLMaterialRenderer::CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, - video::IVideoDriver* driver, s32& outMaterialTypeNr, + video::IVideoDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, - const c8* pixelShaderProgram, + const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, - IShaderConstantSetCallBack* callback, + IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : CD3D9ShaderMaterialRenderer(d3ddev, driver, callback, baseMaterial, userData), @@ -48,15 +48,15 @@ CD3D9HLSLMaterialRenderer::CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, if (vsCompileTarget < 0 || vsCompileTarget > EVST_COUNT) { - os::Printer::log("Invalid HLSL vertex shader compilation target"); + os::Printer::log("Invalid HLSL vertex shader compilation target", ELL_ERROR); return; } - if (!createHLSLVertexShader(vertexShaderProgram, + if (!createHLSLVertexShader(vertexShaderProgram, vertexShaderEntryPointName, VERTEX_SHADER_TYPE_NAMES[vsCompileTarget])) return; - if (!createHLSLPixelShader(pixelShaderProgram, + if (!createHLSLPixelShader(pixelShaderProgram, pixelShaderEntryPointName, PIXEL_SHADER_TYPE_NAMES[psCompileTarget])) return; @@ -64,7 +64,8 @@ CD3D9HLSLMaterialRenderer::CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, outMaterialTypeNr = Driver->addMaterialRenderer(this); } - //! Destructor + +//! Destructor CD3D9HLSLMaterialRenderer::~CD3D9HLSLMaterialRenderer() { if (VSConstantsTable) @@ -76,8 +77,8 @@ CD3D9HLSLMaterialRenderer::~CD3D9HLSLMaterialRenderer() bool CD3D9HLSLMaterialRenderer::createHLSLVertexShader(const char* vertexShaderProgram, - const char* shaderEntryPointName, - const char* shaderTargetName) + const char* shaderEntryPointName, + const char* shaderTargetName) { if (!vertexShaderProgram) return true; @@ -85,56 +86,55 @@ bool CD3D9HLSLMaterialRenderer::createHLSLVertexShader(const char* vertexShaderP LPD3DXBUFFER buffer = 0; LPD3DXBUFFER errors = 0; - #ifdef _IRR_D3D_NO_SHADER_DEBUGGING +#ifdef _IRR_D3D_NO_SHADER_DEBUGGING - // compile without debug info - - HRESULT h = stubD3DXCompileShader( - vertexShaderProgram, - strlen(vertexShaderProgram), - 0, // macros - 0, // no includes - shaderEntryPointName, - shaderTargetName, - 0, // no flags - &buffer, - &errors, - &VSConstantsTable); + // compile without debug info + HRESULT h = stubD3DXCompileShader( + vertexShaderProgram, + strlen(vertexShaderProgram), + 0, // macros + 0, // no includes + shaderEntryPointName, + shaderTargetName, + 0, // no flags + &buffer, + &errors, + &VSConstantsTable); - #else +#else - // compile shader and emitt some debug informations to - // make it possible to debug the shader in visual studio + // compile shader and emitt some debug informations to + // make it possible to debug the shader in visual studio - static int irr_dbg_hlsl_file_nr = 0; - ++irr_dbg_hlsl_file_nr; - char tmp[32]; - sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.vsh", irr_dbg_hlsl_file_nr); + static int irr_dbg_hlsl_file_nr = 0; + ++irr_dbg_hlsl_file_nr; + char tmp[32]; + sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.vsh", irr_dbg_hlsl_file_nr); - FILE* f = fopen(tmp, "wb"); - fwrite(vertexShaderProgram, strlen(vertexShaderProgram), 1, f); - fflush(f); - fclose(f); + FILE* f = fopen(tmp, "wb"); + fwrite(vertexShaderProgram, strlen(vertexShaderProgram), 1, f); + fflush(f); + fclose(f); - HRESULT h = stubD3DXCompileShaderFromFile( - tmp, - 0, // macros - 0, // no includes - shaderEntryPointName, - shaderTargetName, - D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, - &buffer, - &errors, - &VSConstantsTable); + HRESULT h = stubD3DXCompileShaderFromFile( + tmp, + 0, // macros + 0, // no includes + shaderEntryPointName, + shaderTargetName, + D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, + &buffer, + &errors, + &VSConstantsTable); - #endif +#endif if (FAILED(h)) { - os::Printer::log("HLSL vertex shader compilation failed:"); + os::Printer::log("HLSL vertex shader compilation failed:", ELL_ERROR); if (errors) { - os::Printer::log((c8*)errors->GetBufferPointer()); + os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); errors->Release(); if (buffer) buffer->Release(); @@ -150,7 +150,7 @@ bool CD3D9HLSLMaterialRenderer::createHLSLVertexShader(const char* vertexShaderP if (FAILED(pID3DDevice->CreateVertexShader((DWORD*)buffer->GetBufferPointer(), &VertexShader))) { - os::Printer::log("Could not create hlsl vertex shader."); + os::Printer::log("Could not create hlsl vertex shader.", ELL_ERROR); buffer->Release(); return false; } @@ -163,7 +163,7 @@ bool CD3D9HLSLMaterialRenderer::createHLSLVertexShader(const char* vertexShaderP } -bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderProgram, +bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderProgram, const char* shaderEntryPointName, const char* shaderTargetName) { @@ -172,25 +172,71 @@ bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderPro LPD3DXBUFFER buffer = 0; LPD3DXBUFFER errors = 0; - + + DWORD flags = 0; + +#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY + if (Driver->queryFeature(video::EVDF_VERTEX_SHADER_2_0) || Driver->queryFeature(video::EVDF_VERTEX_SHADER_3_0)) + // this one's for newer DX SDKs which don't support ps_1_x anymore + // instead they'll silently compile 1_x as 2_x when using this flag + flags |= D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY; +#endif +#if defined(_IRR_D3D_USE_LEGACY_HLSL_COMPILER) && defined(D3DXSHADER_USE_LEGACY_D3DX9_31_DLL) +#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY + else +#endif + flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL; +#endif + +#ifdef _IRR_D3D_NO_SHADER_DEBUGGING + + // compile without debug info HRESULT h = stubD3DXCompileShader( pixelShaderProgram, - strlen(pixelShaderProgram), + strlen(pixelShaderProgram), 0, // macros 0, // no includes shaderEntryPointName, shaderTargetName, - 0, // no flags (D3DXSHADER_DEBUG) + flags, &buffer, &errors, &PSConstantsTable); +#else + + // compile shader and emitt some debug informations to + // make it possible to debug the shader in visual studio + + static int irr_dbg_hlsl_file_nr = 0; + ++irr_dbg_hlsl_file_nr; + char tmp[32]; + sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.psh", irr_dbg_hlsl_file_nr); + + FILE* f = fopen(tmp, "wb"); + fwrite(pixelShaderProgram, strlen(pixelShaderProgram), 1, f); + fflush(f); + fclose(f); + + HRESULT h = stubD3DXCompileShaderFromFile( + tmp, + 0, // macros + 0, // no includes + shaderEntryPointName, + shaderTargetName, + flags | D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, + &buffer, + &errors, + &PSConstantsTable); + +#endif + if (FAILED(h)) { - os::Printer::log("HLSL pixel shader compilation failed:"); + os::Printer::log("HLSL pixel shader compilation failed:", ELL_ERROR); if (errors) { - os::Printer::log((c8*)errors->GetBufferPointer()); + os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); errors->Release(); if (buffer) buffer->Release(); @@ -206,7 +252,7 @@ bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderPro if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)buffer->GetBufferPointer(), &PixelShader))) { - os::Printer::log("Could not create hlsl pixel shader."); + os::Printer::log("Could not create hlsl pixel shader.", ELL_ERROR); buffer->Release(); return false; } @@ -219,14 +265,14 @@ bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderPro } -bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name, - const f32* floats, int count) +bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name, + const f32* floats, int count) { LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable; if (!tbl) return false; - // currently we only support top level parameters. + // currently we only support top level parameters. // Should be enough for the beginning. (TODO) D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name); @@ -250,6 +296,7 @@ bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name, return true; } + bool CD3D9HLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { if (VSConstantsTable) @@ -258,9 +305,10 @@ bool CD3D9HLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_V return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype); } + void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table) { - // currently we only support top level parameters. + // currently we only support top level parameters. // Should be enough for the beginning. (TODO) // print out constant names @@ -268,7 +316,7 @@ void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table) HRESULT hr = table->GetDesc(&tblDesc); if (!FAILED(hr)) { - for (int i=0; i<(int)tblDesc.Constants; ++i) + for (int i=0; i<(int)tblDesc.Constants; ++i) { D3DXCONSTANT_DESC d; UINT n = 1; @@ -293,4 +341,3 @@ void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table) } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ - diff --git a/src/dep/src/irrlicht/CD3D9HLSLMaterialRenderer.h b/src/dep/src/irrlicht/CD3D9HLSLMaterialRenderer.h index ed63b09..1abb8eb 100644 --- a/src/dep/src/irrlicht/CD3D9HLSLMaterialRenderer.h +++ b/src/dep/src/irrlicht/CD3D9HLSLMaterialRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CD3D9MaterialRenderer.h b/src/dep/src/irrlicht/CD3D9MaterialRenderer.h index e85c17d..4f54de8 100644 --- a/src/dep/src/irrlicht/CD3D9MaterialRenderer.h +++ b/src/dep/src/irrlicht/CD3D9MaterialRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,10 @@ #ifdef _IRR_WINDOWS_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ -#include "d3d9.h" +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#include "irrMath.h" // needed by borland for sqrtf define +#endif +#include #include "IMaterialRenderer.h" @@ -99,7 +102,8 @@ public: E_BLEND_FACTOR srcFact,dstFact; E_MODULATE_FUNC modulate; - unpack_texureBlendFunc ( srcFact, dstFact, modulate, material.MaterialTypeParam ); + u32 alphaSource; + unpack_texureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam ); if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO) { @@ -116,10 +120,24 @@ public: pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - if ( getTexelAlpha ( srcFact ) + getTexelAlpha ( dstFact ) ) + if ( textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) ) { - pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + if (alphaSource==EAS_VERTEX_COLOR) + { + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + } + else if (alphaSource==EAS_TEXTURE) + { + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + } + else + { + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + } } else { @@ -134,6 +152,16 @@ public: } + //! Returns if the material is transparent. + /** The scene management needs to know this for being able to sort the + materials by opaque and transparent. + The return value could be optimized, but we'd need to know the + MaterialTypeParam for it. */ + virtual bool isTransparent() const + { + return true; + } + private: u32 getD3DBlend ( E_BLEND_FACTOR factor ) const @@ -156,20 +184,6 @@ public: return r; } - u32 getTexelAlpha ( E_BLEND_FACTOR factor ) const - { - u32 r = 0; - switch ( factor ) - { - case EBF_SRC_ALPHA: r = 1; break; - case EBF_ONE_MINUS_SRC_ALPHA: r = 1; break; - case EBF_DST_ALPHA: r = 1; break; - case EBF_ONE_MINUS_DST_ALPHA: r = 1; break; - case EBF_SRC_ALPHA_SATURATE: r = 1; break; - } - return r; - } - u32 getD3DModulate ( E_MODULATE_FUNC func ) const { u32 r = D3DTOP_MODULATE; @@ -365,7 +379,8 @@ public: pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255)); + // 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF + pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127); pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); } @@ -387,7 +402,7 @@ public: }; -//! material renderer for all kinds of linghtmaps +//! material renderer for all kinds of lightmaps class CD3D9MaterialRenderer_LIGHTMAP : public CD3D9MaterialRenderer { public: @@ -419,10 +434,10 @@ public: if (material.MaterialType == EMT_LIGHTMAP_ADD) pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); else - if (material.MaterialType == EMT_LIGHTMAP_M4) + if (material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4) pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE4X); else - if (material.MaterialType == EMT_LIGHTMAP_M2) + if (material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2) pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE2X); else pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); @@ -563,23 +578,22 @@ public: { if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { - pID3DDevice->SetTextureStageState (0, D3DTSS_COLOROP, D3DTOP_MODULATE); - pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - pID3DDevice->SetTransform( D3DTS_TEXTURE1, &SphereMapMatrixD3D9 ); - pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); - pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); - pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + pID3DDevice->SetTransform(D3DTS_TEXTURE1, &SphereMapMatrixD3D9 ); + pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); + pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); + pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); @@ -587,9 +601,9 @@ public: virtual void OnUnsetMaterial() { - pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); - pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1); - pID3DDevice->SetTransform( D3DTS_TEXTURE1, &UnitMatrixD3D9 ); + pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); + pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D9); } //! Returns if the material is transparent. The scene managment needs to know this diff --git a/src/dep/src/irrlicht/CD3D9NormalMapRenderer.cpp b/src/dep/src/irrlicht/CD3D9NormalMapRenderer.cpp index 3565aee..3013260 100644 --- a/src/dep/src/irrlicht/CD3D9NormalMapRenderer.cpp +++ b/src/dep/src/irrlicht/CD3D9NormalMapRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CD3D9NormalMapRenderer.h b/src/dep/src/irrlicht/CD3D9NormalMapRenderer.h index 800be4e..b28981d 100644 --- a/src/dep/src/irrlicht/CD3D9NormalMapRenderer.h +++ b/src/dep/src/irrlicht/CD3D9NormalMapRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,10 @@ #ifdef _IRR_WINDOWS_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ -#include "d3d9.h" +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#include "irrMath.h" // needed by borland for sqrtf define +#endif +#include #include "CD3D9ShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" diff --git a/src/dep/src/irrlicht/CD3D9ParallaxMapRenderer.cpp b/src/dep/src/irrlicht/CD3D9ParallaxMapRenderer.cpp index 2e216be..45174c6 100644 --- a/src/dep/src/irrlicht/CD3D9ParallaxMapRenderer.cpp +++ b/src/dep/src/irrlicht/CD3D9ParallaxMapRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -151,7 +151,7 @@ namespace video // Irrlicht Engine D3D9 render path normal map pixel shader version 2.0 const char D3D9_PARALLAX_MAP_PSH_20[] = - ";Irrlicht Engine 0.10 D3D9 render path parallax mapping pixel shader \n"\ + ";Irrlicht Engine D3D9 render path parallax mapping pixel shader \n"\ ";Input: \n"\ " \n"\ ";t0: color map texture coord \n"\ diff --git a/src/dep/src/irrlicht/CD3D9ParallaxMapRenderer.h b/src/dep/src/irrlicht/CD3D9ParallaxMapRenderer.h index a9975c6..f31fd31 100644 --- a/src/dep/src/irrlicht/CD3D9ParallaxMapRenderer.h +++ b/src/dep/src/irrlicht/CD3D9ParallaxMapRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,10 @@ #ifdef _IRR_WINDOWS_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ -#include "d3d9.h" +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#include "irrMath.h" // needed by borland for sqrtf define +#endif +#include #include "CD3D9ShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" @@ -40,6 +43,7 @@ public: //! Returns the render capability of the material. virtual s32 getRenderCapability() const; + virtual void OnSetMaterial(const SMaterial& material) { } virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); diff --git a/src/dep/src/irrlicht/CD3D9ShaderMaterialRenderer.cpp b/src/dep/src/irrlicht/CD3D9ShaderMaterialRenderer.cpp index 03cf69a..8b3c30c 100644 --- a/src/dep/src/irrlicht/CD3D9ShaderMaterialRenderer.cpp +++ b/src/dep/src/irrlicht/CD3D9ShaderMaterialRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -29,7 +29,6 @@ CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3dde : pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData) { - #ifdef _DEBUG setDebugName("CD3D9ShaderMaterialRenderer"); #endif @@ -44,18 +43,15 @@ CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3dde } - //! constructor only for use by derived classes who want to //! create a fall back material for example. CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, - video::IVideoDriver* driver, - IShaderConstantSetCallBack* callback, - IMaterialRenderer* baseMaterial, - s32 userData) + video::IVideoDriver* driver, + IShaderConstantSetCallBack* callback, + IMaterialRenderer* baseMaterial, s32 userData) : pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData) { - #ifdef _DEBUG setDebugName("CD3D9ShaderMaterialRenderer"); #endif @@ -68,8 +64,8 @@ CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3dde } -void CD3D9ShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, - const c8* pixelShaderProgram) +void CD3D9ShaderMaterialRenderer::init(s32& outMaterialTypeNr, + const c8* vertexShaderProgram, const c8* pixelShaderProgram) { outMaterialTypeNr = -1; @@ -86,7 +82,6 @@ void CD3D9ShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexS } - //! Destructor CD3D9ShaderMaterialRenderer::~CD3D9ShaderMaterialRenderer() { @@ -100,9 +95,10 @@ CD3D9ShaderMaterialRenderer::~CD3D9ShaderMaterialRenderer() PixelShader->Release(); if (BaseMaterial) - BaseMaterial->drop (); + BaseMaterial->drop(); } + bool CD3D9ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { // call callback to set shader constants @@ -112,6 +108,7 @@ bool CD3D9ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E return true; } + void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services) { @@ -124,14 +121,14 @@ void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material // set new vertex shader if (FAILED(pID3DDevice->SetVertexShader(VertexShader))) - os::Printer::log("Could not set vertex shader."); + os::Printer::log("Could not set vertex shader.", ELL_WARNING); } // set new pixel shader if (PixelShader) { if (FAILED(pID3DDevice->SetPixelShader(PixelShader))) - os::Printer::log("Could not set pixel shader."); + os::Printer::log("Could not set pixel shader.", ELL_WARNING); } if (BaseMaterial) @@ -145,6 +142,7 @@ void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } + void CD3D9ShaderMaterialRenderer::OnUnsetMaterial() { if (VertexShader) @@ -165,6 +163,7 @@ bool CD3D9ShaderMaterialRenderer::isTransparent() const return BaseMaterial ? BaseMaterial->isTransparent() : false; } + bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh) { if (!pxsh) @@ -178,7 +177,7 @@ bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh) #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile shader without debug info - stubD3DXAssembleShader(pxsh, strlen(pxsh), 0, 0, 0, &code, &errors); + stubD3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, 0, &code, &errors); #else // compile shader and emitt some debug informations to @@ -202,8 +201,8 @@ bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh) if (errors) { // print out compilation errors. - os::Printer::log("Pixel shader compilation failed:"); - os::Printer::log((c8*)errors->GetBufferPointer()); + os::Printer::log("Pixel shader compilation failed:", ELL_ERROR); + os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); if (code) code->Release(); @@ -214,7 +213,7 @@ bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh) if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader))) { - os::Printer::log("Could not create pixel shader."); + os::Printer::log("Could not create pixel shader.", ELL_ERROR); code->Release(); return false; } @@ -224,7 +223,6 @@ bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh) } - bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh) { if (!vtxsh) @@ -238,7 +236,7 @@ bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh) #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile shader without debug info - stubD3DXAssembleShader(vtxsh, strlen(vtxsh), 0, 0, 0, &code, &errors); + stubD3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, 0, &code, &errors); #else @@ -259,12 +257,11 @@ bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh) #endif - if (errors) { // print out compilation errors. - os::Printer::log("Vertex shader compilation failed:"); - os::Printer::log((c8*)errors->GetBufferPointer()); + os::Printer::log("Vertex shader compilation failed:", ELL_ERROR); + os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); if (code) code->Release(); @@ -275,7 +272,7 @@ bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh) if (!code || FAILED(pID3DDevice->CreateVertexShader((DWORD*)code->GetBufferPointer(), &VertexShader))) { - os::Printer::log("Could not create vertex shader."); + os::Printer::log("Could not create vertex shader.", ELL_ERROR); if (code) code->Release(); return false; @@ -285,10 +282,11 @@ bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh) return true; } -HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, - CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, - DWORD Flags, LPD3DXBUFFER* ppShader, - LPD3DXBUFFER* ppErrorMsgs) + +HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData, + UINT SrcDataLen, CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs) { // Because Irrlicht needs to be able to start up even without installed d3d dlls, it // needs to load external d3d dlls manually. examples for the dlls are: @@ -310,16 +308,16 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData, UI // invoke static linked function return D3DXAssembleShader(pSrcData, SrcDataLen, pDefines, pInclude, - Flags, ppShader, ppErrorMsgs); + Flags, ppShader, ppErrorMsgs); #else { // try to load shader functions from the dll and print error if failed. // D3DXAssembleShader signature typedef HRESULT (WINAPI *AssembleShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen, - CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, - DWORD Flags, LPD3DXBUFFER* ppShader, - LPD3DXBUFFER* ppErrorMsgs); + CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, + DWORD Flags, LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); static bool LoadFailed = false; static AssembleShaderFunction pFn = 0; @@ -327,7 +325,7 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData, UI if (!pFn && !LoadFailed) { // try to load dll - core::stringc strDllName = "d3dx9_"; + io::path strDllName = "d3dx9_"; strDllName += (int)D3DX_SDK_VERSION; strDllName += ".dll"; @@ -354,9 +352,10 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData, UI return 0; } + HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile, - CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, - LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs) + CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, + LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs) { // wondering what I'm doing here? // see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader() @@ -369,7 +368,7 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcF #endif // invoke static linked function - return D3DXAssembleShaderFromFile(pSrcFile, pDefines, pInclude, Flags, + return D3DXAssembleShaderFromFileA(pSrcFile, pDefines, pInclude, Flags, ppShader, ppErrorMsgs); #else { @@ -377,8 +376,8 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcF // D3DXAssembleShaderFromFileA signature typedef HRESULT (WINAPI *AssembleShaderFromFileFunction)(LPCSTR pSrcFile, - CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, - LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs); + CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, + LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs); static bool LoadFailed = false; static AssembleShaderFromFileFunction pFn = 0; @@ -386,7 +385,7 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcF if (!pFn && !LoadFailed) { // try to load dll - core::stringc strDllName = "d3dx9_"; + io::path strDllName = "d3dx9_"; strDllName += (int)D3DX_SDK_VERSION; strDllName += ".dll"; @@ -415,9 +414,9 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcF HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, - LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, - LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, - LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable) + LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, + LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable) { // wondering what I'm doing here? // see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader() @@ -437,9 +436,9 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT // D3DXCompileShader typedef HRESULT (WINAPI *D3DXCompileShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, - LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, - LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, - LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); + LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, + LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); static bool LoadFailed = false; static D3DXCompileShaderFunction pFn = 0; @@ -447,7 +446,7 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT if (!pFn && !LoadFailed) { // try to load dll - core::stringc strDllName = "d3dx9_"; + io::path strDllName = "d3dx9_"; strDllName += (int)D3DX_SDK_VERSION; strDllName += ".dll"; @@ -475,9 +474,9 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT } HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, - LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, - LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, - LPD3DXCONSTANTTABLE* ppConstantTable) + LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, + LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable) { // wondering what I'm doing here? // see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader() @@ -490,7 +489,7 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFi #endif // invoke static linked function - return D3DXCompileShaderFromFile(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable); + return D3DXCompileShaderFromFileA(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable); #else { // try to load shader functions from the dll and print error if failed. @@ -507,7 +506,7 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFi if (!pFn && !LoadFailed) { // try to load dll - core::stringc strDllName = "d3dx9_"; + io::path strDllName = "d3dx9_"; strDllName += (int)D3DX_SDK_VERSION; strDllName += ".dll"; @@ -539,4 +538,3 @@ HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFi } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ - diff --git a/src/dep/src/irrlicht/CD3D9ShaderMaterialRenderer.h b/src/dep/src/irrlicht/CD3D9ShaderMaterialRenderer.h index e0d8063..2d90885 100644 --- a/src/dep/src/irrlicht/CD3D9ShaderMaterialRenderer.h +++ b/src/dep/src/irrlicht/CD3D9ShaderMaterialRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,10 @@ #ifdef _IRR_WINDOWS_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ -#include "d3d9.h" +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#include "irrMath.h" // needed by borland for sqrtf define +#endif +#include #include #include "IMaterialRenderer.h" diff --git a/src/dep/src/irrlicht/CD3D9Texture.cpp b/src/dep/src/irrlicht/CD3D9Texture.cpp index dea1753..880c66c 100644 --- a/src/dep/src/irrlicht/CD3D9Texture.cpp +++ b/src/dep/src/irrlicht/CD3D9Texture.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -30,9 +30,10 @@ namespace video { //! rendertarget constructor -CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const char* name) +CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, + const io::path& name, const ECOLOR_FORMAT format) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), - TextureSize(size), ImageSize(size), Pitch(0), + TextureSize(size), ImageSize(size), Pitch(0), ColorFormat(ECF_UNKNOWN), HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true) { #ifdef _DEBUG @@ -43,22 +44,22 @@ CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& si if (Device) Device->AddRef(); - createRenderTarget(); + createRenderTarget(format); } //! constructor CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, - u32 flags, const char* name) + u32 flags, const io::path& name, void* mipmapData) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), -TextureSize(0,0), ImageSize(0,0), Pitch(0), -HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false) + TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN), + HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false) { #ifdef _DEBUG setDebugName("CD3D9Texture"); #endif - const bool generateMipLevels = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); Device=driver->getExposedVideoData().D3D9.D3DDev9; if (Device) @@ -68,22 +69,9 @@ HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false) { if (createTexture(flags, image)) { - if (copyTexture(image) && generateMipLevels) + if (copyTexture(image)) { - // create mip maps. - #ifdef _IRR_USE_D3DXFilterTexture_ - // The D3DXFilterTexture function seems to get linked wrong when - // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. - // So mipmapgeneration is replaced with my own bad generation - HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT); - if (FAILED(hr)) - os::Printer::log("Could not create direct3d mip map levels.", ELL_WARNING); - else - HasMipMaps = true; - #else - createMipMaps(); - HasMipMaps = true; - #endif + regenerateMipMapLevels(mipmapData); } } else @@ -105,29 +93,47 @@ CD3D9Texture::~CD3D9Texture() // we can release the surface. We only use the value of the pointer // hence it is safe to use the dropped pointer... if (DepthSurface) + { if (DepthSurface->drop()) Driver->removeDepthSurface(DepthSurface); + } if (Device) Device->Release(); } -void CD3D9Texture::createRenderTarget() +void CD3D9Texture::createRenderTarget(const ECOLOR_FORMAT format) { // are texture size restrictions there ? if(!Driver->queryFeature(EVDF_TEXTURE_NPOT)) { - TextureSize.Width = getTextureSizeFromSurfaceSize(TextureSize.Width); - TextureSize.Height = getTextureSizeFromSurfaceSize(TextureSize.Height); if (TextureSize != ImageSize) os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION); } + TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); - // get irrlicht format from backbuffer - ColorFormat = Driver->getColorFormat(); D3DFORMAT d3dformat = Driver->getD3DColorFormat(); - setPitch(d3dformat); + + if(ColorFormat == ECF_UNKNOWN) + { + // get irrlicht format from backbuffer + // (This will get overwritten by the custom format if it is provided, else kept.) + ColorFormat = Driver->getColorFormat(); + setPitch(d3dformat); + + // Use color format if provided. + if(format != ECF_UNKNOWN) + { + ColorFormat = format; + d3dformat = Driver->getD3DFormatFromColorFormat(format); + setPitch(d3dformat); // This will likely set pitch to 0 for now. + } + } + else + { + d3dformat = Driver->getD3DFormatFromColorFormat(ColorFormat); + } // create texture HRESULT hr; @@ -169,8 +175,8 @@ bool CD3D9Texture::createMipMaps(u32 level) Texture->GenerateMipSubLevels(); return true; } - // os::Printer::log("manual mipmap"); + // manual mipmap generation IDirect3DSurface9* upperSurface = 0; IDirect3DSurface9* lowerSurface = 0; @@ -258,18 +264,10 @@ bool CD3D9Texture::createMipMaps(u32 level) //! creates the hardware texture bool CD3D9Texture::createTexture(u32 flags, IImage * image) { - core::dimension2d optSize; ImageSize = image->getDimension(); - if (Driver->queryFeature(EVDF_TEXTURE_NPOT)) - optSize=ImageSize; - else - { - optSize.Width = getTextureSizeFromSurfaceSize(ImageSize.Width); - optSize.Height = getTextureSizeFromSurfaceSize(ImageSize.Height); - } + core::dimension2d optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); - HRESULT hr; D3DFORMAT format = D3DFMT_A1R5G5B5; switch(getTextureFormatFromFlags(flags)) @@ -323,7 +321,7 @@ bool CD3D9Texture::createTexture(u32 flags, IImage * image) } } - hr = Device->CreateTexture(optSize.Width, optSize.Height, + HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height, mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all) usage, // usage format, D3DPOOL_MANAGED , &Texture, NULL); @@ -385,30 +383,30 @@ bool CD3D9Texture::copyTexture(IImage * image) //! lock function -void* CD3D9Texture::lock(bool readOnly) +void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel) { if (!Texture) return 0; + MipLevelLocked=mipmapLevel; HRESULT hr; D3DLOCKED_RECT rect; if(!IsRenderTarget) { - hr = Texture->LockRect(0, &rect, 0, readOnly?D3DLOCK_READONLY:0); + hr = Texture->LockRect(mipmapLevel, &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 { - D3DSURFACE_DESC desc; - Texture->GetLevelDesc(0, &desc); if (!RTTSurface) { + // Make RTT surface large enough for all miplevels (including 0) + D3DSURFACE_DESC desc; + Texture->GetLevelDesc(0, &desc); hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0); if (FAILED(hr)) { @@ -418,7 +416,7 @@ void* CD3D9Texture::lock(bool readOnly) } IDirect3DSurface9 *surface = 0; - hr = Texture->GetSurfaceLevel(0, &surface); + hr = Texture->GetSurfaceLevel(mipmapLevel, &surface); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR); @@ -437,8 +435,8 @@ void* CD3D9Texture::lock(bool readOnly) os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR); return 0; } - return rect.pBits; } + return rect.pBits; } @@ -449,39 +447,26 @@ void CD3D9Texture::unlock() return; if (!IsRenderTarget) - Texture->UnlockRect(0); + Texture->UnlockRect(MipLevelLocked); else if (RTTSurface) RTTSurface->UnlockRect(); } //! Returns original size of the texture. -const core::dimension2d& CD3D9Texture::getOriginalSize() const +const core::dimension2d& CD3D9Texture::getOriginalSize() const { return ImageSize; } //! Returns (=size) of the texture. -const core::dimension2d& CD3D9Texture::getSize() const +const core::dimension2d& CD3D9Texture::getSize() const { return TextureSize; } -//! returns the size of a texture which would be the optimize size for rendering it -inline s32 CD3D9Texture::getTextureSizeFromSurfaceSize(s32 size) const -{ - s32 ts = 0x01; - - while(ts < size) - ts <<= 1; - - return ts; -} - - - //! returns driver type of texture (=the driver, who created the texture) E_DRIVER_TYPE CD3D9Texture::getDriverType() const { @@ -489,7 +474,6 @@ E_DRIVER_TYPE CD3D9Texture::getDriverType() const } - //! returns color format of texture ECOLOR_FORMAT CD3D9Texture::getColorFormat() const { @@ -497,7 +481,6 @@ ECOLOR_FORMAT CD3D9Texture::getColorFormat() const } - //! returns pitch of texture (in bytes) u32 CD3D9Texture::getPitch() const { @@ -505,7 +488,6 @@ u32 CD3D9Texture::getPitch() const } - //! returns the DIRECT3D9 Texture IDirect3DBaseTexture9* CD3D9Texture::getDX9Texture() const { @@ -607,10 +589,58 @@ void CD3D9Texture::copy32BitMipMap(char* src, char* tgt, //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void CD3D9Texture::regenerateMipMapLevels() +void CD3D9Texture::regenerateMipMapLevels(void* mipmapData) { - if (HasMipMaps) + if (mipmapData) + { + core::dimension2du size = TextureSize; + u32 level=0; + do + { + if (size.Width>1) + size.Width /=2; + if (size.Height>1) + size.Height /=2; + ++level; + IDirect3DSurface9* mipSurface = 0; + HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); + if (FAILED(hr) || !mipSurface) + { + os::Printer::log("Could not get mipmap level", ELL_WARNING); + return; + } + D3DSURFACE_DESC mipDesc; + mipSurface->GetDesc(&mipDesc); + D3DLOCKED_RECT miplr; + + // lock mipmap surface + if (FAILED(mipSurface->LockRect(&miplr, NULL, 0))) + { + mipSurface->Release(); + os::Printer::log("Could not lock texture", ELL_WARNING); + return; + } + + memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); + mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; + // unlock + mipSurface->UnlockRect(); + // release + mipSurface->Release(); + } while (size.Width != 1 || size.Height != 1); + } + else if (HasMipMaps) + { + // create mip maps. +#ifdef _IRR_USE_D3DXFilterTexture_ + // The D3DXFilterTexture function seems to get linked wrong when + // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. + // So mipmapgeneration is replaced with my own bad generation + HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT); + if (FAILED(hr)) +#endif createMipMaps(); + } } @@ -667,5 +697,3 @@ void CD3D9Texture::setPitch(D3DFORMAT d3dformat) } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ - - diff --git a/src/dep/src/irrlicht/CD3D9Texture.h b/src/dep/src/irrlicht/CD3D9Texture.h index b77ab04..07f189c 100644 --- a/src/dep/src/irrlicht/CD3D9Texture.h +++ b/src/dep/src/irrlicht/CD3D9Texture.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -10,7 +10,10 @@ #include "ITexture.h" #include "IImage.h" -#include "d3d9.h" +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#include "irrMath.h" // needed by borland for sqrtf define +#endif +#include namespace irr { @@ -29,25 +32,26 @@ public: //! constructor CD3D9Texture(IImage* image, CD3D9Driver* driver, - u32 flags, const char* name); + u32 flags, const io::path& name, void* mipmapData=0); //! rendertarget constructor - CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const char* name); + CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const io::path& name, + const ECOLOR_FORMAT format = ECF_UNKNOWN); //! destructor virtual ~CD3D9Texture(); //! lock function - virtual void* lock(bool readOnly = false); + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0); //! unlock function virtual void unlock(); //! Returns original size of the texture. - virtual const core::dimension2d& getOriginalSize() const; + virtual const core::dimension2d& getOriginalSize() const; //! Returns (=size) of the texture. - virtual const core::dimension2d& getSize() const; + virtual const core::dimension2d& getSize() const; //! returns driver type of texture (=the driver, who created the texture) virtual E_DRIVER_TYPE getDriverType() const; @@ -66,7 +70,7 @@ public: //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture - virtual void regenerateMipMapLevels(); + virtual void regenerateMipMapLevels(void* mipmapData=0); //! returns if it is a render target virtual bool isRenderTarget() const; @@ -77,10 +81,7 @@ public: private: friend class CD3D9Driver; - void createRenderTarget(); - - //! returns the size of a texture which would be the optimize size for rendering it - inline s32 getTextureSizeFromSurfaceSize(s32 size) const; + void createRenderTarget(const ECOLOR_FORMAT format = ECF_UNKNOWN); //! creates the hardware texture bool createTexture(u32 flags, IImage * image); @@ -107,9 +108,10 @@ private: IDirect3DSurface9* RTTSurface; CD3D9Driver* Driver; SDepthSurface* DepthSurface; - core::dimension2d TextureSize; - core::dimension2d ImageSize; + core::dimension2d TextureSize; + core::dimension2d ImageSize; s32 Pitch; + u32 MipLevelLocked; ECOLOR_FORMAT ColorFormat; bool HasMipMaps; diff --git a/src/dep/src/irrlicht/CDMFLoader.cpp b/src/dep/src/irrlicht/CDMFLoader.cpp index dc4147b..18ec514 100644 --- a/src/dep/src/irrlicht/CDMFLoader.cpp +++ b/src/dep/src/irrlicht/CDMFLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // @@ -13,7 +13,7 @@ See the header file for additional information including use and distribution rights. */ -#include "IrrCompileConfig.h" +#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DMF_LOADER_ #ifdef _DEBUG @@ -25,7 +25,7 @@ #include "ISceneManager.h" #include "IAttributes.h" #include "SAnimatedMesh.h" -#include "SMeshBufferLightMap.h" +#include "SSkinMeshBuffer.h" #include "irrString.h" #include "irrMath.h" #include "dmfsupport.h" @@ -46,6 +46,32 @@ CDMFLoader::CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys) } +void CDMFLoader::findFile(bool use_mat_dirs, const core::stringc& path, const core::stringc& matPath, core::stringc& filename) +{ + // path + texpath + full name + if (use_mat_dirs && FileSystem->existFile(path+matPath+filename)) + filename = path+matPath+filename; + // path + full name + else if (FileSystem->existFile(path+filename)) + filename = path+filename; + // path + texpath + base name + else if (use_mat_dirs && FileSystem->existFile(path+matPath+FileSystem->getFileBasename(filename))) + filename = path+matPath+FileSystem->getFileBasename(filename); + // path + base name + else if (FileSystem->existFile(path+FileSystem->getFileBasename(filename))) + filename = path+FileSystem->getFileBasename(filename); + // texpath + full name + else if (use_mat_dirs && FileSystem->existFile(matPath+filename)) + filename = matPath+filename; + // texpath + base name + else if (use_mat_dirs && FileSystem->existFile(matPath+FileSystem->getFileBasename(filename))) + filename = matPath+FileSystem->getFileBasename(filename); + // base name + else if (FileSystem->existFile(FileSystem->getFileBasename(filename))) + filename = FileSystem->getFileBasename(filename); +} + + /**Creates/loads an animated mesh from the file. \return Pointer to the created mesh. Returns 0 if loading failed. If you no longer need the mesh, you should call IAnimatedMesh::drop(). @@ -57,7 +83,8 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) video::IVideoDriver* driver = SceneMgr->getVideoDriver(); //Load stringlist - StringList dmfRawFile(file); + StringList dmfRawFile; + LoadFromFile(file, dmfRawFile); if (dmfRawFile.size()==0) return 0; @@ -69,23 +96,21 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) dmfHeader header; //load header + core::array materiali; if (GetDMFHeader(dmfRawFile, header)) { //let's set ambient light SceneMgr->setAmbientLight(header.dmfAmbient); //let's create the correct number of materials, vertices and faces - core::array materiali; dmfVert *verts=new dmfVert[header.numVertices]; dmfFace *faces=new dmfFace[header.numFaces]; //let's get the materials - const bool use_mat_dirs=SceneMgr->getParameters()->getAttributeAsBool(DMF_USE_MATERIALS_DIRS); - #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Loading materials", core::stringc(header.numMaterials).c_str()); #endif - GetDMFMaterials(dmfRawFile, materiali, header.numMaterials, use_mat_dirs); + GetDMFMaterials(dmfRawFile, materiali, header.numMaterials); //let's get vertices and faces #ifdef _IRR_DMF_DEBUG_ @@ -100,7 +125,7 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) for (i=0; iMaterial.MaterialType = video::EMT_LIGHTMAP_LIGHTING; buffer->Material.Wireframe = false; buffer->Material.Lighting = true; @@ -125,24 +150,47 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) verts[faces[i].firstVert+1].pos, verts[faces[i].firstVert+2].pos).getNormal().normalize(); - SMeshBufferLightMap * meshBuffer = (SMeshBufferLightMap*)mesh->getMeshBuffer( + SSkinMeshBuffer* meshBuffer = (SSkinMeshBuffer*)mesh->getMeshBuffer( faces[i].materialID); - const u32 base = meshBuffer->Vertices.size(); + const bool use2TCoords = meshBuffer->Vertices_2TCoords.size() || + materiali[faces[i].materialID].lightmapName.size(); + if (use2TCoords && meshBuffer->Vertices_Standard.size()) + meshBuffer->convertTo2TCoords(); + const u32 base = meshBuffer->Vertices_2TCoords.size()?meshBuffer->Vertices_2TCoords.size():meshBuffer->Vertices_Standard.size(); // Add this face's verts - u32 v; - for (v = 0; v < faces[i].numVerts; v++) + if (use2TCoords) { - const dmfVert& vv = verts[faces[i].firstVert + v]; - video::S3DVertex2TCoords vert(vv.pos, - normal, video::SColor(255,255,255,255), vv.tc, vv.lc); - if (materiali[faces[i].materialID].textureBlend==4 && - SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES)) + // make sure we have the proper type set + meshBuffer->VertexType=video::EVT_2TCOORDS; + for (u32 v = 0; v < faces[i].numVerts; v++) { - vert.TCoords.set(vv.tc.X,-vv.tc.Y); + const dmfVert& vv = verts[faces[i].firstVert + v]; + video::S3DVertex2TCoords vert(vv.pos, + normal, video::SColor(255,255,255,255), vv.tc, vv.lc); + if (materiali[faces[i].materialID].textureBlend==4 && + SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES)) + { + vert.TCoords.set(vv.tc.X,-vv.tc.Y); + } + meshBuffer->Vertices_2TCoords.push_back(vert); + } + } + else + { + for (u32 v = 0; v < faces[i].numVerts; v++) + { + const dmfVert& vv = verts[faces[i].firstVert + v]; + video::S3DVertex vert(vv.pos, + normal, video::SColor(255,255,255,255), vv.tc); + if (materiali[faces[i].materialID].textureBlend==4 && + SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES)) + { + vert.TCoords.set(vv.tc.X,-vv.tc.Y); + } + meshBuffer->Vertices_Standard.push_back(vert); } - meshBuffer->Vertices.push_back(vert); } // Now add the indices @@ -150,7 +198,7 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) // I do it this way instead of a simple fan because it usually // looks a lot better in wireframe, for example. u32 h = faces[i].numVerts - 1, l = 0, c; // High, Low, Center - for (v = 0; v < faces[i].numVerts - 2; v++) + for (u32 v = 0; v < faces[i].numVerts - 2; v++) { if (v & 1) // odd c = h - 1; @@ -168,172 +216,8 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) } } - //load textures and lightmaps in materials. - //don't worry if you receive a could not load texture, cause if you don't need - //a particular material in your scene it will be loaded and then destroyed. -#ifdef _IRR_DMF_DEBUG_ - os::Printer::log("Loading textures."); -#endif - for (i=0; igetParameters()->existsAttribute(DMF_TEXTURE_PATH) ) - path = SceneMgr->getParameters()->getAttributeAsString(DMF_TEXTURE_PATH); - else - path = FileSystem->getFileDir(file->getFileName()); - path += ('/'); - - //texture and lightmap - ITexture *tex = 0; - ITexture *lig = 0; - - //current buffer to apply material - SMeshBufferLightMap* buffer = (SMeshBufferLightMap*)mesh->getMeshBuffer(i); - - //Primary texture is normal - if (materiali[i].textureFlag==0) - { - if (materiali[i].textureBlend==4) - driver->setTextureCreationFlag(ETCF_ALWAYS_32_BIT,true); - if (FileSystem->existFile(path+materiali[i].textureName)) - tex = driver->getTexture((path+materiali[i].textureName).c_str()); - else if (FileSystem->existFile(path+FileSystem->getFileBasename(materiali[i].textureName))) - tex = driver->getTexture((path+FileSystem->getFileBasename(materiali[i].textureName)).c_str()); - else if (FileSystem->existFile(materiali[i].textureName)) - tex = driver->getTexture(materiali[i].textureName.c_str()); - else if (FileSystem->existFile(FileSystem->getFileBasename(materiali[i].textureName))) - tex = driver->getTexture(FileSystem->getFileBasename(materiali[i].textureName).c_str()); -#ifdef _IRR_DMF_DEBUG_ - else - os::Printer::log("Could not load texture", materiali[i].textureName.c_str()); -#endif // _IRR_DMF_DEBUG_ - } - //Primary texture is just a colour - else if(materiali[i].textureFlag==1) - { - SColor color(axtoi(materiali[i].textureName.c_str())); - - //just for compatibility with older Irrlicht versions - //to support transparent materials - if (color.getAlpha()!=255 && materiali[i].textureBlend==4) - driver->setTextureCreationFlag(ETCF_ALWAYS_32_BIT,true); - - CImage *immagine= new CImage(ECF_A8R8G8B8, - core::dimension2d(8,8)); - immagine->fill(color); - tex = driver->addTexture("", immagine); - immagine->drop(); - - //to support transparent materials - if(color.getAlpha()!=255 && materiali[i].textureBlend==4) - { - buffer->Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - buffer->Material.MaterialTypeParam =(((f32) (color.getAlpha()-1))/255.0f); - } - } - - //Lightmap is present - if (materiali[i].lightmapFlag == 0) - lig = driver->getTexture((path+materiali[i].lightmapName).c_str()); - else //no lightmap - { - buffer->Material.MaterialType = video::EMT_SOLID; - const f32 mult = 100.0f - header.dmfShadow; - buffer->Material.AmbientColor=header.dmfAmbient.getInterpolated(SColor(255,0,0,0),mult/100.f); - } - - if (materiali[i].textureBlend==4) - { - buffer->Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - buffer->Material.MaterialTypeParam = - SceneMgr->getParameters()->getAttributeAsFloat(DMF_ALPHA_CHANNEL_REF); - } - - //if texture is present mirror vertically owing to DeleD representation - if (tex && header.dmfVersion<1.1) - { - const core::dimension2d texsize = tex->getSize(); - void* pp = tex->lock(); - if (pp) - { - const video::ECOLOR_FORMAT format = tex->getColorFormat(); - if (format == video::ECF_A1R5G5B5) - { - s16* p = (s16*)pp; - s16 tmp=0; - for (s32 x=0; xunlock(); - tex->regenerateMipMapLevels(); - } - - //if lightmap is present mirror vertically owing to DeleD rapresentation - if (lig && header.dmfVersion<1.1) - { - const core::dimension2d ligsize=lig->getSize(); - void* pp = lig->lock(); - if (pp) - { - video::ECOLOR_FORMAT format = lig->getColorFormat(); - if (format == video::ECF_A1R5G5B5) - { - s16* p = (s16*)pp; - s16 tmp=0; - for (s32 x=0; xunlock(); - lig->regenerateMipMapLevels(); - } - - buffer->Material.setTexture(0, tex); - buffer->Material.setTexture(1, lig); - } - - delete verts; - delete faces; + delete [] verts; + delete [] faces; } // delete all buffers without geometry in it. @@ -349,6 +233,7 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) // Meshbuffer is empty -- drop it mesh->MeshBuffers[i]->drop(); mesh->MeshBuffers.erase(i); + materiali.erase(i); } else { @@ -356,6 +241,168 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) } } + + { + //load textures and lightmaps in materials. + //don't worry if you receive a could not load texture, cause if you don't need + //a particular material in your scene it will be loaded and then destroyed. +#ifdef _IRR_DMF_DEBUG_ + os::Printer::log("Loading textures."); +#endif + const bool use_mat_dirs=!SceneMgr->getParameters()->getAttributeAsBool(DMF_IGNORE_MATERIALS_DIRS); + + core::stringc path; + if ( SceneMgr->getParameters()->existsAttribute(DMF_TEXTURE_PATH) ) + path = SceneMgr->getParameters()->getAttributeAsString(DMF_TEXTURE_PATH); + else + path = FileSystem->getFileDir(file->getFileName()); + path += ('/'); + + for (i=0; igetMeshBufferCount(); i++) + { + //texture and lightmap + video::ITexture *tex = 0; + video::ITexture *lig = 0; + + //current buffer to apply material + video::SMaterial& mat = mesh->getMeshBuffer(i)->getMaterial(); + + //Primary texture is normal + if (materiali[i].textureFlag==0) + { + if (materiali[i].textureBlend==4) + driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true); + findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].textureName); + tex = driver->getTexture(materiali[i].textureName); + } + //Primary texture is just a colour + else if(materiali[i].textureFlag==1) + { + video::SColor color(axtoi(materiali[i].textureName.c_str())); + + //just for compatibility with older Irrlicht versions + //to support transparent materials + if (color.getAlpha()!=255 && materiali[i].textureBlend==4) + driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true); + + video::CImage *immagine= new video::CImage(video::ECF_A8R8G8B8, + core::dimension2d(8,8)); + immagine->fill(color); + tex = driver->addTexture("", immagine); + immagine->drop(); + + //to support transparent materials + if(color.getAlpha()!=255 && materiali[i].textureBlend==4) + { + mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + mat.MaterialTypeParam =(((f32) (color.getAlpha()-1))/255.0f); + } + } + + //Lightmap is present + if (materiali[i].lightmapFlag == 0) + { + findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].lightmapName); + lig = driver->getTexture(materiali[i].lightmapName); + } + else //no lightmap + { + mat.MaterialType = video::EMT_SOLID; + const f32 mult = 100.0f - header.dmfShadow; + mat.AmbientColor=header.dmfAmbient.getInterpolated(video::SColor(255,0,0,0),mult/100.f); + } + + if (materiali[i].textureBlend==4) + { + mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + mat.MaterialTypeParam = + SceneMgr->getParameters()->getAttributeAsFloat(DMF_ALPHA_CHANNEL_REF); + } + + //if texture is present mirror vertically owing to DeleD representation + if (tex && header.dmfVersion<1.1) + { + const core::dimension2d texsize = tex->getSize(); + void* pp = tex->lock(); + if (pp) + { + const video::ECOLOR_FORMAT format = tex->getColorFormat(); + if (format == video::ECF_A1R5G5B5) + { + s16* p = (s16*)pp; + s16 tmp=0; + for (u32 x=0; xunlock(); + tex->regenerateMipMapLevels(); + } + + //if lightmap is present mirror vertically owing to DeleD rapresentation + if (lig && header.dmfVersion<1.1) + { + const core::dimension2d ligsize=lig->getSize(); + void* pp = lig->lock(); + if (pp) + { + video::ECOLOR_FORMAT format = lig->getColorFormat(); + if (format == video::ECF_A1R5G5B5) + { + s16* p = (s16*)pp; + s16 tmp=0; + for (u32 x=0; xunlock(); + lig->regenerateMipMapLevels(); + } + + mat.setTexture(0, tex); + mat.setTexture(1, lig); + } + } + // create bounding box for (i = 0; i < mesh->MeshBuffers.size(); ++i) { @@ -377,9 +424,9 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) /** \brief Tell us if this file is able to be loaded by this class based on the file extension (e.g. ".bsp") \return true if file is loadable.*/ -bool CDMFLoader::isALoadableFileExtension(const c8* filename) const +bool CDMFLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".dmf") != 0; + return core::hasFileExtension ( filename, "dmf" ); } diff --git a/src/dep/src/irrlicht/CDMFLoader.h b/src/dep/src/irrlicht/CDMFLoader.h index 81d8443..34b292c 100644 --- a/src/dep/src/irrlicht/CDMFLoader.h +++ b/src/dep/src/irrlicht/CDMFLoader.h @@ -1,28 +1,28 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -// +// // This file was originally written by Salvatore Russo. -// I (Nikolaus Gebhardt) did some minor modifications changes to it and integrated +// I (Nikolaus Gebhardt) did some minor modifications changes to it and integrated // it into Irrlicht: // - removed STL dependency // - removed log file and replaced it with irrlicht logging // - adapted code formatting a bit to Irrlicht style // - removed memory leaks // Thanks a lot to Salvatore for his work on this and that he gave me -// his permission to add it into Irrlicht. +// his permission to add it into Irrlicht. /* CDMFLoader by Salvatore Russo Version 1.3 - + This loader is used to load DMF files in Irrlicht. Look at the documentation for a sample application. - + Parts of this code are from Murphy McCauley COCTLoader just like GetFaceNormal() or indexes creation routines and a routine to add faces. So please refer to COCTLoader.h to know more about rights granted. - + You can use this software as you wish but you must not remove these notes about license nor credits to others for parts of this code. */ @@ -52,14 +52,14 @@ namespace scene //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; /** creates/loads an animated mesh from the file. \return Pointer to the created mesh. Returns 0 if loading failed. If you no longer need the mesh, you should call IAnimatedMesh::drop(). See IReferenceCounted::drop() for more information.*/ virtual IAnimatedMesh* createMesh(io::IReadFile* file); - + /** loads dynamic lights present in this scene. Note that loaded lights from DeleD must have the suffix \b dynamic_ and must be \b pointlight. Irrlicht correctly loads specular color, diffuse color , position and distance of object affected by light. @@ -78,6 +78,8 @@ namespace scene bool mode = true); private: + void findFile(bool use_mat_dirs, const core::stringc& path, const core::stringc& matPath, core::stringc& filename); + ISceneManager* SceneMgr; io::IFileSystem* FileSystem; }; diff --git a/src/dep/src/irrlicht/CDefaultGUIElementFactory.cpp b/src/dep/src/irrlicht/CDefaultGUIElementFactory.cpp index e9e97f6..db73bd6 100644 --- a/src/dep/src/irrlicht/CDefaultGUIElementFactory.cpp +++ b/src/dep/src/irrlicht/CDefaultGUIElementFactory.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -26,6 +26,7 @@ #include "IGUITable.h" #include "IGUIToolbar.h" #include "IGUIWindow.h" +#include "IGUITreeView.h" namespace irr { @@ -92,7 +93,9 @@ IGUIElement* CDefaultGUIElementFactory::addGUIElement(EGUI_ELEMENT_TYPE type, IG case EGUIET_WINDOW: return Environment->addWindow(core::rect(0,0,100,100),false,0,parent); case EGUIET_SPIN_BOX: - return Environment->addSpinBox(L"0.0", core::rect(0,0,100,100), parent); + return Environment->addSpinBox(L"0.0", core::rect(0,0,100,100), true, parent); + case EGUIET_TREE_VIEW: + return Environment->addTreeView(core::rect(0,0,100,100),parent); default: return 0; } diff --git a/src/dep/src/irrlicht/CDefaultGUIElementFactory.h b/src/dep/src/irrlicht/CDefaultGUIElementFactory.h index 71c4f89..be73a77 100644 --- a/src/dep/src/irrlicht/CDefaultGUIElementFactory.h +++ b/src/dep/src/irrlicht/CDefaultGUIElementFactory.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CDefaultSceneNodeAnimatorFactory.cpp b/src/dep/src/irrlicht/CDefaultSceneNodeAnimatorFactory.cpp index d69bc6d..5cf68f9 100644 --- a/src/dep/src/irrlicht/CDefaultSceneNodeAnimatorFactory.cpp +++ b/src/dep/src/irrlicht/CDefaultSceneNodeAnimatorFactory.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CDefaultSceneNodeAnimatorFactory.h b/src/dep/src/irrlicht/CDefaultSceneNodeAnimatorFactory.h index 7a00b27..3852871 100644 --- a/src/dep/src/irrlicht/CDefaultSceneNodeAnimatorFactory.h +++ b/src/dep/src/irrlicht/CDefaultSceneNodeAnimatorFactory.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CDefaultSceneNodeFactory.cpp b/src/dep/src/irrlicht/CDefaultSceneNodeFactory.cpp index f2a7f68..f16a28e 100644 --- a/src/dep/src/irrlicht/CDefaultSceneNodeFactory.cpp +++ b/src/dep/src/irrlicht/CDefaultSceneNodeFactory.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -36,8 +36,11 @@ CDefaultSceneNodeFactory::CDefaultSceneNodeFactory(ISceneManager* mgr) SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_WATER_SURFACE, "waterSurface")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TERRAIN, "terrain")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_BOX, "skyBox")); + SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_DOME, "skyDome")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SHADOW_VOLUME, "shadowVolume")); - SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCT_TREE, "octTree")); + SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octree")); + // Legacy support + SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octTree")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MESH, "mesh")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_LIGHT, "light")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_EMPTY, "empty")); @@ -51,6 +54,7 @@ CDefaultSceneNodeFactory::CDefaultSceneNodeFactory(ISceneManager* mgr) // legacy, for version <= 1.4.x irr files SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_MAYA, "cameraMaya")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_FPS, "cameraFPS")); + SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_Q3SHADER_SCENE_NODE, "quake3Shader")); } @@ -68,7 +72,7 @@ ISceneNode* CDefaultSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, IScene case ESNT_WATER_SURFACE: return Manager->addWaterSurfaceSceneNode(0, 2.0f, 300.0f, 10.0f, parent); case ESNT_TERRAIN: - return Manager->addTerrainSceneNode((const char*)0, parent, -1, + return Manager->addTerrainSceneNode("", parent, -1, core::vector3df(0.0f,0.0f,0.0f), core::vector3df(0.0f,0.0f,0.0f), core::vector3df(1.0f,1.0f,1.0f), @@ -76,12 +80,14 @@ ISceneNode* CDefaultSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, IScene 4, ETPS_17, 0, true); case ESNT_SKY_BOX: return Manager->addSkyBoxSceneNode(0,0,0,0,0,0, parent); + case ESNT_SKY_DOME: + return Manager->addSkyDomeSceneNode(0, 16, 8, 0.9f, 2.0f, 1000.0f, parent); case ESNT_SHADOW_VOLUME: - return 0; - case ESNT_OCT_TREE: - return Manager->addOctTreeSceneNode((IMesh*)0, parent, -1, 128, true); + return 0; + case ESNT_OCTREE: + return Manager->addOctreeSceneNode((IMesh*)0, parent, -1, 128, true); case ESNT_MESH: - return Manager->addMeshSceneNode(0, parent, -1, core::vector3df(), + return Manager->addMeshSceneNode(0, parent, -1, core::vector3df(), core::vector3df(), core::vector3df(1,1,1), true); case ESNT_LIGHT: return Manager->addLightSceneNode(parent); @@ -134,7 +140,7 @@ ESCENE_NODE_TYPE CDefaultSceneNodeFactory::getCreateableSceneNodeType(u32 idx) c } -//! returns type name of a createable scene node type +//! returns type name of a createable scene node type const c8* CDefaultSceneNodeFactory::getCreateableSceneNodeTypeName(u32 idx) const { if (idx& size) +CDepthBuffer::CDepthBuffer(const core::dimension2d& size) : Buffer(0), Size(0,0) { #ifdef _DEBUG @@ -47,7 +47,7 @@ void CDepthBuffer::clear() #endif u32 zMaxValue; - zMaxValue = *(u32*) &zMax; + zMaxValue = IR(zMax); memset32 ( Buffer, zMaxValue, TotalSize ); } @@ -55,7 +55,7 @@ void CDepthBuffer::clear() //! sets the new size of the zbuffer -void CDepthBuffer::setSize(const core::dimension2d& size) +void CDepthBuffer::setSize(const core::dimension2d& size) { if (size == Size) return; @@ -73,7 +73,7 @@ void CDepthBuffer::setSize(const core::dimension2d& size) //! returns the size of the zbuffer -const core::dimension2d& CDepthBuffer::getSize() const +const core::dimension2d& CDepthBuffer::getSize() const { return Size; } @@ -91,7 +91,7 @@ namespace video { //! creates a ZBuffer -IDepthBuffer* createDepthBuffer(const core::dimension2d& size) +IDepthBuffer* createDepthBuffer(const core::dimension2d& size) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CDepthBuffer(size); @@ -99,7 +99,7 @@ IDepthBuffer* createDepthBuffer(const core::dimension2d& size) return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } - + } // end namespace video } // end namespace irr diff --git a/src/dep/src/irrlicht/CDepthBuffer.h b/src/dep/src/irrlicht/CDepthBuffer.h index 951ea3d..920c7a2 100644 --- a/src/dep/src/irrlicht/CDepthBuffer.h +++ b/src/dep/src/irrlicht/CDepthBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,7 +17,7 @@ namespace video public: //! constructor - CDepthBuffer(const core::dimension2d& size); + CDepthBuffer(const core::dimension2d& size); //! destructor virtual ~CDepthBuffer(); @@ -26,10 +26,10 @@ namespace video virtual void clear(); //! sets the new size of the zbuffer - virtual void setSize(const core::dimension2d& size); + virtual void setSize(const core::dimension2d& size); //! returns the size of the zbuffer - virtual const core::dimension2d& getSize() const; + virtual const core::dimension2d& getSize() const; //! locks the zbuffer virtual void* lock() @@ -52,11 +52,11 @@ namespace video private: u8* Buffer; - core::dimension2d Size; + core::dimension2d Size; u32 TotalSize; u32 Pitch; }; - + } // end namespace video } // end namespace irr diff --git a/src/dep/src/irrlicht/CDummyTransformationSceneNode.cpp b/src/dep/src/irrlicht/CDummyTransformationSceneNode.cpp index cfca942..93d02ad 100644 --- a/src/dep/src/irrlicht/CDummyTransformationSceneNode.cpp +++ b/src/dep/src/irrlicht/CDummyTransformationSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -29,7 +29,6 @@ const core::aabbox3d& CDummyTransformationSceneNode::getBoundingBox() const } - //! Returns a reference to the current relative transformation matrix. //! This is the matrix, this scene node uses instead of scale, translation //! and rotation. @@ -48,4 +47,3 @@ core::matrix4 CDummyTransformationSceneNode::getRelativeTransformation() const } // end namespace scene } // end namespace irr - diff --git a/src/dep/src/irrlicht/CDummyTransformationSceneNode.h b/src/dep/src/irrlicht/CDummyTransformationSceneNode.h index 42103e0..819980a 100644 --- a/src/dep/src/irrlicht/CDummyTransformationSceneNode.h +++ b/src/dep/src/irrlicht/CDummyTransformationSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CEmptySceneNode.cpp b/src/dep/src/irrlicht/CEmptySceneNode.cpp index 23d0271..09383ed 100644 --- a/src/dep/src/irrlicht/CEmptySceneNode.cpp +++ b/src/dep/src/irrlicht/CEmptySceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -49,16 +49,19 @@ const core::aabbox3d& CEmptySceneNode::getBoundingBox() const //! Creates a clone of this scene node and its children. ISceneNode* CEmptySceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { - if (!newParent) newParent = Parent; - if (!newManager) newManager = SceneManager; + if (!newParent) + newParent = Parent; + if (!newManager) + newManager = SceneManager; - CEmptySceneNode* nb = new CEmptySceneNode(newParent, + CEmptySceneNode* nb = new CEmptySceneNode(newParent, newManager, ID); nb->cloneMembers(this, newManager); nb->Box = Box; - nb->drop(); + if ( newParent ) + nb->drop(); return nb; } diff --git a/src/dep/src/irrlicht/CEmptySceneNode.h b/src/dep/src/irrlicht/CEmptySceneNode.h index 87729a6..fd39843 100644 --- a/src/dep/src/irrlicht/CEmptySceneNode.h +++ b/src/dep/src/irrlicht/CEmptySceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CFPSCounter.cpp b/src/dep/src/irrlicht/CFPSCounter.cpp index 21e4bb2..612dd6e 100644 --- a/src/dep/src/irrlicht/CFPSCounter.cpp +++ b/src/dep/src/irrlicht/CFPSCounter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CFPSCounter.h b/src/dep/src/irrlicht/CFPSCounter.h index 19f71a7..4f068cd 100644 --- a/src/dep/src/irrlicht/CFPSCounter.h +++ b/src/dep/src/irrlicht/CFPSCounter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CFileList.cpp b/src/dep/src/irrlicht/CFileList.cpp index cf1fc8a..cbfbe4e 100644 --- a/src/dep/src/irrlicht/CFileList.cpp +++ b/src/dep/src/irrlicht/CFileList.cpp @@ -1,183 +1,155 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CFileList.h" #include "IrrCompileConfig.h" #include "irrArray.h" -#include +#include "coreutil.h" -#if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) -#include -#include - -#include -#include -#include -#include -#endif - -#ifdef _IRR_WINDOWS_API_ - #if !defined ( _WIN32_WCE ) - #include - #include - #endif -#endif +#include "os.h" namespace irr { namespace io { +static const io::path emptyFileListEntry; -CFileList::CFileList() +CFileList::CFileList(const io::path& path, bool ignoreCase, bool ignorePaths) + : IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path) { #ifdef _DEBUG setDebugName("CFileList"); #endif - // -------------------------------------------- - // Windows version - #ifdef _IRR_WINDOWS_API_ - #if !defined ( _WIN32_WCE ) - char tmp[_MAX_PATH]; - _getcwd(tmp, _MAX_PATH); - Path = tmp; - - struct _finddata_t c_file; - long hFile; - FileEntry entry; - - if( (hFile = _findfirst( "*", &c_file )) != -1L ) - { - do - { - entry.Name = c_file.name; - entry.Size = c_file.size; - entry.isDirectory = (_A_SUBDIR & c_file.attrib) != 0; - Files.push_back(entry); - } - while( _findnext( hFile, &c_file ) == 0 ); - - _findclose( hFile ); - } - #endif - - //TODO add drives - //entry.Name = "E:\\"; - //entry.isDirectory = true; - //Files.push_back(entry); - #endif - - // -------------------------------------------- - // Linux version - #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) - - FileEntry entry; - - // Add default parent - even when at /, this is available - entry.Name = ".."; - entry.Size = 0; - entry.isDirectory = true; - Files.push_back(entry); - - // getting the CWD is rather complex as we do not know the size - // so try it until the call was successful - // Note that neither the first nor the second parameter may be 0 according to POSIX - u32 pathSize=256; - char *tmpPath = new char[pathSize]; - while ((pathSize < (1<<16)) && !(getcwd(tmpPath,pathSize))) - { - delete [] tmpPath; - pathSize *= 2; - tmpPath = new char[pathSize]; - } - if (!tmpPath) - return; - Path = tmpPath; - delete [] tmpPath; - // We use the POSIX compliant methods instead of scandir - DIR* dirHandle=opendir(Path.c_str()); - if (!dirHandle) - return; - - struct dirent *dirEntry; - while ((dirEntry=readdir(dirHandle))) - { - if((strcmp(dirEntry->d_name, ".")==0) || - (strcmp(dirEntry->d_name, "..")==0)) - continue; - entry.Name = dirEntry->d_name; - entry.Size = 0; - entry.isDirectory = false; - struct stat buf; - if (stat(dirEntry->d_name, &buf)==0) - { - entry.Size = buf.st_size; - entry.isDirectory = S_ISDIR(buf.st_mode); - } - #if !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__CYGWIN__) - // only available on some systems - else - { - entry.isDirectory = dirEntry->d_type == DT_DIR; - } - #endif - Files.push_back(entry); - } - closedir(dirHandle); - #endif - // sort the list on all platforms - Files.sort(); + Path.replace('\\', '/'); } +CFileList::~CFileList() +{ + Files.clear(); +} u32 CFileList::getFileCount() const { return Files.size(); } - -const c8* CFileList::getFileName(u32 index) const +void CFileList::sort() { - if (index < Files.size()) - return Files[index].Name.c_str(); - else - return 0; + Files.sort(); +} + +const io::path& CFileList::getFileName(u32 index) const +{ + if (index >= Files.size()) + return emptyFileListEntry; + + return Files[index].Name; } //! Gets the full name of a file in the list, path included, based on an index. -const c8* CFileList::getFullFileName(u32 index) +const io::path& CFileList::getFullFileName(u32 index) const { if (index >= Files.size()) - return 0; + return emptyFileListEntry; - if (Files[index].FullName.size() < Files[index].Name.size()) - { - // create full name - Files[index].FullName = Path; - - if (Path.size() > 3) - Files[index].FullName.append('/'); - - Files[index].FullName.append(Files[index].Name); - } - - return Files[index].FullName.c_str(); + return Files[index].FullName; } +//! adds a file or folder +u32 CFileList::addItem(const io::path& fullPath, u32 size, bool isDirectory, u32 id) +{ + SFileListEntry entry; + entry.Size = size; + entry.ID = id; + entry.Name = fullPath; + entry.Name.replace('\\', '/'); + entry.IsDirectory = isDirectory; + + // remove trailing slash + if (entry.Name.lastChar() == '/') + { + entry.IsDirectory = true; + entry.Name[entry.Name.size()-1] = 0; + entry.Name.validate(); + } + + if (IgnoreCase) + entry.Name.make_lower(); + + entry.FullName = entry.Name; + + core::deletePathFromFilename(entry.Name); + + if (IgnorePaths) + entry.FullName = entry.Name; + + //os::Printer::log(Path.c_str(), entry.FullName); + + Files.push_back(entry); + + return Files.size() - 1; +} + +//! Returns the ID of a file in the file list, based on an index. +u32 CFileList::getID(u32 index) const +{ + return index < Files.size() ? Files[index].ID : 0; +} bool CFileList::isDirectory(u32 index) const { bool ret = false; if (index < Files.size()) - ret = Files[index].isDirectory; + ret = Files[index].IsDirectory; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } +//! Returns the size of a file +u32 CFileList::getFileSize(u32 index) const +{ + return index < Files.size() ? Files[index].Size : 0; +} + + +//! Searches for a file or folder within the list, returns the index +s32 CFileList::findFile(const io::path& filename, bool isDirectory = false) const +{ + SFileListEntry entry; + entry.FullName = filename; + entry.IsDirectory = isDirectory; + + // swap + entry.FullName.replace('\\', '/'); + + // remove trailing slash + if (entry.Name.lastChar() == '/') + { + entry.IsDirectory = true; + entry.Name[ entry.Name.size()-1] = 0; + entry.Name.validate(); + } + + if (IgnoreCase) + entry.FullName.make_lower(); + + if (IgnorePaths) + core::deletePathFromFilename(entry.FullName); + + return Files.binary_search(entry); +} + +//! Returns the base path of the file list +const io::path& CFileList::getPath() const +{ + return Path; +} + } // end namespace irr } // end namespace io diff --git a/src/dep/src/irrlicht/CFileList.h b/src/dep/src/irrlicht/CFileList.h index 1ba1195..80d72f3 100644 --- a/src/dep/src/irrlicht/CFileList.h +++ b/src/dep/src/irrlicht/CFileList.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,63 +9,120 @@ #include "irrString.h" #include "irrArray.h" + namespace irr { namespace io { -/*! - FileSystem, which manages where files are, so that modules which - use the the io do not need to know where every file is located. -*/ +//! An entry in a list of files, can be a folder or a file. +struct SFileListEntry +{ + //! The name of the file + /** If this is a file or folder in the virtual filesystem and the archive + was created with the ignoreCase flag then the file name will be lower case. */ + io::path Name; + + //! The name of the file including the path + /** If this is a file or folder in the virtual filesystem and the archive was + created with the ignoreDirs flag then it will be the same as Name. */ + io::path FullName; + + //! The size of the file in bytes + u32 Size; + + //! The ID of the file in an archive + /** This is used to link the FileList entry to extra info held about this + file in an archive, which can hold things like data offset and CRC. */ + u32 ID; + + //! True if this is a folder, false if not. + bool IsDirectory; + + //! The == operator is provided so that CFileList can slowly search the list! + bool operator ==(const struct SFileListEntry& other) const + { + if (IsDirectory != other.IsDirectory) + return false; + + return FullName.equals_ignore_case(other.FullName); + } + + //! The < operator is provided so that CFileList can sort and quickly search the list. + bool operator <(const struct SFileListEntry& other) const + { + if (IsDirectory != other.IsDirectory) + return IsDirectory; + + return FullName.lower_ignore_case(other.FullName); + } +}; + + +//! Implementation of a file list class CFileList : public IFileList { public: - //! constructor - CFileList(); + // CFileList methods + + //! Constructor + /** \param path The path of this file archive */ + CFileList(const io::path& path, bool ignoreCase, bool ignorePaths); + + //! Destructor + virtual ~CFileList(); + + //! Add as a file or folder to the list + /** \param fullPath The file name including path, up to the root of the file list. + \param isDirectory True if this is a directory rather than a file. + \param size The size of the file in bytes. + \param id The ID of the file in the archive which owns it */ + virtual u32 addItem(const io::path& fullPath, u32 size, bool isDirectory, u32 id=0); + + //! Sorts the file list. You should call this after adding any items to the file list + virtual void sort(); //! Returns the amount of files in the filelist. - /** \return Amount of files and directories in the file list. */ virtual u32 getFileCount() const; //! Gets the name of a file in the list, based on an index. - /** \param index is the zero based index of the file which name should - be returned. The index has to be smaller than the amount getFileCount() returns. - \return The file name of the file. Returns 0, if an error occured. */ - virtual const c8* getFileName(u32 index) const; + virtual const io::path& getFileName(u32 index) const; //! Gets the full name of a file in the list, path included, based on an index. - virtual const c8* getFullFileName(u32 index); + virtual const io::path& getFullFileName(u32 index) const; - //! Returns of the file is a directory - /** \param index is the zero based index of the file which name should - be returned. The index has to be smaller than the amount getFileCount() returns. - \return True if the file is a directory, else false. */ + //! Returns the ID of a file in the file list, based on an index. + virtual u32 getID(u32 index) const; + + //! Returns true if the file is a directory virtual bool isDirectory(u32 index) const; -private: + //! Returns the size of a file + virtual u32 getFileSize(u32 index) const; - struct FileEntry - { - core::stringc Name; - core::stringc FullName; - long Size; - bool isDirectory; + //! Searches for a file or folder within the list, returns the index + virtual s32 findFile(const io::path& filename, bool isFolder) const; - bool operator <(const struct FileEntry& other) const - { - if ( isDirectory ^ other.isDirectory ) - return isDirectory; + //! Returns the base path of the file list + virtual const io::path& getPath() const; - return Name.lower_ignore_case ( other.Name ); - } - }; +protected: - core::stringc Path; - core::array< FileEntry > Files; + //! Ignore paths when adding or searching for files + bool IgnorePaths; + + //! Ignore case when adding or searching for files + bool IgnoreCase; + + //! Path to the file list + io::path Path; + + //! List of files + core::array Files; }; + } // end namespace irr } // end namespace io diff --git a/src/dep/src/irrlicht/CFileSystem.cpp b/src/dep/src/irrlicht/CFileSystem.cpp index 52899db..b4c91ea 100644 --- a/src/dep/src/irrlicht/CFileSystem.cpp +++ b/src/dep/src/irrlicht/CFileSystem.cpp @@ -1,29 +1,43 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h +#include "IrrCompileConfig.h" + #include "CFileSystem.h" #include "IReadFile.h" #include "IWriteFile.h" #include "CZipReader.h" +#include "CMountPointReader.h" #include "CPakReader.h" +#include "CNPKReader.h" +#include "CTarReader.h" #include "CFileList.h" #include "CXMLReader.h" #include "CXMLWriter.h" #include "stdio.h" #include "os.h" -#include "IrrCompileConfig.h" #include "CAttributes.h" -#include "CMemoryReadFile.h" +#include "CMemoryFile.h" +#include "CLimitReadFile.h" #if defined (_IRR_WINDOWS_API_) #if !defined ( _WIN32_WCE ) #include // for _chdir + #include // for _access + #include #endif #else - #include - #include - #include + #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) + #include + #include + #include + #include + #include + #include + #include + #include + #endif #endif namespace irr @@ -31,13 +45,36 @@ namespace irr namespace io { - //! constructor CFileSystem::CFileSystem() { #ifdef _DEBUG setDebugName("CFileSystem"); #endif + + setFileListSystem(FILESYSTEM_NATIVE); + //! reset current working directory + getWorkingDirectory(); + +#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ + ArchiveLoader.push_back(new CArchiveLoaderZIP(this)); +#endif + +#ifdef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ + ArchiveLoader.push_back(new CArchiveLoaderMount(this)); +#endif + +#ifdef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ + ArchiveLoader.push_back(new CArchiveLoaderPAK(this)); +#endif + +#ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ + ArchiveLoader.push_back(new CArchiveLoaderNPK(this)); +#endif + +#ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ + ArchiveLoader.push_back(new CArchiveLoaderTAR(this)); +#endif } @@ -46,201 +83,413 @@ CFileSystem::~CFileSystem() { u32 i; - for ( i=0; idrop(); + for ( i=0; i < FileArchives.size(); ++i) + { + FileArchives[i]->drop(); + } - for ( i=0; idrop(); - - for ( i= 0; idrop(); + for ( i=0; i < ArchiveLoader.size(); ++i) + { + ArchiveLoader[i]->drop(); + } } //! opens a file for read access -IReadFile* CFileSystem::createAndOpenFile(const c8* filename) +IReadFile* CFileSystem::createAndOpenFile(const io::path& filename) { IReadFile* file = 0; u32 i; - for ( i=0; iopenFile(filename); - if (file) - return file; - } - - for ( i = 0; iopenFile(filename); - if (file) - return file; - } - - for ( i = 0; iopenFile(filename); + file = FileArchives[i]->createAndOpenFile(filename); if (file) return file; } // Create the file using an absolute path so that it matches // the scheme used by CNullDriver::getTexture(). - return createReadFile(getAbsolutePath(filename).c_str()); + return createReadFile(getAbsolutePath(filename)); } //! Creates an IReadFile interface for treating memory like a file. -IReadFile* CFileSystem::createMemoryReadFile(void* memory, s32 len, - const c8* fileName, bool deleteMemoryWhenDropped) +IReadFile* CFileSystem::createMemoryReadFile(void* memory, s32 len, + const io::path& fileName, bool deleteMemoryWhenDropped) { if (!memory) return 0; else - return new CMemoryReadFile(memory, len, fileName, deleteMemoryWhenDropped); + return new CMemoryFile(memory, len, fileName, deleteMemoryWhenDropped); +} + + +//! Creates an IReadFile interface for reading files inside files +IReadFile* CFileSystem::createLimitReadFile(const io::path& fileName, + IReadFile* alreadyOpenedFile, long pos, long areaSize) +{ + if (!alreadyOpenedFile) + return 0; + else + return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName); +} + + +//! Creates an IReadFile interface for treating memory like a file. +IWriteFile* CFileSystem::createMemoryWriteFile(void* memory, s32 len, + const io::path& fileName, bool deleteMemoryWhenDropped) +{ + if (!memory) + return 0; + else + return new CMemoryFile(memory, len, fileName, deleteMemoryWhenDropped); } //! Opens a file for write access. -IWriteFile* CFileSystem::createAndWriteFile(const c8* filename, bool append) +IWriteFile* CFileSystem::createAndWriteFile(const io::path& filename, bool append) { return createWriteFile(filename, append); } -bool CFileSystem::addFolderFileArchive(const c8* filename, bool ignoreCase, bool ignorePaths) +//! Adds an external archive loader to the engine. +void CFileSystem::addArchiveLoader(IArchiveLoader* loader) { - CUnZipReader* zr = new CUnZipReader(this, filename, ignoreCase, ignorePaths); - if (zr) - UnZipFileSystems.push_back(zr); - #ifdef _DEBUG - else - { - os::Printer::log("Could not open file. Folderfile not added", filename, ELL_ERROR); - } - #endif + if (!loader) + return; - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return (zr!=0); + loader->grab(); + ArchiveLoader.push_back(loader); } -//! adds an zip archive to the filesystem -bool CFileSystem::addZipFileArchive(const c8* filename, bool ignoreCase, bool ignorePaths) +//! move the hirarchy of the filesystem. moves sourceIndex relative up or down +bool CFileSystem::moveFileArchive(u32 sourceIndex, s32 relative) { - CZipReader* zr = 0; - IReadFile* file = createAndOpenFile(filename); - if (file) + bool r = false; + const s32 dest = (s32) sourceIndex + relative; + const s32 dir = relative < 0 ? -1 : 1; + const s32 sourceEnd = ((s32) FileArchives.size() ) - 1; + IFileArchive *t; + + for (s32 s = (s32) sourceIndex;s != dest; s += dir) { - zr = new CZipReader(file, ignoreCase, ignorePaths); - if (zr) - ZipFileSystems.push_back(zr); + if (s < 0 || s > sourceEnd || s + dir < 0 || s + dir > sourceEnd) + continue; - file->drop(); + t = FileArchives[s + dir]; + FileArchives[s + dir] = FileArchives[s]; + FileArchives[s] = t; + r = true; } - #ifdef _DEBUG - else - os::Printer::log("Could not open file. Zipfile not added", filename, ELL_ERROR); - #endif - - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return (zr != 0); + return r; } -//! adds an pak archive to the filesystem -bool CFileSystem::addPakFileArchive(const c8* filename, bool ignoreCase, bool ignorePaths) +//! Adds an archive to the file system. +bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase, + bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType, + const core::stringc& password) { - CPakReader* zr = 0; - IReadFile* file = createAndOpenFile(filename); - if (file) - { - zr = new CPakReader(file, ignoreCase, ignorePaths); - if (zr) - PakFileSystems.push_back(zr); + IFileArchive* archive = 0; + bool ret = false; + u32 i; - file->drop(); + // check if the archive was already loaded + for (i = 0; i < FileArchives.size(); ++i) + { + if (getAbsolutePath(filename) == FileArchives[i]->getFileList()->getPath()) + { + if (password.size()) + FileArchives[i]->Password=password; + return true; + } + } + + // do we know what type it should be? + if (archiveType == EFAT_UNKNOWN || archiveType == EFAT_FOLDER) + { + // try to load archive based on file name + for (i = 0; i < ArchiveLoader.size(); ++i) + { + if (ArchiveLoader[i]->isALoadableFileFormat(filename)) + { + archive = ArchiveLoader[i]->createArchive(filename, ignoreCase, ignorePaths); + if (archive) + break; + } + } + + // try to load archive based on content + if (!archive) + { + io::IReadFile* file = createAndOpenFile(filename); + if (file) + { + for (i = 0; i < ArchiveLoader.size(); ++i) + { + file->seek(0); + if (ArchiveLoader[i]->isALoadableFileFormat(file)) + { + file->seek(0); + archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); + if (archive) + break; + } + } + file->drop(); + } + } } - #ifdef _DEBUG else - os::Printer::log("Could not open file. Pakfile not added", filename, ELL_ERROR); - #endif + { + // try to open archive based on archive loader type + + io::IReadFile* file = 0; + + for (i = 0; i < ArchiveLoader.size(); ++i) + { + if (ArchiveLoader[i]->isALoadableFileFormat(archiveType)) + { + // attempt to open file + if (!file) + file = createAndOpenFile(filename); + + // is the file open? + if (file) + { + // attempt to open archive + file->seek(0); + if (ArchiveLoader[i]->isALoadableFileFormat(file)) + { + file->seek(0); + archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); + if (archive) + break; + } + } + else + { + // couldn't open file + break; + } + } + } + + // if open, close the file + if (file) + file->drop(); + } + + if (archive) + { + FileArchives.push_back(archive); + if (password.size()) + archive->Password=password; + ret = true; + } + else + { + os::Printer::log("Could not create archive for", filename, ELL_ERROR); + } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return (zr != 0); + return ret; +} + + +//! removes an archive from the file system. +bool CFileSystem::removeFileArchive(u32 index) +{ + bool ret = false; + if (index < FileArchives.size()) + { + FileArchives[index]->drop(); + FileArchives.erase(index); + ret = true; + } + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return ret; +} + + +//! removes an archive from the file system. +bool CFileSystem::removeFileArchive(const io::path& filename) +{ + for (u32 i=0; i < FileArchives.size(); ++i) + { + if (filename == FileArchives[i]->getFileList()->getPath()) + return removeFileArchive(i); + } + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; +} + + +//! gets an archive +u32 CFileSystem::getFileArchiveCount() const +{ + return FileArchives.size(); +} + + +IFileArchive* CFileSystem::getFileArchive(u32 index) +{ + return index < getFileArchiveCount() ? FileArchives[index] : 0; } //! Returns the string of the current working directory -const c8* CFileSystem::getWorkingDirectory() +const io::path& CFileSystem::getWorkingDirectory() { -#ifdef _IRR_WINDOWS_API_ - #if !defined ( _WIN32_WCE ) - _getcwd(WorkingDirectory, FILE_SYSTEM_MAX_PATH); - #endif -#endif + EFileSystemType type = FileSystemType; -#if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) - getcwd(WorkingDirectory, (size_t)FILE_SYSTEM_MAX_PATH); -#endif - return WorkingDirectory; + if (type != FILESYSTEM_NATIVE) + { + type = FILESYSTEM_VIRTUAL; + } + else + { + #if defined(_IRR_WINDOWS_CE_PLATFORM_) + // does not need this + #elif defined(_IRR_WINDOWS_API_) + fschar_t tmp[_MAX_PATH]; + #if defined(_IRR_WCHAR_FILESYSTEM ) + _wgetcwd(tmp, _MAX_PATH); + WorkingDirectory[FILESYSTEM_NATIVE] = tmp; + WorkingDirectory[FILESYSTEM_NATIVE].replace(L'\\', L'/'); + #else + _getcwd(tmp, _MAX_PATH); + WorkingDirectory[FILESYSTEM_NATIVE] = tmp; + WorkingDirectory[FILESYSTEM_NATIVE].replace('\\', '/'); + #endif + #endif + + #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) + + // getting the CWD is rather complex as we do not know the size + // so try it until the call was successful + // Note that neither the first nor the second parameter may be 0 according to POSIX + + #if defined(_IRR_WCHAR_FILESYSTEM ) + u32 pathSize=256; + wchar_t *tmpPath = new wchar_t[pathSize]; + while ((pathSize < (1<<16)) && !(wgetcwd(tmpPath,pathSize))) + { + delete [] tmpPath; + pathSize *= 2; + tmpPath = new char[pathSize]; + } + if (tmpPath) + { + WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath; + delete [] tmpPath; + } + #else + u32 pathSize=256; + char *tmpPath = new char[pathSize]; + while ((pathSize < (1<<16)) && !(getcwd(tmpPath,pathSize))) + { + delete [] tmpPath; + pathSize *= 2; + tmpPath = new char[pathSize]; + } + if (tmpPath) + { + WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath; + delete [] tmpPath; + } + #endif + #endif + + WorkingDirectory[type].validate(); + } + + return WorkingDirectory[type]; } //! Changes the current Working Directory to the given string. -bool CFileSystem::changeWorkingDirectoryTo(const c8* newDirectory) +bool CFileSystem::changeWorkingDirectoryTo(const io::path& newDirectory) { bool success=false; -#ifdef _MSC_VER - #if !defined ( _WIN32_WCE ) - success=(_chdir(newDirectory) == 0); + + if (FileSystemType != FILESYSTEM_NATIVE) + { + WorkingDirectory[FILESYSTEM_VIRTUAL] = newDirectory; + flattenFilename(WorkingDirectory[FILESYSTEM_VIRTUAL], ""); + success = 1; + } + else + { + WorkingDirectory[FILESYSTEM_NATIVE] = newDirectory; + +#if defined(_IRR_WINDOWS_CE_PLATFORM_) + success = true; +#elif defined(_MSC_VER) + #if defined(_IRR_WCHAR_FILESYSTEM) + success=(_wchdir(newDirectory.c_str()) == 0); + #else + success=(_chdir(newDirectory.c_str()) == 0); #endif #else - success=(chdir(newDirectory) == 0); + success=(chdir(newDirectory.c_str()) == 0); #endif + } + return success; } -core::stringc CFileSystem::getAbsolutePath(const core::stringc& filename) const +io::path CFileSystem::getAbsolutePath(const io::path& filename) const { - c8 *p=0; - -#ifdef _IRR_WINDOWS_API_ - #if !defined ( _WIN32_WCE ) - c8 fpath[_MAX_PATH]; - p = _fullpath( fpath, filename.c_str(), _MAX_PATH); +#if defined(_IRR_WINDOWS_CE_PLATFORM_) + return filename; +#elif defined(_IRR_WINDOWS_API_) + fschar_t *p=0; + fschar_t fpath[_MAX_PATH]; + #if defined(_IRR_WCHAR_FILESYSTEM ) + p = _wfullpath(fpath, filename.c_str(), _MAX_PATH); + core::stringw tmp(p); + tmp.replace(L'\\', L'/'); + #else + p = _fullpath(fpath, filename.c_str(), _MAX_PATH); + core::stringc tmp(p); + tmp.replace('\\', '/'); #endif - + return tmp; #elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) + c8* p=0; c8 fpath[4096]; fpath[0]=0; p = realpath(filename.c_str(), fpath); if (!p) { - // content in fpath is undefined at this point - if ('0'==fpath[0]) // seems like fpath wasn't altered + // content in fpath is unclear at this point + if (!fpath[0]) // seems like fpath wasn't altered, use our best guess { - // at least remove a ./ prefix - if ('.'==filename[0] && '/'==filename[1]) - return filename.subString(2, filename.size()-2); - else - return filename; + io::path tmp(filename); + return flattenFilename(tmp); } else - return core::stringc(fpath); + return io::path(fpath); } - + if (filename[filename.size()-1]=='/') + return io::path(p)+"/"; + else + return io::path(p); +#else + return io::path(filename); #endif - - return core::stringc(p); } //! returns the directory part of a filename, i.e. all until the first //! slash or backslash, excluding it. If no directory path is prefixed, a '.' //! is returned. -core::stringc CFileSystem::getFileDir(const core::stringc& filename) const +io::path CFileSystem::getFileDir(const io::path& filename) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); @@ -256,17 +505,21 @@ core::stringc CFileSystem::getFileDir(const core::stringc& filename) const //! returns the base part of a filename, i.e. all except for the directory //! part. If no directory path is prefixed, the full name is returned. -core::stringc CFileSystem::getFileBasename(const core::stringc& filename, bool keepExtension) const +io::path CFileSystem::getFileBasename(const io::path& filename, bool keepExtension) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); const s32 lastBackSlash = filename.findLast('\\'); lastSlash = core::max_(lastSlash, lastBackSlash); + + // get number of chars after last dot s32 end = 0; if (!keepExtension) { + // take care to search only after last slash to check only for + // dots in the filename end = filename.findLast('.'); - if (end == -1) + if (end == -1 || end < lastSlash) end=0; else end = filename.size()-end; @@ -281,44 +534,228 @@ core::stringc CFileSystem::getFileBasename(const core::stringc& filename, bool k } -//! Creates a list of files and directories in the current working directory -IFileList* CFileSystem::createFileList() const +//! flatten a path and file name for example: "/you/me/../." becomes "/you" +io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root) const { - return new CFileList(); + directory.replace('\\', '/'); + if (directory.lastChar() != '/') + directory.append('/'); + + io::path dir; + io::path subdir; + + s32 lastpos = 0; + s32 pos = 0; + bool lastWasRealDir=false; + + while ((pos = directory.findNext('/', lastpos)) >= 0) + { + subdir = directory.subString(lastpos, pos - lastpos + 1); + + if (subdir == "../") + { + if (lastWasRealDir) + { + deletePathFromPath(dir, 2); + lastWasRealDir=(dir.size()!=0); + } + else + { + dir.append(subdir); + lastWasRealDir=false; + } + } + else if (subdir == "/") + { + dir = root; + } + else if (subdir != "./" ) + { + dir.append(subdir); + lastWasRealDir=true; + } + + lastpos = pos + 1; + } + directory = dir; + return directory; +} + + +//! Creates a list of files and directories in the current working directory +EFileSystemType CFileSystem::setFileListSystem(EFileSystemType listType) +{ + EFileSystemType current = FileSystemType; + FileSystemType = listType; + return current; +} + + +//! Creates a list of files and directories in the current working directory +IFileList* CFileSystem::createFileList() +{ + CFileList* r = 0; + io::path Path = getWorkingDirectory(); + Path.replace('\\', '/'); + if (Path.lastChar() != '/') + Path.append('/'); + + //! Construct from native filesystem + if (FileSystemType == FILESYSTEM_NATIVE) + { + // -------------------------------------------- + //! Windows version + #ifdef _IRR_WINDOWS_API_ + #if !defined ( _WIN32_WCE ) + + r = new CFileList(Path, true, false); + + struct _tfinddata_t c_file; + long hFile; + + if( (hFile = _tfindfirst( _T("*"), &c_file )) != -1L ) + { + do + { + r->addItem(Path + c_file.name, c_file.size, (_A_SUBDIR & c_file.attrib) != 0, 0); + } + while( _tfindnext( hFile, &c_file ) == 0 ); + + _findclose( hFile ); + } + #endif + + //TODO add drives + //entry.Name = "E:\\"; + //entry.isDirectory = true; + //Files.push_back(entry); + #endif + + // -------------------------------------------- + //! Linux version + #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) + + + r = new CFileList(Path, false, false); + + r->addItem(Path + "..", 0, true, 0); + + //! We use the POSIX compliant methods instead of scandir + DIR* dirHandle=opendir(Path.c_str()); + if (dirHandle) + { + struct dirent *dirEntry; + while ((dirEntry=readdir(dirHandle))) + { + u32 size = 0; + bool isDirectory = false; + + if((strcmp(dirEntry->d_name, ".")==0) || + (strcmp(dirEntry->d_name, "..")==0)) + { + continue; + } + struct stat buf; + if (stat(dirEntry->d_name, &buf)==0) + { + size = buf.st_size; + isDirectory = S_ISDIR(buf.st_mode); + } + #if !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__CYGWIN__) + // only available on some systems + else + { + isDirectory = dirEntry->d_type == DT_DIR; + } + #endif + + r->addItem(Path + dirEntry->d_name, size, isDirectory, 0); + } + closedir(dirHandle); + } + #endif + } + else + { + //! create file list for the virtual filesystem + r = new CFileList(Path, false, false); + + //! add relative navigation + SFileListEntry e2; + SFileListEntry e3; + + //! PWD + r->addItem(Path + ".", 0, true, 0); + + //! parent + r->addItem(Path + "..", 0, true, 0); + + //! merge archives + for (u32 i=0; i < FileArchives.size(); ++i) + { + const IFileList *merge = FileArchives[i]->getFileList(); + + for (u32 j=0; j < merge->getFileCount(); ++j) + { + if (core::isInSameDirectory(Path, merge->getFullFileName(j)) == 0) + { + r->addItem(merge->getFullFileName(j), merge->getFileSize(j), merge->isDirectory(j), 0); + } + } + } + } + + if (r) + r->sort(); + return r; +} + +//! Creates an empty filelist +IFileList* CFileSystem::createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) +{ + return new CFileList(path, ignoreCase, ignorePaths); } //! determines if a file exists and would be able to be opened. -bool CFileSystem::existFile(const c8* filename) const +bool CFileSystem::existFile(const io::path& filename) const { - u32 i; - - for (i=0; ifindFile(filename)!=-1) + for (u32 i=0; i < FileArchives.size(); ++i) + if (FileArchives[i]->getFileList()->findFile(filename)!=-1) return true; - for (i=0; ifindFile(filename)!=-1) - return true; - - for (i=0; ifindFile(filename)!=-1) - return true; - - FILE* f = fopen(filename, "rb"); - if (f) +#if defined(_IRR_WINDOWS_CE_PLATFORM_) +#if defined(_IRR_WCHAR_FILESYSTEM) + HANDLE hFile = CreateFileW(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); +#else + HANDLE hFile = CreateFileW(core::stringw(filename).c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); +#endif + if (hFile == INVALID_HANDLE_VALUE) + return false; + else { - fclose(f); + CloseHandle(hFile); return true; } - +#else _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return false; +#if defined(_MSC_VER) +#if defined(_IRR_WCHAR_FILESYSTEM) + return (_waccess(filename.c_str(), 0) != -1); +#else + return (_access(filename.c_str(), 0) != -1); +#endif +#elif defined(F_OK) + return (access(filename.c_str(), F_OK) != -1); +#else + return (access(filename.c_str(), 0) != -1); +#endif +#endif } //! Creates a XML Reader from a file. -IXMLReader* CFileSystem::createXMLReader(const c8* filename) +IXMLReader* CFileSystem::createXMLReader(const io::path& filename) { IReadFile* file = createAndOpenFile(filename); if (!file) @@ -341,7 +778,7 @@ IXMLReader* CFileSystem::createXMLReader(IReadFile* file) //! Creates a XML Reader from a file. -IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(const c8* filename) +IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(const io::path& filename) { IReadFile* file = createAndOpenFile(filename); if (!file) @@ -364,7 +801,7 @@ IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(IReadFile* file) //! Creates a XML Writer from a file. -IXMLWriter* CFileSystem::createXMLWriter(const c8* filename) +IXMLWriter* CFileSystem::createXMLWriter(const io::path& filename) { IWriteFile* file = createAndWriteFile(filename); IXMLWriter* writer = createXMLWriter(file); diff --git a/src/dep/src/irrlicht/CFileSystem.h b/src/dep/src/irrlicht/CFileSystem.h index 467d9dc..8f68ce2 100644 --- a/src/dep/src/irrlicht/CFileSystem.h +++ b/src/dep/src/irrlicht/CFileSystem.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -15,8 +15,7 @@ namespace io class CZipReader; class CPakReader; - class CUnZipReader; - const s32 FILE_SYSTEM_MAX_PATH = 1024; + class CMountPointReader; /*! FileSystem which uses normal files and one zipfile @@ -32,68 +31,93 @@ public: virtual ~CFileSystem(); //! opens a file for read access - virtual IReadFile* createAndOpenFile(const c8* filename); + virtual IReadFile* createAndOpenFile(const io::path& filename); //! Creates an IReadFile interface for accessing memory like a file. - virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const c8* fileName, bool deleteMemoryWhenDropped = false); + virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped = false); + + //! Creates an IReadFile interface for accessing files inside files + virtual IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize); + + //! Creates an IWriteFile interface for accessing memory like a file. + virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped=false); //! Opens a file for write access. - virtual IWriteFile* createAndWriteFile(const c8* filename, bool append=false); + virtual IWriteFile* createAndWriteFile(const io::path& filename, bool append=false); - //! adds an zip archive to the filesystem - virtual bool addZipFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true); - virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true); + //! Adds an archive to the file system. + virtual bool addFileArchive(const io::path& filename, + bool ignoreCase = true, bool ignorePaths = true, + E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN, + const core::stringc& password=""); - //! adds an pak archive to the filesystem - virtual bool addPakFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true); + //! move the hirarchy of the filesystem. moves sourceIndex relative up or down + virtual bool moveFileArchive( u32 sourceIndex, s32 relative ); + + //! Adds an external archive loader to the engine. + virtual void addArchiveLoader(IArchiveLoader* loader); + + //! gets the file archive count + virtual u32 getFileArchiveCount() const; + + //! gets an archive + virtual IFileArchive* getFileArchive(u32 index); + + //! removes an archive from the file system. + virtual bool removeFileArchive(u32 index); + + //! removes an archive from the file system. + virtual bool removeFileArchive(const io::path& filename); //! Returns the string of the current working directory - virtual const c8* getWorkingDirectory(); + virtual const io::path& getWorkingDirectory(); //! Changes the current Working Directory to the string given. //! The string is operating system dependent. Under Windows it will look //! like this: "drive:\directory\sudirectory\" - virtual bool changeWorkingDirectoryTo(const c8* newDirectory); + virtual bool changeWorkingDirectoryTo(const io::path& newDirectory); //! Converts a relative path to an absolute (unique) path, resolving symbolic links - virtual core::stringc getAbsolutePath(const core::stringc& filename) const; + virtual io::path getAbsolutePath(const io::path& filename) const; //! Returns the directory a file is located in. /** \param filename: The file to get the directory from */ - virtual core::stringc getFileDir(const core::stringc& filename) const; + virtual io::path getFileDir(const io::path& filename) const; //! Returns the base part of a filename, i.e. the name without the directory //! part. If no directory is prefixed, the full name is returned. /** \param filename: The file to get the basename from */ - core::stringc getFileBasename(const core::stringc& filename, bool keepExtension=true) const; + virtual io::path getFileBasename(const io::path& filename, bool keepExtension=true) const; - //! Creates a list of files and directories in the current working directory + //! flatten a path and file name for example: "/you/me/../." becomes "/you" + virtual io::path& flattenFilename( io::path& directory, const io::path& root = "/" ) const; + + virtual EFileSystemType setFileListSystem(EFileSystemType listType); + + //! Creates a list of files and directories in the current working directory //! and returns it. - virtual IFileList* createFileList() const; + virtual IFileList* createFileList(); - //! determinates if a file exists and would be able to be opened. - virtual bool existFile(const c8* filename) const; + //! Creates an empty filelist + virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths); //! determines if a file exists and would be able to be opened. - bool existFile(const core::stringc& filename) const - { - return existFile(filename.c_str()); - } + virtual bool existFile(const io::path& filename) const; //! Creates a XML Reader from a file. - virtual IXMLReader* createXMLReader(const c8* filename); + virtual IXMLReader* createXMLReader(const io::path& filename); //! Creates a XML Reader from a file. virtual IXMLReader* createXMLReader(IReadFile* file); //! Creates a XML Reader from a file. - virtual IXMLReaderUTF8* createXMLReaderUTF8(const c8* filename); + virtual IXMLReaderUTF8* createXMLReaderUTF8(const io::path& filename); //! Creates a XML Reader from a file. virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file); //! Creates a XML Writer from a file. - virtual IXMLWriter* createXMLWriter(const c8* filename); + virtual IXMLWriter* createXMLWriter(const io::path& filename); //! Creates a XML Writer from a file. virtual IXMLWriter* createXMLWriter(IWriteFile* file); @@ -103,10 +127,14 @@ public: private: - core::array ZipFileSystems; - core::array PakFileSystems; - core::array UnZipFileSystems; - c8 WorkingDirectory[FILE_SYSTEM_MAX_PATH]; + //! Currently used FileSystemType + EFileSystemType FileSystemType; + //! WorkingDirectory for Native and Virtual filesystems + io::path WorkingDirectory [2]; + //! currently attached ArchiveLoaders + core::array ArchiveLoader; + //! currently attached Archives + core::array FileArchives; }; diff --git a/src/dep/src/irrlicht/CGUIButton.cpp b/src/dep/src/irrlicht/CGUIButton.cpp index b4aedf4..595994d 100644 --- a/src/dep/src/irrlicht/CGUIButton.cpp +++ b/src/dep/src/irrlicht/CGUIButton.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,10 +18,11 @@ namespace gui //! constructor CGUIButton::CGUIButton(IGUIEnvironment* environment, IGUIElement* parent, - s32 id, core::rect rectangle, bool noclip) -: IGUIButton(environment, parent, id, rectangle), Pressed(false), - IsPushButton(false), UseAlphaChannel(false), Border(true), - ClickTime(0), SpriteBank(0), OverrideFont(0), Image(0), PressedImage(0) + s32 id, core::rect rectangle, bool noclip) +: IGUIButton(environment, parent, id, rectangle), + SpriteBank(0), OverrideFont(0), Image(0), PressedImage(0), + ClickTime(0), IsPushButton(false), Pressed(false), + UseAlphaChannel(false), DrawBorder(true), ScaleImage(false) { #ifdef _DEBUG setDebugName("CGUIButton"); @@ -55,10 +56,25 @@ CGUIButton::~CGUIButton() } +//! Sets if the images should be scaled to fit the button +void CGUIButton::setScaleImage(bool scaleImage) +{ + ScaleImage = scaleImage; +} + + +//! Returns whether the button scale the used images +bool CGUIButton::isScalingImage() const +{ + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return ScaleImage; +} + + //! Sets if the button should use the skin to draw its border void CGUIButton::setDrawBorder(bool border) { - Border = border; + DrawBorder = border; } @@ -99,8 +115,7 @@ bool CGUIButton::OnEvent(const SEvent& event) { case EET_KEY_INPUT_EVENT: if (event.KeyInput.PressedDown && - (event.KeyInput.Key == KEY_RETURN || - event.KeyInput.Key == KEY_SPACE)) + (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { if (!IsPushButton) setPressed(true); @@ -116,14 +131,13 @@ bool CGUIButton::OnEvent(const SEvent& event) } else if (!event.KeyInput.PressedDown && Pressed && - (event.KeyInput.Key == KEY_RETURN || - event.KeyInput.Key == KEY_SPACE)) + (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { //Environment->removeFocus(this); if (!IsPushButton) setPressed(false); - + if (Parent) { SEvent newEvent; @@ -147,7 +161,7 @@ bool CGUIButton::OnEvent(const SEvent& event) if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { if (Environment->hasFocus(this) && - !AbsoluteClippingRect.isPointInside(core::position2d(event.MouseInput.X, event.MouseInput.Y))) + !AbsoluteClippingRect.isPointInside(core::position2d(event.MouseInput.X, event.MouseInput.Y))) { Environment->removeFocus(this); return false; @@ -155,7 +169,7 @@ bool CGUIButton::OnEvent(const SEvent& event) if (!IsPushButton) setPressed(true); - + Environment->setFocus(this); return true; } @@ -178,7 +192,7 @@ bool CGUIButton::OnEvent(const SEvent& event) { setPressed(!Pressed); } - + if ((!IsPushButton && wasPressed && Parent) || (IsPushButton && wasPressed != Pressed)) { @@ -210,46 +224,43 @@ void CGUIButton::draw() IGUISkin* skin = Environment->getSkin(); video::IVideoDriver* driver = Environment->getVideoDriver(); - IGUIFont* font = OverrideFont; - if (!OverrideFont) - font = skin->getFont(EGDF_BUTTON); - - core::rect rect = AbsoluteRect; - // todo: move sprite up and text down if the pressed state has a sprite - // draw sprites for focused and mouse-over - core::position2di spritePos = AbsoluteRect.getCenter(); + // draw sprites for focused and mouse-over + const core::position2di spritePos = AbsoluteRect.getCenter(); if (!Pressed) { - if (Border) - skin->draw3DButtonPaneStandard(this, rect, &AbsoluteClippingRect); + if (DrawBorder) + skin->draw3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect); if (Image) { - core::position2d pos = AbsoluteRect.getCenter(); + core::position2d pos = spritePos; pos.X -= ImageRect.getWidth() / 2; pos.Y -= ImageRect.getHeight() / 2; - driver->draw2DImage(Image, pos, ImageRect, &AbsoluteClippingRect, - video::SColor(255,255,255,255), UseAlphaChannel); + driver->draw2DImage(Image, + ScaleImage? AbsoluteRect : + core::recti(pos, ImageRect.getSize()), + ImageRect, &AbsoluteClippingRect, + 0, UseAlphaChannel); } if (SpriteBank && ButtonSprites[EGBS_BUTTON_UP].Index != -1) { // draw pressed sprite - SpriteBank->draw2DSprite(ButtonSprites[EGBS_BUTTON_UP].Index, spritePos, - &AbsoluteClippingRect, ButtonSprites[EGBS_BUTTON_UP].Color, ClickTime, os::Timer::getTime(), + SpriteBank->draw2DSprite(ButtonSprites[EGBS_BUTTON_UP].Index, spritePos, + &AbsoluteClippingRect, ButtonSprites[EGBS_BUTTON_UP].Color, ClickTime, os::Timer::getTime(), ButtonSprites[EGBS_BUTTON_UP].Loop, true); } } else { - if (Border) - skin->draw3DButtonPanePressed(this, rect, &AbsoluteClippingRect); + if (DrawBorder) + skin->draw3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect); if (PressedImage) { - core::position2d pos = AbsoluteRect.getCenter(); + core::position2d pos = spritePos; pos.X -= PressedImageRect.getWidth() / 2; pos.Y -= PressedImageRect.getHeight() / 2; // patch by Alan Tyndall/Jonas Petersen @@ -258,30 +269,36 @@ void CGUIButton::draw() pos.X += 1; pos.Y += 1; } - driver->draw2DImage(PressedImage, pos, PressedImageRect, &AbsoluteClippingRect, - video::SColor(255,255,255,255), UseAlphaChannel); + driver->draw2DImage(PressedImage, + ScaleImage? AbsoluteRect : + core::recti(pos, PressedImageRect.getSize()), + PressedImageRect, &AbsoluteClippingRect, + 0, UseAlphaChannel); } if (SpriteBank && ButtonSprites[EGBS_BUTTON_DOWN].Index != -1) { // draw sprite - SpriteBank->draw2DSprite(ButtonSprites[EGBS_BUTTON_DOWN].Index, spritePos, - &AbsoluteClippingRect, ButtonSprites[EGBS_BUTTON_DOWN].Color, ClickTime, os::Timer::getTime(), + SpriteBank->draw2DSprite(ButtonSprites[EGBS_BUTTON_DOWN].Index, spritePos, + &AbsoluteClippingRect, ButtonSprites[EGBS_BUTTON_DOWN].Color, ClickTime, os::Timer::getTime(), ButtonSprites[EGBS_BUTTON_DOWN].Loop, true); } - } if (Text.size()) { - rect = AbsoluteRect; - if (Pressed) + IGUIFont* font = OverrideFont; + if (!OverrideFont) + font = skin->getFont(EGDF_BUTTON); + + core::rect rect = AbsoluteRect; + if (Pressed) rect.UpperLeftCorner.Y += 2; if (font) font->draw(Text.c_str(), rect, - skin->getColor(IsEnabled ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), true, true, - &AbsoluteClippingRect); + skin->getColor(IsEnabled ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), + true, true, &AbsoluteClippingRect); } IGUIElement::draw(); @@ -291,6 +308,9 @@ void CGUIButton::draw() //! sets another skin independent font. if this is set to zero, the button uses the font of the skin. void CGUIButton::setOverrideFont(IGUIFont* font) { + if (OverrideFont == font) + return; + if (OverrideFont) OverrideFont->drop(); @@ -301,9 +321,11 @@ void CGUIButton::setOverrideFont(IGUIFont* font) } -//! Sets an image which should be displayed on the button when it is in normal state. +//! Sets an image which should be displayed on the button when it is in normal state. void CGUIButton::setImage(video::ITexture* image) { + if (image) + image->grab(); if (Image) Image->drop(); @@ -311,9 +333,6 @@ void CGUIButton::setImage(video::ITexture* image) if (image) ImageRect = core::rect(core::position2d(0,0), image->getOriginalSize()); - if (Image) - Image->grab(); - if (!PressedImage) setPressedImage(Image); } @@ -322,46 +341,31 @@ void CGUIButton::setImage(video::ITexture* image) //! Sets the image which should be displayed on the button when it is in its normal state. void CGUIButton::setImage(video::ITexture* image, const core::rect& pos) { - if (Image) - Image->drop(); - - Image = image; + setImage(image); ImageRect = pos; - - if (Image) - Image->grab(); - - if (!PressedImage) - setPressedImage(Image, pos); } -//! Sets an image which should be displayed on the button when it is in pressed state. +//! Sets an image which should be displayed on the button when it is in pressed state. void CGUIButton::setPressedImage(video::ITexture* image) { + if (image) + image->grab(); + if (PressedImage) PressedImage->drop(); PressedImage = image; if (image) PressedImageRect = core::rect(core::position2d(0,0), image->getOriginalSize()); - - if (PressedImage) - PressedImage->grab(); } //! Sets the image which should be displayed on the button when it is in its pressed state. void CGUIButton::setPressedImage(video::ITexture* image, const core::rect& pos) { - if (PressedImage) - PressedImage->drop(); - - PressedImage = image; + setPressedImage(image); PressedImageRect = pos; - - if (PressedImage) - PressedImage->grab(); } @@ -419,7 +423,7 @@ bool CGUIButton::isAlphaChannelUsed() const bool CGUIButton::isDrawingBorder() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return Border; + return DrawBorder; } @@ -437,8 +441,9 @@ void CGUIButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWri out->addTexture ("PressedImage", PressedImage); out->addRect ("PressedImageRect", PressedImageRect); - out->addBool ("Border", Border); - out->addBool ("UseAlphaChannel", UseAlphaChannel); + out->addBool ("UseAlphaChannel", isAlphaChannelUsed()); + out->addBool ("Border", isDrawingBorder()); + out->addBool ("ScaleImage", isScalingImage()); // out->addString ("OverrideFont", OverrideFont); } @@ -465,7 +470,8 @@ void CGUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWr setPressedImage( in->getAttributeAsTexture("PressedImage") ); setDrawBorder(in->getAttributeAsBool("Border")); - UseAlphaChannel = in->getAttributeAsBool("UseAlphaChannel"); + setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel")); + setScaleImage(in->getAttributeAsBool("ScaleImage")); // setOverrideFont(in->getAttributeAsString("OverrideFont")); diff --git a/src/dep/src/irrlicht/CGUIButton.h b/src/dep/src/irrlicht/CGUIButton.h index f38f31e..c568d76 100644 --- a/src/dep/src/irrlicht/CGUIButton.h +++ b/src/dep/src/irrlicht/CGUIButton.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -37,20 +37,20 @@ namespace gui //! sets another skin independent font. if this is set to zero, the button uses the font of the skin. virtual void setOverrideFont(IGUIFont* font=0); - //! Sets an image which should be displayed on the button when it is in normal state. - virtual void setImage(video::ITexture* image); + //! Sets an image which should be displayed on the button when it is in normal state. + virtual void setImage(video::ITexture* image=0); - //! Sets an image which should be displayed on the button when it is in normal state. + //! Sets an image which should be displayed on the button when it is in normal state. virtual void setImage(video::ITexture* image, const core::rect& pos); - //! Sets an image which should be displayed on the button when it is in pressed state. - virtual void setPressedImage(video::ITexture* image); + //! Sets an image which should be displayed on the button when it is in pressed state. + virtual void setPressedImage(video::ITexture* image=0); - //! Sets an image which should be displayed on the button when it is in pressed state. + //! Sets an image which should be displayed on the button when it is in pressed state. virtual void setPressedImage(video::ITexture* image, const core::rect& pos); //! Sets the sprite bank used by the button - virtual void setSpriteBank(IGUISpriteBank* bank); + virtual void setSpriteBank(IGUISpriteBank* bank=0); //! Sets the animated sprite for a specific button state /** \param index: Number of the sprite within the sprite bank, use -1 for no sprite @@ -58,34 +58,40 @@ namespace gui \param index: The sprite number from the current sprite bank \param color: The color of the sprite */ - virtual void setSprite(EGUI_BUTTON_STATE state, s32 index, + virtual void setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color=video::SColor(255,255,255,255), bool loop=false); //! Sets if the button should behave like a push button. Which means it //! can be in two states: Normal or Pressed. With a click on the button, //! the user can change the state of the button. - virtual void setIsPushButton(bool isPushButton); + virtual void setIsPushButton(bool isPushButton=true); + + //! Checks whether the button is a push button + virtual bool isPushButton() const; + + //! Sets the pressed state of the button if this is a pushbutton + virtual void setPressed(bool pressed=true); //! Returns if the button is currently pressed virtual bool isPressed() const; - //! Sets the pressed state of the button if this is a pushbutton - virtual void setPressed(bool pressed); - //! Sets if the button should use the skin to draw its border - virtual void setDrawBorder(bool border); - - //! Sets if the alpha channel should be used for drawing images on the button (default is false) - virtual void setUseAlphaChannel(bool useAlphaChannel); + virtual void setDrawBorder(bool border=true); - //! Returns if the alpha channel should be used for drawing images on the button - virtual bool isAlphaChannelUsed() const; - - //! Returns if the button face and border are being drawn + //! Checks if the button face and border are being drawn virtual bool isDrawingBorder() const; - //! Returns whether the button is a push button - virtual bool isPushButton() const; + //! Sets if the alpha channel should be used for drawing images on the button (default is false) + virtual void setUseAlphaChannel(bool useAlphaChannel=true); + + //! Checks if the alpha channel should be used for drawing images on the button + virtual bool isAlphaChannelUsed() const; + + //! Sets if the button should scale the button images to fit + virtual void setScaleImage(bool scaleImage=true); + + //! Checks whether the button scales the used images + virtual bool isScalingImage() const; //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; @@ -102,24 +108,24 @@ namespace gui bool Loop; }; - bool Pressed; - bool IsPushButton; - bool UseAlphaChannel; - - bool Border; - - u32 ClickTime; + ButtonSprite ButtonSprites[EGBS_COUNT]; IGUISpriteBank* SpriteBank; IGUIFont* OverrideFont; - ButtonSprite ButtonSprites[EGBS_COUNT]; - video::ITexture* Image; video::ITexture* PressedImage; core::rect ImageRect; core::rect PressedImageRect; + + u32 ClickTime; + + bool IsPushButton; + bool Pressed; + bool UseAlphaChannel; + bool DrawBorder; + bool ScaleImage; }; } // end namespace gui diff --git a/src/dep/src/irrlicht/CGUICheckBox.cpp b/src/dep/src/irrlicht/CGUICheckBox.cpp index bdb086e..0cae0f0 100644 --- a/src/dep/src/irrlicht/CGUICheckBox.cpp +++ b/src/dep/src/irrlicht/CGUICheckBox.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -19,7 +19,7 @@ namespace gui //! constructor CGUICheckBox::CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) -: IGUICheckBox(environment, parent, id, rectangle), Pressed(false), Checked(checked), checkTime(0) +: IGUICheckBox(environment, parent, id, rectangle), checkTime(0), Pressed(false), Checked(checked) { #ifdef _DEBUG setDebugName("CGUICheckBox"); @@ -31,7 +31,6 @@ CGUICheckBox::CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIEleme } - //! called if an event happened. bool CGUICheckBox::OnEvent(const SEvent& event) { @@ -41,8 +40,7 @@ bool CGUICheckBox::OnEvent(const SEvent& event) { case EET_KEY_INPUT_EVENT: if (event.KeyInput.PressedDown && - (event.KeyInput.Key == KEY_RETURN || - event.KeyInput.Key == KEY_SPACE)) + (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { Pressed = true; return true; @@ -55,8 +53,7 @@ bool CGUICheckBox::OnEvent(const SEvent& event) } else if (!event.KeyInput.PressedDown && Pressed && - (event.KeyInput.Key == KEY_RETURN || - event.KeyInput.Key == KEY_SPACE)) + (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { Pressed = false; if (Parent) @@ -123,7 +120,6 @@ bool CGUICheckBox::OnEvent(const SEvent& event) } - //! draws the element and its children void CGUICheckBox::draw() { @@ -137,8 +133,8 @@ void CGUICheckBox::draw() s32 height = skin->getSize(EGDS_CHECK_BOX_WIDTH); core::rect checkRect(AbsoluteRect.UpperLeftCorner.X, - ((AbsoluteRect.getHeight() - height) / 2) + AbsoluteRect.UpperLeftCorner.Y, - 0, 0); + ((AbsoluteRect.getHeight() - height) / 2) + AbsoluteRect.UpperLeftCorner.Y, + 0, 0); checkRect.LowerRightCorner.X = checkRect.UpperLeftCorner.X + height; checkRect.LowerRightCorner.Y = checkRect.UpperLeftCorner.Y + height; @@ -147,7 +143,7 @@ void CGUICheckBox::draw() false, true, checkRect, &AbsoluteClippingRect); if (Checked && Environment->getSkin()) - Environment->getSkin()->drawIcon(this, EGDI_CHECK_BOX_CHECKED, checkRect.getCenter(), + Environment->getSkin()->drawIcon(this, EGDI_CHECK_BOX_CHECKED, checkRect.getCenter(), checkTime, os::Timer::getTime(), false, &AbsoluteClippingRect); if (Text.size()) @@ -157,8 +153,8 @@ void CGUICheckBox::draw() IGUIFont* font = skin->getFont(); if (font) - font->draw(Text.c_str(), checkRect, - skin->getColor(EGDC_BUTTON_TEXT), false, true, &AbsoluteClippingRect); + font->draw(Text.c_str(), checkRect, + skin->getColor(IsEnabled ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), false, true, &AbsoluteClippingRect); } IGUIElement::draw(); @@ -179,13 +175,15 @@ bool CGUICheckBox::isChecked() const return Checked; } + //! Writes attributes of the element. void CGUICheckBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUICheckBox::serializeAttributes(out,options); - out->addBool ("Checked", Checked ); + out->addBool("Checked", Checked); } + //! Reads attributes of the element void CGUICheckBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { @@ -199,3 +197,4 @@ void CGUICheckBox::deserializeAttributes(io::IAttributes* in, io::SAttributeRead } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ + diff --git a/src/dep/src/irrlicht/CGUICheckBox.h b/src/dep/src/irrlicht/CGUICheckBox.h index 8370680..9e27dc6 100644 --- a/src/dep/src/irrlicht/CGUICheckBox.h +++ b/src/dep/src/irrlicht/CGUICheckBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -42,9 +42,9 @@ namespace gui private: + u32 checkTime; bool Pressed; bool Checked; - u32 checkTime; }; } // end namespace gui diff --git a/src/dep/src/irrlicht/CGUIColorSelectDialog.cpp b/src/dep/src/irrlicht/CGUIColorSelectDialog.cpp index 2667b97..3b556fe 100644 --- a/src/dep/src/irrlicht/CGUIColorSelectDialog.cpp +++ b/src/dep/src/irrlicht/CGUIColorSelectDialog.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -15,7 +15,6 @@ #include "IGUISpriteBank.h" #include "IFileList.h" #include "os.h" -#include "SoftwareDriver2_helper.h" #include "CImage.h" namespace irr @@ -98,8 +97,8 @@ CGUIColorSelectDialog::CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironme ColorRing.Texture = driver->getTexture ( "#colorring" ); if ( 0 == ColorRing.Texture ) { - buildColorRing(core::dimension2d(128, 128), 1, - Environment->getSkin()->getColor(EGDC_3D_SHADOW).color); + buildColorRing(core::dimension2d(128, 128), 1, + Environment->getSkin()->getColor(EGDC_3D_SHADOW)); } core::rect r(20,20, 0,0); @@ -131,6 +130,8 @@ CGUIColorSelectDialog::CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironme } SBatteryItem item; + item.Incoming=0.f; + item.Outgoing=0.f; r.UpperLeftCorner.X = Template[i].x + 15; r.UpperLeftCorner.Y = Template[i].y; @@ -184,16 +185,13 @@ CGUIColorSelectDialog::~CGUIColorSelectDialog() //! renders a antialiased, colored ring -void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, s32 supersample, const u32 borderColor ) +void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, s32 supersample, const video::SColor& borderColor ) { - const core::dimension2d d(dim.Width * supersample, dim.Height * supersample); + const core::dimension2d d(dim.Width * supersample, dim.Height * supersample); video::CImage *RawTexture = new video::CImage(video::ECF_A8R8G8B8, d); RawTexture->fill ( 0x00808080 ); - u8 * data= (u8*) RawTexture->lock(); - const u32 pitch = RawTexture->getPitch(); - const s32 radiusOut = ( d.Width / 2 ) - 4; const s32 fullR2 = radiusOut * radiusOut; @@ -203,14 +201,11 @@ void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, hsl.Saturation = 1.f; core::position2d p; - u32 *dst; for ( p.Y = -radiusOut; p.Y <= radiusOut; p.Y += 1 ) { s32 y2 = p.Y * p.Y; - dst = (u32*) ( (u8* ) data + ( ( 4 + p.Y + radiusOut ) * pitch ) + (4 << 2 ) ); - - for ( p.X = -radiusOut; p.X <= radiusOut; p.X += 1, dst += 1 ) + for (p.X = -radiusOut; p.X <= radiusOut; p.X += 1) { s32 r2 = y2 + ( p.X * p.X ); @@ -224,7 +219,7 @@ void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, const f32 r = sqrtf((f32) r2); // normalize, dotproduct = xnorm - const f32 xn = -p.X * core::reciprocal(r); + const f32 xn = r == 0.f ? 0.f : -p.X * core::reciprocal(r); hsl.Hue = acosf(xn); if ( p.Y > 0 ) @@ -273,20 +268,20 @@ void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, hsl.Luminance = 0.5f; hsl.Saturation = 1.f; hsl.toRGB(rgb); - *dst = rgb.color; - } - if ( rTest >= 0.5f && rTest <= 0.55f ) - { - u32 alpha = (s32) ( (rTest - 0.5f ) * ( 255.f / 0.05f ) ); - *dst = (*dst & 0x00ffffff) | (alpha << 24); - } - - if ( rTest >= 0.95f ) - { - u32 alpha = (s32) ( (rTest - 0.95f ) * ( 255.f / 0.05f ) ); - alpha = 255 - alpha; - *dst = (*dst & 0x00ffffff) | (alpha << 24); + if ( rTest <= 0.55f ) + { + const u32 alpha = (u32) ( (rTest - 0.5f ) * ( 255.f / 0.05f ) ); + rgb.setAlpha(alpha); + } + else if ( rTest >= 0.95f ) + { + const u32 alpha = (u32) ( (rTest - 0.95f ) * ( 255.f / 0.05f ) ); + rgb.setAlpha(255-alpha); + } + else + rgb.setAlpha(255); + RawTexture->setPixel(4+p.X+radiusOut, 4+p.Y+radiusOut, rgb); } } } @@ -297,7 +292,7 @@ void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, if ( supersample > 1 ) { video::CImage * filter = new video::CImage(video::ECF_A8R8G8B8, dim ); - RawTexture->copyToScalingBoxFilter(filter, 0); + RawTexture->copyToScalingBoxFilter(filter); RawTexture->drop(); RawTexture = filter; } @@ -307,7 +302,7 @@ void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, bool generateMipLevels = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, false); - ColorRing.Texture = driver->addTexture ("#colorring", RawTexture); + ColorRing.Texture = driver->addTexture ( L"#colorring", RawTexture); RawTexture->drop(); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, generateMipLevels); diff --git a/src/dep/src/irrlicht/CGUIColorSelectDialog.h b/src/dep/src/irrlicht/CGUIColorSelectDialog.h index d033cf8..447b5a7 100644 --- a/src/dep/src/irrlicht/CGUIColorSelectDialog.h +++ b/src/dep/src/irrlicht/CGUIColorSelectDialog.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -67,8 +67,7 @@ namespace gui }; SColorCircle ColorRing; - void buildColorRing( const core::dimension2d & dim, s32 supersample, const u32 borderColor ); - + void buildColorRing( const core::dimension2d & dim, s32 supersample, const video::SColor& borderColor ); }; @@ -78,3 +77,4 @@ namespace gui #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__ + diff --git a/src/dep/src/irrlicht/CGUIComboBox.cpp b/src/dep/src/irrlicht/CGUIComboBox.cpp index f5220eb..78aa50d 100644 --- a/src/dep/src/irrlicht/CGUIComboBox.cpp +++ b/src/dep/src/irrlicht/CGUIComboBox.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,8 +23,8 @@ namespace gui CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIComboBox(environment, parent, id, rectangle), - ListButton(0), SelectedText(0), ListBox(0), Selected(-1), HasFocus(false), LastFocus(0), - HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER) + ListButton(0), SelectedText(0), ListBox(0), LastFocus(0), + Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), HasFocus(false) { #ifdef _DEBUG setDebugName("CGUIComboBox"); @@ -39,7 +39,7 @@ CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent, core::rect r; r.UpperLeftCorner.X = rectangle.getWidth() - width - 2; r.LowerRightCorner.X = rectangle.getWidth() - 2; - + r.UpperLeftCorner.Y = 2; r.LowerRightCorner.Y = rectangle.getHeight() - 2; @@ -63,15 +63,16 @@ CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent, SelectedText->setSubElement(true); SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER); + if (skin) + SelectedText->setOverrideColor(skin->getColor(EGDC_BUTTON_TEXT)); SelectedText->enableOverrideColor(true); - setNotClipped(true); - // this element can be tabbed to setTabStop(true); setTabOrder(-1); } + void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) { HAlign = horizontal; @@ -79,6 +80,7 @@ void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT ve SelectedText->setTextAlignment(horizontal, vertical); } + //! Returns amount of items in box u32 CGUIComboBox::getItemCount() const { @@ -92,7 +94,27 @@ const wchar_t* CGUIComboBox::getItem(u32 idx) const if (idx >= Items.size()) return 0; - return Items[idx].c_str(); + return Items[idx].Name.c_str(); +} + +//! returns string of an item. the idx may be a value from 0 to itemCount-1 +u32 CGUIComboBox::getItemData(u32 idx) const +{ + if (idx >= Items.size()) + return 0; + + return Items[idx].Data; +} + +//! Returns index based on item data +s32 CGUIComboBox::getIndexForItemData(u32 data ) const +{ + for ( u32 i = 0; i < Items.size (); ++i ) + { + if ( Items[i].Data == data ) + return i; + } + return -1; } @@ -108,6 +130,7 @@ void CGUIComboBox::removeItem(u32 idx) Items.erase(idx); } + //! Returns caption of this element. const wchar_t* CGUIComboBox::getText() const { @@ -116,9 +139,9 @@ const wchar_t* CGUIComboBox::getText() const //! adds an item and returns the index of it -u32 CGUIComboBox::addItem(const wchar_t* text) +u32 CGUIComboBox::addItem(const wchar_t* text, u32 data) { - Items.push_back(core::stringw(text)); + Items.push_back( SComboData ( text, data ) ); if (Selected == -1) setSelected(0); @@ -127,7 +150,6 @@ u32 CGUIComboBox::addItem(const wchar_t* text) } - //! deletes all items in the combo box void CGUIComboBox::clear() { @@ -136,7 +158,6 @@ void CGUIComboBox::clear() } - //! returns id of selected item. returns -1 if no item is selected. s32 CGUIComboBox::getSelected() const { @@ -144,7 +165,6 @@ s32 CGUIComboBox::getSelected() const } - //! sets the selected item. Set this to -1 if no item should be selected void CGUIComboBox::setSelected(s32 idx) { @@ -153,11 +173,12 @@ void CGUIComboBox::setSelected(s32 idx) Selected = idx; if (Selected == -1) - SelectedText->setText(L""); + SelectedText->setText(L""); else - SelectedText->setText(Items[Selected].c_str()); + SelectedText->setText(Items[Selected].Name.c_str()); } + //! called if an event happened. bool CGUIComboBox::OnEvent(const SEvent& event) { @@ -177,7 +198,9 @@ bool CGUIComboBox::OnEvent(const SEvent& event) if (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE) { if (!event.KeyInput.PressedDown) + { openCloseMenu(); + } ListButton->setPressed(ListBox == 0); @@ -190,10 +213,10 @@ bool CGUIComboBox::OnEvent(const SEvent& event) bool absorb = true; switch (event.KeyInput.Key) { - case KEY_DOWN: - setSelected(Selected+1); + case KEY_DOWN: + setSelected(Selected+1); break; - case KEY_UP: + case KEY_UP: setSelected(Selected-1); break; case KEY_HOME: @@ -227,11 +250,10 @@ bool CGUIComboBox::OnEvent(const SEvent& event) switch(event.GUIEvent.EventType) { case EGET_ELEMENT_FOCUS_LOST: - if (ListBox && - (Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) && - event.GUIEvent.Element != this && - event.GUIEvent.Element != ListButton && - event.GUIEvent.Element != ListBox && + if (ListBox && + (Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) && + event.GUIEvent.Element != this && + !isMyChild(event.GUIEvent.Element) && !ListBox->isMyChild(event.GUIEvent.Element)) { openCloseMenu(); @@ -267,7 +289,7 @@ bool CGUIComboBox::OnEvent(const SEvent& event) case EMIE_LMOUSE_PRESSED_DOWN: { core::position2d p(event.MouseInput.X, event.MouseInput.Y); - + // send to list box if (ListBox && ListBox->isPointInside(p) && ListBox->OnEvent(event)) return true; @@ -282,13 +304,15 @@ bool CGUIComboBox::OnEvent(const SEvent& event) if (!(ListBox && ListBox->getAbsolutePosition().isPointInside(p) && ListBox->OnEvent(event))) + { openCloseMenu(); + } return true; } case EMIE_MOUSE_WHEEL: { s32 oldSelected = Selected; - setSelected( Selected +(event.MouseInput.Wheel < 0) ? 1 : -1); + setSelected( Selected + ((event.MouseInput.Wheel < 0) ? 1 : -1)); if (Selected <0) setSelected(0); @@ -312,7 +336,6 @@ bool CGUIComboBox::OnEvent(const SEvent& event) } - void CGUIComboBox::sendSelectionChangedEvent() { if (Parent) @@ -328,7 +351,6 @@ void CGUIComboBox::sendSelectionChangedEvent() } - //! draws the element and its children void CGUIComboBox::draw() { @@ -341,11 +363,23 @@ void CGUIComboBox::draw() { HasFocus = currentFocus == this || isMyChild(currentFocus); LastFocus = currentFocus; + } - SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT)); + // set colors each time as skin-colors can be changed + SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT)); + if(isEnabled()) + { SelectedText->setDrawBackground(HasFocus); SelectedText->setOverrideColor(skin->getColor(HasFocus ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT)); } + else + { + SelectedText->setDrawBackground(false); + SelectedText->setOverrideColor(skin->getColor(EGDC_GRAY_TEXT)); + } + ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL)); + ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL)); + core::rect frameRect(AbsoluteRect); @@ -373,7 +407,7 @@ void CGUIComboBox::openCloseMenu() if (Parent) Parent->bringToFront(this); - IGUISkin* skin = Environment->getSkin(); + IGUISkin* skin = Environment->getSkin(); s32 h = Items.size(); if (h > 5) @@ -391,10 +425,15 @@ void CGUIComboBox::openCloseMenu() ListBox = new CGUIListBox(Environment, this, -1, r, false, true, true); ListBox->setSubElement(true); + ListBox->setNotClipped(true); ListBox->drop(); + // ensure that list box is always completely visible + if (ListBox->getAbsolutePosition().LowerRightCorner.Y > Environment->getRootGUIElement()->getAbsolutePosition().getHeight()) + ListBox->setRelativePosition( core::rect(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0) ); + for (s32 i=0; i<(s32)Items.size(); ++i) - ListBox->addItem(Items[i].c_str()); + ListBox->addItem(Items[i].Name.c_str()); ListBox->setSelected(Selected); @@ -403,6 +442,7 @@ void CGUIComboBox::openCloseMenu() } } + //! Writes attributes of the element. void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { @@ -418,10 +458,11 @@ void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadW core::stringc s = "Item"; s += i; s += "Text"; - out->addString(s.c_str(), Items[i].c_str()); + out->addString(s.c_str(), Items[i].Name.c_str()); } } + //! Reads attributes of the element void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { @@ -440,7 +481,7 @@ void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeRead core::stringc s = "Item"; s += i; s += "Text"; - addItem(in->getAttributeAsStringW(s.c_str()).c_str()); + addItem(in->getAttributeAsStringW(s.c_str()).c_str(), 0); } setSelected(in->getAttributeAsInt("Selected")); diff --git a/src/dep/src/irrlicht/CGUIComboBox.h b/src/dep/src/irrlicht/CGUIComboBox.h index c79755c..dfe288f 100644 --- a/src/dep/src/irrlicht/CGUIComboBox.h +++ b/src/dep/src/irrlicht/CGUIComboBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -35,8 +35,14 @@ namespace gui //! returns string of an item. the idx may be a value from 0 to itemCount-1 virtual const wchar_t* getItem(u32 idx) const; + //! Returns item data of an item. the idx may be a value from 0 to itemCount-1 + virtual u32 getItemData(u32 idx) const; + + //! Returns index based on item data + virtual s32 getIndexForItemData( u32 data ) const; + //! adds an item and returns the index of it - virtual u32 addItem(const wchar_t* text); + virtual u32 addItem(const wchar_t* text, u32 data); //! Removes an item from the combo box. virtual void removeItem(u32 id); @@ -76,11 +82,22 @@ namespace gui IGUIButton* ListButton; IGUIStaticText* SelectedText; IGUIListBox* ListBox; - core::array< core::stringw > Items; - s32 Selected; - bool HasFocus; IGUIElement *LastFocus; + + + struct SComboData + { + SComboData ( const wchar_t * text, u32 data ) + : Name (text), Data ( data ) {} + + core::stringw Name; + u32 Data; + }; + core::array< SComboData > Items; + + s32 Selected; EGUI_ALIGNMENT HAlign, VAlign; + bool HasFocus; }; diff --git a/src/dep/src/irrlicht/CGUIContextMenu.cpp b/src/dep/src/irrlicht/CGUIContextMenu.cpp index fc7e59c..8503059 100644 --- a/src/dep/src/irrlicht/CGUIContextMenu.cpp +++ b/src/dep/src/irrlicht/CGUIContextMenu.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,8 +23,8 @@ namespace gui CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool getFocus, bool allowFocus) - : IGUIContextMenu(environment, parent, id, rectangle), HighLighted(-1), - ChangeTime(0), EventParent(0), AllowFocus(allowFocus), LastFont(0) + : IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0), + CloseHandling(ECMC_REMOVE), HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus) { #ifdef _DEBUG setDebugName("CGUIContextMenu"); @@ -51,6 +51,17 @@ CGUIContextMenu::~CGUIContextMenu() LastFont->drop(); } +//! set behaviour when menus are closed +void CGUIContextMenu::setCloseHandling(ECONTEXT_MENU_CLOSE onClose) +{ + CloseHandling = onClose; +} + +//! get current behaviour when the menue will be closed +ECONTEXT_MENU_CLOSE CGUIContextMenu::getCloseHandling() const +{ + return CloseHandling; +} //! Returns amount of menu items u32 CGUIContextMenu::getItemCount() const @@ -60,29 +71,57 @@ u32 CGUIContextMenu::getItemCount() const //! Adds a menu item. -u32 CGUIContextMenu::addItem(const wchar_t* text, s32 id, bool enabled, bool hasSubMenu, bool checked) +u32 CGUIContextMenu::addItem(const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking) +{ + return insertItem(Items.size(), text, commandId, enabled, hasSubMenu, checked, autoChecking); +} + +//! Insert a menu item at specified position. +u32 CGUIContextMenu::insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled, + bool hasSubMenu, bool checked, bool autoChecking) { SItem s; s.Enabled = enabled; s.Checked = checked; + s.AutoChecking = autoChecking; s.Text = text; s.IsSeparator = (text == 0); s.SubMenu = 0; - s.CommandId = id; + s.CommandId = commandId; if (hasSubMenu) { - s.SubMenu = new CGUIContextMenu(Environment, this, id, + s.SubMenu = new CGUIContextMenu(Environment, this, commandId, core::rect(0,0,100,100), false, false); s.SubMenu->setVisible(false); } - Items.push_back(s); + u32 result = idx; + if ( idx < Items.size() ) + { + Items.insert(s, idx); + } + else + { + Items.push_back(s); + result = Items.size() - 1; + } recalculateSize(); - return Items.size() - 1; + return result; } +s32 CGUIContextMenu::findItemWithCommandId(s32 commandId, u32 idxStartSearch) const +{ + for ( u32 i=idxStartSearch; i= Items.size()) return; + if (menu) + menu->grab(); if (Items[index].SubMenu) Items[index].SubMenu->drop(); @@ -98,7 +139,6 @@ void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu) if (Items[index].SubMenu) { - menu->grab(); menu->AllowFocus = false; if ( Environment->getFocus() == menu ) { @@ -113,7 +153,7 @@ void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu) //! Adds a separator item to the menu void CGUIContextMenu::addSeparator() { - addItem(0, -1, true, false, false); + addItem(0, -1, true, false, false, false); } @@ -137,6 +177,24 @@ void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text) recalculateSize(); } +//! should the element change the checked status on clicking +void CGUIContextMenu::setItemAutoChecking(u32 idx, bool autoChecking) +{ + if ( idx >= Items.size()) + return; + + Items[idx].AutoChecking = autoChecking; +} + +//! does the element change the checked status on clicking +bool CGUIContextMenu::getItemAutoChecking(u32 idx) const +{ + if (idx >= Items.size()) + return false; + + return Items[idx].AutoChecking; +} + //! Returns if a menu item is enabled bool CGUIContextMenu::isItemEnabled(u32 idx) const @@ -230,8 +288,17 @@ bool CGUIContextMenu::OnEvent(const SEvent& event) if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus) { // set event parent of submenus - setEventParent(Parent); - remove(); + setEventParent(EventParent ? EventParent : Parent); + + if ( CloseHandling & ECMC_HIDE ) + { + setVisible(false); + } + if ( CloseHandling & ECMC_REMOVE ) + { + remove(); + } + return false; } break; @@ -242,7 +309,7 @@ bool CGUIContextMenu::OnEvent(const SEvent& event) } break; default: - break; + break; } break; case EET_MOUSE_INPUT_EVENT: @@ -265,7 +332,7 @@ bool CGUIContextMenu::OnEvent(const SEvent& event) highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); return true; default: - break; + break; } break; default: @@ -325,16 +392,20 @@ u32 CGUIContextMenu::sendClick(const core::position2d& p) Items[HighLighted].SubMenu) return 2; + if ( Items[HighLighted].AutoChecking ) + { + Items[HighLighted].Checked = Items[HighLighted].Checked ? false : true; + } + SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED; - if (Parent) - Parent->OnEvent(event); - else if (EventParent) - EventParent->OnEvent(event); + EventParent->OnEvent(event); + else if (Parent) + Parent->OnEvent(event); return 1; } @@ -530,16 +601,15 @@ void CGUIContextMenu::draw() void CGUIContextMenu::recalculateSize() { - IGUISkin* skin = Environment->getSkin(); - IGUIFont* font = skin->getFont(EGDF_MENU); + IGUIFont* font = Environment->getSkin()->getFont(EGDF_MENU); if (!font) return; core::rect rect; rect.UpperLeftCorner = RelativeRect.UpperLeftCorner; - s32 width = 100; - s32 height = 3; + u32 width = 100; + u32 height = 3; u32 i; for (i=0; igetAbsolutePosition().getWidth(); const s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight(); - Items[i].SubMenu->setRelativePosition( - core::rect(width-5, Items[i].PosY, - width+w-5, Items[i].PosY+h)); + core::rect subRect(width-5, Items[i].PosY, width+w-5, Items[i].PosY+h); + + // if it would be drawn beyond the right border, then add it to the left side + gui::IGUIElement * root = Environment->getRootGUIElement(); + if ( root ) + { + core::rect rectRoot( root->getAbsolutePosition() ); + if ( getAbsolutePosition().UpperLeftCorner.X+subRect.LowerRightCorner.X > rectRoot.LowerRightCorner.X ) + { + subRect.UpperLeftCorner.X = -w; + subRect.LowerRightCorner.X = 0; + } + } + + Items[i].SubMenu->setRelativePosition(subRect); } } } @@ -644,6 +726,8 @@ void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeRe out->addInt("ParentItem", i); } + out->addInt("CloseHandling", (s32)CloseHandling); + // write out the item list out->addInt("ItemCount", Items.size()); @@ -662,6 +746,10 @@ void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeRe out->addInt(tmp.c_str(), Items[i].CommandId); tmp = "Enabled"; tmp += i; out->addBool(tmp.c_str(), Items[i].Enabled); + tmp = "Checked"; tmp += i; + out->addBool(tmp.c_str(), Items[i].Checked); + tmp = "AutoChecking"; tmp += i; + out->addBool(tmp.c_str(), Items[i].AutoChecking); } } } @@ -678,6 +766,7 @@ void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeR if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) ) ((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this); + CloseHandling = (ECONTEXT_MENU_CLOSE)in->getAttributeAsInt("CloseHandling"); removeAllItems(); @@ -688,28 +777,37 @@ void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeR { core::stringc tmp; core::stringw txt; - s32 commandid; - bool enabled; - bool checked; + s32 commandid=-1; + bool enabled=true; + bool checked=false; + bool autochecking=false; tmp = "IsSeparator"; tmp += i; - if ( in->getAttributeAsBool(tmp.c_str()) ) + if ( in->existsAttribute(tmp.c_str()) && in->getAttributeAsBool(tmp.c_str()) ) addSeparator(); else { tmp = "Text"; tmp += i; - txt = in->getAttributeAsStringW(tmp.c_str()); + if ( in->existsAttribute(tmp.c_str()) ) + txt = in->getAttributeAsStringW(tmp.c_str()); tmp = "CommandID"; tmp += i; - commandid = in->getAttributeAsInt(tmp.c_str()); + if ( in->existsAttribute(tmp.c_str()) ) + commandid = in->getAttributeAsInt(tmp.c_str()); tmp = "Enabled"; tmp += i; - enabled = in->getAttributeAsBool(tmp.c_str()); + if ( in->existsAttribute(tmp.c_str()) ) + enabled = in->getAttributeAsBool(tmp.c_str()); tmp = "Checked"; tmp += i; - checked = in->getAttributeAsBool(tmp.c_str()); + if ( in->existsAttribute(tmp.c_str()) ) + checked = in->getAttributeAsBool(tmp.c_str()); - addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked); + tmp = "AutoChecking"; tmp += i; + if ( in->existsAttribute(tmp.c_str()) ) + autochecking = in->getAttributeAsBool(tmp.c_str()); + + addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked, autochecking); } } diff --git a/src/dep/src/irrlicht/CGUIContextMenu.h b/src/dep/src/irrlicht/CGUIContextMenu.h index b2317ba..495aef5 100644 --- a/src/dep/src/irrlicht/CGUIContextMenu.h +++ b/src/dep/src/irrlicht/CGUIContextMenu.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -31,12 +31,25 @@ namespace gui //! destructor virtual ~CGUIContextMenu(); + //! set behaviour when menus are closed + virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose); + + //! get current behaviour when the menue will be closed + virtual ECONTEXT_MENU_CLOSE getCloseHandling() const; + //! Returns amount of menu items virtual u32 getItemCount() const; //! Adds a menu item. virtual u32 addItem(const wchar_t* text, s32 commandid, - bool enabled, bool hasSubMenu, bool checked); + bool enabled, bool hasSubMenu, bool checked, bool autoChecking); + + //! Insert a menu item at specified position. + virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled, + bool hasSubMenu, bool checked, bool autoChecking); + + //! Find a item which has the given CommandId starting from given index + virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch) const; //! Adds a separator item to the menu virtual void addSeparator(); @@ -81,6 +94,12 @@ namespace gui //! Sets the visible state of this element. virtual void setVisible(bool visible); + //! should the element change the checked status on clicking + virtual void setItemAutoChecking(u32 idx, bool autoChecking); + + //! does the element change the checked status on clicking + virtual bool getItemAutoChecking(u32 idx) const; + //! Returns command id of a menu item virtual s32 getItemCommandId(u32 idx) const; @@ -90,6 +109,9 @@ namespace gui //! Adds a sub menu from an element that already exists. virtual void setSubMenu(u32 index, CGUIContextMenu* menu); + //! When an eventparent is set it receives events instead of the usual parent element + virtual void setEventParent(IGUIElement *parent); + //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; @@ -107,7 +129,8 @@ namespace gui bool IsSeparator; bool Enabled; bool Checked; - core::dimension2d Dim; + bool AutoChecking; + core::dimension2d Dim; s32 PosY; CGUIContextMenu* SubMenu; s32 CommandId; @@ -130,15 +153,15 @@ namespace gui //! Gets drawing rect of Item virtual core::rect getRect(const SItem& i, const core::rect& absolute) const; - void setEventParent(IGUIElement *parent); - s32 HighLighted; core::array Items; core::position2d Pos; - u32 ChangeTime; IGUIElement* EventParent; - bool AllowFocus; IGUIFont *LastFont; + ECONTEXT_MENU_CLOSE CloseHandling; + s32 HighLighted; + u32 ChangeTime; + bool AllowFocus; }; diff --git a/src/dep/src/irrlicht/CGUIEditBox.cpp b/src/dep/src/irrlicht/CGUIEditBox.cpp index 39ef4f2..fb30ebf 100644 --- a/src/dep/src/irrlicht/CGUIEditBox.cpp +++ b/src/dep/src/irrlicht/CGUIEditBox.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,18 +28,16 @@ namespace gui { //! constructor -CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment, - IGUIElement* parent, s32 id, - const core::rect& rectangle) -: IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false), +CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border, + IGUIEnvironment* environment, IGUIElement* parent, s32 id, + const core::rect& rectangle) + : IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false), Border(border), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0), - OverrideColor(video::SColor(101,255,255,255)), - OverrideFont(0), LastBreakFont(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0), + OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0), + Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0), WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false), - PasswordChar(L'*'), - HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), + PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), CurrentTextRect(0,0,1,1), FrameRect(rectangle) - { #ifdef _DEBUG setDebugName("CGUIEditBox"); @@ -47,7 +45,8 @@ CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* envi Text = text; - Operator = environment->getOSOperator(); + if (Environment) + Operator = Environment->getOSOperator(); if (Operator) Operator->grab(); @@ -56,7 +55,9 @@ CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* envi setTabStop(true); setTabOrder(-1); - IGUISkin *skin = Environment->getSkin(); + IGUISkin *skin = 0; + if (Environment) + skin = Environment->getSkin(); if (Border && skin) { FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1; @@ -66,6 +67,7 @@ CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* envi } breakText(); + calculateScrollPos(); } @@ -84,6 +86,9 @@ CGUIEditBox::~CGUIEditBox() //! Sets another skin independent font. void CGUIEditBox::setOverrideFont(IGUIFont* font) { + if (OverrideFont == font) + return; + if (OverrideFont) OverrideFont->drop(); @@ -128,8 +133,12 @@ void CGUIEditBox::setWordWrap(bool enable) void CGUIEditBox::updateAbsolutePosition() { + core::rect oldAbsoluteRect(AbsoluteRect); IGUIElement::updateAbsolutePosition(); - breakText(); + if ( oldAbsoluteRect != AbsoluteRect ) + { + breakText(); + } } @@ -198,8 +207,7 @@ bool CGUIEditBox::OnEvent(const SEvent& event) if (event.GUIEvent.Caller == this) { MouseMarking = false; - MarkBegin = 0; - MarkEnd = 0; + setTextMarkers(0,0); } } break; @@ -226,24 +234,33 @@ bool CGUIEditBox::processKey(const SEvent& event) return false; bool textChanged = false; + s32 newMarkBegin = MarkBegin; + s32 newMarkEnd = MarkEnd; // control shortcut handling if (event.KeyInput.Control) { + // german backlash '\' entered with control + '?' + if ( event.KeyInput.Char == '\\' ) + { + inputChar(event.KeyInput.Char); + return true; + } + switch(event.KeyInput.Key) { case KEY_KEY_A: // select all - MarkBegin = 0; - MarkEnd = Text.size(); + newMarkBegin = 0; + newMarkEnd = Text.size(); break; case KEY_KEY_C: // copy to clipboard if (!PasswordBox && Operator && MarkBegin != MarkEnd) { - s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; core::stringc s; s = Text.subString(realmbgn, realmend - realmbgn).c_str(); @@ -254,8 +271,8 @@ bool CGUIEditBox::processKey(const SEvent& event) // cut to the clipboard if (!PasswordBox && Operator && MarkBegin != MarkEnd) { - s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; // copy core::stringc sc; @@ -271,8 +288,8 @@ bool CGUIEditBox::processKey(const SEvent& event) Text = s; CursorPos = realmbgn; - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; textChanged = true; } } @@ -284,8 +301,8 @@ bool CGUIEditBox::processKey(const SEvent& event) // paste from the clipboard if (Operator) { - s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; // add new character const c8* p = Operator->getTextFromClipboard(); @@ -322,8 +339,8 @@ bool CGUIEditBox::processKey(const SEvent& event) } } - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; textChanged = true; } break; @@ -331,40 +348,38 @@ bool CGUIEditBox::processKey(const SEvent& event) // move/highlight to start of text if (event.KeyInput.Shift) { - MarkEnd = CursorPos; - MarkBegin = 0; + newMarkEnd = CursorPos; + newMarkBegin = 0; CursorPos = 0; } else { CursorPos = 0; - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; } break; case KEY_END: // move/highlight to end of text if (event.KeyInput.Shift) { - MarkBegin = CursorPos; - MarkEnd = Text.size(); + newMarkBegin = CursorPos; + newMarkEnd = Text.size(); CursorPos = 0; } else { CursorPos = Text.size(); - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; } break; default: return false; } } - // default keyboard handling - - if (!event.KeyInput.Control) + else switch(event.KeyInput.Key) { case KEY_END: @@ -381,14 +396,14 @@ bool CGUIEditBox::processKey(const SEvent& event) if (event.KeyInput.Shift) { if (MarkBegin == MarkEnd) - MarkBegin = CursorPos; + newMarkBegin = CursorPos; - MarkEnd = p; + newMarkEnd = p; } else { - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; } CursorPos = p; BlinkStartTime = os::Timer::getTime(); @@ -407,13 +422,13 @@ bool CGUIEditBox::processKey(const SEvent& event) if (event.KeyInput.Shift) { if (MarkBegin == MarkEnd) - MarkBegin = CursorPos; - MarkEnd = p; + newMarkBegin = CursorPos; + newMarkEnd = p; } else { - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; } CursorPos = p; BlinkStartTime = os::Timer::getTime(); @@ -423,15 +438,11 @@ bool CGUIEditBox::processKey(const SEvent& event) if (MultiLine) { inputChar(L'\n'); + return true; } else { - SEvent e; - e.EventType = EET_GUI_EVENT; - e.GUIEvent.Caller = this; - e.GUIEvent.Element = 0; - e.GUIEvent.EventType = EGET_EDITBOX_ENTER; - Parent->OnEvent(e); + sendGuiEvent( EGET_EDITBOX_ENTER ); } break; case KEY_LEFT: @@ -441,15 +452,15 @@ bool CGUIEditBox::processKey(const SEvent& event) if (CursorPos > 0) { if (MarkBegin == MarkEnd) - MarkBegin = CursorPos; + newMarkBegin = CursorPos; - MarkEnd = CursorPos-1; + newMarkEnd = CursorPos-1; } } else { - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; } if (CursorPos > 0) CursorPos--; @@ -462,15 +473,15 @@ bool CGUIEditBox::processKey(const SEvent& event) if (Text.size() > (u32)CursorPos) { if (MarkBegin == MarkEnd) - MarkBegin = CursorPos; + newMarkBegin = CursorPos; - MarkEnd = CursorPos+1; + newMarkEnd = CursorPos+1; } } else { - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; } if (Text.size() > (u32)CursorPos) CursorPos++; @@ -492,13 +503,13 @@ bool CGUIEditBox::processKey(const SEvent& event) if (event.KeyInput.Shift) { - MarkBegin = mb; - MarkEnd = CursorPos; + newMarkBegin = mb; + newMarkEnd = CursorPos; } else { - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; } } @@ -523,13 +534,13 @@ bool CGUIEditBox::processKey(const SEvent& event) if (event.KeyInput.Shift) { - MarkBegin = mb; - MarkEnd = CursorPos; + newMarkBegin = mb; + newMarkEnd = CursorPos; } else { - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; } } @@ -550,8 +561,8 @@ bool CGUIEditBox::processKey(const SEvent& event) if (MarkBegin != MarkEnd) { // delete marked text - s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; s = Text.subString(0, realmbgn); s.append( Text.subString(realmend, Text.size()-realmend) ); @@ -574,8 +585,8 @@ bool CGUIEditBox::processKey(const SEvent& event) if (CursorPos < 0) CursorPos = 0; BlinkStartTime = os::Timer::getTime(); - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; textChanged = true; } break; @@ -590,8 +601,8 @@ bool CGUIEditBox::processKey(const SEvent& event) if (MarkBegin != MarkEnd) { // delete marked text - s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; s = Text.subString(0, realmbgn); s.append( Text.subString(realmend, Text.size()-realmend) ); @@ -611,8 +622,8 @@ bool CGUIEditBox::processKey(const SEvent& event) CursorPos = (s32)Text.size(); BlinkStartTime = os::Timer::getTime(); - MarkBegin = 0; - MarkEnd = 0; + newMarkBegin = 0; + newMarkEnd = 0; textChanged = true; } break; @@ -649,25 +660,32 @@ bool CGUIEditBox::processKey(const SEvent& event) default: inputChar(event.KeyInput.Char); - break; + return true; } + // Set new text markers + setTextMarkers( newMarkBegin, newMarkEnd ); + // break the text if it has changed if (textChanged) + { breakText(); + sendGuiEvent(EGET_EDITBOX_CHANGED); + } calculateScrollPos(); return true; } + //! draws the element and its children void CGUIEditBox::draw() { if (!IsVisible) return; - bool focus = Environment->hasFocus(this); + const bool focus = Environment->hasFocus(this); IGUISkin* skin = Environment->getSkin(); if (!skin) @@ -702,7 +720,9 @@ void CGUIEditBox::draw() if (font) { if (LastBreakFont != font) + { breakText(); + } // calculate cursor pos @@ -712,17 +732,17 @@ void CGUIEditBox::draw() core::stringw s, s2; // get mark position - bool ml = (!PasswordBox && (WordWrap || MultiLine)); - s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; - s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0; - s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1; - s32 lineCount = ml ? BrokenText.size() : 1; + const bool ml = (!PasswordBox && (WordWrap || MultiLine)); + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0; + const s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1; + const s32 lineCount = ml ? BrokenText.size() : 1; // Save the override color information. // Then, alter it if the edit box is disabled. - bool prevOver = OverrideColorEnabled; - video::SColor prevColor = OverrideColor; + const bool prevOver = OverrideColorEnabled; + const video::SColor prevColor = OverrideColor; if (Text.size()) { @@ -785,6 +805,12 @@ void CGUIEditBox::draw() // highlight start is on this line s = txtLine->subString(0, realmbgn - startPos); mbegin = font->getDimension(s.c_str()).Width; + + // deal with kerning + mbegin += font->getKerningWidth( + &((*txtLine)[realmbgn - startPos]), + realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0); + lineStartPos = realmbgn - startPos; } if (i == hlineStart + hlineCount - 1) @@ -828,7 +854,8 @@ void CGUIEditBox::draw() startPos = BrokenTextPositions[cursorLine]; } s = txtLine->subString(0,CursorPos-startPos); - charcursorpos = font->getDimension(s.c_str()).Width; + charcursorpos = font->getDimension(s.c_str()).Width + + font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0); if (focus && (os::Timer::getTime() - BlinkStartTime) % 700 < 350) { @@ -850,10 +877,9 @@ void CGUIEditBox::draw() void CGUIEditBox::setText(const wchar_t* text) { Text = text; - CursorPos = 0; + if (u32(CursorPos) > Text.size()) + CursorPos = Text.size(); HScrollPos = 0; - MarkBegin = 0; - MarkEnd = 0; breakText(); } @@ -874,9 +900,10 @@ bool CGUIEditBox::isAutoScrollEnabled() const return AutoScroll; } + //! Gets the area of the text in the edit box //! \return Returns the size in pixels of the text -core::dimension2di CGUIEditBox::getTextDimension() +core::dimension2du CGUIEditBox::getTextDimension() { core::rect ret; @@ -890,7 +917,7 @@ core::dimension2di CGUIEditBox::getTextDimension() ret.addInternalPoint(CurrentTextRect.LowerRightCorner); } - return ret.getSize(); + return core::dimension2du(ret.getSize()); } @@ -922,7 +949,9 @@ bool CGUIEditBox::processMouse(const SEvent& event) { CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); if (MouseMarking) - MarkEnd = CursorPos; + { + setTextMarkers( MarkBegin, CursorPos ); + } MouseMarking = false; calculateScrollPos(); return true; @@ -933,7 +962,7 @@ bool CGUIEditBox::processMouse(const SEvent& event) if (MouseMarking) { CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); - MarkEnd = CursorPos; + setTextMarkers( MarkBegin, CursorPos ); calculateScrollPos(); return true; } @@ -945,8 +974,7 @@ bool CGUIEditBox::processMouse(const SEvent& event) BlinkStartTime = os::Timer::getTime(); MouseMarking = true; CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); - MarkBegin = CursorPos; - MarkEnd = CursorPos; + setTextMarkers(CursorPos, CursorPos ); calculateScrollPos(); return true; } @@ -962,11 +990,12 @@ bool CGUIEditBox::processMouse(const SEvent& event) // move cursor CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); + s32 newMarkBegin = MarkBegin; if (!MouseMarking) - MarkBegin = CursorPos; + newMarkBegin = CursorPos; MouseMarking = true; - MarkEnd = CursorPos; + setTextMarkers( newMarkBegin, CursorPos); calculateScrollPos(); return true; } @@ -986,10 +1015,7 @@ s32 CGUIEditBox::getCursorPos(s32 x, s32 y) if (!OverrideFont) font = skin->getFont(); - u32 lineCount = 1; - - if (WordWrap || MultiLine) - lineCount = BrokenText.size(); + const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; core::stringw *txtLine=0; s32 startPos=0; @@ -1143,18 +1169,21 @@ void CGUIEditBox::breakText() void CGUIEditBox::setTextRect(s32 line) { - core::dimension2di d; - s32 lineCount = 1; + core::dimension2du d; - IGUIFont* font = OverrideFont; IGUISkin* skin = Environment->getSkin(); + if (!skin) + return; + + IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont(); + if (!font) - font = skin->getFont(); + return; // get text dimension + const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; if (WordWrap || MultiLine) { - lineCount = BrokenText.size(); d = font->getDimension(BrokenText[line].c_str()); } else @@ -1242,8 +1271,8 @@ void CGUIEditBox::inputChar(wchar_t c) if (MarkBegin != MarkEnd) { // replace marked text - s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; s = Text.subString(0, realmbgn); s.append(c); @@ -1262,11 +1291,12 @@ void CGUIEditBox::inputChar(wchar_t c) } BlinkStartTime = os::Timer::getTime(); - MarkBegin = 0; - MarkEnd = 0; + setTextMarkers(0, 0); } } breakText(); + sendGuiEvent(EGET_EDITBOX_CHANGED); + calculateScrollPos(); } @@ -1283,10 +1313,12 @@ void CGUIEditBox::calculateScrollPos() if (!WordWrap) { // get cursor position - IGUIFont* font = OverrideFont; IGUISkin* skin = Environment->getSkin(); - if (!OverrideFont) - font = skin->getFont(); + if (!skin) + return; + IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont(); + if (!font) + return; core::stringw *txtLine = MultiLine ? &BrokenText[cursLine] : &Text; s32 cPos = MultiLine ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; @@ -1304,7 +1336,6 @@ void CGUIEditBox::calculateScrollPos() HScrollPos = 0; // todo: adjust scrollbar - } // vertical scroll position @@ -1319,6 +1350,31 @@ void CGUIEditBox::calculateScrollPos() // todo: adjust scrollbar } +//! set text markers +void CGUIEditBox::setTextMarkers(s32 begin, s32 end) +{ + if ( begin != MarkBegin || end != MarkEnd ) + { + MarkBegin = begin; + MarkEnd = end; + sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED); + } +} + +//! send some gui event to parent +void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type) +{ + if ( Parent ) + { + SEvent e; + e.EventType = EET_GUI_EVENT; + e.GUIEvent.Caller = this; + e.GUIEvent.Element = 0; + e.GUIEvent.EventType = type; + + Parent->OnEvent(e); + } +} //! Writes attributes of the element. void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const @@ -1362,7 +1418,7 @@ void CGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadW setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]); setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), - (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); + (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); // setOverrideFont(in->getAttributeAsFont("OverrideFont")); } diff --git a/src/dep/src/irrlicht/CGUIEditBox.h b/src/dep/src/irrlicht/CGUIEditBox.h index 4bace92..d3a3841 100644 --- a/src/dep/src/irrlicht/CGUIEditBox.h +++ b/src/dep/src/irrlicht/CGUIEditBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -66,7 +66,7 @@ namespace gui //! Gets the size area of the text in the edit box //! \return Returns the size in pixels of the text - virtual core::dimension2di getTextDimension(); + virtual core::dimension2du getTextDimension(); //! Sets text justification virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); @@ -81,14 +81,14 @@ namespace gui virtual void setText(const wchar_t* text); //! Sets the maximum amount of characters which may be entered in the box. - //! \param max: Maximum amount of characters. If 0, the character amount is + //! \param max: Maximum amount of characters. If 0, the character amount is //! infinity. virtual void setMax(u32 max); //! Returns maximum amount of characters, previously set by setMax(); virtual u32 getMax() const; - //! Sets whether the edit box is a password box. Setting this to true will + //! Sets whether the edit box is a password box. Setting this to true will /** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x \param passwordBox: true to enable password, false to disable \param passwordChar: the character that is displayed instead of letters */ @@ -117,6 +117,10 @@ namespace gui void inputChar(wchar_t c); //! calculates the current scroll position void calculateScrollPos(); + //! send some gui event to parent + void sendGuiEvent(EGUI_EVENT_TYPE type); + //! set text markers + void setTextMarkers(s32 begin, s32 end); bool processKey(const SEvent& event); bool processMouse(const SEvent& event); diff --git a/src/dep/src/irrlicht/CGUIEnvironment.cpp b/src/dep/src/irrlicht/CGUIEnvironment.cpp index c923a3e..0615e85 100644 --- a/src/dep/src/irrlicht/CGUIEnvironment.cpp +++ b/src/dep/src/irrlicht/CGUIEnvironment.cpp @@ -1,5 +1,5 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -19,6 +19,8 @@ #include "CGUIMeshViewer.h" #include "CGUICheckBox.h" #include "CGUIListBox.h" +#include "CGUITreeView.h" +#include "CGUIImageList.h" #include "CGUIFileOpenDialog.h" #include "CGUIColorSelectDialog.h" #include "CGUIStaticText.h" @@ -52,8 +54,8 @@ const wchar_t* IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE = L"type"; //! constructor CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op) -: IGUIElement(EGUIET_ELEMENT, 0, 0, 0, core::rect(core::position2d(0,0), driver ? driver->getScreenSize() : core::dimension2d(0,0))), - Driver(driver), Hovered(0), Focus(0), LastHoveredMousePos(0,0), CurrentSkin(0), +: IGUIElement(EGUIET_ELEMENT, 0, 0, 0, core::rect(core::position2d(0,0), driver ? core::dimension2d(driver->getScreenSize()) : core::dimension2d(0,0))), + Driver(driver), Hovered(0), HoveredNoSubelement(0), Focus(0), LastHoveredMousePos(0,0), CurrentSkin(0), FileSystem(fs), UserReceiver(0), Operator(op) { if (Driver) @@ -82,7 +84,9 @@ CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* drive //set tooltip default ToolTip.LastTime = 0; + ToolTip.EnterTime = 0; ToolTip.LaunchTime = 1000; + ToolTip.RelaunchTime = 500; ToolTip.Element = 0; // environment is root tab group @@ -94,6 +98,12 @@ CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* drive //! destructor CGUIEnvironment::~CGUIEnvironment() { + if ( HoveredNoSubelement && HoveredNoSubelement != this ) + { + HoveredNoSubelement->drop(); + HoveredNoSubelement = 0; + } + if (Hovered && Hovered != this) { Hovered->drop(); @@ -156,10 +166,11 @@ CGUIEnvironment::~CGUIEnvironment() void CGUIEnvironment::loadBuiltInFont() { - const c8* filename = "#DefaultFont"; + io::path filename = "#DefaultFont"; + io::IReadFile* file = io::createMemoryReadFile(BuiltInFontData, BuiltInFontDataSize, filename, false); - CGUIFont* font = new CGUIFont(this, "#DefaultFont"); + CGUIFont* font = new CGUIFont(this, filename ); if (!font->load(file)) { os::Printer::log("Error: Could not load built-in Font. Did you compile without the BMP loader?", ELL_ERROR); @@ -169,7 +180,7 @@ void CGUIEnvironment::loadBuiltInFont() } SFont f; - f.Filename = filename; + f.NamedPath.setPath(filename); f.Font = font; Fonts.push_back(f); @@ -182,17 +193,16 @@ void CGUIEnvironment::drawAll() { if (Driver) { - core::dimension2d dim = Driver->getScreenSize(); + core::dimension2d dim(Driver->getScreenSize()); if (AbsoluteRect.LowerRightCorner.X != dim.Width || AbsoluteRect.LowerRightCorner.Y != dim.Height) { // resize gui environment - DesiredRect.LowerRightCorner.X = Driver->getScreenSize().Width; - DesiredRect.LowerRightCorner.Y = Driver->getScreenSize().Height; + DesiredRect.LowerRightCorner = dim; AbsoluteClippingRect = DesiredRect; AbsoluteRect = DesiredRect; updateAbsolutePosition(); - } + } } // make sure tooltip is always on top @@ -243,7 +253,7 @@ bool CGUIEnvironment::setFocus(IGUIElement* element) currentFocus->drop(); currentFocus = 0; } - + if (element) { currentFocus = Focus; @@ -275,7 +285,7 @@ bool CGUIEnvironment::setFocus(IGUIElement* element) // element is the new focus so it doesn't have to be dropped Focus = element; - + return true; } @@ -308,7 +318,7 @@ bool CGUIEnvironment::removeFocus(IGUIElement* element) Focus->drop(); Focus = 0; } - + return true; } @@ -317,7 +327,7 @@ bool CGUIEnvironment::removeFocus(IGUIElement* element) bool CGUIEnvironment::hasFocus(IGUIElement* element) const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return (element == Focus); + return (element == Focus); } @@ -327,18 +337,21 @@ video::IVideoDriver* CGUIEnvironment::getVideoDriver() const return Driver; } + //! returns the current file system io::IFileSystem* CGUIEnvironment::getFileSystem() const { return FileSystem; } + //! returns the current file system IOSOperator* CGUIEnvironment::getOSOperator() const { return Operator; } + //! clear all GUI elements void CGUIEnvironment::clear() { @@ -354,6 +367,11 @@ void CGUIEnvironment::clear() Hovered->drop(); Hovered = 0; } + if ( HoveredNoSubelement && HoveredNoSubelement != this) + { + HoveredNoSubelement->drop(); + HoveredNoSubelement = 0; + } // get the root's children in case the root changes in future const core::list& children = getRootGUIElement()->getChildren(); @@ -370,7 +388,7 @@ bool CGUIEnvironment::OnEvent(const SEvent& event) if (UserReceiver && (event.EventType != EET_MOUSE_INPUT_EVENT) && (event.EventType != EET_KEY_INPUT_EVENT) - && (event.EventType != EET_GUI_EVENT || event.GUIEvent.Caller != this)) + && (event.EventType != EET_GUI_EVENT || event.GUIEvent.Caller != this)) { ret = UserReceiver->OnEvent(event); } @@ -383,22 +401,20 @@ bool CGUIEnvironment::OnEvent(const SEvent& event) // void CGUIEnvironment::OnPostRender( u32 time ) { - // check tooltip - // launch tooltip - if ( time - ToolTip.LastTime >= ToolTip.LaunchTime && - Hovered && Hovered != this && - ToolTip.Element == 0 && - Hovered != ToolTip.Element && - Hovered->getToolTipText().size() && - getSkin() && + if ( ToolTip.Element == 0 && + HoveredNoSubelement && HoveredNoSubelement != this && + (time - ToolTip.EnterTime >= ToolTip.LaunchTime + || (time - ToolTip.LastTime >= ToolTip.RelaunchTime && time - ToolTip.LastTime < ToolTip.LaunchTime)) && + HoveredNoSubelement->getToolTipText().size() && + getSkin() && getSkin()->getFont(EGDF_TOOLTIP) ) { core::rect pos; pos.UpperLeftCorner = LastHoveredMousePos; - core::dimension2di dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(Hovered->getToolTipText().c_str()); + core::dimension2du dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(HoveredNoSubelement->getToolTipText().c_str()); dim.Width += getSkin()->getSize(EGDS_TEXT_DISTANCE_X)*2; dim.Height += getSkin()->getSize(EGDS_TEXT_DISTANCE_Y)*2; @@ -408,7 +424,7 @@ void CGUIEnvironment::OnPostRender( u32 time ) pos.constrainTo(getAbsolutePosition()); - ToolTip.Element = addStaticText(Hovered->getToolTipText().c_str(), pos, true, true, this, -1, true); + ToolTip.Element = addStaticText(HoveredNoSubelement->getToolTipText().c_str(), pos, true, true, this, -1, true); ToolTip.Element->setOverrideColor(getSkin()->getColor(EGDC_TOOLTIP)); ToolTip.Element->setBackgroundColor(getSkin()->getColor(EGDC_TOOLTIP_BACKGROUND)); ToolTip.Element->setOverrideFont(getSkin()->getFont(EGDF_TOOLTIP)); @@ -419,7 +435,22 @@ void CGUIEnvironment::OnPostRender( u32 time ) pos = ToolTip.Element->getRelativePosition(); pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + textHeight; ToolTip.Element->setRelativePosition(pos); + } + if (ToolTip.Element && ToolTip.Element->isVisible() ) // (isVisible() check only because we might use visibility for ToolTip one day) + { + ToolTip.LastTime = time; + + // got invisible or removed in the meantime? + if ( !HoveredNoSubelement || + !HoveredNoSubelement->isVisible() || + !HoveredNoSubelement->getParent() + ) // got invisible or removed in the meantime? + { + ToolTip.Element->remove(); + ToolTip.Element->drop(); + ToolTip.Element = 0; + } } IGUIElement::OnPostRender ( time ); @@ -430,58 +461,77 @@ void CGUIEnvironment::OnPostRender( u32 time ) void CGUIEnvironment::updateHoveredElement(core::position2d mousePos) { IGUIElement* lastHovered = Hovered; + IGUIElement* lastHoveredNoSubelement = HoveredNoSubelement; LastHoveredMousePos = mousePos; Hovered = getElementFromPoint(mousePos); - if (Hovered) + if ( ToolTip.Element && Hovered == ToolTip.Element ) { - u32 now = os::Timer::getTime (); + // When the mouse is over the ToolTip we remove that so it will be re-created at a new position. + // Note that ToolTip.EnterTime does not get changed here, so it will be re-created at once. + ToolTip.Element->remove(); + ToolTip.Element->drop(); + ToolTip.Element = 0; - if (Hovered != this) - Hovered->grab(); + // Get the real Hovered + Hovered = getElementFromPoint(mousePos); + } - if (Hovered != lastHovered) + // for tooltips we want the element itself and not some of it's subelements + HoveredNoSubelement = Hovered; + while ( HoveredNoSubelement && HoveredNoSubelement->isSubElement() ) + { + HoveredNoSubelement = HoveredNoSubelement->getParent(); + } + + if (Hovered && Hovered != this) + Hovered->grab(); + if ( HoveredNoSubelement && HoveredNoSubelement != this) + HoveredNoSubelement->grab(); + + if (Hovered != lastHovered) + { + SEvent event; + event.EventType = EET_GUI_EVENT; + + if (lastHovered) { - SEvent event; - event.EventType = EET_GUI_EVENT; + event.GUIEvent.Caller = lastHovered; + event.GUIEvent.Element = 0; + event.GUIEvent.EventType = EGET_ELEMENT_LEFT; + lastHovered->OnEvent(event); + } - if (lastHovered) - { - event.GUIEvent.Caller = lastHovered; - event.GUIEvent.EventType = EGET_ELEMENT_LEFT; - lastHovered->OnEvent(event); - } - - if ( ToolTip.Element ) - { - ToolTip.Element->remove(); - ToolTip.Element->drop(); - ToolTip.Element = 0; - ToolTip.LastTime += 500; - } - else - { - // boost tooltip generation for relaunch - if ( now - ToolTip.LastTime < ToolTip.LastTime ) - { - ToolTip.LastTime += 500; - } - else - { - ToolTip.LastTime = now; - } - } - - - event.GUIEvent.Caller = Hovered; + if ( Hovered ) + { + event.GUIEvent.Caller = Hovered; + event.GUIEvent.Element = Hovered; event.GUIEvent.EventType = EGET_ELEMENT_HOVERED; Hovered->OnEvent(event); } - } + } + + if ( lastHoveredNoSubelement != HoveredNoSubelement ) + { + if (ToolTip.Element) + { + ToolTip.Element->remove(); + ToolTip.Element->drop(); + ToolTip.Element = 0; + } + + if ( HoveredNoSubelement ) + { + u32 now = os::Timer::getTime(); + ToolTip.EnterTime = now; + } + } if (lastHovered && lastHovered != this) lastHovered->drop(); + if (lastHoveredNoSubelement && lastHoveredNoSubelement != this) + lastHoveredNoSubelement->drop(); } @@ -526,8 +576,8 @@ bool CGUIEnvironment::postEventFromUser(const SEvent& event) case EET_KEY_INPUT_EVENT: { // send focus changing event - if (event.EventType == EET_KEY_INPUT_EVENT && - event.KeyInput.PressedDown && + if (event.EventType == EET_KEY_INPUT_EVENT && + event.KeyInput.PressedDown && event.KeyInput.Key == KEY_TAB) { IGUIElement *next = getNextElement(event.KeyInput.Shift, event.KeyInput.Control); @@ -655,7 +705,7 @@ IGUIElement* CGUIEnvironment::addGUIElement(const c8* elementName, IGUIElement* //! Saves the current gui into a file. //! \param filename: Name of the file . -bool CGUIEnvironment::saveGUI(const c8* filename, IGUIElement* start) +bool CGUIEnvironment::saveGUI(const io::path& filename, IGUIElement* start) { io::IWriteFile* file = FileSystem->createAndWriteFile(filename); if (!file) @@ -697,7 +747,7 @@ bool CGUIEnvironment::saveGUI(io::IWriteFile* file, IGUIElement* start) //! Loads the gui. Note that the current gui is not cleared before. //! \param filename: Name of the file. -bool CGUIEnvironment::loadGUI(const c8* filename, IGUIElement* parent) +bool CGUIEnvironment::loadGUI(const io::path& filename, IGUIElement* parent) { io::IReadFile* read = FileSystem->createAndOpenFile(filename); if (!read) @@ -732,7 +782,7 @@ bool CGUIEnvironment::loadGUI(io::IReadFile* file, IGUIElement* parent) _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } - + // read file while(reader->read()) { @@ -741,34 +791,33 @@ bool CGUIEnvironment::loadGUI(io::IReadFile* file, IGUIElement* parent) // finish up - reader->drop(); - return true; + reader->drop(); + return true; } //! reads an element -void CGUIEnvironment::readGUIElement(io::IXMLReader* reader, IGUIElement* parent) +void CGUIEnvironment::readGUIElement(io::IXMLReader* reader, IGUIElement* node) { if (!reader) return; - gui::IGUIElement* node = 0; - io::EXML_NODE nodeType = reader->getNodeType(); if (nodeType == io::EXN_NONE || nodeType == io::EXN_UNKNOWN || nodeType == io::EXN_ELEMENT_END) return; - if (!parent && !wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName())) + if (!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName())) { - node = this; // root + if (!node) + node = this; // root } else if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName())) { // find node type and create it - core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE); + const core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE); - node = addGUIElement(attrName.c_str(), parent); + node = addGUIElement(attrName.c_str(), node); if (!node) os::Printer::log("Could not create GUI element of unknown type", attrName.c_str()); @@ -810,7 +859,7 @@ void CGUIEnvironment::readGUIElement(io::IXMLReader* reader, IGUIElement* parent else { os::Printer::log("Found unknown element in irrlicht GUI file", - core::stringc(reader->getNodeName()).c_str()); + core::stringc(reader->getNodeName()).c_str()); } break; @@ -918,9 +967,9 @@ void CGUIEnvironment::deserializeAttributes(io::IAttributes* in, io::SAttributeR } - RelativeRect = AbsoluteRect = - core::rect(core::position2d(0,0), - Driver ? Driver->getScreenSize() : core::dimension2d(0,0)); + RelativeRect = AbsoluteRect = + core::rect(core::position2d(0,0), + Driver ? core::dimension2di(Driver->getScreenSize()) : core::dimension2d(0,0)); } @@ -940,22 +989,25 @@ IGUIButton* CGUIEnvironment::addButton(const core::rect& rectangle, IGUIEle //! adds a window. The returned pointer must not be dropped. -IGUIWindow* CGUIEnvironment::addWindow(const core::rect& rectangle, bool modal, +IGUIWindow* CGUIEnvironment::addWindow(const core::rect& rectangle, bool modal, const wchar_t* text, IGUIElement* parent, s32 id) { parent = parent ? parent : this; - if (modal) - { - parent = new CGUIModalScreen(this, parent, -1); - parent->drop(); - } - IGUIWindow* win = new CGUIWindow(this, parent, id, rectangle); if (text) win->setText(text); win->drop(); + if (modal) + { + // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very + // careful not to get virtual function call, like OnEvent, in the window. + CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); + modalScreen->drop(); + modalScreen->addChild(win); + } + return win; } @@ -974,7 +1026,7 @@ IGUIElement* CGUIEnvironment::addModalScreen(IGUIElement* parent) //! Adds a message box. IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t* text, - bool modal, s32 flag, IGUIElement* parent, s32 id) + bool modal, s32 flag, IGUIElement* parent, s32 id, video::ITexture* image) { if (!CurrentSkin) return 0; @@ -982,28 +1034,32 @@ IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t parent = parent ? parent : this; core::rect rect; - core::dimension2d screenDim, msgBoxDim; + core::dimension2d screenDim, msgBoxDim; screenDim.Width = parent->getAbsolutePosition().getWidth(); screenDim.Height = parent->getAbsolutePosition().getHeight(); - msgBoxDim.Width = CurrentSkin->getSize(gui::EGDS_MESSAGE_BOX_WIDTH); - msgBoxDim.Height = CurrentSkin->getSize(gui::EGDS_MESSAGE_BOX_HEIGHT); + msgBoxDim.Width = 2; + msgBoxDim.Height = 2; rect.UpperLeftCorner.X = (screenDim.Width - msgBoxDim.Width) / 2; rect.UpperLeftCorner.Y = (screenDim.Height - msgBoxDim.Height) / 2; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + msgBoxDim.Width; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + msgBoxDim.Height; + IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag, + parent, id, rect, image); + win->drop(); + if (modal) { - parent = new CGUIModalScreen(this, parent, -1); - parent->drop(); + // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very + // careful not to get virtual function call, like OnEvent, in the CGUIMessageBox. + CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); + modalScreen->drop(); + modalScreen->addChild( win ); } - IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag, - parent, id, rect); - win->drop(); return win; } @@ -1016,6 +1072,7 @@ IGUIScrollBar* CGUIEnvironment::addScrollBar(bool horizontal, const core::rect& rectangle, IGUIElement* parent, s32 id, bool drawBackground) { CGUITable* b = new CGUITable(this, parent ? parent : this, id, rectangle, true, drawBackground, false); @@ -1023,13 +1080,14 @@ IGUITable* CGUIEnvironment::addTable(const core::rect& rectangle, IGUIEleme return b; } -//! Adds an image element. + +//! Adds an image element. IGUIImage* CGUIEnvironment::addImage(video::ITexture* image, core::position2d pos, bool useAlphaChannel, IGUIElement* parent, s32 id, const wchar_t* text) { core::dimension2d sz(0,0); if (image) - sz = image->getOriginalSize(); + sz = core::dimension2d(image->getOriginalSize()); IGUIImage* img = new CGUIImage(this, parent ? parent : this, id, core::rect(pos, sz)); @@ -1079,7 +1137,7 @@ IGUIMeshViewer* CGUIEnvironment::addMeshViewer(const core::rect& rectangle, //! adds a checkbox IGUICheckBox* CGUIEnvironment::addCheckBox(bool checked, const core::rect& rectangle, IGUIElement* parent, s32 id, const wchar_t* text) { - IGUICheckBox* b = new CGUICheckBox(checked, this, + IGUICheckBox* b = new CGUICheckBox(checked, this, parent ? parent : this , id , rectangle); if (text) @@ -1091,9 +1149,8 @@ IGUICheckBox* CGUIEnvironment::addCheckBox(bool checked, const core::rect& //! adds a list box -IGUIListBox* CGUIEnvironment::addListBox(const core::rect& rectangle, - IGUIElement* parent, s32 id, - bool drawBackground) +IGUIListBox* CGUIEnvironment::addListBox(const core::rect& rectangle, + IGUIElement* parent, s32 id, bool drawBackground) { IGUIListBox* b = new CGUIListBox(this, parent ? parent : this, id, rectangle, true, drawBackground, false); @@ -1111,54 +1168,70 @@ IGUIListBox* CGUIEnvironment::addListBox(const core::rect& rectangle, return b; } +//! adds a tree view +IGUITreeView* CGUIEnvironment::addTreeView(const core::rect& rectangle, + IGUIElement* parent, s32 id, + bool drawBackground, + bool scrollBarVertical, bool scrollBarHorizontal) +{ + IGUITreeView* b = new CGUITreeView(this, parent ? parent : this, id, rectangle, + true, drawBackground, scrollBarVertical, scrollBarHorizontal); + + b->setIconFont ( getBuiltInFont () ); + b->drop(); + return b; +} //! adds a file open dialog. The returned pointer must not be dropped. -IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title, - bool modal, - IGUIElement* parent, s32 id) +IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title, + bool modal, IGUIElement* parent, s32 id) { parent = parent ? parent : this; + IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id); + d->drop(); + if (modal) { - parent = new CGUIModalScreen(this, parent, -1); - parent->drop(); + // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very + // careful not to get virtual function call, like OnEvent, in the window. + CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); + modalScreen->drop(); + modalScreen->addChild(d); } - IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id); - - d->drop(); return d; } //! adds a color select dialog. The returned pointer must not be dropped. -IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* title, - bool modal, - IGUIElement* parent, s32 id) +IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* title, + bool modal, IGUIElement* parent, s32 id) { parent = parent ? parent : this; - if (modal) - { - parent = new CGUIModalScreen(this, parent, -1); - parent->drop(); - } - IGUIColorSelectDialog* d = new CGUIColorSelectDialog( title, this, parent, id); - d->drop(); + + if (modal) + { + // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very + // careful not to get virtual function call, like OnEvent, in the window. + CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); + modalScreen->drop(); + modalScreen->addChild(d); + } + return d; } //! adds a static text. The returned pointer must not be dropped. -IGUIStaticText* CGUIEnvironment::addStaticText(const wchar_t* text, - const core::rect& rectangle, - bool border, bool wordWrap, - IGUIElement* parent, s32 id, - bool background) +IGUIStaticText* CGUIEnvironment::addStaticText(const wchar_t* text, + const core::rect& rectangle, + bool border, bool wordWrap, + IGUIElement* parent, s32 id, bool background) { IGUIStaticText* d = new CGUIStaticText(text, border, this, parent ? parent : this, id, rectangle, background); @@ -1171,10 +1244,9 @@ IGUIStaticText* CGUIEnvironment::addStaticText(const wchar_t* text, //! Adds an edit box. The returned pointer must not be dropped. -IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text, - const core::rect& rectangle, - bool border, IGUIElement* parent, - s32 id) +IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text, + const core::rect& rectangle, bool border, + IGUIElement* parent, s32 id) { IGUIEditBox* d = new CGUIEditBox(text, border, this, parent ? parent : this, id, rectangle); @@ -1185,11 +1257,12 @@ IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text, //! Adds a spin box to the environment -IGUISpinBox* CGUIEnvironment::addSpinBox(const wchar_t* text, - const core::rect &rectangle, - IGUIElement* parent, s32 id) +IGUISpinBox* CGUIEnvironment::addSpinBox(const wchar_t* text, + const core::rect &rectangle, + bool border,IGUIElement* parent, s32 id) { - IGUISpinBox* d = new CGUISpinBox(text, this, parent ? parent : this, id, rectangle); + IGUISpinBox* d = new CGUISpinBox(text, border,this, + parent ? parent : this, id, rectangle); d->drop(); return d; @@ -1207,7 +1280,7 @@ IGUITabControl* CGUIEnvironment::addTabControl(const core::rect& rectangle, } -//! Adds tab to the environment. +//! Adds tab to the environment. IGUITab* CGUIEnvironment::addTab(const core::rect& rectangle, IGUIElement* parent, s32 id) { @@ -1222,7 +1295,7 @@ IGUITab* CGUIEnvironment::addTab(const core::rect& rectangle, IGUIContextMenu* CGUIEnvironment::addContextMenu(const core::rect& rectangle, IGUIElement* parent, s32 id) { - IGUIContextMenu* c = new CGUIContextMenu(this, + IGUIContextMenu* c = new CGUIContextMenu(this, parent ? parent : this, id, rectangle, true); c->drop(); return c; @@ -1235,7 +1308,7 @@ IGUIContextMenu* CGUIEnvironment::addMenu(IGUIElement* parent, s32 id) if (!parent) parent = this; - IGUIContextMenu* c = new CGUIMenu(this, + IGUIContextMenu* c = new CGUIMenu(this, parent, id, core::rect(0,0, parent->getAbsolutePosition().getWidth(), parent->getAbsolutePosition().getHeight())); @@ -1265,9 +1338,8 @@ IGUIInOutFader* CGUIEnvironment::addInOutFader(const core::rect* rectangle, if (rectangle) rect = *rectangle; - else - if (Driver) - rect = core::rect(core::position2d(0,0), Driver->getScreenSize()); + else if (Driver) + rect = core::rect(core::position2d(0,0), core::dimension2di(Driver->getScreenSize())); if (!parent) parent = this; @@ -1290,18 +1362,12 @@ IGUIComboBox* CGUIEnvironment::addComboBox(const core::rect& rectangle, //! returns the font -IGUIFont* CGUIEnvironment::getFont(const c8* filename) +IGUIFont* CGUIEnvironment::getFont(const io::path& filename) { // search existing font SFont f; - IGUIFont* ifont=0; - if (!filename) - f.Filename = ""; - else - f.Filename = filename; - - f.Filename.make_lower(); + f.NamedPath.setPath(filename); s32 index = Fonts.binary_search(f); if (index != -1) @@ -1313,11 +1379,12 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) if (!FileSystem->existFile(filename)) { - os::Printer::log("Could not load font because the file does not exist", f.Filename.c_str(), ELL_ERROR); + os::Printer::log("Could not load font because the file does not exist", f.NamedPath.getPath(), ELL_ERROR); return 0; } - io::IXMLReader *xml = FileSystem->createXMLReader(filename); + IGUIFont* ifont=0; + io::IXMLReader *xml = FileSystem->createXMLReader(filename ); if (xml) { // this is an XML font, but we need to know what type @@ -1350,8 +1417,8 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) CGUIFont* font = new CGUIFont(this, filename); ifont = (IGUIFont*)font; // change working directory, for loading textures - core::stringc workingDir = FileSystem->getWorkingDirectory(); - FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.Filename).c_str()); + io::path workingDir = FileSystem->getWorkingDirectory(); + FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.NamedPath.getPath())); // load the font if (!font->load(xml)) @@ -1361,12 +1428,12 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) ifont = 0; } // change working dir back again - FileSystem->changeWorkingDirectoryTo( workingDir.c_str()); + FileSystem->changeWorkingDirectoryTo( workingDir ); } else if (t==EGFT_VECTOR) { // todo: vector fonts - os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.Filename.c_str(), ELL_ERROR); + os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.NamedPath, ELL_ERROR); //CGUIFontVector* font = new CGUIFontVector(Driver); //ifont = (IGUIFont*)font; @@ -1379,9 +1446,9 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) if (!ifont) { - CGUIFont* font = new CGUIFont(this, f.Filename.c_str()); + CGUIFont* font = new CGUIFont(this, f.NamedPath.getPath() ); ifont = (IGUIFont*)font; - if (!font->load(f.Filename.c_str())) + if (!font->load(f.NamedPath.getPath())) { font->drop(); return 0; @@ -1397,57 +1464,21 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) } -IGUISpriteBank* CGUIEnvironment::getSpriteBank(const c8* filename) +//! add an externally loaded font +IGUIFont* CGUIEnvironment::addFont(const io::path& name, IGUIFont* font) { - // search for the file name - - SSpriteBank b; - if (!filename) - b.Filename = ""; - else - b.Filename = filename; - - b.Filename.make_lower(); - - s32 index = Banks.binary_search(b); - if (index != -1) - return Banks[index].Bank; - - // we don't have this sprite bank, we should load it - - if (!FileSystem->existFile(b.Filename.c_str())) + if (font) { - os::Printer::log("Could not load sprite bank because the file does not exist", filename, ELL_ERROR); - return 0; + SFont f; + f.NamedPath.setPath(name); + s32 index = Fonts.binary_search(f); + if (index != -1) + return Fonts[index].Font; + f.Font = font; + Fonts.push_back(f); + font->grab(); } - - // todo: load it! - - return 0; -} - - -IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const c8 *name) -{ - // no duplicate names allowed - - SSpriteBank b; - if (!name) - b.Filename = ""; - else - b.Filename = name; - - const s32 index = Banks.binary_search(b); - if (index != -1) - return 0; - - // create a new sprite bank - - b.Bank = new CGUISpriteBank(this); - - Banks.push_back(b); - - return b.Bank; + return font; } @@ -1461,7 +1492,66 @@ IGUIFont* CGUIEnvironment::getBuiltInFont() const } -//! Returns the root gui element. +IGUISpriteBank* CGUIEnvironment::getSpriteBank(const io::path& filename) +{ + // search for the file name + + SSpriteBank b; + b.NamedPath.setPath(filename); + + s32 index = Banks.binary_search(b); + if (index != -1) + return Banks[index].Bank; + + // we don't have this sprite bank, we should load it + + if (!FileSystem->existFile(b.NamedPath.getPath())) + { + os::Printer::log("Could not load sprite bank because the file does not exist", b.NamedPath.getPath(), ELL_ERROR); + return 0; + } + + // todo: load it! + + return 0; +} + + +IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const io::path& name) +{ + // no duplicate names allowed + + SSpriteBank b; + b.NamedPath.setPath(name); + + const s32 index = Banks.binary_search(b); + if (index != -1) + return 0; + + // create a new sprite bank + + b.Bank = new CGUISpriteBank(this); + Banks.push_back(b); + + return b.Bank; +} + + +//! Creates the image list from the given texture. +IGUIImageList* CGUIEnvironment::createImageList( video::ITexture* texture, + core::dimension2d imageSize, bool useAlphaChannel ) +{ + CGUIImageList* imageList = new CGUIImageList( Driver ); + if( !imageList->createImageList( texture, imageSize, useAlphaChannel ) ) + { + imageList->drop(); + return 0; + } + + return imageList; +} + +//! Returns the root gui element. IGUIElement* CGUIEnvironment::getRootGUIElement() { return this; @@ -1480,13 +1570,13 @@ IGUIElement* CGUIEnvironment::getNextElement(bool reverse, bool group) { startOrder = startPos->getTabOrder(); } - else + else if (!group && Focus && !Focus->isTabGroup()) { startOrder = Focus->getTabOrder(); if (startOrder == -1) { - // this element is not part of the tab cycle, + // this element is not part of the tab cycle, // but its parent might be... IGUIElement *el = Focus; while (el && el->getParent() && startOrder == -1) @@ -1531,4 +1621,3 @@ IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs, #endif // _IRR_COMPILE_WITH_GUI_ - diff --git a/src/dep/src/irrlicht/CGUIEnvironment.h b/src/dep/src/irrlicht/CGUIEnvironment.h index dac1c36..18fa097 100644 --- a/src/dep/src/irrlicht/CGUIEnvironment.h +++ b/src/dep/src/irrlicht/CGUIEnvironment.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -70,20 +70,30 @@ public: See IReferenceCounted::drop() for more information. */ virtual IGUISkin* createSkin(EGUI_SKIN_TYPE type); + //! Creates the image list from the given texture. + virtual IGUIImageList* createImageList( video::ITexture* texture, + core::dimension2d imageSize, bool useAlphaChannel ); + //! returns the font - virtual IGUIFont* getFont(const c8* filename); + virtual IGUIFont* getFont(const io::path& filename); + + //! add an externally loaded font + virtual IGUIFont* addFont(const io::path& name, IGUIFont* font); + + //! returns default font + virtual IGUIFont* getBuiltInFont() const; //! returns the sprite bank - virtual IGUISpriteBank* getSpriteBank(const c8* filename); + virtual IGUISpriteBank* getSpriteBank(const io::path& filename); //! returns the sprite bank - virtual IGUISpriteBank* addEmptySpriteBank(const c8* name); + virtual IGUISpriteBank* addEmptySpriteBank(const io::path& name); //! adds an button. The returned pointer must not be dropped. virtual IGUIButton* addButton(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext = 0); //! adds a window. The returned pointer must not be dropped. - virtual IGUIWindow* addWindow(const core::rect& rectangle, bool modal = false, + virtual IGUIWindow* addWindow(const core::rect& rectangle, bool modal = false, const wchar_t* text=0, IGUIElement* parent=0, s32 id=-1); //! adds a modal screen. The returned pointer must not be dropped. @@ -91,17 +101,18 @@ public: //! Adds a message box. virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0, - bool modal = true, s32 flag = EMBF_OK, IGUIElement* parent=0, s32 id=-1); + bool modal = true, s32 flag = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0); //! adds a scrollbar. The returned pointer must not be dropped. - virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1); + virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1); - //! Adds an image element. + //! Adds an image element. virtual IGUIImage* addImage(video::ITexture* image, core::position2d pos, bool useAlphaChannel=true, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0); //! adds an image. The returned pointer must not be dropped. - virtual IGUIImage* addImage(const core::rect& rectangle, + virtual IGUIImage* addImage(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0); //! adds a checkbox @@ -111,6 +122,11 @@ public: virtual IGUIListBox* addListBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false); + //! adds a tree view + virtual IGUITreeView* addTreeView(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, bool drawBackground=false, + bool scrollBarVertical = true, bool scrollBarHorizontal = false); + //! adds an mesh viewer. The returned pointer must not be dropped. virtual IGUIMeshViewer* addMeshViewer(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0); @@ -125,18 +141,18 @@ public: bool border=false, bool wordWrap=true, IGUIElement* parent=0, s32 id=-1, bool drawBackground = false); //! Adds an edit box. The returned pointer must not be dropped. - virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect& rectangle, + virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect& rectangle, bool border=false, IGUIElement* parent=0, s32 id=-1); //! Adds a spin box to the environment - virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, - IGUIElement* parent=0, s32 id=-1); + virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, + bool border=false,IGUIElement* parent=0, s32 id=-1); //! Adds a tab control to the environment. virtual IGUITabControl* addTabControl(const core::rect& rectangle, IGUIElement* parent=0, bool fillbackground=false, bool border=true, s32 id=-1); - //! Adds tab to the environment. + //! Adds tab to the environment. virtual IGUITab* addTab(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1); @@ -156,7 +172,7 @@ public: IGUIElement* parent=0, s32 id=-1); //! Adds a table element. - virtual IGUITable* addTable(const core::rect& rectangle, + virtual IGUITable* addTable(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false); //! sets the focus to an element @@ -171,13 +187,10 @@ public: //! Returns the element with the focus virtual IGUIElement* getFocus() const; - //! returns default font - virtual IGUIFont* getBuiltInFont() const; - //! Adds an element for fading in or out. virtual IGUIInOutFader* addInOutFader(const core::rect* rectangle=0, IGUIElement* parent=0, s32 id=-1); - //! Returns the root gui element. + //! Returns the root gui element. virtual IGUIElement* getRootGUIElement(); virtual void OnPostRender( u32 time ); @@ -201,27 +214,27 @@ public: //! Saves the current gui into a file. /** \param filename: Name of the file. - \param start: The element to start saving from. - if not specified, the root element will be used */ - virtual bool saveGUI(const c8* filename, IGUIElement* start=0); + \param start: The element to start saving from. + if not specified, the root element will be used */ + virtual bool saveGUI( const io::path& filename, IGUIElement* start=0); //! Saves the current gui into a file. /** \param file: The file to save the GUI to. - \param start: The element to start saving from. + \param start: The element to start saving from. if not specified, the root element will be used */ virtual bool saveGUI(io::IWriteFile* file, IGUIElement* start=0); //! Loads the gui. Note that the current gui is not cleared before. /** \param filename: Name of the file. - \param parent: The parent of all loaded GUI elements, + \param parent: The parent of all loaded GUI elements, if not specified, the root element will be used */ - virtual bool loadGUI(const c8* filename, IGUIElement* parent=0); + virtual bool loadGUI(const io::path& filename, IGUIElement* parent=0); //! Loads the gui. Note that the current gui is not cleared before. /** \param file: IReadFile to load the GUI from - \param parent: The parent of all loaded GUI elements, + \param parent: The parent of all loaded GUI elements, if not specified, the root element will be used */ - virtual bool loadGUI(io::IReadFile* file, IGUIElement* parent=0); + virtual bool loadGUI(io::IReadFile* file, IGUIElement* parent=0); //! Writes attributes of the environment virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; @@ -233,8 +246,7 @@ public: virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* node); //! reads an element - virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* parent); - + virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node); private: @@ -246,31 +258,33 @@ private: struct SFont { - core::stringc Filename; + io::SNamedPath NamedPath; IGUIFont* Font; bool operator < (const SFont& other) const { - return (Filename < other.Filename); + return (NamedPath < other.NamedPath); } }; struct SSpriteBank { - core::stringc Filename; + io::SNamedPath NamedPath; IGUISpriteBank* Bank; bool operator < (const SSpriteBank& other) const { - return (Filename < other.Filename); + return (NamedPath < other.NamedPath); } }; struct SToolTip { - u32 LastTime; - u32 LaunchTime; IGUIStaticText* Element; + u32 LastTime; + u32 EnterTime; + u32 LaunchTime; + u32 RelaunchTime; }; SToolTip ToolTip; @@ -281,6 +295,7 @@ private: core::array Banks; video::IVideoDriver* Driver; IGUIElement* Hovered; + IGUIElement* HoveredNoSubelement; // subelements replaced by their parent, so you only have 'real' elements here IGUIElement* Focus; core::position2d LastHoveredMousePos; IGUISkin* CurrentSkin; diff --git a/src/dep/src/irrlicht/CGUIFileOpenDialog.cpp b/src/dep/src/irrlicht/CGUIFileOpenDialog.cpp index 3c7a183..eb35259 100644 --- a/src/dep/src/irrlicht/CGUIFileOpenDialog.cpp +++ b/src/dep/src/irrlicht/CGUIFileOpenDialog.cpp @@ -1,10 +1,12 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIFileOpenDialog.h" #ifdef _IRR_COMPILE_WITH_GUI_ +#include + #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" @@ -32,7 +34,7 @@ CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title, (parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2, (parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2+FOD_WIDTH, (parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2+FOD_HEIGHT)), - Dragging(false), FileNameText(0), FileList(0) + FileNameText(0), FileList(0), Dragging(false) { #ifdef _DEBUG IGUIElement::setDebugName("CGUIFileOpenDialog"); @@ -49,8 +51,8 @@ CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title, color = skin->getColor(EGDC_WINDOW_SYMBOL); } - s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH); - s32 posx = RelativeRect.getWidth() - buttonw - 4; + const s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH); + const s32 posx = RelativeRect.getWidth() - buttonw - 4; CloseButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close"); @@ -84,7 +86,7 @@ CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title, FileBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); FileBox->grab(); - FileNameText = Environment->addStaticText(0, core::rect(10, 30, RelativeRect.getWidth()-90, 50), true, false, this); + FileNameText = Environment->addEditBox(0, core::rect(10, 30, RelativeRect.getWidth()-90, 50), true, this); FileNameText->setSubElement(true); FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); FileNameText->grab(); @@ -132,6 +134,13 @@ const wchar_t* CGUIFileOpenDialog::getFileName() const return FileName.c_str(); } +//! Returns the directory of the selected file. Returns NULL, if no directory was selected. +const io::path& CGUIFileOpenDialog::getDirectoryName() +{ + FileSystem->flattenFilename ( FileDirectory ); + return FileDirectory; +} + //! called if an event happened. bool CGUIFileOpenDialog::OnEvent(const SEvent& event) @@ -155,11 +164,18 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event) return true; } else - if (event.GUIEvent.Caller == OKButton && FileName != L"") + if (event.GUIEvent.Caller == OKButton ) { - sendSelectedEvent(); - remove(); - return true; + if ( FileDirectory != L"" ) + { + sendSelectedEvent( EGET_DIRECTORY_SELECTED ); + } + if ( FileName != L"" ) + { + sendSelectedEvent( EGET_FILE_SELECTED ); + remove(); + return true; + } } break; @@ -169,9 +185,16 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event) if (FileList && FileSystem) { if (FileList->isDirectory(selected)) + { FileName = L""; + FileDirectory = FileList->getFullFileName(selected); + } else + { + FileDirectory = L""; FileName = FileList->getFullFileName(selected); + } + return true; } } break; @@ -183,18 +206,31 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event) { if (FileList->isDirectory(selected)) { + FileDirectory = FileList->getFullFileName(selected); FileSystem->changeWorkingDirectoryTo(FileList->getFileName(selected)); fillListBox(); - FileName = L""; + FileName = ""; } else { FileName = FileList->getFullFileName(selected); - return true; } + return true; } } break; + case EGET_EDITBOX_ENTER: + if (event.GUIEvent.Caller == FileNameText) + { + io::path dir( FileNameText->getText () ); + if ( FileSystem->changeWorkingDirectoryTo( dir ) ) + { + fillListBox(); + FileName = L""; + } + return true; + } + break; default: break; } @@ -214,6 +250,10 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event) Dragging = false; return true; case EMIE_MOUSE_MOVED: + + if ( !event.MouseInput.isLeftPressed () ) + Dragging = false; + if (Dragging) { // gui window should not be dragged outside its parent @@ -288,28 +328,55 @@ void CGUIFileOpenDialog::fillListBox() FileList = FileSystem->createFileList(); core::stringw s; - for (u32 i=0; igetFileCount(); ++i) +#if !defined(_IRR_WINDOWS_CE_PLATFORM_) + setlocale(LC_ALL,""); +#endif + + if (FileList) { - s = FileList->getFileName(i); - FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE)); + for (u32 i=0; i < FileList->getFileCount(); ++i) + { + #ifndef _IRR_WCHAR_FILESYSTEM + const c8 *cs = (const c8 *)FileList->getFileName(i).c_str(); + wchar_t *ws = new wchar_t[strlen(cs) + 1]; + int len = mbstowcs(ws,cs,strlen(cs)); + ws[len] = 0; + s = ws; + delete [] ws; + #else + s = FileList->getFileName(i).c_str(); + #endif + FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE)); + } } if (FileNameText) { + #ifndef _IRR_WCHAR_FILESYSTEM + const c8 *cs = (const c8 *)FileSystem->getWorkingDirectory().c_str(); + wchar_t *ws = new wchar_t[strlen(cs) + 1]; + int len = mbstowcs(ws,cs,strlen(cs)); + ws[len] = 0; + s = ws; + delete [] ws; + #else s = FileSystem->getWorkingDirectory(); + #endif + + FileDirectory = s; FileNameText->setText(s.c_str()); } } //! sends the event that the file has been selected. -void CGUIFileOpenDialog::sendSelectedEvent() +void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type) { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; - event.GUIEvent.EventType = EGET_FILE_SELECTED; + event.GUIEvent.EventType = type; Parent->OnEvent(event); } diff --git a/src/dep/src/irrlicht/CGUIFileOpenDialog.h b/src/dep/src/irrlicht/CGUIFileOpenDialog.h index 3af2ece..815fb0e 100644 --- a/src/dep/src/irrlicht/CGUIFileOpenDialog.h +++ b/src/dep/src/irrlicht/CGUIFileOpenDialog.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,6 +11,7 @@ #include "IGUIFileOpenDialog.h" #include "IGUIButton.h" #include "IGUIListBox.h" +#include "IGUIEditBox.h" #include "IFileSystem.h" namespace irr @@ -31,6 +32,9 @@ namespace gui //! returns the filename of the selected file. Returns NULL, if no file was selected. virtual const wchar_t* getFileName() const; + //! Returns the directory of the selected file. Returns NULL, if no directory was selected. + virtual const io::path& getDirectoryName(); + //! called if an event happened. virtual bool OnEvent(const SEvent& event); @@ -43,23 +47,24 @@ namespace gui void fillListBox(); //! sends the event that the file has been selected. - void sendSelectedEvent(); + void sendSelectedEvent( EGUI_EVENT_TYPE type ); //! sends the event that the file choose process has been canceld void sendCancelEvent(); core::position2d DragStart; core::stringw FileName; - bool Dragging; + io::path FileDirectory; + IGUIButton* CloseButton; IGUIButton* OKButton; IGUIButton* CancelButton; IGUIListBox* FileBox; - IGUIElement* FileNameText; + IGUIEditBox* FileNameText; IGUIElement* EventParent; io::IFileSystem* FileSystem; - io::IFileList* FileList; + bool Dragging; }; diff --git a/src/dep/src/irrlicht/CGUIFont.cpp b/src/dep/src/irrlicht/CGUIFont.cpp index d07da50..6ce2bf3 100644 --- a/src/dep/src/irrlicht/CGUIFont.cpp +++ b/src/dep/src/irrlicht/CGUIFont.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -19,7 +19,7 @@ namespace gui { //! constructor -CGUIFont::CGUIFont(IGUIEnvironment *env, const c8* filename) +CGUIFont::CGUIFont(IGUIEnvironment *env, const io::path& filename) : Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0), MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0) { @@ -39,6 +39,8 @@ CGUIFont::CGUIFont(IGUIEnvironment *env, const c8* filename) if (Driver) Driver->grab(); + + setInvisibleCharacters ( L" " ); } @@ -78,7 +80,7 @@ bool CGUIFont::load(io::IXMLReader* xml) Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); // load texture - SpriteBank->setTexture(i, Driver->getTexture(fn.c_str())); + SpriteBank->setTexture(i, Driver->getTexture(fn)); // set previous mip-map+filter state Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap); @@ -96,7 +98,7 @@ bool CGUIFont::load(io::IXMLReader* xml) if (alpha == core::stringw("false")) Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0)); } - } + } else if (core::stringw(L"c") == xml->getNodeName()) { // adding a character to this font @@ -112,45 +114,45 @@ bool CGUIFont::load(io::IXMLReader* xml) // parse rectangle core::stringc rectstr = xml->getAttributeValue(L"r"); - wchar_t ch = xml->getAttributeValue(L"c")[0]; + wchar_t ch = xml->getAttributeValue(L"c")[0]; const c8 *c = rectstr.c_str(); s32 val; val = 0; - while (*c >= '0' && *c <= '9') - { - val *= 10; - val += *c - '0'; + while (*c >= '0' && *c <= '9') + { + val *= 10; + val += *c - '0'; c++; } rectangle.UpperLeftCorner.X = val; while (*c == L' ' || *c == L',') c++; val = 0; - while (*c >= '0' && *c <= '9') - { - val *= 10; - val += *c - '0'; + while (*c >= '0' && *c <= '9') + { + val *= 10; + val += *c - '0'; c++; } rectangle.UpperLeftCorner.Y = val; while (*c == L' ' || *c == L',') c++; val = 0; - while (*c >= '0' && *c <= '9') - { - val *= 10; - val += *c - '0'; + while (*c >= '0' && *c <= '9') + { + val *= 10; + val += *c - '0'; c++; } rectangle.LowerRightCorner.X = val; while (*c == L' ' || *c == L',') c++; val = 0; - while (*c >= '0' && *c <= '9') - { - val *= 10; - val += *c - '0'; + while (*c >= '0' && *c <= '9') + { + val *= 10; + val += *c - '0'; c++; } rectangle.LowerRightCorner.Y = val; @@ -158,7 +160,7 @@ bool CGUIFont::load(io::IXMLReader* xml) CharacterMap.insert(ch,Areas.size()); // make frame - f.rectNumber = SpriteBank->getPositions().size(); + f.rectNumber = SpriteBank->getPositions().size(); f.textureNumber = texno; // add frame to sprite @@ -216,17 +218,18 @@ bool CGUIFont::load(io::IReadFile* file) //! loads a font file, native file needed, for texture parsing -bool CGUIFont::load(const c8* filename) +bool CGUIFont::load(const io::path& filename) { if (!Driver) return false; + return loadTexture(Driver->createImageFromFile( filename ), filename); } //! load & prepare font from ITexture -bool CGUIFont::loadTexture(video::IImage* image, const c8* name) +bool CGUIFont::loadTexture(video::IImage* image, const io::path& name) { if (!image) return false; @@ -238,18 +241,20 @@ bool CGUIFont::loadTexture(video::IImage* image, const c8* name) switch(image->getColorFormat()) { case video::ECF_R5G6B5: - tmpImage = new video::CImage(video::ECF_A1R5G5B5,image); + tmpImage = new video::CImage(video::ECF_A1R5G5B5,image->getDimension()); + image->copyTo(tmpImage); deleteTmpImage=true; + break; case video::ECF_A1R5G5B5: - readPositions16bit(tmpImage, lowerRightPositions); + case video::ECF_A8R8G8B8: break; case video::ECF_R8G8B8: - tmpImage = new video::CImage(video::ECF_A8R8G8B8,image); + tmpImage = new video::CImage(video::ECF_A8R8G8B8,image->getDimension()); + image->copyTo(tmpImage); deleteTmpImage=true; - case video::ECF_A8R8G8B8: - readPositions32bit (tmpImage, lowerRightPositions); break; } + readPositions(tmpImage, lowerRightPositions); WrongCharacter = getAreaFromCharacter(L' '); @@ -262,10 +267,19 @@ bool CGUIFont::loadTexture(video::IImage* image, const c8* name) bool ret = ( !SpriteBank->getSprites().empty() && lowerRightPositions ); - if ( ret ) { + bool flag[2]; + flag[0] = Driver->getTextureCreationFlag ( video::ETCF_ALLOW_NON_POWER_2 ); + flag[1] = Driver->getTextureCreationFlag ( video::ETCF_CREATE_MIP_MAPS ); + + Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, true); + Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false ); + SpriteBank->addTexture(Driver->addTexture(name, tmpImage)); + + Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, flag[0] ); + Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flag[1] ); } if (deleteTmpImage) tmpImage->drop(); @@ -277,132 +291,43 @@ bool CGUIFont::loadTexture(video::IImage* image, const c8* name) } -void CGUIFont::readPositions32bit(video::IImage* image, s32& lowerRightPositions) +void CGUIFont::readPositions(video::IImage* image, s32& lowerRightPositions) { - const core::dimension2d& size = image->getDimension(); + const core::dimension2d size = image->getDimension(); - s32* p = (s32*)image->lock(); - if (!p) - { - os::Printer::log("Could not lock texture while preparing texture for a font.", ELL_ERROR); - return; - } + video::SColor colorTopLeft = image->getPixel(0,0); + colorTopLeft.setAlpha(255); + image->setPixel(0,0,colorTopLeft); + video::SColor colorLowerRight = image->getPixel(1,0); + video::SColor colorBackGround = image->getPixel(2,0); + video::SColor colorBackGroundTransparent = 0; - // fix half alpha of top left pixel in some font textures - p[0] |= 0xFF000000; - - s32 colorTopLeft = p[0]; - s32 colorLowerRight = *(p+1); - s32 colorBackGround = *(p+2); - s32 colorBackGroundTransparent = 0; // 0x00FFFFFF & colorBackGround; - - *(p+1) = colorBackGround; + image->setPixel(1,0,colorBackGround); // start parsing core::position2d pos(0,0); - for (pos.Y=0; pos.YgetPixel(pos.X, pos.Y); + if (c == colorTopLeft) { - *p = colorBackGroundTransparent; + image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); SpriteBank->getPositions().push_back(core::rect(pos, pos)); } else - if (*p == colorLowerRight) - { - if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions) - { - image->unlock(); - lowerRightPositions = 0; - return; - } - - *p = colorBackGroundTransparent; - SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos; - // add frame to sprite bank - SGUISpriteFrame f; - f.rectNumber = lowerRightPositions; - f.textureNumber = 0; - SGUISprite s; - s.Frames.push_back(f); - s.frameTime = 0; - SpriteBank->getSprites().push_back(s); - // add character to font - SFontArea a; - a.overhang = 0; - a.underhang = 0; - a.spriteno = lowerRightPositions; - a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth(); - Areas.push_back(a); - // map letter to character - wchar_t ch = (wchar_t)(lowerRightPositions + 32); - CharacterMap.set(ch, lowerRightPositions); - - ++lowerRightPositions; - } - else - if (*p == colorBackGround) - { - *p = colorBackGroundTransparent; - } - ++p; - } - } - - // Positions parsed. - - image->unlock(); -} - - -void CGUIFont::readPositions16bit(video::IImage* image, s32& lowerRightPositions) -{ - core::dimension2d size = image->getDimension(); - - s16* p = (s16*)image->lock(); - if (!p) - { - os::Printer::log("Could not lock texture while preparing texture for a font.", ELL_ERROR); - return; - } - - // fix half alpha of top left pixel in some font textures - p[0] |= 0x8000; - - s16 colorTopLeft = p[0]; - s16 colorLowerRight = *(p+1); - s16 colorBackGround = *(p+2); - s16 colorBackGroundTransparent = 0; // 0x7FFF & colorBackGround; - - *(p+1) = colorBackGround; - - // start parsing - - core::position2d pos(0,0); - for (pos.Y=0; pos.YgetPositions().push_back(core::rect(pos, pos)); - } - else - if (*p == colorLowerRight) + if (c == colorLowerRight) { // too many lower right points if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions) { - image->unlock(); lowerRightPositions = 0; return; } - *p = colorBackGroundTransparent; + image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos; // add frame to sprite bank SGUISpriteFrame f; @@ -426,23 +351,80 @@ void CGUIFont::readPositions16bit(video::IImage* image, s32& lowerRightPositions ++lowerRightPositions; } else - if (*p == colorBackGround) - *p = colorBackGroundTransparent; - ++p; + if (c == colorBackGround) + image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); + } + } +} + + +//! set an Pixel Offset on Drawing ( scale position on width ) +void CGUIFont::setKerningWidth(s32 kerning) +{ + GlobalKerningWidth = kerning; +} + + +//! set an Pixel Offset on Drawing ( scale position on width ) +s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const +{ + s32 ret = GlobalKerningWidth; + + if (thisLetter) + { + ret += Areas[getAreaFromCharacter(*thisLetter)].overhang; + + if (previousLetter) + { + ret += Areas[getAreaFromCharacter(*previousLetter)].underhang; } } - // Positions parsed. + return ret; +} - image->unlock(); + +//! set an Pixel Offset on Drawing ( scale position on height ) +void CGUIFont::setKerningHeight(s32 kerning) +{ + GlobalKerningHeight = kerning; +} + + +//! set an Pixel Offset on Drawing ( scale position on height ) +s32 CGUIFont::getKerningHeight () const +{ + return GlobalKerningHeight; +} + + +//! returns the sprite number from a given character +u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const +{ + return Areas[getAreaFromCharacter(*c)].spriteno; +} + + +s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const +{ + core::map::Node* n = CharacterMap.find(c); + if (n) + return n->getValue(); + else + return WrongCharacter; +} + +void CGUIFont::setInvisibleCharacters( const wchar_t *s ) +{ + Invisible = s; } //! returns the dimension of text -core::dimension2d CGUIFont::getDimension(const wchar_t* text) const +core::dimension2d CGUIFont::getDimension(const wchar_t* text) const { - core::dimension2d dim(0, 0); - core::dimension2d thisLine(0, MaxHeight); + core::dimension2d dim(0, 0); + core::dimension2d thisLine(0, MaxHeight); for (const wchar_t* p = text; *p; ++p) { @@ -479,118 +461,26 @@ core::dimension2d CGUIFont::getDimension(const wchar_t* text) const return dim; } - -//! set an Pixel Offset on Drawing ( scale position on width ) -void CGUIFont::setKerningWidth ( s32 kerning ) -{ - GlobalKerningWidth = kerning; -} - - -//! set an Pixel Offset on Drawing ( scale position on width ) -s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const -{ - s32 ret = GlobalKerningWidth; - - if (thisLetter) - { - ret += Areas[getAreaFromCharacter(*thisLetter)].overhang; - - if (previousLetter) - { - ret += Areas[getAreaFromCharacter(*previousLetter)].underhang; - } - } - - return ret; -} - - -//! set an Pixel Offset on Drawing ( scale position on height ) -void CGUIFont::setKerningHeight ( s32 kerning ) -{ - GlobalKerningHeight = kerning; -} - - -//! set an Pixel Offset on Drawing ( scale position on height ) -s32 CGUIFont::getKerningHeight () const -{ - return GlobalKerningHeight; -} - - -//! returns the sprite number from a given character -u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const -{ - return Areas[getAreaFromCharacter(*c)].spriteno; -} - - -s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const -{ - core::map::Node* n = CharacterMap.find(c); - if (n) - return n->getValue(); - else - return WrongCharacter; -} - - -/* -//! draws an text and clips it to the specified rectangle if wanted -void CGUIFont::draw(const wchar_t* text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip) -{ - if (!Driver) - return; - - core::dimension2d textDimension; - core::position2d offset = position.UpperLeftCorner; - - if (hcenter || vcenter) - { - textDimension = getDimension(text); - - if (hcenter) - offset.X = ((position.getWidth() - textDimension.Width)>>1) + offset.X; - - if (vcenter) - offset.Y = ((position.getHeight() - textDimension.Height)>>1) + offset.Y; - } - - core::array indices; - indices.reallocate(core::stringw(text).size()); - u32 n; - while(*text) - { - n = (*text) - 32; - if ( n > Positions.size()) - n = WrongCharacter; - indices.push_back(n); - ++text; - } - Driver->draw2DImage(Texture, offset, Positions, indices, GlobalKerningWidth, clip, color, true); -} -*/ - - //! draws some text and clips it to the specified rectangle if wanted -void CGUIFont::draw(const wchar_t* text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip) +void CGUIFont::draw(const core::stringw& text, const core::rect& position, + video::SColor color, + bool hcenter, bool vcenter, const core::rect* clip + ) { if (!Driver) return; - core::dimension2d textDimension; + core::dimension2d textDimension; // NOTE: don't make this u32 or the >> later on can fail when the dimension widht is < position width core::position2d offset = position.UpperLeftCorner; if (hcenter || vcenter || clip) - textDimension = getDimension(text); + textDimension = getDimension(text.c_str()); if (hcenter) - offset.X = ((position.getWidth() - textDimension.Width)>>1) + offset.X; + offset.X += (position.getWidth() - textDimension.Width) >> 1; if (vcenter) - offset.Y = ((position.getHeight() - textDimension.Height)>>1) + offset.Y; + offset.Y += (position.getHeight() - textDimension.Height) >> 1; if (clip) { @@ -600,18 +490,50 @@ void CGUIFont::draw(const wchar_t* text, const core::rect& position, video: return; } - while(*text) + core::array indices(text.size()); + core::array offsets(text.size()); + + for(u32 i = 0;i < text.size();i++) { - SFontArea& area = Areas[getAreaFromCharacter(*text)]; + wchar_t c = text[i]; + + bool lineBreak=false; + if ( c == L'\r') // Mac or Windows breaks + { + lineBreak = true; + if ( text[i + 1] == L'\n') // Windows breaks + c = text[++i]; + } + else if ( c == L'\n') // Unix breaks + { + lineBreak = true; + } + + if (lineBreak) + { + offset.Y += MaxHeight; + offset.X = position.UpperLeftCorner.X; + + if ( hcenter ) + { + offset.X += (position.getWidth() - textDimension.Width) >> 1; + } + continue; + } + + SFontArea& area = Areas[getAreaFromCharacter(c)]; offset.X += area.underhang; - - SpriteBank->draw2DSprite(area.spriteno, offset, clip, color); + if ( Invisible.findFirst ( c ) < 0 ) + { + indices.push_back(area.spriteno); + offsets.push_back(offset); + } offset.X += area.width + area.overhang + GlobalKerningWidth; - - ++text; } + + SpriteBank->draw2DSpriteBatch(indices, offsets, clip, color); } @@ -625,7 +547,7 @@ s32 CGUIFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const { const SFontArea& a = Areas[getAreaFromCharacter(text[idx])]; - x += a.width + a.overhang + a.underhang; + x += a.width + a.overhang + a.underhang + GlobalKerningWidth; if (x >= pixel_x) return idx; @@ -646,3 +568,4 @@ IGUISpriteBank* CGUIFont::getSpriteBank() const } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ + diff --git a/src/dep/src/irrlicht/CGUIFont.h b/src/dep/src/irrlicht/CGUIFont.h index 9884d02..2362760 100644 --- a/src/dep/src/irrlicht/CGUIFont.h +++ b/src/dep/src/irrlicht/CGUIFont.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -34,13 +34,13 @@ class CGUIFont : public IGUIFontBitmap public: //! constructor - CGUIFont(IGUIEnvironment* env, const c8* filename); + CGUIFont(IGUIEnvironment* env, const io::path& filename); //! destructor virtual ~CGUIFont(); //! loads a font from a texture file - bool load(const c8* filename); + bool load(const io::path& filename); //! loads a font from a texture file bool load(io::IReadFile* file); @@ -49,12 +49,12 @@ public: bool load(io::IXMLReader* xml); //! draws an text and clips it to the specified rectangle if wanted - virtual void draw(const wchar_t* text, const core::rect& position, + virtual void draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0); //! returns the dimension of a text - virtual core::dimension2d getDimension(const wchar_t* text) const; + virtual core::dimension2d getDimension(const wchar_t* text) const; //! Calculates the index of the character in the text which is on a specific position. virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const; @@ -76,6 +76,8 @@ public: //! returns the sprite number from a given character virtual u32 getSpriteNoFromChar(const wchar_t *c) const; + virtual void setInvisibleCharacters( const wchar_t *s ); + private: struct SFontArea @@ -88,10 +90,9 @@ private: }; //! load & prepare font from ITexture - bool loadTexture(video::IImage * image, const c8* name); + bool loadTexture(video::IImage * image, const io::path& name); - void readPositions16bit(video::IImage* texture, s32& lowerRightPositions); - void readPositions32bit(video::IImage* texture, s32& lowerRightPositions); + void readPositions(video::IImage* texture, s32& lowerRightPositions); s32 getAreaFromCharacter (const wchar_t c) const; void setMaxHeight(); @@ -104,6 +105,8 @@ private: u32 WrongCharacter; s32 MaxHeight; s32 GlobalKerningWidth, GlobalKerningHeight; + + core::stringw Invisible; }; } // end namespace gui diff --git a/src/dep/src/irrlicht/CGUIImage.cpp b/src/dep/src/irrlicht/CGUIImage.cpp index 1a11232..7044c05 100644 --- a/src/dep/src/irrlicht/CGUIImage.cpp +++ b/src/dep/src/irrlicht/CGUIImage.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -15,11 +15,10 @@ namespace gui { - //! constructor CGUIImage::CGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) -: IGUIImage(environment, parent, id, rectangle), Color(255,255,255,255), - Texture(0), UseAlphaChannel(false), ScaleImage(false) +: IGUIImage(environment, parent, id, rectangle), Texture(0), Color(255,255,255,255), + UseAlphaChannel(false), ScaleImage(false) { #ifdef _DEBUG setDebugName("CGUIImage"); @@ -27,7 +26,6 @@ CGUIImage::CGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, } - //! destructor CGUIImage::~CGUIImage() { @@ -36,7 +34,6 @@ CGUIImage::~CGUIImage() } - //! sets an image void CGUIImage::setImage(video::ITexture* image) { @@ -77,14 +74,14 @@ void CGUIImage::draw() { const video::SColor Colors[] = {Color,Color,Color,Color}; - driver->draw2DImage(Texture, AbsoluteRect, - core::rect(core::position2d(0,0), Texture->getOriginalSize()), + driver->draw2DImage(Texture, AbsoluteRect, + core::rect(core::position2d(0,0), core::dimension2di(Texture->getOriginalSize())), &AbsoluteClippingRect, Colors, UseAlphaChannel); } else { - driver->draw2DImage(Texture, AbsoluteRect.UpperLeftCorner, - core::rect(core::position2d(0,0), Texture->getOriginalSize()), + driver->draw2DImage(Texture, AbsoluteRect.UpperLeftCorner, + core::rect(core::position2d(0,0), core::dimension2di(Texture->getOriginalSize())), &AbsoluteClippingRect, Color, UseAlphaChannel); } } @@ -103,12 +100,14 @@ void CGUIImage::setUseAlphaChannel(bool use) UseAlphaChannel = use; } + //! sets if the image should use its alpha channel to draw itself void CGUIImage::setScaleImage(bool scale) { ScaleImage = scale; } + //! Returns true if the image is scaled to fit, false if not bool CGUIImage::isImageScaled() const { @@ -136,6 +135,7 @@ void CGUIImage::serializeAttributes(io::IAttributes* out, io::SAttributeReadWrit } + //! Reads attributes of the element void CGUIImage::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { @@ -148,10 +148,9 @@ void CGUIImage::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWri } - - } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ + diff --git a/src/dep/src/irrlicht/CGUIImage.h b/src/dep/src/irrlicht/CGUIImage.h index 171cef5..d070ff3 100644 --- a/src/dep/src/irrlicht/CGUIImage.h +++ b/src/dep/src/irrlicht/CGUIImage.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -52,10 +52,9 @@ namespace gui //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); - private: - video::SColor Color; video::ITexture* Texture; + video::SColor Color; bool UseAlphaChannel; bool ScaleImage; diff --git a/src/dep/src/irrlicht/CGUIImageList.cpp b/src/dep/src/irrlicht/CGUIImageList.cpp new file mode 100644 index 0000000..e02030d --- /dev/null +++ b/src/dep/src/irrlicht/CGUIImageList.cpp @@ -0,0 +1,93 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de +// modified by Thomas Alten + +#include "CGUIImageList.h" + + +namespace irr +{ +namespace gui +{ + +//! constructor +CGUIImageList::CGUIImageList( video::IVideoDriver* driver ) + : Driver( driver ), + Texture( 0 ), + ImageCount( 0 ), + ImageSize( 0, 0 ), + ImagesPerRow( 0 ), + UseAlphaChannel( false ) +{ + #ifdef _DEBUG + setDebugName( "CGUIImageList" ); + #endif + + if( Driver ) + { + Driver->grab(); + } +} + + + +//! destructor +CGUIImageList::~CGUIImageList() +{ + if( Driver ) + { + Driver->drop(); + } + + if( Texture ) + { + Texture->drop(); + } +} + + +//! Creates the image list from texture. +bool CGUIImageList::createImageList(video::ITexture* texture, + core::dimension2d imageSize, + bool useAlphaChannel) +{ + if( !texture ) + { + return false; + } + + Texture = texture; + Texture->grab(); + + ImageSize = imageSize; + + ImagesPerRow = Texture->getSize().Width / ImageSize.Width; + ImageCount = ImagesPerRow * Texture->getSize().Height / ImageSize.Height; + + UseAlphaChannel = useAlphaChannel; + + return true; +} + +//! Draws an image and clips it to the specified rectangle if wanted +void CGUIImageList::draw( s32 index, const core::position2d& destPos, + const core::rect* clip /*= 0*/ ) +{ + core::rect sourceRect; + + if( !Driver || index < 0 || index >= ImageCount ) + { + return; + } + + sourceRect.UpperLeftCorner.X = ( index % ImagesPerRow ) * ImageSize.Width; + sourceRect.UpperLeftCorner.Y = ( index / ImagesPerRow ) * ImageSize.Height; + sourceRect.LowerRightCorner.X = sourceRect.UpperLeftCorner.X + ImageSize.Width; + sourceRect.LowerRightCorner.Y = sourceRect.UpperLeftCorner.Y + ImageSize.Height; + + Driver->draw2DImage( Texture, destPos, sourceRect, clip, + video::SColor( 255, 255, 255, 255 ), UseAlphaChannel ); +} + +} // end namespace gui +} // end namespace irr diff --git a/src/dep/src/irrlicht/CGUIImageList.h b/src/dep/src/irrlicht/CGUIImageList.h new file mode 100644 index 0000000..18221c8 --- /dev/null +++ b/src/dep/src/irrlicht/CGUIImageList.h @@ -0,0 +1,68 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de + +#ifndef __C_GUI_IMAGE_LIST_H_INCLUDED__ +#define __C_GUI_IMAGE_LIST_H_INCLUDED__ + +#include "IGUIImageList.h" +#include "IVideoDriver.h" + +namespace irr +{ +namespace gui +{ + +class CGUIImageList : public IGUIImageList +{ +public: + + //! constructor + CGUIImageList( video::IVideoDriver* Driver ); + + //! destructor + virtual ~CGUIImageList(); + + //! Creates the image list from texture. + //! \param texture: The texture to use + //! \param imageSize: Size of a single image + //! \param useAlphaChannel: true if the alpha channel from the texture should be used + //! \return + //! true if the image list was created + bool createImageList( + video::ITexture* texture, + core::dimension2d imageSize, + bool useAlphaChannel ); + + //! Draws an image and clips it to the specified rectangle if wanted + //! \param index: Index of the image + //! \param destPos: Position of the image to draw + //! \param clip: Optional pointer to a rectalgle against which the text will be clipped. + //! If the pointer is null, no clipping will be done. + virtual void draw( s32 index, const core::position2d& destPos, + const core::rect* clip = 0 ); + + //! Returns the count of Images in the list. + //! \return Returns the count of Images in the list. + virtual s32 getImageCount() const + { return ImageCount; } + + //! Returns the size of the images in the list. + //! \return Returns the size of the images in the list. + virtual core::dimension2d getImageSize() const + { return ImageSize; } + +private: + + video::IVideoDriver* Driver; + video::ITexture* Texture; + s32 ImageCount; + core::dimension2d ImageSize; + s32 ImagesPerRow; + bool UseAlphaChannel; +}; + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/src/dep/src/irrlicht/CGUIInOutFader.cpp b/src/dep/src/irrlicht/CGUIInOutFader.cpp index e89304f..9f1fa54 100644 --- a/src/dep/src/irrlicht/CGUIInOutFader.cpp +++ b/src/dep/src/irrlicht/CGUIInOutFader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -63,7 +63,6 @@ void CGUIInOutFader::draw() } - //! Gets the color to fade out to or to fade in from. video::SColor CGUIInOutFader::getColor() const { @@ -71,7 +70,6 @@ video::SColor CGUIInOutFader::getColor() const } - //! Sets the color to fade out to or to fade in from. void CGUIInOutFader::setColor(video::SColor color) { @@ -90,7 +88,7 @@ void CGUIInOutFader::setColor(video::SColor color) if (Action == EFA_FADE_OUT) { - FullColor.setAlpha(0); + FullColor.setAlpha(0); TransColor.setAlpha(255); } else @@ -102,6 +100,7 @@ void CGUIInOutFader::setColor(video::SColor color) */ } + void CGUIInOutFader::setColor(video::SColor source, video::SColor dest) { Color[0] = source; @@ -123,7 +122,7 @@ void CGUIInOutFader::setColor(video::SColor source, video::SColor dest) //! Returns if the fade in or out process is done. -bool CGUIInOutFader::isReady() const +bool CGUIInOutFader::isReady() const { u32 now = os::Timer::getTime(); bool ret = (now > EndTime); @@ -132,7 +131,6 @@ bool CGUIInOutFader::isReady() const } - //! Starts the fade in process. void CGUIInOutFader::fadeIn(u32 time) { @@ -152,6 +150,7 @@ void CGUIInOutFader::fadeOut(u32 time) setColor(Color[0],Color[1]); } + //! Writes attributes of the element. void CGUIInOutFader::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { @@ -162,6 +161,7 @@ void CGUIInOutFader::serializeAttributes(io::IAttributes* out, io::SAttributeRea } + //! Reads attributes of the element void CGUIInOutFader::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { @@ -172,7 +172,6 @@ void CGUIInOutFader::deserializeAttributes(io::IAttributes* in, io::SAttributeRe } - } // end namespace gui } // end namespace irr diff --git a/src/dep/src/irrlicht/CGUIInOutFader.h b/src/dep/src/irrlicht/CGUIInOutFader.h index 7cf58b0..0618f62 100644 --- a/src/dep/src/irrlicht/CGUIInOutFader.h +++ b/src/dep/src/irrlicht/CGUIInOutFader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -59,12 +59,11 @@ namespace gui u32 StartTime; u32 EndTime; - EFadeAction Action; + EFadeAction Action; video::SColor Color[2]; video::SColor FullColor; video::SColor TransColor; - }; } // end namespace gui diff --git a/src/dep/src/irrlicht/CGUIListBox.cpp b/src/dep/src/irrlicht/CGUIListBox.cpp index 6f88037..251cedf 100644 --- a/src/dep/src/irrlicht/CGUIListBox.cpp +++ b/src/dep/src/irrlicht/CGUIListBox.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,11 +23,11 @@ namespace gui CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool clip, bool drawBack, bool moveOverSelect) -: IGUIListBox(environment, parent, id, rectangle), Selected(-1), ItemHeight(0), +: IGUIListBox(environment, parent, id, rectangle), Selected(-1), + ItemHeight(0),ItemHeightOverride(0), TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0), - ScrollBar(0), Selecting(false), DrawBack(drawBack), - MoveOverSelect(moveOverSelect), selectTime(0), AutoScroll(true), - KeyBuffer(), LastKeyTime(0), HighlightWhenNotFocused(true) + ScrollBar(0), selectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack), + MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true) { #ifdef _DEBUG setDebugName("CGUIListBox"); @@ -36,17 +36,14 @@ CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, IGUISkin* skin = Environment->getSkin(); const s32 s = skin->getSize(EGDS_SCROLLBAR_SIZE); - ScrollBar = new CGUIScrollBar(false, Environment, this, 0, + ScrollBar = new CGUIScrollBar(false, Environment, this, -1, core::rect(RelativeRect.getWidth() - s, 0, RelativeRect.getWidth(), RelativeRect.getHeight()), !clip); ScrollBar->setSubElement(true); ScrollBar->setTabStop(false); ScrollBar->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); ScrollBar->setVisible(false); - ScrollBar->drop(); - ScrollBar->setPos(0); - ScrollBar->grab(); setNotClipped(!clip); @@ -152,17 +149,23 @@ void CGUIListBox::recalculateItemHeight() Font->drop(); Font = skin->getFont(); - ItemHeight = 0; + if ( 0 == ItemHeightOverride ) + ItemHeight = 0; if (Font) { - ItemHeight = Font->getDimension(L"A").Height + 4; + if ( 0 == ItemHeightOverride ) + ItemHeight = Font->getDimension(L"A").Height + 4; + Font->grab(); } } TotalItemHeight = ItemHeight * Items.size(); ScrollBar->setMax(TotalItemHeight - AbsoluteRect.getHeight()); + s32 minItemHeight = ItemHeight > 0 ? ItemHeight : 1; + ScrollBar->setSmallStep ( minItemHeight ); + ScrollBar->setLargeStep ( 2*minItemHeight ); if ( TotalItemHeight <= AbsoluteRect.getHeight() ) ScrollBar->setVisible(false); @@ -191,6 +194,21 @@ void CGUIListBox::setSelected(s32 id) recalculateScrollPos(); } +//! sets the selected item. Set this to -1 if no item should be selected +void CGUIListBox::setSelected(const wchar_t *item) +{ + s32 index = -1; + + if ( item ) + { + for ( index = 0; index < (s32) Items.size(); ++index ) + { + if ( Items[index].text == item ) + break; + } + } + setSelected ( index ); +} //! called if an event happened. bool CGUIListBox::OnEvent(const SEvent& event) @@ -370,7 +388,7 @@ bool CGUIListBox::OnEvent(const SEvent& event) switch(event.MouseInput.Event) { case EMIE_MOUSE_WHEEL: - ScrollBar->setPos(ScrollBar->getPos() + (s32)event.MouseInput.Wheel*-10); + ScrollBar->setPos(ScrollBar->getPos() + (s32)event.MouseInput.Wheel*-ItemHeight/2); return true; case EMIE_LMOUSE_PRESSED_DOWN: @@ -432,6 +450,8 @@ void CGUIListBox::selectNew(s32 ypos, bool onlyHover) recalculateScrollPos(); + gui::EGUI_EVENT_TYPE eventType = (Selected == oldSelected && now < selectTime + 500) ? EGET_LISTBOX_SELECTED_AGAIN : EGET_LISTBOX_CHANGED; + selectTime = now; // post the news if (Parent && !onlyHover) { @@ -439,10 +459,9 @@ void CGUIListBox::selectNew(s32 ypos, bool onlyHover) event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; - event.GUIEvent.EventType = (Selected == oldSelected && now < selectTime + 500) ? EGET_LISTBOX_SELECTED_AGAIN : EGET_LISTBOX_CHANGED; + event.GUIEvent.EventType = eventType; Parent->OnEvent(event); } - selectTime = now; } @@ -577,6 +596,8 @@ u32 CGUIListBox::addItem(const wchar_t* text, s32 icon) void CGUIListBox::setSpriteBank(IGUISpriteBank* bank) { + if ( bank == IconBank ) + return; if (IconBank) IconBank->drop(); @@ -856,6 +877,20 @@ video::SColor CGUIListBox::getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) con } } +//! set global itemHeight +void CGUIListBox::setItemHeight( s32 height ) +{ + ItemHeight = height; + ItemHeightOverride = 1; +} + + +//! Sets whether to draw the background +void CGUIListBox::setDrawBackground(bool draw) +{ + DrawBack = draw; +} + } // end namespace gui } // end namespace irr diff --git a/src/dep/src/irrlicht/CGUIListBox.h b/src/dep/src/irrlicht/CGUIListBox.h index 88e51f8..2e4f9e5 100644 --- a/src/dep/src/irrlicht/CGUIListBox.h +++ b/src/dep/src/irrlicht/CGUIListBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,7 +23,7 @@ namespace gui { public: //! constructor - CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, + CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool clip=true, bool drawBack=false, bool moveOverSelect=false); @@ -48,6 +48,9 @@ namespace gui //! sets the selected item. Set this to -1 if no item should be selected virtual void setSelected(s32 id); + //! sets the selected item. Set this to -1 if no item should be selected + virtual void setSelected(const wchar_t *item); + //! called if an event happened. virtual bool OnEvent(const SEvent& event); @@ -72,8 +75,8 @@ namespace gui //! An icon is an index within the icon sprite bank. Several default icons are available in the //! skin through getIcon virtual void setSpriteBank(IGUISpriteBank* bank); - - //! sets if automatic scrolling is enabled or not. Default is true. + + //! set whether the listbox should scroll to newly selected items virtual void setAutoScrollEnabled(bool scroll); //! returns true if automatic scrolling is enabled, false if not. @@ -97,33 +100,40 @@ namespace gui //! clear all item colors at index virtual void clearItemOverrideColor(u32 index); - //! clear item color at index for given colortype + //! clear item color at index for given colortype virtual void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType); //! has the item at index its color overwritten? virtual bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const; - //! return the overwrite color at given item index. + //! return the overwrite color at given item index. virtual video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const; //! return the default color which is used for the given colorType virtual video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const; - //! set the item at the given index + //! set the item at the given index virtual void setItem(u32 index, const wchar_t* text, s32 icon); - //! Insert the item at the given index + //! Insert the item at the given index //! Return the index on success or -1 on failure. virtual s32 insertItem(u32 index, const wchar_t* text, s32 icon); //! Swap the items at the given indices virtual void swapItems(u32 index1, u32 index2); + //! set global itemHeight + virtual void setItemHeight( s32 height ); + + //! Sets whether to draw the background + virtual void setDrawBackground(bool draw); + + private: struct ListItem { - ListItem() : icon(-1) + ListItem() : icon(-1) {} core::stringw text; @@ -152,18 +162,19 @@ namespace gui core::array< ListItem > Items; s32 Selected; s32 ItemHeight; + s32 ItemHeightOverride; s32 TotalItemHeight; s32 ItemsIconWidth; gui::IGUIFont* Font; gui::IGUISpriteBank* IconBank; gui::IGUIScrollBar* ScrollBar; + u32 selectTime; + u32 LastKeyTime; + core::stringw KeyBuffer; bool Selecting; bool DrawBack; bool MoveOverSelect; - u32 selectTime; bool AutoScroll; - core::stringw KeyBuffer; - u32 LastKeyTime; bool HighlightWhenNotFocused; }; diff --git a/src/dep/src/irrlicht/CGUIMenu.cpp b/src/dep/src/irrlicht/CGUIMenu.cpp index 542fed0..9dad2a0 100644 --- a/src/dep/src/irrlicht/CGUIMenu.cpp +++ b/src/dep/src/irrlicht/CGUIMenu.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,6 +9,7 @@ #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" +#include "IGUIWindow.h" #include "os.h" @@ -19,8 +20,8 @@ namespace gui //! constructor CGUIMenu::CGUIMenu(IGUIEnvironment* environment, IGUIElement* parent, - s32 id, core::rect rectangle) - : CGUIContextMenu(environment, parent, id, rectangle, false, true) + s32 id, core::rect rectangle) + : CGUIContextMenu(environment, parent, id, rectangle, false, true) { #ifdef _DEBUG setDebugName("CGUIMenu"); @@ -42,7 +43,7 @@ void CGUIMenu::draw() IGUISkin* skin = Environment->getSkin(); IGUIFont* font = skin->getFont(EGDF_MENU); - + if (font != LastFont) { if (LastFont) @@ -87,7 +88,7 @@ void CGUIMenu::draw() c = EGDC_GRAY_TEXT; if (font) - font->draw(Items[i].Text.c_str(), rect, + font->draw(Items[i].Text.c_str(), rect, skin->getColor(c), true, true, &AbsoluteClippingRect); } } @@ -135,26 +136,42 @@ bool CGUIMenu::OnEvent(const SEvent& event) } if (Parent) - Parent->bringToFront(this); + Parent->bringToFront(this); core::position2d p(event.MouseInput.X, event.MouseInput.Y); bool shouldCloseSubMenu = hasOpenSubMenu(); if (!AbsoluteClippingRect.isPointInside(p)) { shouldCloseSubMenu = false; + } + highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); + if ( shouldCloseSubMenu ) + { + Environment->removeFocus(this); + } + + return true; + } + case EMIE_LMOUSE_LEFT_UP: + { + core::position2d p(event.MouseInput.X, event.MouseInput.Y); + if (!AbsoluteClippingRect.isPointInside(p)) + { s32 t = sendClick(p); if ((t==0 || t==1) && Environment->hasFocus(this)) Environment->removeFocus(this); } - highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); - if ( shouldCloseSubMenu ) - closeAllSubMenus(); - - return true; + + return true; } case EMIE_MOUSE_MOVED: - if (Environment->hasFocus(this)) - highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), hasOpenSubMenu()); + if (Environment->hasFocus(this) && HighLighted >= 0) + { + s32 oldHighLighted = HighLighted; + highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); + if ( HighLighted < 0 ) + HighLighted = oldHighLighted; // keep last hightlight active when moving outside the area + } return true; default: break; @@ -168,28 +185,41 @@ bool CGUIMenu::OnEvent(const SEvent& event) return IGUIElement::OnEvent(event); } - void CGUIMenu::recalculateSize() { + core::rect clientRect; // client rect of parent + if ( Parent && Parent->hasType(EGUIET_WINDOW) ) + { + clientRect = static_cast(Parent)->getClientRect(); + } + else if ( Parent ) + { + clientRect = core::rect(0,0, Parent->getAbsolutePosition().getWidth(), + Parent->getAbsolutePosition().getHeight()); + } + else + { + clientRect = RelativeRect; + } + + IGUISkin* skin = Environment->getSkin(); IGUIFont* font = skin->getFont(EGDF_MENU); if (!font) { if (Parent && skin) - RelativeRect = core::rect(0,0, - Parent->getAbsolutePosition().LowerRightCorner.X, - skin->getSize(EGDS_MENU_HEIGHT)); + RelativeRect = core::rect(clientRect.UpperLeftCorner.X, clientRect.UpperLeftCorner.Y, + clientRect.LowerRightCorner.X, clientRect.UpperLeftCorner.Y+skin->getSize(EGDS_MENU_HEIGHT)); return; } core::rect rect; - rect.UpperLeftCorner.X = 0; - rect.UpperLeftCorner.Y = 0; + rect.UpperLeftCorner = clientRect.UpperLeftCorner; s32 height = font->getDimension(L"A").Height + 5; //if (skin && height < skin->getSize ( EGDS_MENU_HEIGHT )) // height = skin->getSize(EGDS_MENU_HEIGHT); - s32 width = 0; + s32 width = rect.UpperLeftCorner.X; s32 i; for (i=0; i<(s32)Items.size(); ++i) @@ -209,11 +239,10 @@ void CGUIMenu::recalculateSize() width += Items[i].Dim.Width; } - if (Parent) - width = Parent->getAbsolutePosition().getWidth(); + width = clientRect.getWidth(); - rect.LowerRightCorner.X = width; - rect.LowerRightCorner.Y = height; + rect.LowerRightCorner.X = rect.UpperLeftCorner.X + width; + rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + height; setRelativePosition(rect); @@ -241,12 +270,14 @@ core::rect CGUIMenu::getHRect(const SItem& i, const core::rect& absolu return r; } + //! Gets drawing rect of Item core::rect CGUIMenu::getRect(const SItem& i, const core::rect& absolute) const { return getHRect(i, absolute); } + void CGUIMenu::updateAbsolutePosition() { if (Parent) diff --git a/src/dep/src/irrlicht/CGUIMenu.h b/src/dep/src/irrlicht/CGUIMenu.h index 391dd86..c506187 100644 --- a/src/dep/src/irrlicht/CGUIMenu.h +++ b/src/dep/src/irrlicht/CGUIMenu.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -49,3 +49,4 @@ namespace gui #endif // __C_GUI_MENU_H_INCLUDED__ #endif // _IRR_COMPILE_WITH_GUI_ + diff --git a/src/dep/src/irrlicht/CGUIMeshViewer.cpp b/src/dep/src/irrlicht/CGUIMeshViewer.cpp index 99685da..bd80975 100644 --- a/src/dep/src/irrlicht/CGUIMeshViewer.cpp +++ b/src/dep/src/irrlicht/CGUIMeshViewer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -40,14 +40,12 @@ CGUIMeshViewer::~CGUIMeshViewer() //! sets the mesh to be shown void CGUIMeshViewer::setMesh(scene::IAnimatedMesh* mesh) { + if (mesh) + mesh->grab(); if (Mesh) Mesh->drop(); Mesh = mesh; - if (!Mesh) - return; - else - Mesh->grab(); /* This might be used for proper transformation etc. core::vector3df center(0.0f,0.0f,0.0f); @@ -172,4 +170,3 @@ void CGUIMeshViewer::draw() #endif // _IRR_COMPILE_WITH_GUI_ - diff --git a/src/dep/src/irrlicht/CGUIMeshViewer.h b/src/dep/src/irrlicht/CGUIMeshViewer.h index ee0b3ed..02ce363 100644 --- a/src/dep/src/irrlicht/CGUIMeshViewer.h +++ b/src/dep/src/irrlicht/CGUIMeshViewer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CGUIMessageBox.cpp b/src/dep/src/irrlicht/CGUIMessageBox.cpp index 8073e35..36c1932 100644 --- a/src/dep/src/irrlicht/CGUIMessageBox.cpp +++ b/src/dep/src/irrlicht/CGUIMessageBox.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,6 +9,7 @@ #include "IGUIEnvironment.h" #include "IGUIButton.h" #include "IGUIFont.h" +#include "ITexture.h" namespace irr { @@ -18,9 +19,10 @@ namespace gui //! constructor CGUIMessageBox::CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* caption, const wchar_t* text, s32 flags, - IGUIElement* parent, s32 id, core::rect rectangle) + IGUIElement* parent, s32 id, core::rect rectangle, video::ITexture* image) : CGUIWindow(environment, parent, id, rectangle), OkButton(0), CancelButton(0), YesButton(0), NoButton(0), StaticText(0), + Icon(0), IconTexture(image), Flags(flags), MessageText(text), Pressed(false) { #ifdef _DEBUG @@ -43,6 +45,9 @@ CGUIMessageBox::CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* capt Environment->setFocus(this); + if ( IconTexture ) + IconTexture->grab(); + refreshControls(); } @@ -64,61 +69,134 @@ CGUIMessageBox::~CGUIMessageBox() if (NoButton) NoButton->drop(); + + if (Icon) + Icon->drop(); + + if ( IconTexture ) + IconTexture->drop(); } +void CGUIMessageBox::setButton(IGUIButton*& button, bool isAvailable, const core::rect & btnRect, const wchar_t * text, IGUIElement*& focusMe) +{ + // add/remove ok button + if (isAvailable) + { + if (!button) + { + button = Environment->addButton(btnRect, this); + button->setSubElement(true); + button->grab(); + } + else + button->setRelativePosition(btnRect); + + button->setText(text); + + focusMe = button; + } + else if (button) + { + button->drop(); + button->remove(); + button =0; + } +} void CGUIMessageBox::refreshControls() { + // Layout can be seen as 4 boxes (a layoutmanager would be nice) + // One box at top over the whole width for title + // Two boxes with same height at the middle beside each other for icon and for text + // One box at the bottom for the buttons + const IGUISkin* skin = Environment->getSkin(); - IGUIElement* focusMe = 0; - const s32 buttonHeight = skin->getSize(EGDS_BUTTON_HEIGHT); - const s32 buttonWidth = skin->getSize(EGDS_BUTTON_WIDTH); - const s32 titleHeight = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH)+2; + const s32 buttonHeight = skin->getSize(EGDS_BUTTON_HEIGHT); + const s32 buttonWidth = skin->getSize(EGDS_BUTTON_WIDTH); + const s32 titleHeight = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH)+2; // titlebar has no own constant const s32 buttonDistance = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); + const s32 borderWidth = skin->getSize(EGDS_MESSAGE_BOX_GAP_SPACE); - // add static multiline text - - core::dimension2d dim(AbsoluteClippingRect.getWidth() - buttonWidth, - AbsoluteClippingRect.getHeight() - (buttonHeight * 3)); - const core::position2d pos((AbsoluteClippingRect.getWidth() - dim.Width) / 2, - buttonHeight / 2 + titleHeight); - + // add the static text for the message + core::rect staticRect; + staticRect.UpperLeftCorner.X = borderWidth; + staticRect.UpperLeftCorner.Y = titleHeight + borderWidth; + staticRect.LowerRightCorner.X = staticRect.UpperLeftCorner.X + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH); + staticRect.LowerRightCorner.Y = staticRect.UpperLeftCorner.Y + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT); if (!StaticText) { - StaticText = Environment->addStaticText(MessageText.c_str(), - core::rect(pos, dim), false, false, this); + StaticText = Environment->addStaticText(MessageText.c_str(), staticRect, false, false, this); + StaticText->setWordWrap(true); StaticText->setSubElement(true); StaticText->grab(); } else { - StaticText->setRelativePosition(core::rect(pos, dim)); + StaticText->setRelativePosition(staticRect); StaticText->setText(MessageText.c_str()); } - // adjust static text height + s32 textHeight = StaticText->getTextHeight(); + s32 textWidth = StaticText->getTextWidth() + 6; // +6 because the static itself needs that + const s32 iconHeight = IconTexture ? IconTexture->getOriginalSize().Height : 0; - const s32 textHeight = StaticText->getTextHeight(); - core::rect tmp = StaticText->getRelativePosition(); - tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + textHeight; - StaticText->setRelativePosition(tmp); - dim.Height = textHeight; + if ( textWidth < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) ) + textWidth = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) + 6; + // no neeed to check for max because it couldn't get larger due to statictextbox. + if ( textHeight < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT) ) + textHeight = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT); + if ( textHeight > skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT) ) + textHeight = skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT); - // adjust message box height + // content is text + icons + borders (but not titlebar) + s32 contentHeight = textHeight > iconHeight ? textHeight : iconHeight; + contentHeight += borderWidth; + s32 contentWidth = 0; - tmp = getRelativePosition(); - s32 msgBoxHeight = textHeight + core::floor32(2.5f * buttonHeight) + titleHeight; + // add icon + if ( IconTexture ) + { + core::position2d iconPos; + iconPos.Y = titleHeight + borderWidth; + if ( iconHeight < textHeight ) + iconPos.Y += (textHeight-iconHeight) / 2; + iconPos.X = borderWidth; - // adjust message box position + if (!Icon) + { + Icon = Environment->addImage(IconTexture, iconPos, true, this); + Icon->setSubElement(true); + Icon->grab(); + } + else + { + core::rect iconRect( iconPos.X, iconPos.Y, iconPos.X + IconTexture->getOriginalSize().Width, iconPos.Y + IconTexture->getOriginalSize().Height ); + Icon->setRelativePosition(iconRect); + } - tmp.UpperLeftCorner.Y = (Parent->getAbsolutePosition().getHeight() - msgBoxHeight) / 2; - tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + msgBoxHeight; - setRelativePosition(tmp); + contentWidth += borderWidth + IconTexture->getOriginalSize().Width; + } + else if ( Icon ) + { + Icon->drop(); + Icon->remove(); + Icon = 0; + } - // add buttons + // position text + core::rect textRect; + textRect.UpperLeftCorner.X = contentWidth + borderWidth; + textRect.UpperLeftCorner.Y = titleHeight + borderWidth; + if ( textHeight < iconHeight ) + textRect.UpperLeftCorner.Y += (iconHeight-textHeight) / 2; + textRect.LowerRightCorner.X = textRect.UpperLeftCorner.X + textWidth; + textRect.LowerRightCorner.Y = textRect.UpperLeftCorner.Y + textHeight; + contentWidth += 2*borderWidth + textWidth; + StaticText->setRelativePosition( textRect ); + // find out button size needs s32 countButtons = 0; if (Flags & EMBF_OK) ++countButtons; @@ -129,122 +207,44 @@ void CGUIMessageBox::refreshControls() if (Flags & EMBF_NO) ++countButtons; + s32 buttonBoxWidth = countButtons * buttonWidth + 2 * borderWidth; + if ( countButtons > 1 ) + buttonBoxWidth += (countButtons-1) * buttonDistance; + s32 buttonBoxHeight = buttonHeight + 2 * borderWidth; + + // calc new message box sizes + core::rect tmp = getRelativePosition(); + s32 msgBoxHeight = titleHeight + contentHeight + buttonBoxHeight; + s32 msgBoxWidth = contentWidth > buttonBoxWidth ? contentWidth : buttonBoxWidth; + + // adjust message box position + tmp.UpperLeftCorner.Y = (Parent->getAbsolutePosition().getHeight() - msgBoxHeight) / 2; + tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + msgBoxHeight; + tmp.UpperLeftCorner.X = (Parent->getAbsolutePosition().getWidth() - msgBoxWidth) / 2; + tmp.LowerRightCorner.X = tmp.UpperLeftCorner.X + msgBoxWidth; + setRelativePosition(tmp); + + // add buttons + core::rect btnRect; - btnRect.UpperLeftCorner.Y = pos.Y + dim.Height + buttonHeight / 2; + btnRect.UpperLeftCorner.Y = titleHeight + contentHeight + borderWidth; btnRect.LowerRightCorner.Y = btnRect.UpperLeftCorner.Y + buttonHeight; - btnRect.UpperLeftCorner.X = (AbsoluteClippingRect.getWidth() - - ((buttonWidth + buttonDistance)*countButtons)) / 2; + btnRect.UpperLeftCorner.X = borderWidth; + if ( contentWidth > buttonBoxWidth ) + btnRect.UpperLeftCorner.X += (contentWidth - buttonBoxWidth) / 2; // center buttons btnRect.LowerRightCorner.X = btnRect.UpperLeftCorner.X + buttonWidth; - // add/remove ok button - if (Flags & EMBF_OK) - { - if (!OkButton) - { - OkButton = Environment->addButton(btnRect, this); - OkButton->setSubElement(true); - OkButton->grab(); - } - else - OkButton->setRelativePosition(btnRect); - - OkButton->setText(skin->getDefaultText(EGDT_MSG_BOX_OK)); - - btnRect.LowerRightCorner.X += buttonWidth + buttonDistance; - btnRect.UpperLeftCorner.X += buttonWidth + buttonDistance; - - focusMe = OkButton; - } - else if (OkButton) - { - OkButton->drop(); - OkButton->remove(); - OkButton = 0; - } - - // add cancel button - if (Flags & EMBF_CANCEL) - { - if (!CancelButton) - { - CancelButton = Environment->addButton(btnRect, this); - CancelButton->setSubElement(true); - CancelButton->grab(); - } - else - CancelButton->setRelativePosition(btnRect); - - CancelButton->setText(skin->getDefaultText(EGDT_MSG_BOX_CANCEL)); - - btnRect.LowerRightCorner.X += buttonWidth + buttonDistance; - btnRect.UpperLeftCorner.X += buttonWidth + buttonDistance; - - if (!focusMe) - focusMe = CancelButton; - - } - else if (CancelButton) - { - CancelButton->drop(); - CancelButton->remove(); - CancelButton = 0; - } - - - // add/remove yes button - if (Flags & EMBF_YES) - { - if (!YesButton) - { - YesButton = Environment->addButton(btnRect, this); - YesButton->setSubElement(true); - YesButton->grab(); - } - else - YesButton->setRelativePosition(btnRect); - - YesButton->setText(skin->getDefaultText(EGDT_MSG_BOX_YES)); - - btnRect.LowerRightCorner.X += buttonWidth + buttonDistance; - btnRect.UpperLeftCorner.X += buttonWidth + buttonDistance; - - if (!focusMe) - focusMe = YesButton; - } - else if (YesButton) - { - YesButton->drop(); - YesButton->remove(); - YesButton = 0; - } - - // add no button - if (Flags & EMBF_NO) - { - if (!NoButton) - { - NoButton = Environment->addButton(btnRect, this); - NoButton->setSubElement(true); - NoButton->grab(); - } - else - NoButton->setRelativePosition(btnRect); - - NoButton->setText(skin->getDefaultText(EGDT_MSG_BOX_NO)); - - btnRect.LowerRightCorner.X += buttonWidth + buttonDistance; - btnRect.UpperLeftCorner.X += buttonWidth + buttonDistance; - - if (!focusMe) - focusMe = NoButton; - - } - else if (NoButton) - { - NoButton->drop(); - NoButton->remove(); - NoButton = 0; - } + IGUIElement* focusMe = 0; + setButton(OkButton, (Flags & EMBF_OK) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_OK), focusMe); + if ( Flags & EMBF_OK ) + btnRect += core::position2d(buttonWidth + buttonDistance, 0); + setButton(CancelButton, (Flags & EMBF_CANCEL) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_CANCEL), focusMe); + if ( Flags & EMBF_CANCEL ) + btnRect += core::position2d(buttonWidth + buttonDistance, 0); + setButton(YesButton, (Flags & EMBF_YES) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_YES), focusMe); + if ( Flags & EMBF_YES ) + btnRect += core::position2d(buttonWidth + buttonDistance, 0); + setButton(NoButton, (Flags & EMBF_NO) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_NO), focusMe); if (Environment->hasFocus(this) && focusMe) Environment->setFocus(focusMe); @@ -295,8 +295,8 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) { // cancel press if (OkButton) OkButton->setPressed(false); - if (YesButton) OkButton->setPressed(false); - if (NoButton) OkButton->setPressed(false); + if (YesButton) YesButton->setPressed(false); + if (NoButton) NoButton->setPressed(false); Pressed = false; } else @@ -321,6 +321,8 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) { if (OkButton && event.KeyInput.Key == KEY_RETURN) { + setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC + Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK; Parent->OnEvent(outevent); remove(); @@ -329,6 +331,8 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) else if ((CancelButton || CloseButton) && event.KeyInput.Key == KEY_ESCAPE) { + setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC + Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL; Parent->OnEvent(outevent); remove(); @@ -337,6 +341,8 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) else if (YesButton && event.KeyInput.Key == KEY_KEY_Y) { + setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC + Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES; Parent->OnEvent(outevent); remove(); @@ -345,6 +351,8 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) else if (NoButton && event.KeyInput.Key == KEY_KEY_N) { + setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC + Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO; Parent->OnEvent(outevent); remove(); @@ -357,6 +365,8 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) { if (event.GUIEvent.Caller == OkButton) { + setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC + Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK; Parent->OnEvent(outevent); remove(); @@ -366,6 +376,8 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) if (event.GUIEvent.Caller == CancelButton || event.GUIEvent.Caller == CloseButton) { + setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC + Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL; Parent->OnEvent(outevent); remove(); @@ -374,6 +386,8 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) else if (event.GUIEvent.Caller == YesButton) { + setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC + Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES; Parent->OnEvent(outevent); remove(); @@ -382,6 +396,8 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) else if (event.GUIEvent.Caller == NoButton) { + setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC + Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO; Parent->OnEvent(outevent); remove(); @@ -397,6 +413,7 @@ bool CGUIMessageBox::OnEvent(const SEvent& event) return CGUIWindow::OnEvent(event); } + //! Writes attributes of the element. void CGUIMessageBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { @@ -406,10 +423,12 @@ void CGUIMessageBox::serializeAttributes(io::IAttributes* out, io::SAttributeRea out->addBool ("CancelButton", (Flags & EMBF_CANCEL) != 0 ); out->addBool ("YesButton", (Flags & EMBF_YES) != 0 ); out->addBool ("NoButton", (Flags & EMBF_NO) != 0 ); + out->addTexture ("Texture", IconTexture); out->addString ("MessageText", MessageText.c_str()); } + //! Reads attributes of the element void CGUIMessageBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { @@ -420,6 +439,15 @@ void CGUIMessageBox::deserializeAttributes(io::IAttributes* in, io::SAttributeRe Flags |= in->getAttributeAsBool("YesButton") ? EMBF_YES : 0; Flags |= in->getAttributeAsBool("NoButton") ? EMBF_NO : 0; + if ( IconTexture ) + { + IconTexture->drop(); + IconTexture = NULL; + } + IconTexture = in->getAttributeAsTexture("Texture"); + if ( IconTexture ) + IconTexture->grab(); + MessageText = in->getAttributeAsStringW("MessageText").c_str(); CGUIWindow::deserializeAttributes(in,options); @@ -431,6 +459,5 @@ void CGUIMessageBox::deserializeAttributes(io::IAttributes* in, io::SAttributeRe } // end namespace gui } // end namespace irr - #endif // _IRR_COMPILE_WITH_GUI_ diff --git a/src/dep/src/irrlicht/CGUIMessageBox.h b/src/dep/src/irrlicht/CGUIMessageBox.h index 80cde84..ed0a2f3 100644 --- a/src/dep/src/irrlicht/CGUIMessageBox.h +++ b/src/dep/src/irrlicht/CGUIMessageBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -10,6 +10,7 @@ #include "CGUIWindow.h" #include "IGUIStaticText.h" +#include "IGUIImage.h" #include "irrArray.h" namespace irr @@ -23,7 +24,7 @@ namespace gui //! constructor CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* caption, const wchar_t* text, s32 flag, - IGUIElement* parent, s32 id, core::rect rectangle); + IGUIElement* parent, s32 id, core::rect rectangle, video::ITexture* image=0); //! destructor virtual ~CGUIMessageBox(); @@ -40,12 +41,15 @@ namespace gui private: void refreshControls(); + void setButton(IGUIButton*& button, bool isAvailable, const core::rect & btnRect, const wchar_t * text, IGUIElement*& focusMe); IGUIButton* OkButton; IGUIButton* CancelButton; IGUIButton* YesButton; IGUIButton* NoButton; IGUIStaticText* StaticText; + IGUIImage * Icon; + video::ITexture * IconTexture; s32 Flags; core::stringw MessageText; @@ -57,4 +61,4 @@ namespace gui #endif // _IRR_COMPILE_WITH_GUI_ -#endif +#endif diff --git a/src/dep/src/irrlicht/CGUIModalScreen.cpp b/src/dep/src/irrlicht/CGUIModalScreen.cpp index 084ef40..95c5e74 100644 --- a/src/dep/src/irrlicht/CGUIModalScreen.cpp +++ b/src/dep/src/irrlicht/CGUIModalScreen.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,36 +17,84 @@ namespace gui //! constructor CGUIModalScreen::CGUIModalScreen(IGUIEnvironment* environment, IGUIElement* parent, s32 id) -: IGUIElement(EGUIET_MODAL_SCREEN, environment, parent, id, parent->getAbsolutePosition()), +: IGUIElement(EGUIET_MODAL_SCREEN, environment, parent, id, core::recti(0, 0, parent->getAbsolutePosition().getWidth(), parent->getAbsolutePosition().getHeight()) ), MouseDownTime(0) { #ifdef _DEBUG setDebugName("CGUIModalScreen"); #endif setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); - + // this element is a tab group setTabGroup(true); } +bool CGUIModalScreen::canTakeFocus(IGUIElement* target) const +{ + return (target && ((const IGUIElement*)target == this // this element can take it + || isMyChild(target) // own childs also + || (target->getType() == EGUIET_MODAL_SCREEN )// other modals also fine + || (target->getParent() && target->getParent()->getType() == EGUIET_MODAL_SCREEN ))) // childs of other modals will do + ; +} + +bool CGUIModalScreen::isVisible() const +{ + // any parent invisible? + IGUIElement * parentElement = getParent(); + while ( parentElement ) + { + if ( !parentElement->isVisible() ) + return false; + parentElement = parentElement->getParent(); + } + + // if we have no children then the modal is probably abused as a way to block input + if ( Children.empty() ) + { + return IGUIElement::isVisible(); + } + + // any child visible? + bool visible = false; + core::list::ConstIterator it = Children.begin(); + for (; it != Children.end(); ++it) + { + if ( (*it)->isVisible() ) + { + visible = true; + break; + } + } + return visible; +} + +bool CGUIModalScreen::isPointInside(const core::position2d& point) const +{ + return true; +} //! called if an event happened. bool CGUIModalScreen::OnEvent(const SEvent& event) { + if (!IsEnabled || !isVisible() ) + return IGUIElement::OnEvent(event); + switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case EGET_ELEMENT_FOCUSED: - // only children are allowed the focus - if (event.GUIEvent.Caller != this && !isMyChild(event.GUIEvent.Caller)) + if ( !canTakeFocus(event.GUIEvent.Caller)) + { Environment->setFocus(this); + } + IGUIElement::OnEvent(event); return false; case EGET_ELEMENT_FOCUS_LOST: - // only children are allowed the focus - if (!(isMyChild(event.GUIEvent.Element) || event.GUIEvent.Element == this)) - { + if ( !canTakeFocus(event.GUIEvent.Element)) + { MouseDownTime = os::Timer::getTime(); return true; } @@ -69,7 +117,7 @@ bool CGUIModalScreen::OnEvent(const SEvent& event) default: break; } - + IGUIElement::OnEvent(event); return true; // absorb everything else @@ -110,16 +158,18 @@ void CGUIModalScreen::draw() } - //! Removes a child. void CGUIModalScreen::removeChild(IGUIElement* child) { IGUIElement::removeChild(child); if (Children.empty()) + { remove(); + } } + //! adds a child void CGUIModalScreen::addChild(IGUIElement* child) { @@ -144,16 +194,17 @@ void CGUIModalScreen::updateAbsolutePosition() IGUIElement::updateAbsolutePosition(); } + //! Writes attributes of the element. void CGUIModalScreen::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { - // these don't get serialized, their status is added to their children. + IGUIElement::serializeAttributes(out,options); } //! Reads attributes of the element void CGUIModalScreen::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { - // these don't get deserialized. children create them if required + IGUIElement::deserializeAttributes(in, options); } @@ -161,3 +212,4 @@ void CGUIModalScreen::deserializeAttributes(io::IAttributes* in, io::SAttributeR } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ + diff --git a/src/dep/src/irrlicht/CGUIModalScreen.h b/src/dep/src/irrlicht/CGUIModalScreen.h index 38e339b..0286d4c 100644 --- a/src/dep/src/irrlicht/CGUIModalScreen.h +++ b/src/dep/src/irrlicht/CGUIModalScreen.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -38,12 +38,23 @@ namespace gui //! Updates the absolute position. virtual void updateAbsolutePosition(); + //! Modalscreen is not a typical element, but rather acts like a state for it's children. + //! isVisible is overriden to give this a useful behaviour, so that a modal will no longer + //! be active when its parent is invisible or all its children are invisible. + virtual bool isVisible() const; + + //! Modals are infinite so every point is inside + virtual bool isPointInside(const core::position2d& point) const; + //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + protected: + virtual bool canTakeFocus(IGUIElement* target) const; + private: u32 MouseDownTime; @@ -56,3 +67,4 @@ namespace gui #endif // _IRR_COMPILE_WITH_GUI_ #endif + diff --git a/src/dep/src/irrlicht/CGUIScrollBar.cpp b/src/dep/src/irrlicht/CGUIScrollBar.cpp index b5959d5..6b5ea3c 100644 --- a/src/dep/src/irrlicht/CGUIScrollBar.cpp +++ b/src/dep/src/irrlicht/CGUIScrollBar.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -26,7 +26,7 @@ CGUIScrollBar::CGUIScrollBar(bool horizontal, IGUIEnvironment* environment, : IGUIScrollBar(environment, parent, id, rectangle), UpButton(0), DownButton(0), Dragging(false), Horizontal(horizontal), DraggedBySlider(false), TrayClick(false), Pos(0), DrawPos(0), - DrawHeight(0), Max(100), SmallStep(10), LargeStep(50), DesiredPos(0), + DrawHeight(0), Min(0), Max(100), SmallStep(10), LargeStep(50), DesiredPos(0), LastChange(0) { #ifdef _DEBUG @@ -80,7 +80,7 @@ bool CGUIScrollBar::OnEvent(const SEvent& event) setPos(Pos+SmallStep); break; case KEY_HOME: - setPos(0); + setPos(Min); break; case KEY_PRIOR: setPos(Pos-LargeStep); @@ -134,12 +134,21 @@ bool CGUIScrollBar::OnEvent(const SEvent& event) } break; case EET_MOUSE_INPUT_EVENT: + { + const core::position2di p(event.MouseInput.X, event.MouseInput.Y); + bool isInside = isPointInside ( p ); switch(event.MouseInput.Event) { case EMIE_MOUSE_WHEEL: if (Environment->hasFocus(this)) - { // thanks to a bug report by REAPER - setPos(getPos() + (s32)event.MouseInput.Wheel* -SmallStep); + { + // thanks to a bug report by REAPER + // thanks to tommi by tommi for another bugfix + // everybody needs a little thanking. hallo niko!;-) + setPos( getPos() + + ( (s32)event.MouseInput.Wheel * SmallStep * (Horizontal ? 1 : -1 ) ) + ); + SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; @@ -151,66 +160,77 @@ bool CGUIScrollBar::OnEvent(const SEvent& event) break; case EMIE_LMOUSE_PRESSED_DOWN: { - if (AbsoluteClippingRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y))) + if (isInside) { Dragging = true; - DraggedBySlider = SliderRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y)); + DraggedBySlider = SliderRect.isPointInside(p); TrayClick = !DraggedBySlider; - DesiredPos = getPosFromMousePos(event.MouseInput.X, event.MouseInput.Y); + DesiredPos = getPosFromMousePos(p); + Environment->setFocus ( this ); return true; } break; } case EMIE_LMOUSE_LEFT_UP: case EMIE_MOUSE_MOVED: - if (Dragging) + { + if ( !event.MouseInput.isLeftPressed () ) + Dragging = false; + + if ( !Dragging ) + return isInside; + + if ( event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP ) + Dragging = false; + + const s32 newPos = getPosFromMousePos(p); + const s32 oldPos = Pos; + + if (!DraggedBySlider) { - if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) - Dragging = false; - - const s32 newPos = getPosFromMousePos(event.MouseInput.X, event.MouseInput.Y); - const s32 oldPos = Pos; - - if (!DraggedBySlider) + if ( isInside ) { - if (AbsoluteClippingRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y))) - { - DraggedBySlider = SliderRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y)); - TrayClick = !DraggedBySlider; - } - else - { - TrayClick = false; - if (event.MouseInput.Event == EMIE_MOUSE_MOVED) - return true; - } + DraggedBySlider = SliderRect.isPointInside(p); + TrayClick = !DraggedBySlider; } - + if (DraggedBySlider) { setPos(newPos); } else { - DesiredPos = newPos; + TrayClick = false; + if (event.MouseInput.Event == EMIE_MOUSE_MOVED) + return isInside; } - - if (Pos != oldPos && Parent) - { - SEvent newEvent; - newEvent.EventType = EET_GUI_EVENT; - newEvent.GUIEvent.Caller = this; - newEvent.GUIEvent.Element = 0; - newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED; - Parent->OnEvent(newEvent); - } - return true; } - break; + + if (DraggedBySlider) + { + setPos(newPos); + } + else + { + DesiredPos = newPos; + } + + if (Pos != oldPos && Parent) + { + SEvent newEvent; + newEvent.EventType = EET_GUI_EVENT; + newEvent.GUIEvent.Caller = this; + newEvent.GUIEvent.Element = 0; + newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED; + Parent->OnEvent(newEvent); + } + return isInside; + } break; + default: break; } - break; + } break; default: break; } @@ -219,30 +239,20 @@ bool CGUIScrollBar::OnEvent(const SEvent& event) return IGUIElement::OnEvent(event); } -//! draws the element and its children -void CGUIScrollBar::draw() +void CGUIScrollBar::OnPostRender(u32 timeMs) { - if (!IsVisible) - return; - - IGUISkin* skin = Environment->getSkin(); - if (!skin) - return; - - u32 now = os::Timer::getRealTime(); - - if (Dragging && !DraggedBySlider && TrayClick && now > LastChange + 200) + if (Dragging && !DraggedBySlider && TrayClick && timeMs > LastChange + 200) { - LastChange = now; + LastChange = timeMs; const s32 oldPos = Pos; if (DesiredPos >= Pos + LargeStep) setPos(Pos + LargeStep); - else + else if (DesiredPos <= Pos - LargeStep) setPos(Pos - LargeStep); - else + else if (DesiredPos >= Pos - LargeStep && DesiredPos <= Pos + LargeStep) setPos(DesiredPos); @@ -257,12 +267,32 @@ void CGUIScrollBar::draw() } } +} + +//! draws the element and its children +void CGUIScrollBar::draw() +{ + if (!IsVisible) + return; + + IGUISkin* skin = Environment->getSkin(); + if (!skin) + return; + + + video::SColor iconColor = skin->getColor(EGDC_WINDOW_SYMBOL); + if ( iconColor != CurrentIconColor ) + { + refreshControls(); + } + + SliderRect = AbsoluteRect; // draws the background skin->draw2DRectangle(this, skin->getColor(EGDC_SCROLLBAR), SliderRect, &AbsoluteClippingRect); - if (Max!=0) + if ( core::isnotzero ( range() ) ) { // recalculate slider rectangle if (Horizontal) @@ -283,72 +313,52 @@ void CGUIScrollBar::draw() IGUIElement::draw(); } + void CGUIScrollBar::updateAbsolutePosition() { IGUIElement::updateAbsolutePosition(); // todo: properly resize refreshControls(); - - if (Horizontal) - { - const f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight()*3.0f)) / (f32)Max; - DrawPos = (s32)((Pos * f) + ((f32)RelativeRect.getHeight() * 0.5f)); - DrawHeight = RelativeRect.getHeight(); - } - else - { - f32 f = 0.0f; - if (Max != 0) - f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth()*3.0f)) / (f32)Max; - - DrawPos = (s32)((Pos * f) + ((f32)RelativeRect.getWidth() * 0.5f)); - DrawHeight = RelativeRect.getWidth(); - } + setPos ( Pos ); } -s32 CGUIScrollBar::getPosFromMousePos(s32 x, s32 y) const +//! +s32 CGUIScrollBar::getPosFromMousePos(const core::position2di &pos) const { + f32 w, p; if (Horizontal) { - const f32 w = RelativeRect.getWidth() - f32(RelativeRect.getHeight())*3.0f; - const f32 p = x - AbsoluteRect.UpperLeftCorner.X - RelativeRect.getHeight()*1.5f; - return s32( p/w * f32(Max) ); + w = RelativeRect.getWidth() - f32(RelativeRect.getHeight())*3.0f; + p = pos.X - AbsoluteRect.UpperLeftCorner.X - RelativeRect.getHeight()*1.5f; } else { - const f32 h = RelativeRect.getHeight() - f32(RelativeRect.getWidth())*3.0f; - const f32 p = y - AbsoluteRect.UpperLeftCorner.Y - RelativeRect.getWidth()*1.5f; - return s32( p/h * f32(Max) ); + w = RelativeRect.getHeight() - f32(RelativeRect.getWidth())*3.0f; + p = pos.Y - AbsoluteRect.UpperLeftCorner.Y - RelativeRect.getWidth()*1.5f; } + return (s32) ( p/w * range() ) + Min; } - //! sets the position of the scrollbar void CGUIScrollBar::setPos(s32 pos) { - if (pos < 0) - Pos = 0; - else if (pos > Max) - Pos = Max; - else - Pos = pos; + Pos = core::s32_clamp ( pos, Min, Max ); if (Horizontal) { - const f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight()*3.0f)) / (f32)Max; - DrawPos = (s32)((Pos * f) + ((f32)RelativeRect.getHeight() * 0.5f)); + f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight()*3.0f)) / range(); + DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getHeight() * 0.5f)); DrawHeight = RelativeRect.getHeight(); } else { - f32 f = 0.0f; - if (Max != 0) - f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth()*3.0f)) / (f32)Max; + f32 f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth()*3.0f)) / range(); - DrawPos = (s32)((Pos * f) + ((f32)RelativeRect.getWidth() * 0.5f)); + DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getWidth() * 0.5f)); DrawHeight = RelativeRect.getWidth(); } + } @@ -368,6 +378,7 @@ void CGUIScrollBar::setSmallStep(s32 step) SmallStep = 10; } + //! gets the small step value s32 CGUIScrollBar::getLargeStep() const { @@ -385,7 +396,6 @@ void CGUIScrollBar::setLargeStep(s32 step) } - //! gets the maximum value of the scrollbar. s32 CGUIScrollBar::getMax() const { @@ -396,12 +406,27 @@ s32 CGUIScrollBar::getMax() const //! sets the maximum value of the scrollbar. void CGUIScrollBar::setMax(s32 max) { - if (max > 0) - Max = max; - else - Max = 0; + Max = core::max_ ( max, Min ); - bool enable = (Max != 0); + bool enable = core::isnotzero ( range() ); + UpButton->setEnabled(enable); + DownButton->setEnabled(enable); + setPos(Pos); +} + +//! gets the minimum value of the scrollbar. +s32 CGUIScrollBar::getMin() const +{ + return Min; +} + + +//! sets the minimum value of the scrollbar. +void CGUIScrollBar::setMin(s32 min) +{ + Min = core::min_ ( min, Max ); + + bool enable = core::isnotzero ( range() ); UpButton->setEnabled(enable); DownButton->setEnabled(enable); setPos(Pos); @@ -418,7 +443,7 @@ s32 CGUIScrollBar::getPos() const //! refreshes the position and text on child buttons void CGUIScrollBar::refreshControls() { - video::SColor color(255,255,255,255); + CurrentIconColor = video::SColor(255,255,255,255); IGUISkin* skin = Environment->getSkin(); IGUISpriteBank* sprites = 0; @@ -426,7 +451,7 @@ void CGUIScrollBar::refreshControls() if (skin) { sprites = skin->getSpriteBank(); - color = skin->getColor(EGDC_WINDOW_SYMBOL); + CurrentIconColor = skin->getColor(EGDC_WINDOW_SYMBOL); } if (Horizontal) @@ -441,8 +466,8 @@ void CGUIScrollBar::refreshControls() if (sprites) { UpButton->setSpriteBank(sprites); - UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), color); - UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), color); + UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor); + UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor); } UpButton->setRelativePosition(core::rect(0,0, h, h)); UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); @@ -455,8 +480,8 @@ void CGUIScrollBar::refreshControls() if (sprites) { DownButton->setSpriteBank(sprites); - DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), color); - DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), color); + DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor); + DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor); } DownButton->setRelativePosition(core::rect(RelativeRect.getWidth()-h, 0, RelativeRect.getWidth(), h)); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); @@ -473,8 +498,8 @@ void CGUIScrollBar::refreshControls() if (sprites) { UpButton->setSpriteBank(sprites); - UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_UP), color); - UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_UP), color); + UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor); + UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor); } UpButton->setRelativePosition(core::rect(0,0, w, w)); UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); @@ -487,8 +512,8 @@ void CGUIScrollBar::refreshControls() if (sprites) { DownButton->setSpriteBank(sprites); - DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), color); - DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), color); + DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor); + DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor); } DownButton->setRelativePosition(core::rect(0,RelativeRect.getHeight()-w, w, RelativeRect.getHeight())); DownButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); @@ -503,9 +528,11 @@ void CGUIScrollBar::serializeAttributes(io::IAttributes* out, io::SAttributeRead out->addBool("Horizontal", Horizontal); out->addInt ("Value", Pos); - out->addInt ("Max", Max); + out->addInt ("Min", Min); + out->addInt ("Max", Max); out->addInt ("SmallStep", SmallStep); out->addInt ("LargeStep", LargeStep); + // CurrentIconColor - not serialized as continuiously updated } @@ -515,10 +542,12 @@ void CGUIScrollBar::deserializeAttributes(io::IAttributes* in, io::SAttributeRea IGUIScrollBar::deserializeAttributes(in,options); Horizontal = in->getAttributeAsBool("Horizontal"); + setMin(in->getAttributeAsInt("Min")); setMax(in->getAttributeAsInt("Max")); setPos(in->getAttributeAsInt("Value")); setSmallStep(in->getAttributeAsInt("SmallStep")); setLargeStep(in->getAttributeAsInt("LargeStep")); + // CurrentIconColor - not serialized as continuiously updated refreshControls(); } diff --git a/src/dep/src/irrlicht/CGUIScrollBar.h b/src/dep/src/irrlicht/CGUIScrollBar.h index 6bcdc50..cb57867 100644 --- a/src/dep/src/irrlicht/CGUIScrollBar.h +++ b/src/dep/src/irrlicht/CGUIScrollBar.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -34,12 +34,21 @@ namespace gui //! draws the element and its children virtual void draw(); + virtual void OnPostRender(u32 timeMs); + + //! gets the maximum value of the scrollbar. virtual s32 getMax() const; //! sets the maximum value of the scrollbar. virtual void setMax(s32 max); + //! gets the minimum value of the scrollbar. + virtual s32 getMin() const; + + //! sets the minimum value of the scrollbar. + virtual void setMin(s32 min); + //! gets the small step value virtual s32 getSmallStep() const; @@ -70,7 +79,7 @@ namespace gui private: void refreshControls(); - s32 getPosFromMousePos(s32 x, s32 y) const; + s32 getPosFromMousePos(const core::position2di &p) const; IGUIButton* UpButton; IGUIButton* DownButton; @@ -84,11 +93,15 @@ namespace gui s32 Pos; s32 DrawPos; s32 DrawHeight; + s32 Min; s32 Max; s32 SmallStep; s32 LargeStep; s32 DesiredPos; u32 LastChange; + video::SColor CurrentIconColor; + + f32 range () const { return (f32) ( Max - Min ); } }; } // end namespace gui diff --git a/src/dep/src/irrlicht/CGUISkin.cpp b/src/dep/src/irrlicht/CGUISkin.cpp index d63bcb8..d6335da 100644 --- a/src/dep/src/irrlicht/CGUISkin.cpp +++ b/src/dep/src/irrlicht/CGUISkin.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,7 +9,6 @@ #include "IGUISpriteBank.h" #include "IVideoDriver.h" #include "IAttributes.h" -#include "SoftwareDriver2_helper.h" namespace irr { @@ -23,9 +22,7 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver) setDebugName("CGUISkin"); #endif - if ( (Type == EGST_WINDOWS_CLASSIC) | - (Type == EGST_WINDOWS_METALLIC) - ) + if ((Type == EGST_WINDOWS_CLASSIC) || (Type == EGST_WINDOWS_METALLIC)) { Colors[EGDC_3D_DARK_SHADOW] = video::SColor(101,50,50,50); Colors[EGDC_3D_SHADOW] = video::SColor(101,130,130,130); @@ -33,14 +30,14 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver) Colors[EGDC_3D_HIGH_LIGHT] = video::SColor(101,255,255,255); Colors[EGDC_3D_LIGHT] = video::SColor(101,210,210,210); Colors[EGDC_ACTIVE_BORDER] = video::SColor(101,16,14,115); - Colors[EGDC_ACTIVE_CAPTION] = video::SColor(200,255,255,255); + Colors[EGDC_ACTIVE_CAPTION] = video::SColor(255,255,255,255); Colors[EGDC_APP_WORKSPACE] = video::SColor(101,100,100,100); Colors[EGDC_BUTTON_TEXT] = video::SColor(240,10,10,10); Colors[EGDC_GRAY_TEXT] = video::SColor(240,130,130,130); Colors[EGDC_HIGH_LIGHT] = video::SColor(101,8,36,107); Colors[EGDC_HIGH_LIGHT_TEXT] = video::SColor(240,255,255,255); Colors[EGDC_INACTIVE_BORDER] = video::SColor(101,165,165,165); - Colors[EGDC_INACTIVE_CAPTION] = video::SColor(101,210,210,210); + Colors[EGDC_INACTIVE_CAPTION] = video::SColor(255,30,30,30); Colors[EGDC_TOOLTIP] = video::SColor(200,0,0,0); Colors[EGDC_TOOLTIP_BACKGROUND]= video::SColor(200,255,255,225); Colors[EGDC_SCROLLBAR] = video::SColor(101,230,230,230); @@ -57,9 +54,12 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver) Sizes[EGDS_MESSAGE_BOX_HEIGHT] = 200; Sizes[EGDS_BUTTON_WIDTH] = 80; Sizes[EGDS_BUTTON_HEIGHT] = 30; - + Sizes[EGDS_TEXT_DISTANCE_X] = 2; Sizes[EGDS_TEXT_DISTANCE_Y] = 0; + + Sizes[EGDS_TITLEBARTEXT_DISTANCE_X] = 2; + Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 0; } else { @@ -68,17 +68,17 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver) //Colors[EGDC_3D_FACE] = 0xc0c9ccd4; // tab background Colors[EGDC_3D_FACE] = 0xc0cbd2d9; // tab background Colors[EGDC_3D_SHADOW] = 0x50e4e8f1; // tab background, and left-top highlight - Colors[EGDC_3D_HIGH_LIGHT] = 0x40c7ccdc; + Colors[EGDC_3D_HIGH_LIGHT] = 0x40c7ccdc; Colors[EGDC_3D_LIGHT] = 0x802e313a; Colors[EGDC_ACTIVE_BORDER] = 0x80404040; // window title - Colors[EGDC_ACTIVE_CAPTION] = 0xf0d0d0d0; + Colors[EGDC_ACTIVE_CAPTION] = 0xffd0d0d0; Colors[EGDC_APP_WORKSPACE] = 0xc0646464; // unused Colors[EGDC_BUTTON_TEXT] = 0xd0161616; Colors[EGDC_GRAY_TEXT] = 0x3c141414; Colors[EGDC_HIGH_LIGHT] = 0x6c606060; Colors[EGDC_HIGH_LIGHT_TEXT]= 0xd0e0e0e0; Colors[EGDC_INACTIVE_BORDER]= 0xf0a5a5a5; - Colors[EGDC_INACTIVE_CAPTION]= 0xf0d2d2d2; + Colors[EGDC_INACTIVE_CAPTION]= 0xffd2d2d2; Colors[EGDC_TOOLTIP] = 0xf00f2033; Colors[EGDC_TOOLTIP_BACKGROUND]=0xc0cbd2d9; Colors[EGDC_SCROLLBAR] = 0xf0e0e0e0; @@ -98,8 +98,17 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver) Sizes[EGDS_TEXT_DISTANCE_X] = 3; Sizes[EGDS_TEXT_DISTANCE_Y] = 2; + + Sizes[EGDS_TITLEBARTEXT_DISTANCE_X] = 3; + Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 2; } + Sizes[EGDS_MESSAGE_BOX_GAP_SPACE] = 15; + Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH] = 0; + Sizes[EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH] = 500; + Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT] = 0; + Sizes[EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT] = 99999; + Texts[EGDT_MSG_BOX_OK] = L"OK"; Texts[EGDT_MSG_BOX_CANCEL] = L"Cancel"; Texts[EGDT_MSG_BOX_YES] = L"Yes"; @@ -137,8 +146,7 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver) for (u32 i=0; i= EGDS_COUNT) + if ((u32)which >= EGDF_COUNT) return; - if (Fonts[which]) - Fonts[which]->drop(); + if (font) + { + font->grab(); + if (Fonts[which]) + Fonts[which]->drop(); - Fonts[which] = font; - - if (Fonts[which]) - Fonts[which]->grab(); + Fonts[which] = font; + } } @@ -229,12 +237,12 @@ IGUISpriteBank* CGUISkin::getSpriteBank() const //! set a new sprite bank or remove one by passing 0 void CGUISkin::setSpriteBank(IGUISpriteBank* bank) { - if (SpriteBank) - SpriteBank->drop(); - if (bank) bank->grab(); + if (SpriteBank) + SpriteBank->drop(); + SpriteBank = bank; } @@ -248,6 +256,7 @@ u32 CGUISkin::getIcon(EGUI_DEFAULT_ICON icon) const return 0; } + //! Sets a default icon void CGUISkin::setIcon(EGUI_DEFAULT_ICON icon, u32 index) { @@ -255,6 +264,7 @@ void CGUISkin::setIcon(EGUI_DEFAULT_ICON icon, u32 index) Icons[icon] = index; } + //! Returns a default text. For example for Message box button captions: //! "OK", "Cancel", "Yes", "No" and so on. const wchar_t* CGUISkin::getDefaultText(EGUI_DEFAULT_TEXT text) const @@ -274,6 +284,7 @@ void CGUISkin::setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText) Texts[which] = newText; } + //! draws a standard 3d button pane /** Used for drawing for example buttons in normal state. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and @@ -380,7 +391,7 @@ is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param bgcolor: Background color. \param flat: Specifies if the sunken pane should be flat or displayed as sunken - deep into the ground. +deep into the ground. \param rect: Defining area where to draw. \param clip: Clip area. */ void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor, @@ -441,102 +452,140 @@ void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor, //! draws a window background -/** Used for drawing the background of dialogs and windows. -\param element: Pointer to the element which wishes to draw this. This parameter -is usually not used by ISkin, but can be used for example by more complex -implementations to find out how to draw the part exactly. -\param titleBarColor: Title color. -\param drawTitleBar: True to enable title drawing. -\param rect: Defining area where to draw. -\param clip: Clip area. -\return Returns rect where to draw title bar text. */ +// return where to draw title bar text. core::rect CGUISkin::draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& r, - const core::rect* cl) + const core::rect* clip, + core::rect* checkClientArea) { if (!Driver) + { + if ( checkClientArea ) + { + *checkClientArea = r; + } return r; + } core::rect rect = r; + // top border rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; - Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); + } + // left border rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1; - Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); + } + // right border dark outer line rect.UpperLeftCorner.X = r.LowerRightCorner.X - 1; rect.LowerRightCorner.X = r.LowerRightCorner.X; rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; - Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); + } + // right border bright innner line rect.UpperLeftCorner.X -= 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y += 1; rect.LowerRightCorner.Y -= 1; - Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); + } + // bottom border dark outer line rect.UpperLeftCorner.X = r.UpperLeftCorner.X; rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = r.LowerRightCorner.X; - Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); + } + // bottom border bright inner line rect.UpperLeftCorner.X += 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y -= 1; rect.LowerRightCorner.Y -= 1; - Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); + } + // client area for background rect = r; rect.UpperLeftCorner.X +=1; rect.UpperLeftCorner.Y +=1; rect.LowerRightCorner.X -= 2; rect.LowerRightCorner.Y -= 2; - - if (!UseGradient) + if (checkClientArea) { - Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, cl); - } - else - if ( Type == EGST_BURNING_SKIN ) - { - const video::SColor c1 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.9f ); - const video::SColor c2 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.8f ); - - Driver->draw2DRectangle(rect, c1, c1, c2, c2, cl); - } - else - { - const video::SColor c2 = getColor(EGDC_3D_SHADOW); - const video::SColor c1 = getColor(EGDC_3D_FACE); - Driver->draw2DRectangle(rect, c1, c1, c1, c2, cl); + *checkClientArea = rect; } + if ( !checkClientArea ) + { + if (!UseGradient) + { + Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip); + } + else if ( Type == EGST_BURNING_SKIN ) + { + const video::SColor c1 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.9f ); + const video::SColor c2 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.8f ); + + Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip); + } + else + { + const video::SColor c2 = getColor(EGDC_3D_SHADOW); + const video::SColor c1 = getColor(EGDC_3D_FACE); + Driver->draw2DRectangle(rect, c1, c1, c1, c2, clip); + } + } + + // title bar rect = r; rect.UpperLeftCorner.X += 2; rect.UpperLeftCorner.Y += 2; rect.LowerRightCorner.X -= 2; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + getSize(EGDS_WINDOW_BUTTON_WIDTH) + 2; - if (drawTitleBar) + if (drawTitleBar ) { - // draw title bar - //if (!UseGradient) - // Driver->draw2DRectangle(titleBarColor, rect, cl); - //else - if ( Type == EGST_BURNING_SKIN ) + if (checkClientArea) { - const video::SColor c = titleBarColor.getInterpolated( 0xffffffff, 0.8f); - Driver->draw2DRectangle(rect, titleBarColor, titleBarColor, c, c, cl); + (*checkClientArea).UpperLeftCorner.Y = rect.LowerRightCorner.Y; } else { - const video::SColor c = titleBarColor.getInterpolated(video::SColor(255,0,0,0), 0.2f); - Driver->draw2DRectangle(rect, titleBarColor, c, titleBarColor, c, cl); + // draw title bar + //if (!UseGradient) + // Driver->draw2DRectangle(titleBarColor, rect, clip); + //else + if ( Type == EGST_BURNING_SKIN ) + { + const video::SColor c = titleBarColor.getInterpolated( video::SColor(titleBarColor.getAlpha(),255,255,255), 0.8f); + Driver->draw2DRectangle(rect, titleBarColor, titleBarColor, c, c, clip); + } + else + { + const video::SColor c = titleBarColor.getInterpolated(video::SColor(titleBarColor.getAlpha(),0,0,0), 0.2f); + Driver->draw2DRectangle(rect, titleBarColor, c, titleBarColor, c, clip); + } } } @@ -562,7 +611,7 @@ void CGUISkin::draw3DMenuPane(IGUIElement* element, core::rect rect = r; if ( Type == EGST_BURNING_SKIN ) - { + { rect.UpperLeftCorner.Y -= 3; draw3DButtonPaneStandard(element, rect, clip); return; @@ -693,7 +742,7 @@ void CGUISkin::draw3DTabButton(IGUIElement* element, bool active, tr.LowerRightCorner.Y = tr.UpperLeftCorner.Y + 1; tr.UpperLeftCorner.X += 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); - + // draw left highlight tr = frameRect; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; @@ -707,17 +756,15 @@ void CGUISkin::draw3DTabButton(IGUIElement* element, bool active, tr.LowerRightCorner.X -= 2; Driver->draw2DRectangle(getColor(EGDC_3D_FACE), tr, clip); - // draw right middle gray shadow tr.LowerRightCorner.X += 1; tr.UpperLeftCorner.X = tr.LowerRightCorner.X - 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip); - tr.LowerRightCorner.X += 1; tr.UpperLeftCorner.X += 1; tr.UpperLeftCorner.Y += 1; - Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), tr, clip); + Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), tr, clip); } else { @@ -725,7 +772,7 @@ void CGUISkin::draw3DTabButton(IGUIElement* element, bool active, tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1; tr.UpperLeftCorner.X += 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); - + // draw left highlight tr = frameRect; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; @@ -739,20 +786,18 @@ void CGUISkin::draw3DTabButton(IGUIElement* element, bool active, tr.LowerRightCorner.X -= 2; tr.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_FACE), tr, clip); - + // draw right middle gray shadow tr.LowerRightCorner.X += 1; tr.UpperLeftCorner.X = tr.LowerRightCorner.X - 1; //tr.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip); - tr.LowerRightCorner.X += 1; tr.UpperLeftCorner.X += 1; tr.LowerRightCorner.Y -= 1; - Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), tr, clip); + Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), tr, clip); } - } @@ -785,7 +830,6 @@ void CGUISkin::draw3DTabBody(IGUIElement* element, bool border, bool background, tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); - // draw right shadow tr.UpperLeftCorner.X = rect.LowerRightCorner.X - 1; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; @@ -795,7 +839,6 @@ void CGUISkin::draw3DTabBody(IGUIElement* element, bool border, bool background, tr = rect; tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip); - } else { @@ -803,23 +846,21 @@ void CGUISkin::draw3DTabBody(IGUIElement* element, bool border, bool background, tr.LowerRightCorner.Y -= tabHeight + 2; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); - + // draw right shadow tr.UpperLeftCorner.X = rect.LowerRightCorner.X - 1; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip); - + // draw lower shadow tr = rect; tr.LowerRightCorner.Y = tr.UpperLeftCorner.Y + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); - } } if (background) { - if ( alignment == EGUIA_UPPERLEFT ) { tr = rect; @@ -851,9 +892,9 @@ void CGUISkin::draw3DTabBody(IGUIElement* element, bool border, bool background, //! draws an icon, usually from the skin's sprite bank -/** \param parent: Pointer to the element which wishes to draw this icon. -This parameter is usually not used by IGUISkin, but can be used for example -by more complex implementations to find out how to draw the part exactly. +/** \param parent: Pointer to the element which wishes to draw this icon. +This parameter is usually not used by IGUISkin, but can be used for example +by more complex implementations to find out how to draw the part exactly. \param icon: Specifies the icon to be drawn. \param position: The position to draw the icon \param starttime: The time at the start of the animation @@ -862,14 +903,15 @@ by more complex implementations to find out how to draw the part exactly. \param clip: Clip area. */ void CGUISkin::drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon, const core::position2di position, - u32 starttime, u32 currenttime, + u32 starttime, u32 currenttime, bool loop, const core::rect* clip) { if (!SpriteBank) return; - SpriteBank->draw2DSprite(Icons[icon], position, clip, - video::SColor(255,0,0,0), starttime, currenttime, loop, true); + // TODO: we need another state for disabled elements (can't add now because it's an interface change) + SpriteBank->draw2DSprite(Icons[icon], position, clip, + Colors[EGDC_WINDOW_SYMBOL], starttime, currenttime, loop, true); } @@ -889,7 +931,7 @@ void CGUISkin::draw2DRectangle(IGUIElement* element, //! Writes attributes of the object. -//! Implement this to expose the attributes of your scene node animator for +//! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. void CGUISkin::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { @@ -909,7 +951,7 @@ void CGUISkin::serializeAttributes(io::IAttributes* out, io::SAttributeReadWrite //! Reads attributes of the object. -//! Implement this to set the attributes of your scene node animator for +//! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. void CGUISkin::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { @@ -933,4 +975,3 @@ void CGUISkin::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWrit #endif // _IRR_COMPILE_WITH_GUI_ - diff --git a/src/dep/src/irrlicht/CGUISkin.h b/src/dep/src/irrlicht/CGUISkin.h index 7d7b56a..a99b353 100644 --- a/src/dep/src/irrlicht/CGUISkin.h +++ b/src/dep/src/irrlicht/CGUISkin.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -58,56 +58,56 @@ namespace gui virtual u32 getIcon(EGUI_DEFAULT_ICON icon) const; //! Sets a default icon - /** Sets the sprite index used for drawing icons like arrows, - close buttons and ticks in checkboxes + /** Sets the sprite index used for drawing icons like arrows, + close buttons and ticks in checkboxes \param icon: Enum specifying which icon to change \param index: The sprite index used to draw this icon */ virtual void setIcon(EGUI_DEFAULT_ICON icon, u32 index); //! Returns a default text. /** For example for Message box button captions: - "OK", "Cancel", "Yes", "No" and so on. */ + "OK", "Cancel", "Yes", "No" and so on. */ virtual const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const; - //! Sets a default text. + //! Sets a default text. /** For example for Message box button captions: - "OK", "Cancel", "Yes", "No" and so on. */ + "OK", "Cancel", "Yes", "No" and so on. */ virtual void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText); //! draws a standard 3d button pane - /** Used for drawing for example buttons in normal state. + /** Used for drawing for example buttons in normal state. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and - EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. + EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param rect: Defining area where to draw. \param clip: Clip area. \param element: Pointer to the element which wishes to draw this. This parameter - is usually not used by ISkin, but can be used for example by more complex + is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. */ - virtual void draw3DButtonPaneStandard(IGUIElement* element, + virtual void draw3DButtonPaneStandard(IGUIElement* element, const core::rect& rect, const core::rect* clip=0); //! draws a pressed 3d button pane - /** Used for drawing for example buttons in pressed state. + /** Used for drawing for example buttons in pressed state. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and - EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. + EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param rect: Defining area where to draw. \param clip: Clip area. \param element: Pointer to the element which wishes to draw this. This parameter - is usually not used by ISkin, but can be used for example by more complex + is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. */ - virtual void draw3DButtonPanePressed(IGUIElement* element, + virtual void draw3DButtonPanePressed(IGUIElement* element, const core::rect& rect, const core::rect* clip=0); //! draws a sunken 3d pane /** Used for drawing the background of edit, combo or check boxes. \param element: Pointer to the element which wishes to draw this. This parameter - is usually not used by ISkin, but can be used for example by more complex - implementations to find out how to draw the part exactly. + is usually not used by ISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. \param bgcolor: Background color. - \param flat: Specifies if the sunken pane should be flat or displayed as sunken - deep into the ground. + \param flat: Specifies if the sunken pane should be flat or displayed as sunken + deep into the ground. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DSunkenPane(IGUIElement* element, @@ -119,25 +119,30 @@ namespace gui //! draws a window background /** Used for drawing the background of dialogs and windows. \param element: Pointer to the element which wishes to draw this. This parameter - is usually not used by ISkin, but can be used for example by more complex - implementations to find out how to draw the part exactly. + is usually not used by ISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. \param titleBarColor: Title color. \param drawTitleBar: True to enable title drawing. \param rect: Defining area where to draw. \param clip: Clip area. - \return Returns rect where to draw title bar text. */ + \param checkClientArea: When set to non-null the function will not draw anything, + but will instead return the clientArea which can be used for drawing by the calling window. + That is the area without borders and without titlebar. + \return Returns rect where it would be good to draw title bar text. This will + work even when checkClientArea is set to a non-null value.*/ virtual core::rect draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& rect, - const core::rect* clip=0); + const core::rect* clip, + core::rect* checkClientArea); //! draws a standard 3d menu pane - /** Used for drawing for menus and context menus. + /** Used for drawing for menus and context menus. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and - EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. + EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param element: Pointer to the element which wishes to draw this. This parameter - is usually not used by ISkin, but can be used for example by more complex - implementations to find out how to draw the part exactly. + is usually not used by ISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DMenuPane(IGUIElement* element, @@ -145,10 +150,10 @@ namespace gui const core::rect* clip=0); //! draws a standard 3d tool bar - /** Used for drawing for toolbars and menus. + /** Used for drawing for toolbars and menus. \param element: Pointer to the element which wishes to draw this. This parameter - is usually not used by ISkin, but can be used for example by more complex - implementations to find out how to draw the part exactly. + is usually not used by ISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DToolBar(IGUIElement* element, @@ -156,10 +161,10 @@ namespace gui const core::rect* clip=0); //! draws a tab button - /** Used for drawing for tab buttons on top of tabs. + /** Used for drawing for tab buttons on top of tabs. \param element: Pointer to the element which wishes to draw this. This parameter - is usually not used by ISkin, but can be used for example by more complex - implementations to find out how to draw the part exactly. + is usually not used by ISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. \param active: Specifies if the tab is currently active. \param rect: Defining area where to draw. \param clip: Clip area. */ @@ -167,9 +172,9 @@ namespace gui const core::rect& rect, const core::rect* clip=0, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT); //! draws a tab control body - /** \param element: Pointer to the element which wishes to draw this. This parameter - is usually not used by ISkin, but can be used for example by more complex - implementations to find out how to draw the part exactly. + /** \param element: Pointer to the element which wishes to draw this. This parameter + is usually not used by ISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. \param border: Specifies if the border should be drawn. \param background: Specifies if the background should be drawn. \param rect: Defining area where to draw. @@ -178,9 +183,9 @@ namespace gui const core::rect& rect, const core::rect* clip=0, s32 tabHeight=-1, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT); //! draws an icon, usually from the skin's sprite bank - /** \param element: Pointer to the element which wishes to draw this icon. - This parameter is usually not used by IGUISkin, but can be used for example - by more complex implementations to find out how to draw the part exactly. + /** \param element: Pointer to the element which wishes to draw this icon. + This parameter is usually not used by IGUISkin, but can be used for example + by more complex implementations to find out how to draw the part exactly. \param icon: Specifies the icon to be drawn. \param position: The position to draw the icon \param starttime: The time at the start of the animation @@ -189,20 +194,20 @@ namespace gui \param clip: Clip area. */ virtual void drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon, const core::position2di position, - u32 starttime=0, u32 currenttime=0, + u32 starttime=0, u32 currenttime=0, bool loop=false, const core::rect* clip=0); //! draws a 2d rectangle. - /** \param element: Pointer to the element which wishes to draw this icon. - This parameter is usually not used by IGUISkin, but can be used for example - by more complex implementations to find out how to draw the part exactly. - \param color: Color of the rectangle to draw. The alpha component specifies how + /** \param element: Pointer to the element which wishes to draw this icon. + This parameter is usually not used by IGUISkin, but can be used for example + by more complex implementations to find out how to draw the part exactly. + \param color: Color of the rectangle to draw. The alpha component specifies how transparent the rectangle will be. \param pos: Position of the rectangle. \param clip: Pointer to rectangle against which the rectangle will be clipped. If the pointer is null, no clipping will be performed. */ - virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color, + virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color, const core::rect& pos, const core::rect* clip = 0); @@ -210,12 +215,12 @@ namespace gui virtual EGUI_SKIN_TYPE getType() const; //! Writes attributes of the object. - //! Implement this to expose the attributes of your scene node animator for + //! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the object. - //! Implement this to set the attributes of your scene node animator for + //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); diff --git a/src/dep/src/irrlicht/CGUISpinBox.cpp b/src/dep/src/irrlicht/CGUISpinBox.cpp index 107c9c1..b42df91 100644 --- a/src/dep/src/irrlicht/CGUISpinBox.cpp +++ b/src/dep/src/irrlicht/CGUISpinBox.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2006-2008 Michael Zeilfelder +// Copyright (C) 2006-2010 Michael Zeilfelder // This file uses the licence of the Irrlicht Engine. #include "CGUISpinBox.h" @@ -9,7 +9,6 @@ #include "IGUIEnvironment.h" #include "IEventReceiver.h" #include "fast_atof.h" -#include #include @@ -19,13 +18,18 @@ namespace gui { //! constructor -CGUISpinBox::CGUISpinBox(const wchar_t* text, IGUIEnvironment* environment, +CGUISpinBox::CGUISpinBox(const wchar_t* text, bool border,IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle) : IGUISpinBox(environment, parent, id, rectangle), EditBox(0), ButtonSpinUp(0), ButtonSpinDown(0), StepSize(1.f), RangeMin(-FLT_MAX), RangeMax(FLT_MAX), FormatString(L"%f"), DecimalPlaces(-1) { + #ifdef _DEBUG + setDebugName("CGUISpinBox"); + #endif + + CurrentIconColor = video::SColor(255,255,255,255); s32 ButtonWidth = 16; IGUISpriteBank *sb = 0; if (environment && environment->getSkin()) @@ -49,27 +53,14 @@ CGUISpinBox::CGUISpinBox(const wchar_t* text, IGUIEnvironment* environment, ButtonSpinUp->setSubElement(true); ButtonSpinUp->setTabStop(false); ButtonSpinUp->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_CENTER); - if (sb) - { - IGUISkin *skin = environment->getSkin(); - ButtonSpinDown->setSpriteBank(sb); - ButtonSpinDown->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL)); - ButtonSpinDown->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL)); - ButtonSpinUp->setSpriteBank(sb); - ButtonSpinUp->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_UP), skin->getColor(EGDC_WINDOW_SYMBOL)); - ButtonSpinUp->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_UP), skin->getColor(EGDC_WINDOW_SYMBOL)); - } - else - { - ButtonSpinDown->setText(L"-"); - ButtonSpinUp->setText(L"+"); - } const core::rect rectEdit(0, 0, rectangle.getWidth() - ButtonWidth - 1, rectangle.getHeight()); - EditBox = Environment->addEditBox(text, rectEdit, true, this, -1); + EditBox = Environment->addEditBox(text, rectEdit, border, this, -1); EditBox->grab(); EditBox->setSubElement(true); EditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); + + refreshSprites(); } @@ -84,6 +75,31 @@ CGUISpinBox::~CGUISpinBox() EditBox->drop(); } +void CGUISpinBox::refreshSprites() +{ + IGUISpriteBank *sb = 0; + if (Environment && Environment->getSkin()) + { + sb = Environment->getSkin()->getSpriteBank(); + } + + if (sb) + { + IGUISkin * skin = Environment->getSkin(); + CurrentIconColor = skin->getColor(EGDC_WINDOW_SYMBOL); + ButtonSpinDown->setSpriteBank(sb); + ButtonSpinDown->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), CurrentIconColor); + ButtonSpinDown->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), CurrentIconColor); + ButtonSpinUp->setSpriteBank(sb); + ButtonSpinUp->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_UP), CurrentIconColor); + ButtonSpinUp->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_UP), CurrentIconColor); + } + else + { + ButtonSpinDown->setText(L"-"); + ButtonSpinUp->setText(L"+"); + } +} IGUIEditBox* CGUISpinBox::getEditBox() const { @@ -166,6 +182,21 @@ bool CGUISpinBox::OnEvent(const SEvent& event) bool changeEvent = false; switch(event.EventType) { + case EET_MOUSE_INPUT_EVENT: + switch(event.MouseInput.Event) + { + case EMIE_MOUSE_WHEEL: + { + f32 val = getValue() + (StepSize * event.MouseInput.Wheel); + setValue(val); + changeEvent = true; + } + break; + default: + break; + } + break; + case EET_GUI_EVENT: if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) { @@ -184,7 +215,7 @@ bool CGUISpinBox::OnEvent(const SEvent& event) changeEvent = true; } } - if ( event.GUIEvent.EventType == EGET_EDITBOX_ENTER ) + if ( event.GUIEvent.EventType == EGET_EDITBOX_CHANGED ) { if (event.GUIEvent.Caller == EditBox) { @@ -217,10 +248,15 @@ bool CGUISpinBox::OnEvent(const SEvent& event) void CGUISpinBox::verifyValueRange() { + // TODO: This should be called in "draw" similar to the way it's done in CGUIWindow. + // But guess I can't in bugfix-release as overloading draw would break binary compitibility. + // So added here to allow users at least to manually force the element to having new skin-colors. + refreshSprites(); + f32 val = getValue(); - if ( val < RangeMin ) + if ( val+core::ROUNDING_ERROR_f32 < RangeMin ) val = RangeMin; - else if ( val > RangeMax ) + else if ( val-core::ROUNDING_ERROR_f32 > RangeMax ) val = RangeMax; else return; @@ -255,6 +291,7 @@ void CGUISpinBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWr out->addInt("DecimalPlaces", DecimalPlaces); } + //! Reads attributes of the element void CGUISpinBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { diff --git a/src/dep/src/irrlicht/CGUISpinBox.h b/src/dep/src/irrlicht/CGUISpinBox.h index a16065d..24be85c 100644 --- a/src/dep/src/irrlicht/CGUISpinBox.h +++ b/src/dep/src/irrlicht/CGUISpinBox.h @@ -1,4 +1,4 @@ -// Copyright (C) 2006-2008 Michael Zeilfelder +// Copyright (C) 2006-2010 Michael Zeilfelder // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -22,7 +22,7 @@ namespace gui public: //! constructor - CGUISpinBox(const wchar_t* text, IGUIEnvironment* environment, + CGUISpinBox(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle); //! destructor @@ -80,10 +80,12 @@ namespace gui protected: virtual void verifyValueRange(); + void refreshSprites(); IGUIEditBox * EditBox; IGUIButton * ButtonSpinUp; IGUIButton * ButtonSpinDown; + video::SColor CurrentIconColor; f32 StepSize; f32 RangeMin; f32 RangeMax; diff --git a/src/dep/src/irrlicht/CGUISpriteBank.cpp b/src/dep/src/irrlicht/CGUISpriteBank.cpp index ed75ee7..e4960a6 100644 --- a/src/dep/src/irrlicht/CGUISpriteBank.cpp +++ b/src/dep/src/irrlicht/CGUISpriteBank.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,6 +17,10 @@ namespace gui CGUISpriteBank::CGUISpriteBank(IGUIEnvironment* env) : Environment(env), Driver(0) { + #ifdef _DEBUG + setDebugName("CGUISpriteBank"); + #endif + if (Environment) { Driver = Environment->getVideoDriver(); @@ -77,25 +81,62 @@ void CGUISpriteBank::addTexture(video::ITexture* texture) void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture) { - while (index > Textures.size()) + while (index >= Textures.size()) Textures.push_back(0); - if (Textures[index]) - Textures[index]->drop(); - if (texture) texture->grab(); + if (Textures[index]) + Textures[index]->drop(); + Textures[index] = texture; } +//! clear everything +void CGUISpriteBank::clear() +{ + // drop textures + for (u32 i=0; idrop(); + Textures.clear(); + Sprites.clear(); + Rectangles.clear(); +} + +//! Add the texture and use it for a single non-animated sprite. +s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* texture) +{ + if ( !texture ) + return -1; + + addTexture(texture); + u32 textureIndex = getTextureCount() - 1; + + u32 rectangleIndex = Rectangles.size(); + Rectangles.push_back( core::rect(0,0, texture->getOriginalSize().Width, texture->getOriginalSize().Height) ); + + SGUISprite sprite; + sprite.frameTime = 0; + + SGUISpriteFrame frame; + frame.textureNumber = textureIndex; + frame.rectNumber = rectangleIndex; + sprite.Frames.push_back( frame ); + + Sprites.push_back( sprite ); + + return Sprites.size() - 1; +} + //! draws a sprite in 2d with scale and color void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip, const video::SColor& color, u32 starttime, u32 currenttime, bool loop, bool center) { - if (Sprites[index].Frames.empty() || index >= Sprites.size()) + if (index >= Sprites.size() || Sprites[index].Frames.empty() ) return; // work out frame number @@ -132,6 +173,74 @@ void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos, } +void CGUISpriteBank::draw2DSpriteBatch( const core::array& indices, + const core::array& pos, + const core::rect* clip, + const video::SColor& color, + u32 starttime, u32 currenttime, + bool loop, bool center) +{ + const irr::u32 drawCount = core::min_(indices.size(), pos.size()); + + core::array drawBatches(Textures.size()); + for(u32 i = 0;i < Textures.size();i++) + { + drawBatches.push_back(SDrawBatch()); + drawBatches[i].positions.reallocate(drawCount); + drawBatches[i].sourceRects.reallocate(drawCount); + } + + for(u32 i = 0;i < drawCount;i++) + { + const u32 index = indices[i]; + + if (index >= Sprites.size() || Sprites[index].Frames.empty() ) + continue; + + // work out frame number + u32 frame = 0; + if (Sprites[index].frameTime) + { + u32 f = ((currenttime - starttime) / Sprites[index].frameTime); + if (loop) + frame = f % Sprites[index].Frames.size(); + else + frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f; + } + + const u32 texNum = Sprites[index].Frames[frame].textureNumber; + + SDrawBatch& currentBatch = drawBatches[texNum]; + + const u32 rn = Sprites[index].Frames[frame].rectNumber; + if (rn >= Rectangles.size()) + return; + + const core::rect& r = Rectangles[rn]; + + if (center) + { + core::position2di p = pos[i]; + p -= r.getSize() / 2; + + currentBatch.positions.push_back(p); + currentBatch.sourceRects.push_back(r); + } + else + { + currentBatch.positions.push_back(pos[i]); + currentBatch.sourceRects.push_back(r); + } + } + + for(u32 i = 0;i < drawBatches.size();i++) + { + if(!drawBatches[i].positions.empty() && !drawBatches[i].sourceRects.empty()) + Driver->draw2DImageBatch(Textures[i], drawBatches[i].positions, + drawBatches[i].sourceRects, clip, color, true); + } +} + } // namespace gui } // namespace irr diff --git a/src/dep/src/irrlicht/CGUISpriteBank.h b/src/dep/src/irrlicht/CGUISpriteBank.h index 5881e2b..11377c7 100644 --- a/src/dep/src/irrlicht/CGUISpriteBank.h +++ b/src/dep/src/irrlicht/CGUISpriteBank.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -40,14 +40,34 @@ public: virtual void addTexture(video::ITexture* texture); virtual void setTexture(u32 index, video::ITexture* texture); - //! draws a sprite in 2d with position and color + //! Add the texture and use it for a single non-animated sprite. + virtual s32 addTextureAsSprite(video::ITexture* texture); + + //! clears sprites, rectangles and textures + virtual void clear(); + + //! Draws a sprite in 2d with position and color virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip=0, const video::SColor& color= video::SColor(255,255,255,255), u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false); + //! Draws a sprite batch in 2d using an array of positions and a color + virtual void draw2DSpriteBatch(const core::array& indices, const core::array& pos, + const core::rect* clip=0, + const video::SColor& color= video::SColor(255,255,255,255), + u32 starttime=0, u32 currenttime=0, + bool loop=true, bool center=false); + protected: - core::array Sprites; + struct SDrawBatch + { + core::array positions; + core::array sourceRects; + u32 textureNumber; + }; + + core::array Sprites; core::array< core::rect > Rectangles; core::array Textures; IGUIEnvironment* Environment; @@ -62,4 +82,3 @@ protected: #endif // __C_GUI_SPRITE_BANK_H_INCLUDED__ - diff --git a/src/dep/src/irrlicht/CGUIStaticText.cpp b/src/dep/src/irrlicht/CGUIStaticText.cpp index 3039fb8..5d40dad 100644 --- a/src/dep/src/irrlicht/CGUIStaticText.cpp +++ b/src/dep/src/irrlicht/CGUIStaticText.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -21,9 +21,9 @@ CGUIStaticText::CGUIStaticText(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle, bool background) -: IGUIStaticText(environment, parent, id, rectangle), Border(border), +: IGUIStaticText(environment, parent, id, rectangle), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT), - OverrideColorEnabled(false), WordWrap(false), Background(background), + Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background), OverrideColor(video::SColor(101,255,255,255)), BGColor(video::SColor(101,210,210,210)), OverrideFont(0), LastBreakFont(0) { @@ -64,6 +64,9 @@ void CGUIStaticText::draw() if (Background) { + if ( !OverrideBGColorEnabled ) // skin-colors can change + BGColor = skin->getColor(gui::EGDC_3D_FACE); + driver->draw2DRectangle(BGColor, frameRect, &AbsoluteClippingRect); } @@ -88,12 +91,12 @@ void CGUIStaticText::draw() { if (VAlign == EGUIA_LOWERRIGHT) { - frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - + frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - font->getDimension(L"A").Height - font->getKerningHeight(); } if (HAlign == EGUIA_LOWERRIGHT) { - frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - + frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - font->getDimension(Text.c_str()).Width; } @@ -122,7 +125,7 @@ void CGUIStaticText::draw() { if (HAlign == EGUIA_LOWERRIGHT) { - r.UpperLeftCorner.X = frameRect.LowerRightCorner.X - + r.UpperLeftCorner.X = frameRect.LowerRightCorner.X - font->getDimension(BrokenText[i].c_str()).Width; } @@ -177,6 +180,7 @@ void CGUIStaticText::setOverrideColor(video::SColor color) void CGUIStaticText::setBackgroundColor(video::SColor color) { BGColor = color; + OverrideBGColorEnabled = true; Background = true; } @@ -274,17 +278,17 @@ void CGUIStaticText::breakText() if (c == L'\r') // Mac or Windows breaks { lineBreak = true; - c = ' '; if (Text[i+1] == L'\n') // Windows breaks { Text.erase(i+1); --size; } + c = '\0'; } else if (c == L'\n') // Unix breaks { lineBreak = true; - c = ' '; + c = '\0'; } if (c == L' ' || c == 0 || i == (size-1)) @@ -349,6 +353,7 @@ void CGUIStaticText::setText(const wchar_t* text) breakText(); } + void CGUIStaticText::updateAbsolutePosition() { IGUIElement::updateAbsolutePosition(); @@ -424,9 +429,11 @@ void CGUIStaticText::serializeAttributes(io::IAttributes* out, io::SAttributeRea out->addBool ("Border", Border); out->addBool ("OverrideColorEnabled",OverrideColorEnabled); - out->addBool ("WordWrap", WordWrap); + out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled); + out->addBool ("WordWrap", WordWrap); out->addBool ("Background", Background); out->addColor ("OverrideColor", OverrideColor); + out->addColor ("BGColor", BGColor); out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); @@ -440,11 +447,12 @@ void CGUIStaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeRe IGUIStaticText::deserializeAttributes(in,options); Border = in->getAttributeAsBool("Border"); - OverrideColor = in->getAttributeAsColor("OverrideColor"); - enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled")); + OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled"); setWordWrap(in->getAttributeAsBool("WordWrap")); Background = in->getAttributeAsBool("Background"); + OverrideColor = in->getAttributeAsColor("OverrideColor"); + BGColor = in->getAttributeAsColor("BGColor"); setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); diff --git a/src/dep/src/irrlicht/CGUIStaticText.h b/src/dep/src/irrlicht/CGUIStaticText.h index 9a7f4b9..94ff4cf 100644 --- a/src/dep/src/irrlicht/CGUIStaticText.h +++ b/src/dep/src/irrlicht/CGUIStaticText.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -91,9 +91,10 @@ namespace gui //! Breaks the single text line. void breakText(); - bool Border; EGUI_ALIGNMENT HAlign, VAlign; + bool Border; bool OverrideColorEnabled; + bool OverrideBGColorEnabled; bool WordWrap; bool Background; diff --git a/src/dep/src/irrlicht/CGUITabControl.cpp b/src/dep/src/irrlicht/CGUITabControl.cpp index 488a3c9..ecef7ce 100644 --- a/src/dep/src/irrlicht/CGUITabControl.cpp +++ b/src/dep/src/irrlicht/CGUITabControl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,20 +24,19 @@ namespace gui //! constructor CGUITab::CGUITab(s32 number, IGUIEnvironment* environment, - IGUIElement* parent, const core::rect& rectangle, + IGUIElement* parent, const core::rect& rectangle, s32 id) : IGUITab(environment, parent, id, rectangle), Number(number), - DrawBackground(false), BackColor(0,0,0,0) + BackColor(0,0,0,0), OverrideTextColorEnabled(false), TextColor(255,0,0,0), + DrawBackground(false) { #ifdef _DEBUG setDebugName("CGUITab"); #endif - IGUISkin* skin = environment->getSkin(); + const IGUISkin* const skin = environment->getSkin(); if (skin) TextColor = skin->getColor(EGDC_BUTTON_TEXT); - else - TextColor.set(255,0,0,0); } @@ -55,6 +54,13 @@ void CGUITab::setNumber(s32 n) Number = n; } +void CGUITab::refreshSkinColors() +{ + if ( !OverrideTextColorEnabled ) + { + TextColor = Environment->getSkin()->getColor(EGDC_BUTTON_TEXT); + } +} //! draws the element and its children void CGUITab::draw() @@ -84,17 +90,21 @@ void CGUITab::setBackgroundColor(video::SColor c) BackColor = c; } + //! sets the color of the text void CGUITab::setTextColor(video::SColor c) { + OverrideTextColorEnabled = true; TextColor = c; } + video::SColor CGUITab::getTextColor() const { return TextColor; } + //! returns true if the tab is drawing its background, false if not bool CGUITab::isDrawingBackground() const { @@ -118,6 +128,7 @@ void CGUITab::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteO out->addInt ("TabNumber", Number); out->addBool ("DrawBackground", DrawBackground); out->addColor ("BackColor", BackColor); + out->addBool ("OverrideTextColorEnabled", OverrideTextColorEnabled); out->addColor ("TextColor", TextColor); } @@ -131,7 +142,12 @@ void CGUITab::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWrite setNumber(in->getAttributeAsInt("TabNumber")); setDrawBackground(in->getAttributeAsBool("DrawBackground")); setBackgroundColor(in->getAttributeAsColor("BackColor")); + bool override = in->getAttributeAsBool("OverrideTextColorEnabled"); setTextColor(in->getAttributeAsColor("TextColor")); + if ( !override ) + { + OverrideTextColorEnabled = false; + } if (Parent && Parent->getType() == EGUIET_TAB_CONTROL) { @@ -148,7 +164,7 @@ void CGUITab::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWrite //! constructor CGUITabControl::CGUITabControl(IGUIEnvironment* environment, - IGUIElement* parent, const core::rect& rectangle, + IGUIElement* parent, const core::rect& rectangle, bool fillbackground, bool border, s32 id) : IGUITabControl(environment, parent, id, rectangle), ActiveTab(-1), Border(border), FillBackground(fillbackground), ScrollControl(false), TabHeight(0), VerticalAlignment(EGUIA_UPPERLEFT), @@ -156,7 +172,7 @@ CGUITabControl::CGUITabControl(IGUIEnvironment* environment, { #ifdef _DEBUG setDebugName("CGUITabControl"); - #endif + #endif video::SColor color(255,255,255,255); IGUISkin* skin = Environment->getSkin(); @@ -195,7 +211,7 @@ CGUITabControl::CGUITabControl(IGUIEnvironment* environment, DownButton->setVisible(false); DownButton->setSubElement(true); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); - DownButton->setOverrideFont(Environment->getBuiltInFont()); + DownButton->setOverrideFont(Environment->getBuiltInFont()); DownButton->grab(); } @@ -370,6 +386,7 @@ bool CGUITabControl::OnEvent(const SEvent& event) return IGUIElement::OnEvent(event); } + void CGUITabControl::scrollLeft() { if ( CurrentScrollTabIndex > 0 ) @@ -377,6 +394,7 @@ void CGUITabControl::scrollLeft() recalculateScrollBar(); } + void CGUITabControl::scrollRight() { if ( CurrentScrollTabIndex < (s32)(Tabs.size()) - 1 ) @@ -387,6 +405,30 @@ void CGUITabControl::scrollRight() recalculateScrollBar(); } +s32 CGUITabControl::calcTabWidth(s32 pos, IGUIFont* font, const wchar_t* text, bool withScrollControl) +{ + if ( !font ) + return 0; + + s32 len = font->getDimension(text).Width + TabExtraWidth; + if ( TabMaxWidth > 0 && len > TabMaxWidth ) + len = TabMaxWidth; + + // check if we miss the place to draw the tab-button + if ( withScrollControl && ScrollControl && pos+len > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 ) + { + s32 tabMinWidth = font->getDimension(L"A").Width; + if ( TabExtraWidth > 0 && TabExtraWidth > tabMinWidth ) + tabMinWidth = TabExtraWidth; + + if ( ScrollControl && pos+tabMinWidth <= UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 ) + { + len = UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 - pos; + } + } + return len; +} + bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl) { if ( startIndex >= (s32)Tabs.size() ) @@ -419,7 +461,7 @@ bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl) text = Tabs[i]->getText(); // get text length - s32 len = font->getDimension(text).Width + TabExtraWidth; + s32 len = calcTabWidth(pos, font, text, false); // always without withScrollControl here or len would be shortened frameRect.LowerRightCorner.X += len; @@ -427,7 +469,7 @@ bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl) frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len; pos += len; - if ( withScrollControl && pos > AbsoluteRect.LowerRightCorner.X - TabMaxWidth) + if ( withScrollControl && pos > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2) return true; if ( !withScrollControl && pos > AbsoluteRect.LowerRightCorner.X ) @@ -437,6 +479,7 @@ bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl) return false; } + bool CGUITabControl::selectTab(core::position2d p) { IGUISkin* skin = Environment->getSkin(); @@ -467,13 +510,13 @@ bool CGUITabControl::selectTab(core::position2d p) text = Tabs[i]->getText(); // get text length - s32 len = font->getDimension(text).Width + TabExtraWidth; + s32 len = calcTabWidth(pos, font, text, true); + if ( ScrollControl && pos+len > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 ) + return false; + frameRect.UpperLeftCorner.X = pos; frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len; - if ( ScrollControl && pos > AbsoluteRect.LowerRightCorner.X) - return false; - pos += len; if (frameRect.isPointInside(p)) @@ -506,7 +549,7 @@ void CGUITabControl::draw() if (!font) return; - + if ( VerticalAlignment == EGUIA_UPPERLEFT ) { frameRect.UpperLeftCorner.Y += 2; @@ -521,6 +564,9 @@ void CGUITabControl::draw() core::rect tr; s32 pos = frameRect.UpperLeftCorner.X + 2; + bool needLeftScroll = CurrentScrollTabIndex > 0; + bool needRightScroll = false; + // left and right pos of the active tab s32 left = 0; s32 right = 0; @@ -528,7 +574,7 @@ void CGUITabControl::draw() //const wchar_t* activetext = 0; CGUITab *activeTab = 0; - for (u32 i=0; igetText(); // get text length - s32 len = font->getDimension(text).Width + TabExtraWidth; + s32 len = calcTabWidth(pos, font, text, true); + if ( ScrollControl && pos+len > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 ) + { + needRightScroll = true; + break; + } frameRect.LowerRightCorner.X += len; - frameRect.UpperLeftCorner.X = pos; frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len; - if ( ScrollControl && pos > frameRect.LowerRightCorner.X ) - break; - pos += len; + if ( text ) + Tabs[i]->refreshSkinColors(); + if ((s32)i == ActiveTab) { left = frameRect.UpperLeftCorner.X; @@ -561,13 +611,13 @@ void CGUITabControl::draw() // draw text font->draw(text, frameRect, Tabs[i]->getTextColor(), - true, true, &AbsoluteClippingRect); + true, true, &frameRect); } } // draw active tab if (left != 0 && right != 0 && activeTab != 0) - { + { // draw upper highlight frame if ( VerticalAlignment == EGUIA_UPPERLEFT ) { @@ -576,10 +626,10 @@ void CGUITabControl::draw() frameRect.UpperLeftCorner.Y -= 2; skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment); - + // draw text font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(), - true, true, &AbsoluteClippingRect); + true, true, &frameRect); tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X; tr.LowerRightCorner.X = left - 1; @@ -599,10 +649,10 @@ void CGUITabControl::draw() frameRect.LowerRightCorner.Y += 2; skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment); - + // draw text font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(), - true, true, &AbsoluteClippingRect); + true, true, &frameRect); tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X; tr.LowerRightCorner.X = left - 1; @@ -637,9 +687,16 @@ void CGUITabControl::draw() skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment); + // enable scrollcontrols on need + if ( UpButton ) + UpButton->setEnabled(needLeftScroll); + if ( DownButton ) + DownButton->setEnabled(needRightScroll); + IGUIElement::draw(); } + //! Set the height of the tabs void CGUITabControl::setTabHeight( s32 height ) { @@ -648,17 +705,30 @@ void CGUITabControl::setTabHeight( s32 height ) TabHeight = height; - TabMaxWidth = 2 * TabHeight; - + recalculateScrollButtonPlacement(); recalculateScrollBar(); } + //! Get the height of the tabs s32 CGUITabControl::getTabHeight() const { return TabHeight; } +//! set the maximal width of a tab. Per default width is 0 which means "no width restriction". +void CGUITabControl::setTabMaxWidth(s32 width ) +{ + TabMaxWidth = width; +} + +//! get the maximal width of a tab +s32 CGUITabControl::getTabMaxWidth() const +{ + return TabMaxWidth; +} + + //! Set the extra width added to tabs on each side of the text void CGUITabControl::setTabExtraWidth( s32 extraWidth ) { @@ -670,18 +740,23 @@ void CGUITabControl::setTabExtraWidth( s32 extraWidth ) recalculateScrollBar(); } + //! Get the extra width added to tabs on each side of the text s32 CGUITabControl::getTabExtraWidth() const { return TabExtraWidth; } + void CGUITabControl::recalculateScrollBar() { + if (!UpButton || !DownButton) + return; + ScrollControl = needScrollControl() || CurrentScrollTabIndex > 0; if (ScrollControl) - { + { UpButton->setVisible( true ); DownButton->setVisible( true ); } @@ -691,17 +766,27 @@ void CGUITabControl::recalculateScrollBar() DownButton->setVisible( false ); } - this->bringToFront( UpButton ); - this->bringToFront( DownButton ); + bringToFront( UpButton ); + bringToFront( DownButton ); } + //! Set the alignment of the tabs void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment ) { VerticalAlignment = alignment; + recalculateScrollButtonPlacement(); + recalculateScrollBar(); +} + +void CGUITabControl::recalculateScrollButtonPlacement() +{ IGUISkin* skin = Environment->getSkin(); s32 ButtonSize = 16; + s32 ButtonHeight = TabHeight - 2; + if ( ButtonHeight < 0 ) + ButtonHeight = TabHeight; if (skin) { ButtonSize = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); @@ -709,28 +794,25 @@ void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment ) ButtonSize = TabHeight; } - TabMaxWidth = s32(f32(ButtonSize) * 2.5f); - s32 ButtonX = RelativeRect.getWidth() - TabMaxWidth - 1; + s32 ButtonX = RelativeRect.getWidth() - (s32)(2.5f*(f32)ButtonSize) - 1; s32 ButtonY = 0; if (VerticalAlignment == EGUIA_UPPERLEFT) { - ButtonY = (TabHeight / 2) - (ButtonSize / 2); + ButtonY = 2 + (TabHeight / 2) - (ButtonHeight / 2); UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); } else { - ButtonY = RelativeRect.getHeight() - (TabHeight / 2) - (ButtonSize / 2); + ButtonY = RelativeRect.getHeight() - (TabHeight / 2) - (ButtonHeight / 2) - 2; UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); } - - UpButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonSize)); - ButtonX += ButtonSize + 1; - DownButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonSize)); - recalculateScrollBar(); + UpButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight)); + ButtonX += ButtonSize + 1; + DownButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight)); } //! Get the alignment of the tabs @@ -739,12 +821,14 @@ EGUI_ALIGNMENT CGUITabControl::getTabVerticalAlignment() const return VerticalAlignment; } + //! Returns which tab is currently active s32 CGUITabControl::getActiveTab() const { return ActiveTab; } + //! Brings a tab to front. bool CGUITabControl::setActiveTab(s32 idx) { @@ -766,12 +850,13 @@ bool CGUITabControl::setActiveTab(s32 idx) event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_TAB_CHANGED; - Parent->OnEvent(event); + Parent->OnEvent(event); } return true; } + bool CGUITabControl::setActiveTab(IGUIElement *tab) { for (s32 i=0; i<(s32)Tabs.size(); ++i) @@ -780,6 +865,7 @@ bool CGUITabControl::setActiveTab(IGUIElement *tab) return false; } + //! Removes a child. void CGUITabControl::removeChild(IGUIElement* child) { @@ -813,6 +899,7 @@ void CGUITabControl::removeChild(IGUIElement* child) recalculateScrollBar(); } + //! Update the position of the element, decides scroll button status void CGUITabControl::updateAbsolutePosition() { @@ -820,6 +907,7 @@ void CGUITabControl::updateAbsolutePosition() recalculateScrollBar(); } + //! Writes attributes of the element. void CGUITabControl::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { @@ -829,6 +917,7 @@ void CGUITabControl::serializeAttributes(io::IAttributes* out, io::SAttributeRea out->addBool("Border", Border); out->addBool("FillBackground", FillBackground); out->addInt ("TabHeight", TabHeight); + out->addInt ("TabMaxWidth", TabMaxWidth); out->addEnum("TabVerticalAlignment", s32(VerticalAlignment), GUIAlignmentNames); } @@ -842,6 +931,7 @@ void CGUITabControl::deserializeAttributes(io::IAttributes* in, io::SAttributeRe ActiveTab = -1; setTabHeight(in->getAttributeAsInt("TabHeight")); + TabMaxWidth = in->getAttributeAsInt("TabMaxWidth"); IGUITabControl::deserializeAttributes(in,options); @@ -855,4 +945,3 @@ void CGUITabControl::deserializeAttributes(io::IAttributes* in, io::SAttributeRe #endif // _IRR_COMPILE_WITH_GUI_ - diff --git a/src/dep/src/irrlicht/CGUITabControl.h b/src/dep/src/irrlicht/CGUITabControl.h index 5a5d6be..b63f207 100644 --- a/src/dep/src/irrlicht/CGUITabControl.h +++ b/src/dep/src/irrlicht/CGUITabControl.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -47,7 +47,7 @@ namespace gui //! sets the color of the background, if it should be drawn. virtual void setBackgroundColor(video::SColor c); - + //! sets the color of the text virtual void setTextColor(video::SColor c); @@ -65,18 +65,19 @@ namespace gui //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + //! only for internal use by CGUITabControl + void refreshSkinColors(); private: s32 Number; - bool DrawBackground; video::SColor BackColor; + bool OverrideTextColorEnabled; video::SColor TextColor; - + bool DrawBackground; }; - //! A standard tab control class CGUITabControl : public IGUITabControl { @@ -127,9 +128,16 @@ namespace gui //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + //! Get the height of the tabs virtual s32 getTabHeight() const; + //! set the maximal width of a tab. Per default width is 0 which means "no width restriction". + virtual void setTabMaxWidth(s32 width ); + + //! get the maximal width of a tab + virtual s32 getTabMaxWidth() const; + //! Set the alignment of the tabs //! note: EGUIA_CENTER is not an option virtual void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment ); @@ -152,7 +160,9 @@ namespace gui void scrollLeft(); void scrollRight(); bool needScrollControl( s32 startIndex=0, bool withScrollControl=false ); + s32 calcTabWidth(s32 pos, IGUIFont* font, const wchar_t* text, bool withScrollControl ); + void recalculateScrollButtonPlacement(); void recalculateScrollBar(); core::array Tabs; diff --git a/src/dep/src/irrlicht/CGUITable.cpp b/src/dep/src/irrlicht/CGUITable.cpp index 2feb874..33cfbff 100644 --- a/src/dep/src/irrlicht/CGUITable.cpp +++ b/src/dep/src/irrlicht/CGUITable.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,7 +24,7 @@ namespace gui //! constructor CGUITable::CGUITable(IGUIEnvironment* environment, IGUIElement* parent, - s32 id, core::rect rectangle, bool clip, + s32 id, const core::rect& rectangle, bool clip, bool drawBack, bool moveOverSelect) : IGUITable(environment, parent, id, rectangle), Font(0), VerticalScrollBar(0), HorizontalScrollBar(0), @@ -78,12 +78,6 @@ void CGUITable::addColumn(const wchar_t* caption, s32 columnIndex) tabHeader.Width = Font->getDimension(caption).Width + (CellWidthPadding * 2) + ARROW_PAD; tabHeader.OrderingMode = EGCO_NONE; - IGUISkin* skin = Environment->getSkin(); - if (skin) - { - tabHeader.TextColor = skin->getColor(EGDC_BUTTON_TEXT); - } - if ( columnIndex < 0 || columnIndex >= (s32)Columns.size() ) { Columns.push_back(tabHeader); @@ -109,6 +103,7 @@ void CGUITable::addColumn(const wchar_t* caption, s32 columnIndex) recalculateWidths(); } + //! remove a column from the table void CGUITable::removeColumn(u32 columnIndex) { @@ -126,16 +121,19 @@ void CGUITable::removeColumn(u32 columnIndex) recalculateWidths(); } + s32 CGUITable::getColumnCount() const { return Columns.size(); } + s32 CGUITable::getRowCount() const { return Rows.size(); } + bool CGUITable::setActiveColumn(s32 idx, bool doOrder ) { if (idx < 0 || idx >= (s32)Columns.size()) @@ -162,6 +160,7 @@ bool CGUITable::setActiveColumn(s32 idx, bool doOrder ) SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; + event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_TABLE_HEADER_CHANGED; Parent->OnEvent(event); } @@ -191,6 +190,7 @@ bool CGUITable::setActiveColumn(s32 idx, bool doOrder ) SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; + event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_TABLE_HEADER_CHANGED; Parent->OnEvent(event); } @@ -198,16 +198,19 @@ bool CGUITable::setActiveColumn(s32 idx, bool doOrder ) return true; } + s32 CGUITable::getActiveColumn() const { return ActiveTab; } + EGUI_ORDERING_MODE CGUITable::getActiveColumnOrdering() const { return CurrentOrdering; } + void CGUITable::setColumnWidth(u32 columnIndex, u32 width) { if ( columnIndex < Columns.size() ) @@ -239,10 +242,12 @@ bool CGUITable::hasResizableColumns() const } -void CGUITable::addRow(u32 rowIndex) +u32 CGUITable::addRow(u32 rowIndex) { if ( rowIndex > Rows.size() ) - return; + { + rowIndex = Rows.size(); + } Row row; @@ -251,15 +256,17 @@ void CGUITable::addRow(u32 rowIndex) else Rows.insert(row, rowIndex); + Rows[rowIndex].Items.reallocate(Columns.size()); for ( u32 i = 0 ; i < Columns.size() ; ++i ) { - Cell cell; - Rows[rowIndex].Items.push_back(cell); + Rows[rowIndex].Items.push_back(Cell()); } recalculateHeights(); + return rowIndex; } + void CGUITable::removeRow(u32 rowIndex) { if ( rowIndex > Rows.size() ) @@ -273,8 +280,9 @@ void CGUITable::removeRow(u32 rowIndex) recalculateHeights(); } + //! adds an list item, returns id of item -void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text) +void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { @@ -287,24 +295,28 @@ void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text) } } -void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text, video::SColor color) +void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { Rows[rowIndex].Items[columnIndex].Text = text; breakText( Rows[rowIndex].Items[columnIndex].Text, Rows[rowIndex].Items[columnIndex].BrokenText, Columns[columnIndex].Width ); Rows[rowIndex].Items[columnIndex].Color = color; + Rows[rowIndex].Items[columnIndex].IsOverrideColor = true; } } + void CGUITable::setCellColor(u32 rowIndex, u32 columnIndex, video::SColor color) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { Rows[rowIndex].Items[columnIndex].Color = color; + Rows[rowIndex].Items[columnIndex].IsOverrideColor = true; } } + void CGUITable::setCellData(u32 rowIndex, u32 columnIndex, void *data) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) @@ -313,6 +325,7 @@ void CGUITable::setCellData(u32 rowIndex, u32 columnIndex, void *data) } } + const wchar_t* CGUITable::getCellText(u32 rowIndex, u32 columnIndex ) const { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) @@ -323,6 +336,7 @@ const wchar_t* CGUITable::getCellText(u32 rowIndex, u32 columnIndex ) const return 0; } + void* CGUITable::getCellData(u32 rowIndex, u32 columnIndex ) const { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) @@ -333,9 +347,11 @@ void* CGUITable::getCellData(u32 rowIndex, u32 columnIndex ) const return 0; } + //! clears the list void CGUITable::clear() { + Selected = -1; Rows.clear(); Columns.clear(); @@ -348,8 +364,10 @@ void CGUITable::clear() recalculateWidths(); } + void CGUITable::clearRows() { + Selected = -1; Rows.clear(); if (VerticalScrollBar) @@ -358,11 +376,23 @@ void CGUITable::clearRows() recalculateHeights(); } + +/*! +*/ s32 CGUITable::getSelected() const { return Selected; } +//! set wich row is currently selected +void CGUITable::setSelected( s32 index ) +{ + Selected = -1; + if ( index >= 0 && index < (s32) Rows.size() ) + Selected = index; +} + + void CGUITable::recalculateWidths() { TotalItemWidth=0; @@ -373,6 +403,7 @@ void CGUITable::recalculateWidths() checkScrollbars(); } + void CGUITable::recalculateHeights() { TotalItemHeight = 0; @@ -396,6 +427,7 @@ void CGUITable::recalculateHeights() checkScrollbars(); } + // automatic enabled/disabling and resizing of scrollbars void CGUITable::checkScrollbars() { @@ -484,6 +516,7 @@ void CGUITable::checkScrollbars() } } + void CGUITable::refreshControls() { updateAbsolutePosition(); @@ -657,6 +690,7 @@ void CGUITable::swapRows(u32 rowIndexA, u32 rowIndexB) } + bool CGUITable::dragColumnStart(s32 xpos, s32 ypos) { if ( !ResizableColumns ) @@ -665,7 +699,7 @@ bool CGUITable::dragColumnStart(s32 xpos, s32 ypos) if ( ypos > ( AbsoluteRect.UpperLeftCorner.Y + ItemHeight ) ) return false; - const s32 CLICK_AREA = 3; // to left and right of line which can be dragged + const s32 CLICK_AREA = 12; // to left and right of line which can be dragged s32 pos = AbsoluteRect.UpperLeftCorner.X+1; if ( HorizontalScrollBar && HorizontalScrollBar->isVisible() ) @@ -691,6 +725,7 @@ bool CGUITable::dragColumnStart(s32 xpos, s32 ypos) return false; } + bool CGUITable::dragColumnUpdate(s32 xpos) { if ( !ResizableColumns || CurrentResizedColumn < 0 || CurrentResizedColumn >= s32(Columns.size()) ) @@ -708,6 +743,7 @@ bool CGUITable::dragColumnUpdate(s32 xpos) return false; } + bool CGUITable::selectColumnHeader(s32 xpos, s32 ypos) { if ( ypos > ( AbsoluteRect.UpperLeftCorner.Y + ItemHeight ) ) @@ -735,6 +771,7 @@ bool CGUITable::selectColumnHeader(s32 xpos, s32 ypos) return false; } + void CGUITable::orderRows(s32 columnIndex, EGUI_ORDERING_MODE mode) { Row swap; @@ -813,6 +850,7 @@ void CGUITable::selectNew(s32 ypos, bool onlyHover) SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; + event.GUIEvent.Element = 0; event.GUIEvent.EventType = (Selected != oldSelected) ? EGET_TABLE_CHANGED : EGET_TABLE_SELECTED_AGAIN; Parent->OnEvent(event); } @@ -911,6 +949,8 @@ void CGUITable::draw() } else { + if ( !Rows[i].Items[j].IsOverrideColor ) // skin-colors can change + Rows[i].Items[j].Color = skin->getColor(EGDC_BUTTON_TEXT); font->draw(Rows[i].Items[j].BrokenText.c_str(), textRect, IsEnabled ? Rows[i].Items[j].Color : skin->getColor(EGDC_GRAY_TEXT), false, true, &clientClip); } @@ -996,7 +1036,7 @@ void CGUITable::breakText(const core::stringw& text, core::stringw& brokenText, c[1] = L'\0'; const u32 maxLength = cellWidth - (CellWidthPadding * 2); - const s32 maxLengthDots = cellWidth - (CellWidthPadding * 2) - font->getDimension(L"...").Width; + const u32 maxLengthDots = cellWidth - (CellWidthPadding * 2) - font->getDimension(L"...").Width; const u32 size = text.size(); u32 pos = 0; @@ -1053,8 +1093,6 @@ void CGUITable::serializeAttributes(io::IAttributes* out, io::SAttributeReadWrit label = "Column"; label += i; label += "name"; out->addString(label.c_str(), Columns[i].Name.c_str() ); - label = "Column"; label += i; label += "color"; - out->addColor(label.c_str(), Columns[i].TextColor ); label = "Column"; label += i; label += "width"; out->addInt(label.c_str(), Columns[i].Width ); label = "Column"; label += i; label += "OrderingMode"; @@ -1080,6 +1118,8 @@ void CGUITable::serializeAttributes(io::IAttributes* out, io::SAttributeReadWrit // core::stringw BrokenText; // can be recalculated label = "Row"; label += i; label += "cell"; label += c; label += "color"; out->addColor(label.c_str(), Rows[i].Items[c].Color ); + label = "Row"; label += i; label += "cell"; label += c; label += "IsOverrideColor"; + out->addColor(label.c_str(), Rows[i].Items[c].IsOverrideColor ); // void *data; // can't be serialized } } @@ -1123,8 +1163,6 @@ void CGUITable::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWri label = "Column"; label += i; label += "name"; column.Name = core::stringw(in->getAttributeAsString(label.c_str()).c_str()); - label = "Column"; label += i; label += "color"; - column.TextColor = in->getAttributeAsColor(label.c_str()); label = "Column"; label += i; label += "width"; column.Width = in->getAttributeAsInt(label.c_str()); label = "Column"; label += i; label += "OrderingMode"; @@ -1163,6 +1201,9 @@ void CGUITable::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWri breakText( cell.Text, cell.BrokenText, Columns[c].Width ); label = "Row"; label += i; label += "cell"; label += c; label += "color"; cell.Color = in->getAttributeAsColor(label.c_str()); + label = "Row"; label += i; label += "cell"; label += c; label += "IsOverrideColor"; + cell.IsOverrideColor = in->getAttributeAsBool(label.c_str()); + cell.Data = NULL; Rows[Rows.size()-1].Items.push_back(cell); diff --git a/src/dep/src/irrlicht/CGUITable.h b/src/dep/src/irrlicht/CGUITable.h index 4f02be0..465adba 100644 --- a/src/dep/src/irrlicht/CGUITable.h +++ b/src/dep/src/irrlicht/CGUITable.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -26,8 +26,8 @@ namespace gui { public: //! constructor - CGUITable(IGUIEnvironment* environment, IGUIElement* parent, - s32 id, core::rect rectangle, bool clip=true, + CGUITable(IGUIEnvironment* environment, IGUIElement* parent, + s32 id, const core::rect& rectangle, bool clip=true, bool drawBack=false, bool moveOverSelect=true); //! destructor @@ -45,7 +45,7 @@ namespace gui //! Makes a column active. This will trigger an ordering process. /** \param idx: The id of the column to make active. - \return Returns true if successful. */ + \return True if successful. */ virtual bool setActiveColumn(s32 columnIndex, bool doOrder=false); //! Returns which header is currently active @@ -56,23 +56,26 @@ namespace gui //! set a column width virtual void setColumnWidth(u32 columnIndex, u32 width); - + //! columns can be resized by drag 'n drop virtual void setResizableColumns(bool resizable); - + //! can columns be resized by dran 'n drop? virtual bool hasResizableColumns() const; - //! This tells the table control which ordering mode should be used when - //! a column header is clicked. + //! This tells the table control which ordering mode should be used when + //! a column header is clicked. /** \param columnIndex: The index of the column header. \param state: If true, a EGET_TABLE_HEADER_CHANGED message will be sent and you can order the table data as you whish.*/ - //! \param mode: One of the modes defined in EGUI_COLUMN_ORDERING + //! \param mode: One of the modes defined in EGUI_COLUMN_ORDERING virtual void setColumnOrdering(u32 columnIndex, EGUI_COLUMN_ORDERING mode); //! Returns which row is currently selected virtual s32 getSelected() const; + //! set wich row is currently selected + virtual void setSelected( s32 index ); + //! Returns amount of rows in the tabcontrol virtual s32 getRowCount() const; @@ -83,7 +86,7 @@ namespace gui than the actual number of rows by more than one, it won't be created. Note that if you create a row that is not at the end, there might be performance issues*/ - virtual void addRow(u32 rowIndex); + virtual u32 addRow(u32 rowIndex); //! Remove a row from the table virtual void removeRow(u32 rowIndex); @@ -99,15 +102,15 @@ namespace gui //! a new row is added or the cells data is changed. This makes //! the system more flexible and doesn't make you pay the cost //! of ordering when adding a lot of rows. - //! \param columnIndex: When set to -1 the active column is used. + //! \param columnIndex: When set to -1 the active column is used. virtual void orderRows(s32 columnIndex=-1, EGUI_ORDERING_MODE mode=EGOM_NONE); //! Set the text of a cell - virtual void setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text); + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text); //! Set the text of a cell, and set a color of this cell. - virtual void setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text, video::SColor color); + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color); //! Set the data of a cell //! data will not be serialized. @@ -155,9 +158,10 @@ namespace gui struct Cell { - Cell() : Data(0) {} + Cell() : IsOverrideColor(false), Data(0) {} core::stringw Text; core::stringw BrokenText; + bool IsOverrideColor; video::SColor Color; void *Data; }; @@ -172,7 +176,6 @@ namespace gui { Column() : Width(0), OrderingMode(EGCO_NONE) {} core::stringw Name; - video::SColor TextColor; u32 Width; EGUI_COLUMN_ORDERING OrderingMode; }; diff --git a/src/dep/src/irrlicht/CGUIToolBar.cpp b/src/dep/src/irrlicht/CGUIToolBar.cpp index f57c1fd..5a28ed6 100644 --- a/src/dep/src/irrlicht/CGUIToolBar.cpp +++ b/src/dep/src/irrlicht/CGUIToolBar.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -69,7 +69,7 @@ bool CGUIToolBar::OnEvent(const SEvent& event) { if (IsEnabled) { - if (event.EventType == EET_MOUSE_INPUT_EVENT && + if (event.EventType == EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { if (AbsoluteClippingRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y))) @@ -116,18 +116,32 @@ void CGUIToolBar::updateAbsolutePosition() //! Adds a button to the tool bar IGUIButton* CGUIToolBar::addButton(s32 id, const wchar_t* text,const wchar_t* tooltiptext, - video::ITexture* img, video::ITexture* pressed, bool isPushButton, + video::ITexture* img, video::ITexture* pressed, bool isPushButton, bool useAlphaChannel) { ButtonX += 3; - core::rect rectangle(ButtonX,2,0,0); + core::rect rectangle(ButtonX,2,ButtonX+1,3); if ( img ) { - const core::dimension2di &size = img->getOriginalSize(); + const core::dimension2du &size = img->getOriginalSize(); rectangle.LowerRightCorner.X = rectangle.UpperLeftCorner.X + size.Width + 8; rectangle.LowerRightCorner.Y = rectangle.UpperLeftCorner.Y + size.Height + 6; } + + if ( text ) + { + IGUISkin* skin = Environment->getSkin(); + IGUIFont * font = skin->getFont(EGDF_BUTTON); + if ( font ) + { + core::dimension2d dim = font->getDimension(text); + if ( (s32)dim.Width > rectangle.getWidth() ) + rectangle.LowerRightCorner.X = rectangle.UpperLeftCorner.X + dim.Width + 8; + if ( (s32)dim.Height > rectangle.getHeight() ) + rectangle.LowerRightCorner.Y = rectangle.UpperLeftCorner.Y + dim.Height + 6; + } + } ButtonX += rectangle.getWidth(); @@ -151,10 +165,10 @@ IGUIButton* CGUIToolBar::addButton(s32 id, const wchar_t* text,const wchar_t* to if (useAlphaChannel) button->setUseAlphaChannel(useAlphaChannel); - + return button; } - + } // end namespace gui } // end namespace irr diff --git a/src/dep/src/irrlicht/CGUIToolBar.h b/src/dep/src/irrlicht/CGUIToolBar.h index 0bacb18..9271a7d 100644 --- a/src/dep/src/irrlicht/CGUIToolBar.h +++ b/src/dep/src/irrlicht/CGUIToolBar.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CGUITreeView.cpp b/src/dep/src/irrlicht/CGUITreeView.cpp new file mode 100644 index 0000000..04359bd --- /dev/null +++ b/src/dep/src/irrlicht/CGUITreeView.cpp @@ -0,0 +1,1093 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de +// expaned by burningwater + +#include "CGUITreeView.h" + +#ifdef _IRR_COMPILE_WITH_GUI_ + +#include "IGUISkin.h" +#include "IGUIEnvironment.h" +#include "IVideoDriver.h" +#include "IGUIFont.h" +#include "CGUIScrollBar.h" +#include "os.h" + +namespace irr +{ +namespace gui +{ + +CGUITreeViewNode::CGUITreeViewNode( CGUITreeView* owner, CGUITreeViewNode* parent ) + : Owner(owner), Parent(parent), ImageIndex(-1), SelectedImageIndex(-1), + Data(0), Data2(0), Expanded(false) +{ +#ifdef _DEBUG + setDebugName( "CGUITreeView" ); +#endif +} + +CGUITreeViewNode::~CGUITreeViewNode() +{ + if( Owner && this == Owner->getSelected() ) + { + setSelected( false ); + } + + clearChilds(); + + if( Data2 ) + { + Data2->drop(); + } +} + +IGUITreeView* CGUITreeViewNode::getOwner() const +{ + return Owner; +} + +IGUITreeViewNode* CGUITreeViewNode::getParent() const +{ + return Parent; +} + +void CGUITreeViewNode::setText( const wchar_t* text ) +{ + Text = text; +} + +void CGUITreeViewNode::setIcon( const wchar_t* icon ) +{ + Icon = icon; +} + +void CGUITreeViewNode::clearChilds() +{ + core::list::Iterator it; + + for( it = Childs.begin(); it != Childs.end(); it++ ) + { + ( *it )->drop(); + } + Childs.clear(); +} + +IGUITreeViewNode* CGUITreeViewNode::addChildBack( + const wchar_t* text, + const wchar_t* icon /*= 0*/, + s32 imageIndex /*= -1*/, + s32 selectedImageIndex /*= -1*/, + void* data /*= 0*/, + IReferenceCounted* data2 /*= 0*/ ) +{ + CGUITreeViewNode* newChild = new CGUITreeViewNode( Owner, this ); + + Childs.push_back( newChild ); + newChild->Text = text; + newChild->Icon = icon; + newChild->ImageIndex = imageIndex; + newChild->SelectedImageIndex = selectedImageIndex; + newChild->Data = data; + newChild->Data2 = data2; + if( data2 ) + { + data2->grab(); + } + return newChild; +} + +IGUITreeViewNode* CGUITreeViewNode::addChildFront( + const wchar_t* text, + const wchar_t* icon /*= 0*/, + s32 imageIndex /*= -1*/, + s32 selectedImageIndex /*= -1*/, + void* data /*= 0*/, + IReferenceCounted* data2 /*= 0*/ ) +{ + CGUITreeViewNode* newChild = new CGUITreeViewNode( Owner, this ); + + Childs.push_front( newChild ); + newChild->Text = text; + newChild->Icon = icon; + newChild->ImageIndex = imageIndex; + newChild->SelectedImageIndex = selectedImageIndex; + newChild->Data = data; + newChild->Data2 = data2; + if( data2 ) + { + data2->grab(); + } + return newChild; +} + +IGUITreeViewNode* CGUITreeViewNode::insertChildAfter( + IGUITreeViewNode* other, + const wchar_t* text, + const wchar_t* icon /*= 0*/, + s32 imageIndex /*= -1*/, + s32 selectedImageIndex /*= -1*/, + void* data /*= 0*/, + IReferenceCounted* data2/* = 0*/ ) +{ + core::list::Iterator itOther; + CGUITreeViewNode* newChild = 0; + + for( itOther = Childs.begin(); itOther != Childs.end(); itOther++ ) + { + if( other == *itOther ) + { + newChild = new CGUITreeViewNode( Owner, this ); + newChild->Text = text; + newChild->Icon = icon; + newChild->ImageIndex = imageIndex; + newChild->SelectedImageIndex = selectedImageIndex; + newChild->Data = data; + newChild->Data2 = data2; + if( data2 ) + { + data2->grab(); + } + Childs.insert_after( itOther, newChild ); + break; + } + } + return newChild; +} + +IGUITreeViewNode* CGUITreeViewNode::insertChildBefore( + IGUITreeViewNode* other, + const wchar_t* text, + const wchar_t* icon /*= 0*/, + s32 imageIndex /*= -1*/, + s32 selectedImageIndex /*= -1*/, + void* data /*= 0*/, + IReferenceCounted* data2/* = 0*/ ) +{ + core::list::Iterator itOther; + CGUITreeViewNode* newChild = 0; + + for( itOther = Childs.begin(); itOther != Childs.end(); itOther++ ) + { + if( other == *itOther ) + { + newChild = new CGUITreeViewNode( Owner, this ); + newChild->Text = text; + newChild->Icon = icon; + newChild->ImageIndex = imageIndex; + newChild->SelectedImageIndex = selectedImageIndex; + newChild->Data = data; + newChild->Data2 = data2; + if( data2 ) + { + data2->grab(); + } + Childs.insert_before( itOther, newChild ); + break; + } + } + return newChild; +} + +IGUITreeViewNode* CGUITreeViewNode::getFirstChild() const +{ + if( Childs.empty() ) + { + return 0; + } + else + { + return *( Childs.begin() ); + } +} + +IGUITreeViewNode* CGUITreeViewNode::getLastChild() const +{ + if( Childs.empty() ) + { + return 0; + } + else + { + return *( Childs.getLast() ); + } +} + +IGUITreeViewNode* CGUITreeViewNode::getPrevSibling() const +{ + core::list::Iterator itThis; + core::list::Iterator itOther; + CGUITreeViewNode* other = 0; + + if( Parent ) + { + for( itThis = Parent->Childs.begin(); itThis != Parent->Childs.end(); itThis++ ) + { + if( this == *itThis ) + { + if( itThis != Parent->Childs.begin() ) + { + other = *itOther; + } + break; + } + itOther = itThis; + } + } + return other; +} + +IGUITreeViewNode* CGUITreeViewNode::getNextSibling() const +{ + core::list::Iterator itThis; + CGUITreeViewNode* other = 0; + + if( Parent ) + { + for( itThis = Parent->Childs.begin(); itThis != Parent->Childs.end(); itThis++ ) + { + if( this == *itThis ) + { + if( itThis != Parent->Childs.getLast() ) + { + other = *( ++itThis ); + } + break; + } + } + } + return other; +} + +IGUITreeViewNode* CGUITreeViewNode::getNextVisible() const +{ + IGUITreeViewNode* next = 0; + IGUITreeViewNode* node = 0; + + node = const_cast( this ); + + if( node->getExpanded() && node->hasChilds() ) + { + next = node->getFirstChild(); + } + else + { + next = node->getNextSibling(); + } + while( !next && node->getParent() ) + { + next = node->getParent()->getNextSibling(); + if( !next ) + { + node = node->getParent(); + } + } + + return next; +} + +bool CGUITreeViewNode::deleteChild( IGUITreeViewNode* child ) +{ + core::list::Iterator itChild; + bool deleted = false; + + for( itChild = Childs.begin(); itChild != Childs.end(); itChild++ ) + { + if( child == *itChild ) + { + child->drop(); + Childs.erase( itChild ); + deleted = true; + break; + } + } + return deleted; +} + +bool CGUITreeViewNode::moveChildUp( IGUITreeViewNode* child ) +{ + core::list::Iterator itChild; + core::list::Iterator itOther; + CGUITreeViewNode* nodeTmp; + bool moved = false; + + for( itChild = Childs.begin(); itChild != Childs.end(); itChild++ ) + { + if( child == *itChild ) + { + if( itChild != Childs.begin() ) + { + nodeTmp = *itChild; + *itChild = *itOther; + *itOther = nodeTmp; + moved = true; + } + break; + } + itOther = itChild; + } + return moved; +} + +bool CGUITreeViewNode::moveChildDown( IGUITreeViewNode* child ) +{ + core::list::Iterator itChild; + core::list::Iterator itOther; + CGUITreeViewNode* nodeTmp; + bool moved = false; + + for( itChild = Childs.begin(); itChild != Childs.end(); itChild++ ) + { + if( child == *itChild ) + { + if( itChild != Childs.getLast() ) + { + itOther = itChild; + ++itOther; + nodeTmp = *itChild; + *itChild = *itOther; + *itOther = nodeTmp; + moved = true; + } + break; + } + } + return moved; +} + +void CGUITreeViewNode::setExpanded( bool expanded ) +{ + Expanded = expanded; +} + +void CGUITreeViewNode::setSelected( bool selected ) +{ + if( Owner ) + { + if( selected ) + { + Owner->Selected = this; + } + else + { + if( Owner->Selected == this ) + { + Owner->Selected = 0; + } + } + } +} + +bool CGUITreeViewNode::getSelected() const +{ + if( Owner ) + { + return Owner->Selected == (IGUITreeViewNode*)this; + } + else + { + return false; + } +} + +bool CGUITreeViewNode::isRoot() const +{ + return ( Owner && ( this == Owner->Root ) ); +} + +s32 CGUITreeViewNode::getLevel() const +{ + if( Parent ) + { + return Parent->getLevel() + 1; + } + else + { + return 0; + } +} + +bool CGUITreeViewNode::isVisible() const +{ + if( Parent ) + { + return Parent->getExpanded() && Parent->isVisible(); + } + else + { + return true; + } +} + + +//! constructor +CGUITreeView::CGUITreeView(IGUIEnvironment* environment, IGUIElement* parent, + s32 id, core::rect rectangle, bool clip, + bool drawBack,bool scrollBarVertical, bool scrollBarHorizontal) + : IGUITreeView( environment, parent, id, rectangle ), + Root(0), Selected(0), + ItemHeight( 0 ), + IndentWidth( 0 ), + TotalItemHeight( 0 ), + TotalItemWidth ( 0 ), + Font( 0 ), + IconFont( 0 ), + ScrollBarH( 0 ), + ScrollBarV( 0 ), + ImageList( 0 ), + LastEventNode( 0 ), + LinesVisible( true ), + Selecting( false ), + Clip( clip ), + DrawBack( drawBack ), + ImageLeftOfIcon( true ) +{ +#ifdef _DEBUG + setDebugName( "CGUITreeView" ); +#endif + + IGUISkin* skin = Environment->getSkin(); + s32 s = skin->getSize( EGDS_SCROLLBAR_SIZE ); + + if ( scrollBarVertical ) + { + ScrollBarV = new CGUIScrollBar( false, Environment, this, 0, + core::rect( RelativeRect.getWidth() - s, + 0, + RelativeRect.getWidth(), + RelativeRect.getHeight() - (scrollBarHorizontal ? s : 0 ) + ), + !clip ); + ScrollBarV->drop(); + + ScrollBarV->setPos( 0 ); + ScrollBarV->grab(); + } + + if ( scrollBarHorizontal ) + { + ScrollBarH = new CGUIScrollBar( true, Environment, this, 1, + core::rect( 0, RelativeRect.getHeight() - s, RelativeRect.getWidth() - s, RelativeRect.getHeight() ), + !clip ); + ScrollBarH->drop(); + + ScrollBarH->setPos( 0 ); + ScrollBarH->grab(); + } + + Root = new CGUITreeViewNode( this, 0 ); + Root->Expanded = true; + + recalculateItemHeight(); +} + + +//! destructor +CGUITreeView::~CGUITreeView() +{ + if( ScrollBarV ) + { + ScrollBarV->drop(); + } + + if( ScrollBarH ) + { + ScrollBarH->drop(); + } + + if( Font ) + { + Font->drop(); + } + + if( IconFont ) + { + IconFont->drop(); + } + + if( ImageList ) + { + ImageList->drop(); + } + + if( Root ) + { + Root->drop(); + } +} + +void CGUITreeView::recalculateItemHeight() +{ + IGUISkin* skin = Environment->getSkin(); + IGUITreeViewNode* node; + + if( Font != skin->getFont() ) + { + if( Font ) + { + Font->drop(); + } + + Font = skin->getFont(); + ItemHeight = 0; + + if( Font ) + { + ItemHeight = Font->getDimension( L"A" ).Height + 4; + Font->grab(); + } + + if( IconFont ) + { + s32 height = IconFont->getDimension( L" " ).Height; + if( height > ItemHeight ) + { + ItemHeight = height; + } + } + if( ImageList ) + { + if( ImageList->getImageSize().Height + 1 > ItemHeight ) + { + ItemHeight = ImageList->getImageSize().Height + 1; + } + } + } + + IndentWidth = ItemHeight; + if( IndentWidth < 9 ) + { + IndentWidth = 9; + } + else if( IndentWidth > 15 ) + { + IndentWidth = 15; + } + else + { + if( ( ( IndentWidth >> 1 ) << 1 ) - IndentWidth == 0 ) + { + --IndentWidth; + } + } + + TotalItemHeight = 0; + TotalItemWidth = AbsoluteRect.getWidth() * 2; + node = Root->getFirstChild(); + while( node ) + { + TotalItemHeight += ItemHeight; + node = node->getNextVisible(); + } + + if ( ScrollBarV ) + ScrollBarV->setMax( TotalItemHeight - AbsoluteRect.getHeight() ); + + if ( ScrollBarH ) + ScrollBarH->setMax( TotalItemWidth - AbsoluteRect.getWidth() ); + +} + +//! called if an event happened. +bool CGUITreeView::OnEvent( const SEvent &event ) +{ + switch( event.EventType ) + { + case EET_GUI_EVENT: + switch( event.GUIEvent.EventType ) + { + case gui::EGET_SCROLL_BAR_CHANGED: + if( event.GUIEvent.Caller == ScrollBarV || event.GUIEvent.Caller == ScrollBarH ) + { + //s32 pos = ( ( gui::IGUIScrollBar* )event.GUIEvent.Caller )->getPos(); + return true; + } + break; + case gui::EGET_ELEMENT_FOCUS_LOST: + { + Selecting = false; + return false; + } + break; + default: + break; + } + break; + case EET_MOUSE_INPUT_EVENT: + { + core::position2d p( event.MouseInput.X, event.MouseInput.Y ); + + switch( event.MouseInput.Event ) + { + case EMIE_MOUSE_WHEEL: + if ( ScrollBarV ) + ScrollBarV->setPos( ScrollBarV->getPos() + (s32)event.MouseInput.Wheel * -10 ); + return true; + break; + + case EMIE_LMOUSE_PRESSED_DOWN: + + if (Environment->hasFocus(this) && !AbsoluteClippingRect.isPointInside(p) ) + { + Environment->removeFocus(this); + return false; + } + + if( Environment->hasFocus( this ) && + ( ( ScrollBarV && ScrollBarV->getAbsolutePosition().isPointInside( p ) && ScrollBarV->OnEvent( event ) ) || + ( ScrollBarH && ScrollBarH->getAbsolutePosition().isPointInside( p ) && ScrollBarH->OnEvent( event ) ) + ) + ) + { + return true; + } + + Selecting = true; + Environment->setFocus( this ); + return true; + break; + + case EMIE_LMOUSE_LEFT_UP: + if( Environment->hasFocus( this ) && + ( ( ScrollBarV && ScrollBarV->getAbsolutePosition().isPointInside( p ) && ScrollBarV->OnEvent( event ) ) || + ( ScrollBarH && ScrollBarH->getAbsolutePosition().isPointInside( p ) && ScrollBarH->OnEvent( event ) ) + ) + ) + { + return true; + } + + Selecting = false; + Environment->removeFocus( this ); + mouseAction( event.MouseInput.X, event.MouseInput.Y ); + return true; + break; + + case EMIE_MOUSE_MOVED: + if( Selecting ) + { + if( getAbsolutePosition().isPointInside( p ) ) + { + mouseAction( event.MouseInput.X, event.MouseInput.Y, true ); + return true; + } + } + break; + default: + break; + } + } + break; + default: + break; + } + + + return Parent ? Parent->OnEvent( event ) : false; +} + +/*! +*/ +void CGUITreeView::mouseAction( s32 xpos, s32 ypos, bool onlyHover /*= false*/ ) +{ + IGUITreeViewNode* oldSelected = Selected; + IGUITreeViewNode* hitNode = 0; + s32 selIdx; + s32 n; + IGUITreeViewNode* node; + SEvent event; + + event.EventType = EET_GUI_EVENT; + event.GUIEvent.Caller = this; + event.GUIEvent.Element = 0; + + xpos -= AbsoluteRect.UpperLeftCorner.X; + ypos -= AbsoluteRect.UpperLeftCorner.Y; + + // find new selected item. + if( ItemHeight != 0 && ScrollBarV ) + { + selIdx = ( ( ypos - 1 ) + ScrollBarV->getPos() ) / ItemHeight; + } + + hitNode = 0; + node = Root->getFirstChild(); + n = 0; + while( node ) + { + if( selIdx == n ) + { + hitNode = node; + break; + } + node = node->getNextVisible(); + ++n; + } + + if( hitNode && xpos > hitNode->getLevel() * IndentWidth ) + { + Selected = hitNode; + } + + if( hitNode && !onlyHover + && xpos < hitNode->getLevel() * IndentWidth + && xpos > ( hitNode->getLevel() - 1 ) * IndentWidth + && hitNode->hasChilds() ) + { + hitNode->setExpanded( !hitNode->getExpanded() ); + + // post expand/collaps news + if( hitNode->getExpanded() ) + { + event.GUIEvent.EventType = EGET_TREEVIEW_NODE_EXPAND; + } + else + { + event.GUIEvent.EventType = EGET_TREEVIEW_NODE_COLLAPS; + } + LastEventNode = hitNode; + Parent->OnEvent( event ); + LastEventNode = 0; + } + + if( Selected && !Selected->isVisible() ) + { + Selected = 0; + } + + // post selection news + + if( Parent && !onlyHover && Selected != oldSelected ) + { + if( oldSelected ) + { + event.GUIEvent.EventType = EGET_TREEVIEW_NODE_DESELECT; + LastEventNode = oldSelected; + Parent->OnEvent( event ); + LastEventNode = 0; + } + if( Selected ) + { + event.GUIEvent.EventType = EGET_TREEVIEW_NODE_SELECT; + LastEventNode = Selected; + Parent->OnEvent( event ); + LastEventNode = 0; + } + } +} + + +//! draws the element and its children +void CGUITreeView::draw() +{ + if( !IsVisible ) + { + return; + } + + recalculateItemHeight(); // if the font changed + + IGUISkin* skin = Environment->getSkin(); + irr::video::IVideoDriver* driver = Environment->getVideoDriver(); + + core::rect* clipRect = 0; + if( Clip ) + { + clipRect = &AbsoluteClippingRect; + } + + // draw background + core::rect frameRect( AbsoluteRect ); + + if( DrawBack ) + { + driver->draw2DRectangle( skin->getColor( EGDC_3D_HIGH_LIGHT ), frameRect, + clipRect ); + } + + // draw the border + frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), frameRect, + clipRect ); + + frameRect.LowerRightCorner.Y = AbsoluteRect.LowerRightCorner.Y; + frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), frameRect, + clipRect ); + + frameRect = AbsoluteRect; + frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_HIGH_LIGHT ), frameRect, + clipRect ); + + frameRect = AbsoluteRect; + frameRect.UpperLeftCorner.Y = AbsoluteRect.LowerRightCorner.Y - 1; + frameRect.LowerRightCorner.Y = AbsoluteRect.LowerRightCorner.Y; + driver->draw2DRectangle( skin->getColor( EGDC_3D_HIGH_LIGHT ), frameRect, + clipRect ); + + + // draw items + + core::rect clientClip( AbsoluteRect ); + clientClip.UpperLeftCorner.Y += 1; + clientClip.UpperLeftCorner.X += 1; + clientClip.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X; + clientClip.LowerRightCorner.Y -= 1; + + if ( ScrollBarV ) + clientClip.LowerRightCorner.X -= skin->getSize( EGDS_SCROLLBAR_SIZE ); + if ( ScrollBarH ) + clientClip.LowerRightCorner.Y -= skin->getSize( EGDS_SCROLLBAR_SIZE ); + + if( clipRect ) + { + clientClip.clipAgainst( *clipRect ); + } + + frameRect = AbsoluteRect; + frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize( EGDS_SCROLLBAR_SIZE ); + frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight; + + if ( ScrollBarV ) + { + frameRect.UpperLeftCorner.Y -= ScrollBarV->getPos(); + frameRect.LowerRightCorner.Y -= ScrollBarV->getPos(); + } + + if ( ScrollBarH ) + { + frameRect.UpperLeftCorner.X -= ScrollBarH->getPos(); + frameRect.LowerRightCorner.X -= ScrollBarH->getPos(); + } + + IGUITreeViewNode* node = Root->getFirstChild(); + while( node ) + { + frameRect.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X + 1 + node->getLevel() * IndentWidth; + + if( frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y + && frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y ) + { + if( node == Selected ) + { + driver->draw2DRectangle( skin->getColor( EGDC_HIGH_LIGHT ), frameRect, &clientClip ); + } + + if( node->hasChilds() ) + { + core::rect rc; + core::rect expanderRect; + + expanderRect.UpperLeftCorner.X = frameRect.UpperLeftCorner.X - IndentWidth + 2; + expanderRect.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y + ( ( frameRect.getHeight() - ( IndentWidth - 4 ) ) >> 1 ); + expanderRect.LowerRightCorner.X = expanderRect.UpperLeftCorner.X + IndentWidth - 4; + expanderRect.LowerRightCorner.Y = expanderRect.UpperLeftCorner.Y + IndentWidth - 4; + + // box upper line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X; + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y; + rc.LowerRightCorner.X = expanderRect.LowerRightCorner.X; + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // box left line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X; + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y; + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; + rc.LowerRightCorner.Y = expanderRect.LowerRightCorner.Y; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // box right line + rc.UpperLeftCorner.X = expanderRect.LowerRightCorner.X - 1; + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y; + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; + rc.LowerRightCorner.Y = expanderRect.LowerRightCorner.Y; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // box bottom line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X; + rc.UpperLeftCorner.Y = expanderRect.LowerRightCorner.Y - 1; + rc.LowerRightCorner.X = expanderRect.LowerRightCorner.X; + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // horizontal '-' line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X + 2; + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y + ( expanderRect.getHeight() >> 1 ); + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + expanderRect.getWidth() - 4; + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_BUTTON_TEXT ), rc, + clipRect ); + + if( !node->getExpanded() ) + { + // vertical '+' line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X + ( expanderRect.getWidth() >> 1 ); + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y + 2; + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + expanderRect.getHeight() - 4; + driver->draw2DRectangle( skin->getColor( EGDC_BUTTON_TEXT ), rc, + clipRect ); + } + } + + core::rect textRect = frameRect; + + if( Font ) + { + s32 iconWidth = 0; + for( s32 n = 0; n < 2; ++n ) + { + s32 index = node->getImageIndex(); + if( ( ImageList && index >= 0 ) + && ( ( ImageLeftOfIcon && n == 0 ) + || ( !ImageLeftOfIcon && n == 1 ) ) ) + { + index = node->getSelectedImageIndex(); + if( node != Selected || index < 0 ) + { + index = node->getImageIndex(); + } + ImageList->draw( + index, + core::position2d( + textRect.UpperLeftCorner.X, + textRect.UpperLeftCorner.Y + ( ( textRect.getHeight() - ImageList->getImageSize().Height ) >> 1 ) ), + &clientClip ); + iconWidth += ImageList->getImageSize().Width + 3; + textRect.UpperLeftCorner.X += ImageList->getImageSize().Width + 3; + } + else if( ( IconFont && reinterpret_cast( node )->Icon.size() ) + && ( ( ImageLeftOfIcon && n == 1 ) + || ( !ImageLeftOfIcon && n == 0 ) ) ) + { + IconFont->draw( node->getIcon(), textRect, skin->getColor( ( node == Selected ) ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT ), false, true, &clientClip ); + iconWidth += IconFont->getDimension( node->getIcon() ).Width + 3; + textRect.UpperLeftCorner.X += IconFont->getDimension( node->getIcon() ).Width + 3; + } + } + + Font->draw( node->getText(), textRect, skin->getColor( ( node == Selected ) ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT ), false, true, &clientClip ); + + textRect.UpperLeftCorner.X -= iconWidth; + } + + // draw the lines if neccessary + if( LinesVisible ) + { + core::rect rc; + + // horizontal line + rc.UpperLeftCorner.X = frameRect.UpperLeftCorner.X - IndentWidth - ( IndentWidth >> 1 ) - 1; + rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y + ( ( frameRect.getHeight() ) >> 1 ); + if( node->hasChilds() ) + { + rc.LowerRightCorner.X = frameRect.UpperLeftCorner.X - IndentWidth; + } + else + { + rc.LowerRightCorner.X = frameRect.UpperLeftCorner.X - 2; + } + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + if( node->getParent() != Root ) + { + // vertical line + if( node == node->getParent()->getFirstChild() ) + { + rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - ( ( frameRect.getHeight() - IndentWidth ) >> 1 ); + } + else + { + rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - ( frameRect.getHeight() >> 1 ); + } + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // the vertical lines of all parents + IGUITreeViewNode* nodeTmp = node->getParent(); + rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - ( frameRect.getHeight() >> 1 ); + for( s32 n = 0; n < node->getLevel() - 2; ++n ) + { + rc.UpperLeftCorner.X -= IndentWidth; + rc.LowerRightCorner.X -= IndentWidth; + if( nodeTmp != nodeTmp->getParent()->getLastChild() ) + { + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + } + nodeTmp = nodeTmp->getParent(); + } + } + } + } + + frameRect.UpperLeftCorner.Y += ItemHeight; + frameRect.LowerRightCorner.Y += ItemHeight; + + node = node->getNextVisible(); + } + + IGUIElement::draw(); +} + +//! Sets the font which should be used as icon font. This font is set to the Irrlicht engine +//! built-in-font by default. Icons can be displayed in front of every list item. +//! An icon is a string, displayed with the icon font. When using the build-in-font of the +//! Irrlicht engine as icon font, the icon strings defined in GUIIcons.h can be used. +void CGUITreeView::setIconFont( IGUIFont* font ) +{ + s32 height; + + if ( font ) + font->grab(); + if ( IconFont ) + { + IconFont->drop(); + } + + IconFont = font; + if( IconFont ) + { + height = IconFont->getDimension( L" " ).Height; + if( height > ItemHeight ) + { + ItemHeight = height; + } + } +} + +//! Sets the image list which should be used for the image and selected image of every node. +//! The default is 0 (no images). +void CGUITreeView::setImageList( IGUIImageList* imageList ) +{ + if (imageList ) + imageList->grab(); + if( ImageList ) + { + ImageList->drop(); + } + + ImageList = imageList; + if( ImageList ) + { + if( ImageList->getImageSize().Height + 1 > ItemHeight ) + { + ItemHeight = ImageList->getImageSize().Height + 1; + } + } +} + +} // end namespace gui +} // end namespace irr + + +#endif // _IRR_COMPILE_WITH_GUI_ diff --git a/src/dep/src/irrlicht/CGUITreeView.h b/src/dep/src/irrlicht/CGUITreeView.h new file mode 100644 index 0000000..782d043 --- /dev/null +++ b/src/dep/src/irrlicht/CGUITreeView.h @@ -0,0 +1,331 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de + +#ifndef __C_GUI_TREE_VIEW_H_INCLUDED__ +#define __C_GUI_TREE_VIEW_H_INCLUDED__ + +#include "IGUITreeView.h" +#include "irrList.h" + + +namespace irr +{ +namespace gui +{ + // forward declarations + class IGUIFont; + class IGUIScrollBar; + class CGUITreeView; + + //! Node for gui tree view + class CGUITreeViewNode : public IGUITreeViewNode + { + friend class CGUITreeView; + + public: + //! constructor + CGUITreeViewNode( CGUITreeView* owner, CGUITreeViewNode* parent ); + + //! destructor + ~CGUITreeViewNode(); + + //! returns the owner (tree view) of this node + virtual IGUITreeView* getOwner() const; + + //! Returns the parent node of this node. + virtual IGUITreeViewNode* getParent() const; + + //! returns the text of the node + virtual const wchar_t* getText() const + { return Text.c_str(); } + + //! sets the text of the node + virtual void setText( const wchar_t* text ); + + //! returns the icon text of the node + virtual const wchar_t* getIcon() const + { return Icon.c_str(); } + + //! sets the icon text of the node + virtual void setIcon( const wchar_t* icon ); + + //! returns the image index of the node + virtual u32 getImageIndex() const + { return ImageIndex; } + + //! sets the image index of the node + virtual void setImageIndex( u32 imageIndex ) + { ImageIndex = imageIndex; } + + //! returns the image index of the node + virtual u32 getSelectedImageIndex() const + { return SelectedImageIndex; } + + //! sets the image index of the node + virtual void setSelectedImageIndex( u32 imageIndex ) + { SelectedImageIndex = imageIndex; } + + //! returns the user data (void*) of this node + virtual void* getData() const + { return Data; } + + //! sets the user data (void*) of this node + virtual void setData( void* data ) + { Data = data; } + + //! returns the user data2 (IReferenceCounted) of this node + virtual IReferenceCounted* getData2() const + { return Data2; } + + //! sets the user data2 (IReferenceCounted) of this node + virtual void setData2( IReferenceCounted* data ) + { + if( Data2 ) + { + Data2->drop(); + } + Data2 = data; + if( Data2 ) + { + Data2->grab(); + } + } + + //! returns the child item count + virtual u32 getChildCount() const + { return Childs.getSize(); } + + //! removes all childs (recursive) from this node + virtual void clearChilds(); + + //! returns true if this node has child nodes + virtual bool hasChilds() const + { return !Childs.empty(); } + + //! Adds a new node behind the last child node. + //! \param text text of the new node + //! \param icon icon text of the new node + //! \param imageIndex index of the image for the new node (-1 = none) + //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + //! \param data user data (void*) of the new node + //! \param data2 user data2 (IReferenceCounted*) of the new node + //! \return + //! returns the new node + virtual IGUITreeViewNode* addChildBack( + const wchar_t* text, + const wchar_t* icon = 0, + s32 imageIndex = -1, + s32 selectedImageIndex = -1, + void* data = 0, + IReferenceCounted* data2 = 0); + + //! Adds a new node before the first child node. + //! \param text text of the new node + //! \param icon icon text of the new node + //! \param imageIndex index of the image for the new node (-1 = none) + //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + //! \param data user data (void*) of the new node + //! \param data2 user data2 (IReferenceCounted*) of the new node + //! \return + //! returns the new node + virtual IGUITreeViewNode* addChildFront( + const wchar_t* text, + const wchar_t* icon = 0, + s32 imageIndex = -1, + s32 selectedImageIndex = -1, + void* data = 0, + IReferenceCounted* data2 = 0 ); + + //! Adds a new node behind the other node. + //! The other node has also te be a child node from this node. + //! \param text text of the new node + //! \param icon icon text of the new node + //! \param imageIndex index of the image for the new node (-1 = none) + //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + //! \param data user data (void*) of the new node + //! \param data2 user data2 (IReferenceCounted*) of the new node + //! \return + //! returns the new node or 0 if other is no child node from this + virtual IGUITreeViewNode* insertChildAfter( + IGUITreeViewNode* other, + const wchar_t* text, + const wchar_t* icon = 0, + s32 imageIndex = -1, + s32 selectedImageIndex = -1, + void* data = 0, + IReferenceCounted* data2 = 0 ); + + //! Adds a new node before the other node. + //! The other node has also te be a child node from this node. + //! \param text text of the new node + //! \param icon icon text of the new node + //! \param imageIndex index of the image for the new node (-1 = none) + //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + //! \param data user data (void*) of the new node + //! \param data2 user data2 (IReferenceCounted*) of the new node + //! \return + //! returns the new node or 0 if other is no child node from this + virtual IGUITreeViewNode* insertChildBefore( + IGUITreeViewNode* other, + const wchar_t* text, + const wchar_t* icon = 0, + s32 imageIndex = -1, + s32 selectedImageIndex = -1, + void* data = 0, + IReferenceCounted* data2 = 0 ); + + //! Return the first child note from this node. + virtual IGUITreeViewNode* getFirstChild() const; + + //! Return the last child note from this node. + virtual IGUITreeViewNode* getLastChild() const; + + //! Returns the preverse sibling node from this node. + virtual IGUITreeViewNode* getPrevSibling() const; + + //! Returns the next sibling node from this node. + virtual IGUITreeViewNode* getNextSibling() const; + + //! Returns the next visible (expanded, may be out of scrolling) node from this node. + virtual IGUITreeViewNode* getNextVisible() const; + + //! Deletes a child node. + virtual bool deleteChild( IGUITreeViewNode* child ); + + //! Moves a child node one position up. + virtual bool moveChildUp( IGUITreeViewNode* child ); + + //! Moves a child node one position down. + virtual bool moveChildDown( IGUITreeViewNode* child ); + + //! Returns true if the node is expanded (childs are visible). + virtual bool getExpanded() const + { return Expanded; } + + //! Sets if the node is expanded. + virtual void setExpanded( bool expanded ); + + //! Returns true if the node is currently selected. + virtual bool getSelected() const; + + //! Sets this node as selected. + virtual void setSelected( bool selected ); + + //! Returns true if this node is the root node. + virtual bool isRoot() const; + + //! Returns the level of this node. + virtual s32 getLevel() const; + + //! Returns true if this node is visible (all parents are expanded). + virtual bool isVisible() const; + + private: + + CGUITreeView* Owner; + CGUITreeViewNode* Parent; + core::stringw Text; + core::stringw Icon; + s32 ImageIndex; + s32 SelectedImageIndex; + void* Data; + IReferenceCounted* Data2; + bool Expanded; + core::list Childs; + }; + + + //! Default tree view GUI element. + class CGUITreeView : public IGUITreeView + { + friend class CGUITreeViewNode; + + public: + //! constructor + CGUITreeView( IGUIEnvironment* environment, IGUIElement* parent, + s32 id, core::rect rectangle, bool clip = true, + bool drawBack = false, bool scrollBarVertical = true, bool scrollBarHorizontal = true ); + + //! destructor + virtual ~CGUITreeView(); + + //! returns the root node (not visible) from the tree. + virtual IGUITreeViewNode* getRoot() const + { return Root; } + + //! returns the selected node of the tree or 0 if none is selected + virtual IGUITreeViewNode* getSelected() const + { return Selected; } + + //! returns true if the tree lines are visible + virtual bool getLinesVisible() const + { return LinesVisible; } + + //! sets if the tree lines are visible + virtual void setLinesVisible( bool visible ) + { LinesVisible = visible; } + + //! called if an event happened. + virtual bool OnEvent( const SEvent &event ); + + //! draws the element and its children + virtual void draw(); + + //! Sets the font which should be used as icon font. This font is set to the Irrlicht engine + //! built-in-font by default. Icons can be displayed in front of every list item. + //! An icon is a string, displayed with the icon font. When using the build-in-font of the + //! Irrlicht engine as icon font, the icon strings defined in GUIIcons.h can be used. + virtual void setIconFont( IGUIFont* font ); + + //! Sets the image list which should be used for the image and selected image of every node. + //! The default is 0 (no images). + virtual void setImageList( IGUIImageList* imageList ); + + //! Returns the image list which is used for the nodes. + virtual IGUIImageList* getImageList() const + { return ImageList; } + + //! Sets if the image is left of the icon. Default is true. + virtual void setImageLeftOfIcon( bool bLeftOf ) + { ImageLeftOfIcon = bLeftOf; } + + //! Returns if the Image is left of the icon. Default is true. + virtual bool getImageLeftOfIcon() const + { return ImageLeftOfIcon; } + + //! Returns the node which is associated to the last event. + virtual IGUITreeViewNode* getLastEventNode() const + { return LastEventNode; } + + private: + //! calculates the heigth of an node and of all visible nodes. + void recalculateItemHeight(); + + //! executes an mouse action (like selectNew of CGUIListBox) + void mouseAction( s32 xpos, s32 ypos, bool onlyHover = false ); + + CGUITreeViewNode* Root; + IGUITreeViewNode* Selected; + s32 ItemHeight; + s32 IndentWidth; + s32 TotalItemHeight; + s32 TotalItemWidth; + IGUIFont* Font; + IGUIFont* IconFont; + IGUIScrollBar* ScrollBarH; + IGUIScrollBar* ScrollBarV; + IGUIImageList* ImageList; + IGUITreeViewNode* LastEventNode; + bool LinesVisible; + bool Selecting; + bool Clip; + bool DrawBack; + bool ImageLeftOfIcon; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/src/dep/src/irrlicht/CGUIWindow.cpp b/src/dep/src/irrlicht/CGUIWindow.cpp index 8210462..0b4807f 100644 --- a/src/dep/src/irrlicht/CGUIWindow.cpp +++ b/src/dep/src/irrlicht/CGUIWindow.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -19,7 +19,7 @@ namespace gui //! constructor CGUIWindow::CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) -: IGUIWindow(environment, parent, id, rectangle), Dragging(false) +: IGUIWindow(environment, parent, id, rectangle), Dragging(false), IsDraggable(true), DrawBackground(true), DrawTitlebar(true), IsActive(false) { #ifdef _DEBUG setDebugName("CGUIWindow"); @@ -29,57 +29,36 @@ CGUIWindow::CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id if (environment) skin = environment->getSkin(); - IGUISpriteBank* sprites = 0; - video::SColor color(255,255,255,255); - + CurrentIconColor = video::SColor(255,255,255,255); + s32 buttonw = 15; if (skin) { buttonw = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); - sprites = skin->getSpriteBank(); - color = skin->getColor(EGDC_WINDOW_SYMBOL); } s32 posx = RelativeRect.getWidth() - buttonw - 4; - CloseButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, + CloseButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close" ); CloseButton->setSubElement(true); CloseButton->setTabStop(false); CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); - if (sprites) - { - CloseButton->setSpriteBank(sprites); - CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), color); - CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), color); - } posx -= buttonw + 2; - RestoreButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, + RestoreButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_RESTORE) : L"Restore" ); RestoreButton->setVisible(false); RestoreButton->setSubElement(true); RestoreButton->setTabStop(false); RestoreButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); - if (sprites) - { - RestoreButton->setSpriteBank(sprites); - RestoreButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_RESTORE), color); - RestoreButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_RESTORE), color); - } posx -= buttonw + 2; - MinButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, + MinButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_MINIMIZE) : L"Minimize" ); MinButton->setVisible(false); MinButton->setSubElement(true); MinButton->setTabStop(false); MinButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); - if (sprites) - { - MinButton->setSpriteBank(sprites); - MinButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_MINIMIZE), color); - MinButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_MINIMIZE), color); - } MinButton->grab(); RestoreButton->grab(); @@ -89,6 +68,9 @@ CGUIWindow::CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id setTabGroup(true); setTabStop(true); setTabOrder(-1); + + refreshSprites(); + updateClientRect(); } @@ -105,6 +87,35 @@ CGUIWindow::~CGUIWindow() CloseButton->drop(); } +void CGUIWindow::refreshSprites() +{ + if (!Environment) + return; + IGUISkin* skin = Environment->getSkin(); + if ( !skin ) + return; + + IGUISpriteBank* sprites = skin->getSpriteBank(); + if ( !sprites ) + return; + + CurrentIconColor = skin->getColor(EGDC_WINDOW_SYMBOL); + + if (sprites) + { + CloseButton->setSpriteBank(sprites); + CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), CurrentIconColor); + CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), CurrentIconColor); + + RestoreButton->setSpriteBank(sprites); + RestoreButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_RESTORE), CurrentIconColor); + RestoreButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_RESTORE), CurrentIconColor); + + MinButton->setSpriteBank(sprites); + MinButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_MINIMIZE), CurrentIconColor); + MinButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_MINIMIZE), CurrentIconColor); + } +} //! called if an event happened. bool CGUIWindow::OnEvent(const SEvent& event) @@ -118,12 +129,20 @@ bool CGUIWindow::OnEvent(const SEvent& event) if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) { Dragging = false; + IsActive = false; } else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED) { if (Parent && ((event.GUIEvent.Caller == this) || isMyChild(event.GUIEvent.Caller))) + { Parent->bringToFront(this); + IsActive = true; + } + else + { + IsActive = false; + } } else if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) @@ -160,7 +179,7 @@ bool CGUIWindow::OnEvent(const SEvent& event) case EMIE_LMOUSE_PRESSED_DOWN: DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; - Dragging = true; + Dragging = IsDraggable; if (Parent) Parent->bringToFront(this); return true; @@ -168,17 +187,18 @@ bool CGUIWindow::OnEvent(const SEvent& event) Dragging = false; return true; case EMIE_MOUSE_MOVED: + if (!event.MouseInput.isLeftPressed()) + Dragging = false; + if (Dragging) { // gui window should not be dragged outside its parent - if (Parent) - if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 || + if (Parent && + (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 || event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 || event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 || - event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1) - - return true; - + event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)) + return true; move(core::position2d(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y)); DragStart.X = event.MouseInput.X; @@ -208,27 +228,41 @@ void CGUIWindow::updateAbsolutePosition() //! draws the element and its children void CGUIWindow::draw() { - if (!IsVisible) - return; - - IGUISkin* skin = Environment->getSkin(); - - core::rect rect = AbsoluteRect; - core::rect *cl = &AbsoluteClippingRect; - - // draw body fast - rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), - AbsoluteRect, &AbsoluteClippingRect); - - if (Text.size()) + if (IsVisible) { - rect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X); - rect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y); - rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; + IGUISkin* skin = Environment->getSkin(); - IGUIFont* font = skin->getFont(EGDF_WINDOW); - if (font) - font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true, cl); + + // update each time because the skin is allowed to change this always. + updateClientRect(); + + if ( CurrentIconColor != skin->getColor(EGDC_WINDOW_SYMBOL) ) + refreshSprites(); + + core::rect rect = AbsoluteRect; + + // draw body fast + if (DrawBackground) + { + rect = skin->draw3DWindowBackground(this, DrawTitlebar, + skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER), + AbsoluteRect, &AbsoluteClippingRect); + + if (DrawTitlebar && Text.size()) + { + rect.UpperLeftCorner.X += skin->getSize(EGDS_TITLEBARTEXT_DISTANCE_X); + rect.UpperLeftCorner.Y += skin->getSize(EGDS_TITLEBARTEXT_DISTANCE_Y); + rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; + + IGUIFont* font = skin->getFont(EGDF_WINDOW); + if (font) + { + font->draw(Text.c_str(), rect, + skin->getColor(IsActive ? EGDC_ACTIVE_CAPTION:EGDC_INACTIVE_CAPTION), + false, true, &AbsoluteClippingRect); + } + } + } } IGUIElement::draw(); @@ -256,6 +290,113 @@ IGUIButton* CGUIWindow::getMaximizeButton() const } +//! Returns true if the window is draggable, false if not +bool CGUIWindow::isDraggable() const +{ + return IsDraggable; +} + + +//! Sets whether the window is draggable +void CGUIWindow::setDraggable(bool draggable) +{ + IsDraggable = draggable; + + if (Dragging && !IsDraggable) + Dragging = false; +} + + +//! Set if the window background will be drawn +void CGUIWindow::setDrawBackground(bool draw) +{ + DrawBackground = draw; +} + + +//! Get if the window background will be drawn +bool CGUIWindow::getDrawBackground() const +{ + return DrawBackground; +} + + +//! Set if the window titlebar will be drawn +void CGUIWindow::setDrawTitlebar(bool draw) +{ + DrawTitlebar = draw; +} + + +//! Get if the window titlebar will be drawn +bool CGUIWindow::getDrawTitlebar() const +{ + return DrawTitlebar; +} + + +void CGUIWindow::updateClientRect() +{ + if (! DrawBackground ) + { + ClientRect = core::rect(0,0, AbsoluteRect.getWidth(), AbsoluteRect.getHeight()); + return; + } + IGUISkin* skin = Environment->getSkin(); + skin->draw3DWindowBackground(this, DrawTitlebar, + skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER), + AbsoluteRect, &AbsoluteClippingRect, &ClientRect); + ClientRect -= AbsoluteRect.UpperLeftCorner; +} + + +//! Returns the rectangle of the drawable area (without border, without titlebar and without scrollbars) +core::rect CGUIWindow::getClientRect() const +{ + return ClientRect; +} + + +//! Writes attributes of the element. +void CGUIWindow::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const +{ + IGUIWindow::serializeAttributes(out,options); + + out->addBool("IsDraggable", IsDraggable); + out->addBool("DrawBackground", DrawBackground); + out->addBool("DrawTitlebar", DrawTitlebar); + + // Currently we can't just serialize attributes of sub-elements. + // To do this we either + // a) allow further serialization after attribute serialiation (second function, callback or event) + // b) add an IGUIElement attribute + // c) extend the attribute system to allow attributes to have sub-attributes + // We just serialize the most important info for now until we can do one of the above solutions. + out->addBool("IsCloseVisible", CloseButton->isVisible()); + out->addBool("IsMinVisible", MinButton->isVisible()); + out->addBool("IsRestoreVisible", RestoreButton->isVisible()); +} + + +//! Reads attributes of the element +void CGUIWindow::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) +{ +IGUIWindow::deserializeAttributes(in,options); + + Dragging = false; + IsActive = false; + IsDraggable = in->getAttributeAsBool("IsDraggable"); + DrawBackground = in->getAttributeAsBool("DrawBackground"); + DrawTitlebar = in->getAttributeAsBool("DrawTitlebar"); + + CloseButton->setVisible(in->getAttributeAsBool("IsCloseVisible")); + MinButton->setVisible(in->getAttributeAsBool("IsMinVisible")); + RestoreButton->setVisible(in->getAttributeAsBool("IsRestoreVisible")); + + updateClientRect(); +} + + } // end namespace gui } // end namespace irr diff --git a/src/dep/src/irrlicht/CGUIWindow.h b/src/dep/src/irrlicht/CGUIWindow.h index 2573d68..2740fee 100644 --- a/src/dep/src/irrlicht/CGUIWindow.h +++ b/src/dep/src/irrlicht/CGUIWindow.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -44,14 +44,50 @@ namespace gui //! Returns pointer to the maximize button virtual IGUIButton* getMaximizeButton() const; + //! Returns true if the window is draggable, false if not + virtual bool isDraggable() const; + + //! Sets whether the window is draggable + virtual void setDraggable(bool draggable); + + //! Set if the window background will be drawn + virtual void setDrawBackground(bool draw); + + //! Get if the window background will be drawn + virtual bool getDrawBackground() const; + + //! Set if the window titlebar will be drawn + //! Note: If the background is not drawn, then the titlebar is automatically also not drawn + virtual void setDrawTitlebar(bool draw); + + //! Get if the window titlebar will be drawn + virtual bool getDrawTitlebar() const; + + //! Returns the rectangle of the drawable area (without border and without titlebar) + virtual core::rect getClientRect() const; + + //! Writes attributes of the element. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; + + //! Reads attributes of the element + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + protected: - core::position2d DragStart; - bool Dragging; + void updateClientRect(); + void refreshSprites(); IGUIButton* CloseButton; IGUIButton* MinButton; IGUIButton* RestoreButton; + core::rect ClientRect; + video::SColor CurrentIconColor; + + core::position2d DragStart; + bool Dragging, IsDraggable; + bool DrawBackground; + bool DrawTitlebar; + bool IsActive; }; } // end namespace gui @@ -59,5 +95,5 @@ namespace gui #endif // _IRR_COMPILE_WITH_GUI_ -#endif +#endif diff --git a/src/dep/src/irrlicht/CGeometryCreator.cpp b/src/dep/src/irrlicht/CGeometryCreator.cpp index ccb1982..094cf65 100644 --- a/src/dep/src/irrlicht/CGeometryCreator.cpp +++ b/src/dep/src/irrlicht/CGeometryCreator.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -16,12 +16,63 @@ namespace irr namespace scene { +IMesh* CGeometryCreator::createCubeMesh(const core::vector3df& size) const +{ + SMeshBuffer* buffer = new SMeshBuffer(); + + // Create indices + const u16 u[36] = { 0,2,1, 0,3,2, 1,5,4, 1,2,5, 4,6,7, 4,5,6, + 7,3,0, 7,6,3, 9,5,2, 9,8,5, 0,11,10, 0,10,7}; + + buffer->Indices.set_used(36); + + for (u32 i=0; i<36; ++i) + buffer->Indices[i] = u[i]; + + + // Create vertices + video::SColor clr(255,255,255,255); + + buffer->Vertices.reallocate(12); + + buffer->Vertices.push_back(video::S3DVertex(0,0,0, -1,-1,-1, clr, 0, 1)); + buffer->Vertices.push_back(video::S3DVertex(1,0,0, 1,-1,-1, clr, 1, 1)); + buffer->Vertices.push_back(video::S3DVertex(1,1,0, 1, 1,-1, clr, 1, 0)); + buffer->Vertices.push_back(video::S3DVertex(0,1,0, -1, 1,-1, clr, 0, 0)); + buffer->Vertices.push_back(video::S3DVertex(1,0,1, 1,-1, 1, clr, 0, 1)); + buffer->Vertices.push_back(video::S3DVertex(1,1,1, 1, 1, 1, clr, 0, 0)); + buffer->Vertices.push_back(video::S3DVertex(0,1,1, -1, 1, 1, clr, 1, 0)); + buffer->Vertices.push_back(video::S3DVertex(0,0,1, -1,-1, 1, clr, 1, 1)); + buffer->Vertices.push_back(video::S3DVertex(0,1,1, -1, 1, 1, clr, 0, 1)); + buffer->Vertices.push_back(video::S3DVertex(0,1,0, -1, 1,-1, clr, 1, 1)); + buffer->Vertices.push_back(video::S3DVertex(1,0,1, 1,-1, 1, clr, 1, 0)); + buffer->Vertices.push_back(video::S3DVertex(1,0,0, 1,-1,-1, clr, 0, 0)); + + // Recalculate bounding box + buffer->BoundingBox.reset(0,0,0); + + for (u32 i=0; i<12; ++i) + { + buffer->Vertices[i].Pos -= core::vector3df(0.5f, 0.5f, 0.5f); + buffer->Vertices[i].Pos *= size; + buffer->BoundingBox.addInternalPoint(buffer->Vertices[i].Pos); + } + + SMesh* mesh = new SMesh; + mesh->addMeshBuffer(buffer); + buffer->drop(); + + mesh->recalculateBoundingBox(); + return mesh; +} + + // creates a hill plane IMesh* CGeometryCreator::createHillPlaneMesh( const core::dimension2d& tileSize, const core::dimension2d& tc, video::SMaterial* material, f32 hillHeight, const core::dimension2d& ch, - const core::dimension2d& textureRepeatCount) + const core::dimension2d& textureRepeatCount) const { core::dimension2d tileCount = tc; core::dimension2d countHills = ch; @@ -59,7 +110,7 @@ IMesh* CGeometryCreator::createHillPlaneMesh( vtx.Pos.set(sx - center.X, 0, sy - center.Y); vtx.TCoords.set(tsx, 1.0f - tsy); - if (hillHeight != 0.0f) + if (core::isnotzero(hillHeight)) vtx.Pos.Y = sinf(vtx.Pos.X * countHills.Width * core::PI / center.X) * cosf(vtx.Pos.Z * countHills.Height * core::PI / center.Y) * hillHeight; @@ -107,6 +158,7 @@ IMesh* CGeometryCreator::createHillPlaneMesh( buffer->Material = *material; buffer->recalculateBoundingBox(); + buffer->setHardwareMappingHint(EHM_STATIC); SMesh* mesh = new SMesh(); mesh->addMeshBuffer(buffer); @@ -119,8 +171,8 @@ IMesh* CGeometryCreator::createHillPlaneMesh( IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, f32 maxHeight, video::IVideoDriver* driver, - const core::dimension2d& maxVtxBlockSize, - bool debugBorders) + const core::dimension2d& maxVtxBlockSize, + bool debugBorders) const { if (!texture || !heightmap) return 0; @@ -134,17 +186,17 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture, SMesh* mesh = new SMesh(); const u32 tm = os::Timer::getRealTime()/1000; - const core::dimension2d hMapSize= heightmap->getDimension(); - const core::dimension2d tMapSize= texture->getDimension(); + const core::dimension2d hMapSize= heightmap->getDimension(); + const core::dimension2d tMapSize= texture->getDimension(); const core::position2d thRel(static_cast(tMapSize.Width) / hMapSize.Width, static_cast(tMapSize.Height) / hMapSize.Height); maxHeight /= 255.0f; // height step per color value - core::position2d processed(0,0); + core::position2d processed(0,0); while (processed.Y blockSize = maxVtxBlockSize; + core::dimension2d blockSize = maxVtxBlockSize; if (processed.X + blockSize.Width > hMapSize.Width) blockSize.Width = hMapSize.Width - processed.X; if (processed.Y + blockSize.Height > hMapSize.Height) @@ -154,7 +206,7 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture, buffer->setHardwareMappingHint(scene::EHM_STATIC); buffer->Vertices.reallocate(blockSize.getArea()); // add vertices of vertex block - s32 y; + u32 y; core::vector2df pos(0.f, processed.Y*stretchSize.Height); const core::vector2df bs(1.f/blockSize.Width, 1.f/blockSize.Height); core::vector2df tc(0.f, 0.5f*bs.Y); @@ -162,7 +214,7 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture, { pos.X=processed.X*stretchSize.Width; tc.X=0.5f*bs.X; - for (s32 x=0; xgetPixel(x+processed.X, y+processed.Y).getAverage() * maxHeight; @@ -181,7 +233,7 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture, s32 c1 = 0; for (y=0; ygetColorFormat(), texture->getDimension()); + texture->copyTo(img, core::position2di(0,0), core::recti( core::position2d(core::floor32(processed.X*thRel.X), core::floor32(processed.Y*thRel.Y)), - core::dimension2d(core::floor32(blockSize.Width*thRel.X), core::floor32(blockSize.Height*thRel.Y))); + core::dimension2d(core::floor32(blockSize.Width*thRel.X), core::floor32(blockSize.Height*thRel.Y))), 0); sprintf(textureName, "terrain%u_%u", tm, mesh->getMeshBufferCount()); @@ -265,7 +318,7 @@ IMesh* CGeometryCreator::createArrowMesh(const u32 tesselationCylinder, const f32 width0, const f32 width1, const video::SColor vtxColor0, - const video::SColor vtxColor1) + const video::SColor vtxColor1) const { SMesh* mesh = (SMesh*)createCylinderMesh(width0, cylinderHeight, tesselationCylinder, vtxColor0, false); @@ -275,19 +328,21 @@ IMesh* CGeometryCreator::createArrowMesh(const u32 tesselationCylinder, scene::IMeshBuffer* buffer = mesh2->getMeshBuffer(i); for (u32 j=0; jgetVertexCount(); ++j) buffer->getPosition(j).Y += cylinderHeight; + buffer->setDirty(EBT_VERTEX); + buffer->recalculateBoundingBox(); mesh->addMeshBuffer(buffer); } mesh2->drop(); + mesh->setHardwareMappingHint(EHM_STATIC); + mesh->recalculateBoundingBox(); return mesh; } /* A sphere with proper normals and texture coords */ -IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCountY) +IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCountY) const { - SMeshBuffer* buffer = new SMeshBuffer(); - // thanks to Alfaz93 who made his code available for Irrlicht on which // this one is based! @@ -297,21 +352,20 @@ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCo polyCountX = 2; if (polyCountY < 2) polyCountY = 2; - if (polyCountX * polyCountY > 32767) // prevent u16 overflow + while (polyCountX * polyCountY > 32767) // prevent u16 overflow { - if (polyCountX > polyCountY) // prevent u16 overflow - polyCountX = 32767/polyCountY-1; - else - polyCountY = 32767/(polyCountX+1); + polyCountX /= 2; + polyCountY /= 2; } - u32 polyCountXPitch = polyCountX+1; // get to same vertex on next level - buffer->Vertices.set_used((polyCountXPitch * polyCountY) + 2); - buffer->Indices.set_used((polyCountX * polyCountY) * 6); + const u32 polyCountXPitch = polyCountX+1; // get to same vertex on next level + + SMeshBuffer* buffer = new SMeshBuffer(); + + buffer->Indices.reallocate((polyCountX * polyCountY) * 6); const video::SColor clr(100, 255,255,255); - u32 i=0; u32 level = 0; for (u32 p1 = 0; p1 < polyCountY-1; ++p1) @@ -320,25 +374,22 @@ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCo for (u32 p2 = 0; p2 < polyCountX - 1; ++p2) { const u32 curr = level + p2; - buffer->Indices[i] = curr + polyCountXPitch; - buffer->Indices[++i] = curr; - buffer->Indices[++i] = curr + 1; - buffer->Indices[++i] = curr + polyCountXPitch; - buffer->Indices[++i] = curr+1; - buffer->Indices[++i] = curr + 1 + polyCountXPitch; - ++i; + buffer->Indices.push_back(curr + polyCountXPitch); + buffer->Indices.push_back(curr); + buffer->Indices.push_back(curr + 1); + buffer->Indices.push_back(curr + polyCountXPitch); + buffer->Indices.push_back(curr+1); + buffer->Indices.push_back(curr + 1 + polyCountXPitch); } // the connectors from front to end - buffer->Indices[i] = level + polyCountX - 1 + polyCountXPitch; - buffer->Indices[++i] = level + polyCountX - 1; - buffer->Indices[++i] = level + polyCountX; - ++i; + buffer->Indices.push_back(level + polyCountX - 1 + polyCountXPitch); + buffer->Indices.push_back(level + polyCountX - 1); + buffer->Indices.push_back(level + polyCountX); - buffer->Indices[i] = level + polyCountX - 1 + polyCountXPitch; - buffer->Indices[++i] = level + polyCountX; - buffer->Indices[++i] = level + polyCountX + polyCountXPitch; - ++i; + buffer->Indices.push_back(level + polyCountX - 1 + polyCountXPitch); + buffer->Indices.push_back(level + polyCountX); + buffer->Indices.push_back(level + polyCountX + polyCountXPitch); level += polyCountXPitch; } @@ -350,43 +401,41 @@ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCo { // create triangles which are at the top of the sphere - buffer->Indices[i] = polyCountSq; - buffer->Indices[++i] = p2 + 1; - buffer->Indices[++i] = p2; - ++i; + buffer->Indices.push_back(polyCountSq); + buffer->Indices.push_back(p2 + 1); + buffer->Indices.push_back(p2); // create triangles which are at the bottom of the sphere - buffer->Indices[i] = polyCountSqM1 + p2; - buffer->Indices[++i] = polyCountSqM1 + p2 + 1; - buffer->Indices[++i] = polyCountSq1; - ++i; + buffer->Indices.push_back(polyCountSqM1 + p2); + buffer->Indices.push_back(polyCountSqM1 + p2 + 1); + buffer->Indices.push_back(polyCountSq1); } // create final triangle which is at the top of the sphere - buffer->Indices[i] = polyCountSq; - buffer->Indices[++i] = polyCountX; - buffer->Indices[++i] = polyCountX-1; - ++i; + buffer->Indices.push_back(polyCountSq); + buffer->Indices.push_back(polyCountX); + buffer->Indices.push_back(polyCountX-1); // create final triangle which is at the bottom of the sphere - buffer->Indices[i] = polyCountSqM1 + polyCountX - 1; - buffer->Indices[++i] = polyCountSqM1; - buffer->Indices[++i] = polyCountSq1; + buffer->Indices.push_back(polyCountSqM1 + polyCountX - 1); + buffer->Indices.push_back(polyCountSqM1); + buffer->Indices.push_back(polyCountSq1); // calculate the angle which separates all points in a circle const f64 AngleX = 2 * core::PI / polyCountX; const f64 AngleY = core::PI / polyCountY; - i = 0; + u32 i=0; f64 axz; // we don't start at 0. f64 ay = 0;//AngleY / 2; + buffer->Vertices.set_used((polyCountXPitch * polyCountY) + 2); for (u32 y = 0; y < polyCountY; ++y) { ay += AngleY; @@ -450,13 +499,16 @@ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCo mesh->addMeshBuffer(buffer); buffer->drop(); + mesh->setHardwareMappingHint(EHM_STATIC); mesh->recalculateBoundingBox(); return mesh; } /* A cylinder with proper normals and texture coords */ -IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& color, bool closeTop, f32 oblique) +IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, + u32 tesselation, const video::SColor& color, + bool closeTop, f32 oblique) const { SMeshBuffer* buffer = new SMeshBuffer(); @@ -468,10 +520,10 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, u32 tesselat u32 i; video::S3DVertex v; v.Color = color; - buffer->Vertices.reallocate(tesselation*4+(closeTop?2:1)); - buffer->Indices.reallocate((tesselation*2)*(closeTop?12:9)); + buffer->Vertices.reallocate(tesselation*4+4+(closeTop?2:1)); + buffer->Indices.reallocate((tesselation*2+1)*(closeTop?12:9)); f32 tcx = 0.f; - for ( i = 0; i != tesselation; ++i ) + for ( i = 0; i <= tesselation; ++i ) { const f32 angle = angleStep * i; v.Pos.X = radius * cosf(angle); @@ -508,25 +560,27 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, u32 tesselat tcx += recTesselation; } - const u32 nonWrappedSize = ( tesselation* 4 ) - 2; - for ( i = 0; i != nonWrappedSize; i += 2 ) + // indices for the main hull part + const u32 nonWrappedSize = tesselation* 4; + for (i=0; i != nonWrappedSize; i += 2) { - buffer->Indices.push_back ( i + 2 ); - buffer->Indices.push_back ( i + 0 ); - buffer->Indices.push_back ( i + 1 ); + buffer->Indices.push_back(i + 2); + buffer->Indices.push_back(i + 0); + buffer->Indices.push_back(i + 1); - buffer->Indices.push_back ( i + 2 ); - buffer->Indices.push_back ( i + 1 ); - buffer->Indices.push_back ( i + 3 ); + buffer->Indices.push_back(i + 2); + buffer->Indices.push_back(i + 1); + buffer->Indices.push_back(i + 3); } - buffer->Indices.push_back ( 0 ); - buffer->Indices.push_back ( i + 0 ); - buffer->Indices.push_back ( i + 1 ); + // two closing quads between end and start + buffer->Indices.push_back(0); + buffer->Indices.push_back(i + 0); + buffer->Indices.push_back(i + 1); - buffer->Indices.push_back ( 0 ); - buffer->Indices.push_back ( i + 1 ); - buffer->Indices.push_back ( 1 ); + buffer->Indices.push_back(0); + buffer->Indices.push_back(i + 1); + buffer->Indices.push_back(1); // close down v.Pos.X = 0.f; @@ -537,20 +591,20 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, u32 tesselat v.Normal.Z = 0.f; v.TCoords.X = 1.f; v.TCoords.Y = 1.f; - buffer->Vertices.push_back ( v ); + buffer->Vertices.push_back(v); - u32 index = buffer->Vertices.size () - 1; + u32 index = buffer->Vertices.size() - 1; for ( i = 0; i != nonWrappedSize; i += 2 ) { - buffer->Indices.push_back ( index ); - buffer->Indices.push_back ( i + 0 ); - buffer->Indices.push_back ( i + 2 ); + buffer->Indices.push_back(index); + buffer->Indices.push_back(i + 0); + buffer->Indices.push_back(i + 2); } - buffer->Indices.push_back ( index ); - buffer->Indices.push_back ( i + 0 ); - buffer->Indices.push_back ( 0 ); + buffer->Indices.push_back(index); + buffer->Indices.push_back(i + 0); + buffer->Indices.push_back(0); if (closeTop) { @@ -563,25 +617,26 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, u32 tesselat v.Normal.Z = 0.f; v.TCoords.X = 0.f; v.TCoords.Y = 0.f; - buffer->Vertices.push_back ( v ); + buffer->Vertices.push_back(v); - index = buffer->Vertices.size () - 1; + index = buffer->Vertices.size() - 1; for ( i = 0; i != nonWrappedSize; i += 2 ) { - buffer->Indices.push_back ( i + 1 ); - buffer->Indices.push_back ( index ); - buffer->Indices.push_back ( i + 3 ); + buffer->Indices.push_back(i + 1); + buffer->Indices.push_back(index); + buffer->Indices.push_back(i + 3); } - buffer->Indices.push_back ( i + 1 ); - buffer->Indices.push_back ( index ); - buffer->Indices.push_back ( 1 ); + buffer->Indices.push_back(i + 1); + buffer->Indices.push_back(index); + buffer->Indices.push_back(1); } buffer->recalculateBoundingBox(); SMesh* mesh = new SMesh(); mesh->addMeshBuffer(buffer); + mesh->setHardwareMappingHint(EHM_STATIC); mesh->recalculateBoundingBox(); buffer->drop(); return mesh; @@ -589,7 +644,10 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, u32 tesselat /* A cone with proper normals and texture coords */ -IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& colorTop, const video::SColor& colorBottom, f32 oblique) +IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation, + const video::SColor& colorTop, + const video::SColor& colorBottom, + f32 oblique) const { SMeshBuffer* buffer = new SMeshBuffer(); @@ -634,9 +692,9 @@ IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation, for ( i = 0; i != nonWrappedSize; i += 1 ) { - buffer->Indices.push_back ( i + 0 ); - buffer->Indices.push_back ( index ); - buffer->Indices.push_back ( i + 1 ); + buffer->Indices.push_back(i + 0); + buffer->Indices.push_back(index); + buffer->Indices.push_back(i + 1); } buffer->Indices.push_back(i + 0); @@ -671,6 +729,160 @@ IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation, mesh->addMeshBuffer(buffer); buffer->drop(); + mesh->setHardwareMappingHint(EHM_STATIC); + mesh->recalculateBoundingBox(); + return mesh; +} + + +void CGeometryCreator::addToBuffer(const video::S3DVertex& v, SMeshBuffer* Buffer) const +{ + const s32 tnidx = Buffer->Vertices.linear_reverse_search(v); + const bool alreadyIn = (tnidx != -1); + u16 nidx = (u16)tnidx; + if (!alreadyIn) + { + nidx = (u16)Buffer->Vertices.size(); + Buffer->Indices.push_back(nidx); + Buffer->Vertices.push_back(v); + } + else + Buffer->Indices.push_back(nidx); +} + + +IMesh* CGeometryCreator::createVolumeLightMesh( + const u32 subdivideU, const u32 subdivideV, + const video::SColor footColor, const video::SColor tailColor, + const f32 lpDistance, const core::vector3df& lightDim) const +{ + SMeshBuffer* Buffer = new SMeshBuffer(); + Buffer->setHardwareMappingHint(EHM_STATIC); + + const core::vector3df lightPoint(0, -(lpDistance*lightDim.Y), 0); + const f32 ax = lightDim.X * 0.5f; // X Axis + const f32 az = lightDim.Z * 0.5f; // Z Axis + + Buffer->Vertices.clear(); + Buffer->Vertices.reallocate(6+12*(subdivideU+subdivideV)); + Buffer->Indices.clear(); + Buffer->Indices.reallocate(6+12*(subdivideU+subdivideV)); + //draw the bottom foot.. the glowing region + addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, footColor, 0, 1),Buffer); + addToBuffer(video::S3DVertex( ax, 0, az, 0,0,0, footColor, 1, 1),Buffer); + addToBuffer(video::S3DVertex( ax, 0,-az, 0,0,0, footColor, 1, 0),Buffer); + + addToBuffer(video::S3DVertex( ax, 0,-az, 0,0,0, footColor, 1, 0),Buffer); + addToBuffer(video::S3DVertex(-ax, 0,-az, 0,0,0, footColor, 0, 0),Buffer); + addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, footColor, 0, 1),Buffer); + + f32 tu = 0.f; + const f32 tuStep = 1.f/subdivideU; + f32 bx = -ax; + const f32 bxStep = lightDim.X * tuStep; + // Slices in X/U space + for (u32 i = 0; i <= subdivideU; ++i) + { + // These are the two endpoints for a slice at the foot + core::vector3df end1(bx, 0.0f, -az); + core::vector3df end2(bx, 0.0f, az); + + end1 -= lightPoint; // get a vector from point to lightsource + end1.normalize(); // normalize vector + end1 *= lightDim.Y; // multiply it out by shootlength + + end1.X += bx; // Add the original point location to the vector + end1.Z -= az; + + // Do it again for the other point. + end2 -= lightPoint; + end2.normalize(); + end2 *= lightDim.Y; + + end2.X += bx; + end2.Z += az; + + addToBuffer(video::S3DVertex(bx , 0, az, 0,0,0, footColor, tu, 1),Buffer); + addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, footColor, tu, 0),Buffer); + addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, tu, 1),Buffer); + + addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, footColor, tu, 0),Buffer); + addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, tailColor, tu, 0),Buffer); + addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, tu, 1),Buffer); + + //back side + addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, tu, 1),Buffer); + addToBuffer(video::S3DVertex(-bx , 0, -az, 0,0,0, footColor, tu, 1),Buffer); + addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, footColor, tu, 0),Buffer); + + addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, footColor, tu, 0),Buffer); + addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, tailColor, tu, 0),Buffer); + addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, tu, 1),Buffer); + tu += tuStep; + bx += bxStep; + } + + f32 tv = 0.f; + const f32 tvStep = 1.f/subdivideV; + f32 bz = -az; + const f32 bzStep = lightDim.Z * tvStep; + // Slices in Z/V space + for(u32 i = 0; i <= subdivideV; ++i) + { + // These are the two endpoints for a slice at the foot + core::vector3df end1(-ax, 0.0f, bz); + core::vector3df end2(ax, 0.0f, bz); + + end1 -= lightPoint; // get a vector from point to lightsource + end1.normalize(); // normalize vector + end1 *= lightDim.Y; // multiply it out by shootlength + + end1.X -= ax; // Add the original point location to the vector + end1.Z += bz; + + // Do it again for the other point. + end2 -= lightPoint; + end2.normalize(); + end2 *= lightDim.Y; + + end2.X += ax; + end2.Z += bz; + + addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, footColor, 0, tv),Buffer); + addToBuffer(video::S3DVertex(ax , 0, bz, 0,0,0, footColor, 1, tv),Buffer); + addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, 1, tv),Buffer); + + addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, 1, tv),Buffer); + addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, tailColor, 0, tv),Buffer); + addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, footColor, 0, tv),Buffer); + + //back side + addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, footColor, 0, tv),Buffer); + addToBuffer(video::S3DVertex(-ax , 0, -bz, 0,0,0, footColor, 1, tv),Buffer); + addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, 1, tv),Buffer); + + addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, 1, tv),Buffer); + addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, tailColor, 0, tv),Buffer); + addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, footColor, 0, tv),Buffer); + tv += tvStep; + bz += bzStep; + } + + Buffer->recalculateBoundingBox(); + + Buffer->Material.MaterialType = video::EMT_ONETEXTURE_BLEND; + Buffer->Material.MaterialTypeParam = pack_texureBlendFunc( video::EBF_SRC_COLOR, video::EBF_SRC_ALPHA, video::EMFN_MODULATE_1X ); + + Buffer->Material.Lighting = false; + Buffer->Material.ZWriteEnable = false; + + Buffer->setDirty(EBT_VERTEX_AND_INDEX); + + Buffer->recalculateBoundingBox(); + SMesh* mesh = new SMesh(); + mesh->addMeshBuffer(Buffer); + Buffer->drop(); + mesh->recalculateBoundingBox(); return mesh; } diff --git a/src/dep/src/irrlicht/CGeometryCreator.h b/src/dep/src/irrlicht/CGeometryCreator.h index babe2c2..81f8b81 100644 --- a/src/dep/src/irrlicht/CGeometryCreator.h +++ b/src/dep/src/irrlicht/CGeometryCreator.h @@ -1,53 +1,60 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GEOMETRY_CREATOR_H_INCLUDED__ #define __C_GEOMETRY_CREATOR_H_INCLUDED__ -#include "IMesh.h" -#include "IImage.h" - - +#include "IGeometryCreator.h" +#include "SMeshBuffer.h" namespace irr { -namespace video -{ - class IVideoDriver; - class SMaterial; -} namespace scene { //! class for creating geometry on the fly -class CGeometryCreator +class CGeometryCreator : public IGeometryCreator { + void addToBuffer(const video::S3DVertex& v, SMeshBuffer* Buffer) const; public: + IMesh* createCubeMesh(const core::vector3df& size) const; - static IMesh* createHillPlaneMesh( + IMesh* createHillPlaneMesh( const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material, f32 hillHeight, const core::dimension2d& countHills, - const core::dimension2d& textureRepeatCount); + const core::dimension2d& textureRepeatCount) const; - static IMesh* createTerrainMesh(video::IImage* texture, + IMesh* createTerrainMesh(video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, f32 maxHeight, video::IVideoDriver* driver, - const core::dimension2d& defaultVertexBlockSize, - bool debugBorders=false); + const core::dimension2d& defaultVertexBlockSize, + bool debugBorders=false) const; - static IMesh* createArrowMesh(const u32 tesselationCylinder, + IMesh* createArrowMesh(const u32 tesselationCylinder, const u32 tesselationCone, const f32 height, const f32 cylinderHeight, const f32 width0, const f32 width1, const video::SColor vtxColor0, - const video::SColor vtxColor1); + const video::SColor vtxColor1) const; - static IMesh* createSphereMesh(f32 radius, u32 polyCountX, u32 polyCountY); + IMesh* createSphereMesh(f32 radius, u32 polyCountX, u32 polyCountY) const; - static IMesh* createCylinderMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& color=video::SColor(0xffffffff), bool closeTop=true, f32 oblique=0.f); + IMesh* createCylinderMesh(f32 radius, f32 length, u32 tesselation, + const video::SColor& color=0xffffffff, + bool closeTop=true, f32 oblique=0.f) const; - static IMesh* createConeMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& colorTop=video::SColor(0xffffffff), const video::SColor& colorBottom=video::SColor(0xffffffff), f32 oblique=0.f); + IMesh* createConeMesh(f32 radius, f32 length, u32 tesselation, + const video::SColor& colorTop=0xffffffff, + const video::SColor& colorBottom=0xffffffff, + f32 oblique=0.f) const; + + IMesh* createVolumeLightMesh( + const u32 subdivideU=32, const u32 subdivideV=32, + const video::SColor footColor=0xffffffff, + const video::SColor tailColor=0xffffffff, + const f32 lpDistance = 8.f, + const core::vector3df& lightDim = core::vector3df(1.f,1.2f,1.f)) const; }; diff --git a/src/dep/src/irrlicht/CImage.cpp b/src/dep/src/irrlicht/CImage.cpp index 13233e5..879c519 100644 --- a/src/dep/src/irrlicht/CImage.cpp +++ b/src/dep/src/irrlicht/CImage.cpp @@ -1,992 +1,35 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImage.h" #include "irrString.h" -#include "SoftwareDriver2_helper.h" #include "CColorConverter.h" - -namespace irr -{ - - struct SBlitJob - { - AbsRectangle Dest; - AbsRectangle Source; - - u32 argb; - - void * src; - void * dst; - - s32 width; - s32 height; - - u32 srcPitch; - u32 dstPitch; - - u32 srcPixelMul; - u32 dstPixelMul; - }; - - // Blitter Operation - enum eBlitter - { - BLITTER_INVALID = 0, - BLITTER_COLOR, - BLITTER_COLOR_ALPHA, - BLITTER_TEXTURE, - BLITTER_TEXTURE_ALPHA_BLEND, - BLITTER_TEXTURE_ALPHA_COLOR_BLEND - }; - - typedef void (*tExecuteBlit) ( const SBlitJob * job ); - - - // Bitfields Cohen Sutherland - enum eClipCode - { - CLIPCODE_EMPTY = 0, - CLIPCODE_BOTTOM = 1, - CLIPCODE_TOP = 2, - CLIPCODE_LEFT = 4, - CLIPCODE_RIGHT = 8 - }; - -inline u32 GetClipCode( const AbsRectangle &r, const core::position2d &p ) -{ - u32 code = CLIPCODE_EMPTY; - - if ( p.X < r.x0 ) - code = CLIPCODE_LEFT; - else - if ( p.X > r.x1 ) - code = CLIPCODE_RIGHT; - - if ( p.Y < r.y0 ) - code |= CLIPCODE_TOP; - else - if ( p.Y > r.y1 ) - code |= CLIPCODE_BOTTOM; - - return code; -} - - -/*! - Cohen Sutherland clipping - @return: 1 if valid -*/ - -static int ClipLine(const AbsRectangle &clipping, - core::position2d &p0, - core::position2d &p1, - const core::position2d& p0_in, - const core::position2d& p1_in) -{ - u32 code0; - u32 code1; - u32 code; - - p0 = p0_in; - p1 = p1_in; - - code0 = GetClipCode( clipping, p0 ); - code1 = GetClipCode( clipping, p1 ); - - // trivial accepted - while ( code0 | code1 ) - { - s32 x=0; - s32 y=0; - - // trivial reject - if ( code0 & code1 ) - return 0; - - if ( code0 ) - { - // clip first point - code = code0; - } - else - { - // clip last point - code = code1; - } - - if ( (code & CLIPCODE_BOTTOM) == CLIPCODE_BOTTOM ) - { - // clip bottom viewport - y = clipping.y1; - x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); - } - else - if ( (code & CLIPCODE_TOP) == CLIPCODE_TOP ) - { - // clip to viewport - y = clipping.y0; - x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); - } - else - if ( (code & CLIPCODE_RIGHT) == CLIPCODE_RIGHT ) - { - // clip right viewport - x = clipping.x1; - y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); - } - else - if ( (code & CLIPCODE_LEFT) == CLIPCODE_LEFT ) - { - // clip left viewport - x = clipping.x0; - y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); - } - - if ( code == code0 ) - { - // modify first point - p0.X = x; - p0.Y = y; - code0 = GetClipCode( clipping, p0 ); - } - else - { - // modify second point - p1.X = x; - p1.Y = y; - code1 = GetClipCode( clipping, p1 ); - } - } - - return 1; -} - -/* -*/ -inline void GetClip(AbsRectangle &clipping, video::IImage * t) -{ - clipping.x0 = 0; - clipping.y0 = 0; - clipping.x1 = t->getDimension().Width - 1; - clipping.y1 = t->getDimension().Height - 1; -} - -/* -*/ -static void RenderLine32_Decal(video::IImage *t, - const core::position2d &p0, - const core::position2d &p1, - u32 argb ) -{ - s32 dx = p1.X - p0.X; - s32 dy = p1.Y - p0.Y; - - s32 c; - s32 m; - s32 d = 0; - s32 run; - - s32 xInc = 4; - s32 yInc = (s32) t->getPitch(); - - if ( dx < 0 ) - { - xInc = -xInc; - dx = -dx; - } - - if ( dy < 0 ) - { - yInc = -yInc; - dy = -dy; - } - - u32 *dst; - dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); - - if ( dy > dx ) - { - s32 tmp; - tmp = dx; - dx = dy; - dy = tmp; - tmp = xInc; - xInc = yInc; - yInc = tmp; - } - - c = dx << 1; - m = dy << 1; - - run = dx; - while ( run ) - { - *dst = argb; - - dst = (u32*) ( (u8*) dst + xInc ); // x += xInc - d += m; - if ( d > dx ) - { - dst = (u32*) ( (u8*) dst + yInc ); // y += yInc - d -= c; - } - run -= 1; - } - - t->unlock(); -} - - -/* -*/ -static void RenderLine32_Blend(video::IImage *t, - const core::position2d &p0, - const core::position2d &p1, - u32 argb, u32 alpha) -{ - s32 dx = p1.X - p0.X; - s32 dy = p1.Y - p0.Y; - - s32 c; - s32 m; - s32 d = 0; - s32 run; - - s32 xInc = 4; - s32 yInc = (s32) t->getPitch(); - - if ( dx < 0 ) - { - xInc = -xInc; - dx = -dx; - } - - if ( dy < 0 ) - { - yInc = -yInc; - dy = -dy; - } - - u32 *dst; - dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); - - if ( dy > dx ) - { - s32 tmp; - tmp = dx; - dx = dy; - dy = tmp; - tmp = xInc; - xInc = yInc; - yInc = tmp; - } - - c = dx << 1; - m = dy << 1; - - run = dx; - while ( run ) - { - *dst = PixelBlend32( *dst, argb, alpha ); - - dst = (u32*) ( (u8*) dst + xInc ); // x += xInc - d += m; - if ( d > dx ) - { - dst = (u32*) ( (u8*) dst + yInc ); // y += yInc - d -= c; - } - run -= 1; - } - - t->unlock(); -} - -/* -*/ -static void RenderLine16_Decal(video::IImage *t, - const core::position2d &p0, - const core::position2d &p1, - u32 argb ) -{ - s32 dx = p1.X - p0.X; - s32 dy = p1.Y - p0.Y; - - s32 c; - s32 m; - s32 d = 0; - s32 run; - - s32 xInc = 2; - s32 yInc = (s32) t->getPitch(); - - if ( dx < 0 ) - { - xInc = -xInc; - dx = -dx; - } - - if ( dy < 0 ) - { - yInc = -yInc; - dy = -dy; - } - - u16 *dst; - dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); - - if ( dy > dx ) - { - s32 tmp; - tmp = dx; - dx = dy; - dy = tmp; - tmp = xInc; - xInc = yInc; - yInc = tmp; - } - - c = dx << 1; - m = dy << 1; - - run = dx; - while ( run ) - { - *dst = (u16)argb; - - dst = (u16*) ( (u8*) dst + xInc ); // x += xInc - d += m; - if ( d > dx ) - { - dst = (u16*) ( (u8*) dst + yInc ); // y += yInc - d -= c; - } - run -= 1; - } - - t->unlock(); -} - -/* -*/ -static void RenderLine16_Blend(video::IImage *t, - const core::position2d &p0, - const core::position2d &p1, - u32 argb, - u32 alpha) -{ - s32 dx = p1.X - p0.X; - s32 dy = p1.Y - p0.Y; - - s32 c; - s32 m; - s32 d = 0; - s32 run; - - s32 xInc = 2; - s32 yInc = (s32) t->getPitch(); - - if ( dx < 0 ) - { - xInc = -xInc; - dx = -dx; - } - - if ( dy < 0 ) - { - yInc = -yInc; - dy = -dy; - } - - u16 *dst; - dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); - - if ( dy > dx ) - { - s32 tmp; - tmp = dx; - dx = dy; - dy = tmp; - tmp = xInc; - xInc = yInc; - yInc = tmp; - } - - c = dx << 1; - m = dy << 1; - - run = dx; - while ( run ) - { - *dst = PixelBlend16( *dst, argb, alpha ); - - dst = (u16*) ( (u8*) dst + xInc ); // x += xInc - d += m; - if ( d > dx ) - { - dst = (u16*) ( (u8*) dst + yInc ); // y += yInc - d -= c; - } - run -= 1; - } - - t->unlock(); -} - - -/*! -*/ -static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job ) -{ - const void *src = (void*) job->src; - void *dst = (void*) job->dst; - - const u32 widthPitch = job->width * job->dstPixelMul; - for ( s32 dy = 0; dy != job->height; ++dy ) - { - memcpy( dst, src, widthPitch ); - - src = (void*) ( (u8*) (src) + job->srcPitch ); - dst = (void*) ( (u8*) (dst) + job->dstPitch ); - } -} - - -/*! -*/ -static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job ) -{ - const u32 *src = static_cast(job->src); - u16 *dst = static_cast(job->dst); - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - //16 bit Blitter depends on pre-multiplied color - const u32 s = PixelLerp32( src[dx] | 0xFF000000, extractAlpha( src[dx] ) ); - dst[dx] = video::A8R8G8B8toA1R5G5B5( s ); - } - - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job ) -{ - const void *src = (void*) job->src; - u16 *dst = (u16*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - u8 * s = (u8*) src; - - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = video::RGB16(s[0], s[1], s[2]); - s += 3; - } - - src = (void*) ( (u8*) (src) + job->srcPitch ); - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } -} - - -/*! -*/ -static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job ) -{ - const u16 *src = (u16*) job->src; - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = video::A1R5G5B5toA8R8G8B8( src[dx] ); - } - - src = (u16*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -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 ) -{ - void *src = (void*) job->src; - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - u8 * s = (u8*) src; - - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2]; - s += 3; - } - - src = (void*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -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 ; - } - -} - - -/*! -*/ -static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job ) -{ - u32 dx; - s32 dy; - - u32 *src = (u32*) job->src; - u32 *dst = (u32*) job->dst; - - - const u32 rdx = job->width >> 1; - const u32 off = core::if_c_a_else_b( job->width & 1 ,job->width - 1, 0 ); - - - if ( 0 == off ) - { - for ( dy = 0; dy != job->height; ++dy ) - { - for ( dx = 0; dx != rdx; ++dx ) - { - dst[dx] = PixelBlend16_simd( dst[dx], src[dx] ); - } - - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } - - } - else - { - for ( dy = 0; dy != job->height; ++dy ) - { - for ( dx = 0; dx != rdx; ++dx ) - { - dst[dx] = PixelBlend16_simd( dst[dx], src[dx] ); - } - - ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] ); - - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } - - } -} - -/*! -*/ -static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job ) -{ - u32 *src = (u32*) job->src; - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend32( dst[dx], src[dx] ); - } - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job ) -{ - u16 *src = (u16*) job->src; - u16 *dst = (u16*) job->dst; - - u16 blend = video::A8R8G8B8toA1R5G5B5 ( job->argb ); - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend16( dst[dx], PixelMul16_2( src[dx], blend ) ); - } - src = (u16*) ( (u8*) (src) + job->srcPitch ); - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } -} - - -/*! -*/ -static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job ) -{ - u32 *src = (u32*) job->src; - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend32( dst[dx], PixelMul32_2( src[dx], job->argb ) ); - } - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_Color_16_to_16( const SBlitJob * job ) -{ - u16 *dst = (u16*) job->dst; - - u16 c0 = video::A8R8G8B8toA1R5G5B5( job->argb ); - u32 c = c0 | c0 << 16; - - if ( 0 == (job->srcPitch & 3 ) ) - { - for ( s32 dy = 0; dy != job->height; ++dy ) - { - memset32( dst, c, job->srcPitch ); - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } - } - else - { - s32 dx = job->width - 1; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - memset32( dst, c, job->srcPitch ); - dst[dx] = c0; - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } - - } -} - -/*! -*/ -static void executeBlit_Color_32_to_32( const SBlitJob * job ) -{ - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - memset32( dst, job->argb, job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job ) -{ - u16 *dst = (u16*) job->dst; - - const u32 alpha = extractAlpha( job->argb ) >> 3; - const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb ); - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend16( dst[dx], src, alpha ); - } - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job ) -{ - u32 *dst = (u32*) job->dst; - - const u32 alpha = extractAlpha( job->argb ); - const u32 src = job->argb; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend32( dst[dx], src, alpha ); - } - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static tExecuteBlit getBlitter( eBlitter operation,const video::IImage * dest,const video::IImage * source ) -{ - video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) -1; - video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) -1; - - if ( source ) - sourceFormat = source->getColorFormat(); - - if ( dest ) - destFormat = dest->getColorFormat(); - - switch ( operation ) - { - case BLITTER_TEXTURE: - { - if ( sourceFormat == destFormat ) - return executeBlit_TextureCopy_x_to_x; - - if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_A8R8G8B8 ) - return executeBlit_TextureCopy_32_to_16; - - if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_R8G8B8 ) - return executeBlit_TextureCopy_24_to_16; - - 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: - { - if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_A1R5G5B5 ) - return executeBlit_TextureBlend_16_to_16; - - if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_A8R8G8B8 ) - return executeBlit_TextureBlend_32_to_32; - - } break; - - case BLITTER_TEXTURE_ALPHA_COLOR_BLEND: - { - if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_A1R5G5B5 ) - return executeBlit_TextureBlendColor_16_to_16; - - if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_A8R8G8B8 ) - return executeBlit_TextureBlendColor_32_to_32; - } break; - - case BLITTER_COLOR: - { - if ( destFormat == video::ECF_A1R5G5B5 ) - return executeBlit_Color_16_to_16; - - if ( destFormat == video::ECF_A8R8G8B8 ) - return executeBlit_Color_32_to_32; - } break; - - case BLITTER_COLOR_ALPHA: - { - if ( destFormat == video::ECF_A1R5G5B5 ) - return executeBlit_ColorAlpha_16_to_16; - - if ( destFormat == video::ECF_A8R8G8B8 ) - return executeBlit_ColorAlpha_32_to_32; - - } break; - - case BLITTER_INVALID: - break; - } -/* - char buf[64]; - sprintf( buf, "Blit: %d %d->%d unsupported",operation,sourceFormat,destFormat ); - os::Printer::log(buf ); -*/ - return 0; - -} - - - -/*! - a generic 2D Blitter -*/ -static s32 Blit(eBlitter operation, - video::IImage * dest, - const core::rect *destClipping, - const core::position2d *destPos, - video::IImage * const source, - const core::rect *sourceClipping, - u32 argb) -{ - tExecuteBlit blitter = getBlitter( operation, dest, source ); - if ( 0 == blitter ) - { - return 0; - } - - // Clipping - AbsRectangle sourceClip; - AbsRectangle destClip; - AbsRectangle v; - - SBlitJob job; - - if ( sourceClipping ) - { - sourceClip.x0 = sourceClipping->UpperLeftCorner.X; - sourceClip.y0 = sourceClipping->UpperLeftCorner.Y; - sourceClip.x1 = sourceClipping->LowerRightCorner.X; - sourceClip.y1 = sourceClipping->LowerRightCorner.Y; - } - else - { - sourceClip.x0 = 0; - sourceClip.y0 = 0; - sourceClip.x1 = source ? source->getDimension().Width : 0; - sourceClip.y1 = source ? source->getDimension().Height : 0; - } - - if ( destClipping ) - { - destClip.x0 = destClipping->UpperLeftCorner.X; - destClip.y0 = destClipping->UpperLeftCorner.Y; - destClip.x1 = destClipping->LowerRightCorner.X; - destClip.y1 = destClipping->LowerRightCorner.Y; - } - else - { - destClip.x0 = 0; - destClip.y0 = 0; - destClip.x1 = dest ? dest->getDimension().Width : 0; - destClip.y1 = dest ? dest->getDimension().Height : 0; - } - - v.x0 = destPos ? destPos->X : 0; - v.y0 = destPos ? destPos->Y : 0; - v.x1 = v.x0 + ( sourceClip.x1 - sourceClip.x0 ); - v.y1 = v.y0 + ( sourceClip.y1 - sourceClip.y0 ); - - intersect( job.Dest, destClip, v ); - if ( !isValid( job.Dest ) ) - return 0; - - job.width = job.Dest.x1 - job.Dest.x0; - job.height = job.Dest.y1 - job.Dest.y0; - - - job.Source.x0 = sourceClip.x0 + ( job.Dest.x0 - v.x0 ); - job.Source.x1 = job.Source.x0 + job.width; - - job.Source.y0 = sourceClip.y0 + ( job.Dest.y0 - v.y0 ); - job.Source.y1 = job.Source.y0 + job.height; - - job.argb = argb; - - if ( source ) - { - job.srcPitch = source->getPitch(); - job.srcPixelMul = source->getBytesPerPixel(); - job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) ); - } - else - { - // use srcPitch for color operation on dest - job.srcPitch = job.width * dest->getBytesPerPixel(); - } - - job.dstPitch = dest->getPitch(); - job.dstPixelMul = dest->getBytesPerPixel(); - job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) ); - - blitter( &job ); - - if ( source ) - source->unlock(); - - if ( dest ) - dest->unlock(); - - return 1; -} - -} +#include "CBlit.h" namespace irr { namespace video { -//! constructor -CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size) +//! Constructor of empty image +CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size) :Data(0), Size(size), Format(format), DeleteMemory(true) { initData(); } -//! constructor -CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* data, +//! Constructor from raw data +CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* data, bool ownForeignMemory, bool deleteForeignMemory) : Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory) { if (ownForeignMemory) { - Data = (void*)0xbadf00d; + Data = (u8*)0xbadf00d; initData(); - Data = data; + Data = (u8*)data; } else { @@ -997,55 +40,19 @@ CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* d } - -//! constructor -CImage::CImage(ECOLOR_FORMAT format, IImage* imageToCopy) -: Data(0), Format(format), DeleteMemory(true) -{ - if (!imageToCopy) - return; - - Size = imageToCopy->getDimension(); - initData(); - - // now copy data from other image - - Blit ( BLITTER_TEXTURE, this, 0, 0, imageToCopy, 0,0 ); -} - - - -//! constructor -CImage::CImage(IImage* imageToCopy, const core::position2d& pos, - const core::dimension2d& size) - : Data(0), Size(0,0), DeleteMemory(true) -{ - if (!imageToCopy) - return; - - Format = imageToCopy->getColorFormat(); - Size = size; - - initData(); - - core::rect sClip( pos.X, pos.Y, pos.X + size.Width,pos.Y + size.Height ); - Blit (BLITTER_TEXTURE, this, 0, 0, imageToCopy, &sClip, 0); -} - - - //! assumes format and size has been set and creates the rest void CImage::initData() { - setBitMasks(); - BitsPerPixel = getBitsPerPixelFromFormat(Format); - BytesPerPixel = BitsPerPixel / 8; +#ifdef _DEBUG + setDebugName("CImage"); +#endif + BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8; // Pitch should be aligned... Pitch = BytesPerPixel * Size.Width; if (!Data) - Data = new s8[Size.Height * Pitch]; + Data = new u8[Size.Height * Pitch]; } @@ -1053,22 +60,21 @@ void CImage::initData() CImage::~CImage() { if ( DeleteMemory ) - delete [] (s8*)Data; + delete [] Data; } //! Returns width and height of image data. -const core::dimension2d& CImage::getDimension() const +const core::dimension2d& CImage::getDimension() const { return Size; } - //! Returns bits per pixel. u32 CImage::getBitsPerPixel() const { - return BitsPerPixel; + return getBitsPerPixelFromFormat(Format); } @@ -1079,7 +85,6 @@ u32 CImage::getBytesPerPixel() const } - //! Returns image data size in bytes u32 CImage::getImageDataSizeInBytes() const { @@ -1087,7 +92,6 @@ u32 CImage::getImageDataSizeInBytes() const } - //! Returns image data size in pixels u32 CImage::getImageDataSizeInPixels() const { @@ -1095,110 +99,105 @@ u32 CImage::getImageDataSizeInPixels() const } - //! returns mask for red value of a pixel u32 CImage::getRedMask() const { - return RedMask; + switch(Format) + { + case ECF_A1R5G5B5: + return 0x1F<<10; + case ECF_R5G6B5: + return 0x1F<<11; + case ECF_R8G8B8: + return 0x00FF0000; + case ECF_A8R8G8B8: + return 0x00FF0000; + default: + return 0x0; + } } - //! returns mask for green value of a pixel u32 CImage::getGreenMask() const { - return GreenMask; + switch(Format) + { + case ECF_A1R5G5B5: + return 0x1F<<5; + case ECF_R5G6B5: + return 0x3F<<5; + case ECF_R8G8B8: + return 0x0000FF00; + case ECF_A8R8G8B8: + return 0x0000FF00; + default: + return 0x0; + } } - //! returns mask for blue value of a pixel u32 CImage::getBlueMask() const { - return BlueMask; + switch(Format) + { + case ECF_A1R5G5B5: + return 0x1F; + case ECF_R5G6B5: + return 0x1F; + case ECF_R8G8B8: + return 0x000000FF; + case ECF_A8R8G8B8: + return 0x000000FF; + default: + return 0x0; + } } - //! returns mask for alpha value of a pixel u32 CImage::getAlphaMask() const -{ - return AlphaMask; -} - - -void CImage::setBitMasks() { switch(Format) { case ECF_A1R5G5B5: - AlphaMask = 0x1<<15; - RedMask = 0x1F<<10; - GreenMask = 0x1F<<5; - BlueMask = 0x1F; - break; + return 0x1<<15; case ECF_R5G6B5: - AlphaMask = 0x0; - RedMask = 0x1F<<11; - GreenMask = 0x3F<<5; - BlueMask = 0x1F; - break; + return 0x0; case ECF_R8G8B8: - AlphaMask = 0x0; - RedMask = 0x00FF0000; - GreenMask = 0x0000FF00; - BlueMask = 0x000000FF; - break; + return 0x0; case ECF_A8R8G8B8: - AlphaMask = 0xFF000000; - RedMask = 0x00FF0000; - GreenMask = 0x0000FF00; - BlueMask = 0x000000FF; - break; + return 0xFF000000; + default: + return 0x0; } } -u32 CImage::getBitsPerPixelFromFormat(ECOLOR_FORMAT format) -{ - switch(format) - { - case ECF_A1R5G5B5: - return 16; - case ECF_R5G6B5: - return 16; - case ECF_R8G8B8: - return 24; - case ECF_A8R8G8B8: - return 32; - } - - return 0; -} - //! sets a pixel -void CImage::setPixel(u32 x, u32 y, const SColor &color ) +void CImage::setPixel(u32 x, u32 y, const SColor &color, bool blend) { - if (x >= (u32)Size.Width || y >= (u32)Size.Height) + if (x >= Size.Width || y >= Size.Height) return; switch(Format) { case ECF_A1R5G5B5: { - u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 )); + u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 )); *dest = video::A8R8G8B8toA1R5G5B5( color.color ); } break; case ECF_R5G6B5: { - u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 )); + u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 )); *dest = video::A8R8G8B8toR5G6B5( color.color ); } break; case ECF_R8G8B8: { - u8* dest = (u8*) Data + ( y * Pitch ) + ( x * 3 ); + u8* dest = Data + ( y * Pitch ) + ( x * 3 ); dest[0] = (u8)color.getRed(); dest[1] = (u8)color.getGreen(); dest[2] = (u8)color.getBlue(); @@ -1206,8 +205,8 @@ void CImage::setPixel(u32 x, u32 y, const SColor &color ) case ECF_A8R8G8B8: { - u32 * dest = (u32*) ((u8*) Data + ( y * Pitch ) + ( x << 2 )); - *dest = color.color; + u32 * dest = (u32*) (Data + ( y * Pitch ) + ( x << 2 )); + *dest = blend ? PixelBlend32 ( *dest, color.color ) : color.color; } break; } } @@ -1216,7 +215,7 @@ void CImage::setPixel(u32 x, u32 y, const SColor &color ) //! returns a pixel SColor CImage::getPixel(u32 x, u32 y) const { - if (x >= (u32)Size.Width || y >= (u32)Size.Height) + if (x >= Size.Width || y >= Size.Height) return SColor(0); switch(Format) @@ -1229,7 +228,7 @@ SColor CImage::getPixel(u32 x, u32 y) const return ((u32*)Data)[y*Size.Width + x]; case ECF_R8G8B8: { - u8* p = &((u8*)Data)[(y*3)*Size.Width + (x*3)]; + u8* p = Data+(y*3)*Size.Width + (x*3); return SColor(255,p[0],p[1],p[2]); } } @@ -1245,30 +244,21 @@ ECOLOR_FORMAT CImage::getColorFormat() const } -//! draws a rectangle -void CImage::drawRectangle(const core::rect& rect, const SColor &color) -{ - Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA, - this, 0, &rect.UpperLeftCorner, 0, &rect, color.color); -} - - -//! copies this surface into another +//! copies this surface into another at given position void CImage::copyTo(IImage* target, const core::position2d& pos) { Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0); } -//! copies this surface into another +//! copies this surface partially into another at given position void CImage::copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect) { Blit(BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0); } - -//! copies this surface into another, using the alpha mask, an cliprect and a color to add with +//! copies this surface into another, using the alpha mask, a cliprect and a color to add with void CImage::copyToWithAlpha(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const SColor &color, const core::rect* clipRect) { // color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF @@ -1277,6 +267,195 @@ void CImage::copyToWithAlpha(IImage* target, const core::position2d& pos, c } +//! copies this surface into another, scaling it to the target image size +// note: this is very very slow. +void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch) +{ + if (!target || !width || !height) + return; + + const u32 bpp=getBitsPerPixelFromFormat(format)/8; + if (0==pitch) + pitch = width*bpp; + + if (Format==format && Size.Width==width && Size.Height==height) + { + if (pitch==Pitch) + { + memcpy(target, Data, height*pitch); + return; + } + else + { + u8* tgtpos = (u8*) target; + u8* srcpos = Data; + const u32 bwidth = width*bpp; + const u32 rest = pitch-bwidth; + for (u32 y=0; y& targetSize = target->getDimension(); + + if (targetSize==Size) + { + copyTo(target); + return; + } + + copyToScaling(target->lock(), targetSize.Width, targetSize.Height, target->getColorFormat()); + target->unlock(); +} + + +//! copies this surface into another, scaling it to fit it. +void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend) +{ + const core::dimension2d destSize = target->getDimension(); + + const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width; + const f32 sourceYStep = (f32) Size.Height / (f32) destSize.Height; + + target->lock(); + + s32 fx = core::ceil32( sourceXStep ); + s32 fy = core::ceil32( sourceYStep ); + f32 sx; + f32 sy; + + sy = 0.f; + for ( u32 y = 0; y != destSize.Height; ++y ) + { + sx = 0.f; + for ( u32 x = 0; x != destSize.Width; ++x ) + { + target->setPixel( x, y, + getPixelBox( core::floor32(sx), core::floor32(sy), fx, fy, bias ), blend ); + sx += sourceXStep; + } + sy += sourceYStep; + } + + target->unlock(); +} + + +//! fills the surface with given color +void CImage::fill(const SColor &color) +{ + u32 c; + + switch ( Format ) + { + case ECF_A1R5G5B5: + c = color.toA1R5G5B5(); + c |= c << 16; + break; + case ECF_R5G6B5: + c = video::A8R8G8B8toR5G6B5( color.color ); + c |= c << 16; + break; + case ECF_A8R8G8B8: + c = color.color; + break; + case ECF_R8G8B8: + { + u8 rgb[3]; + CColorConverter::convert_A8R8G8B8toR8G8B8(&color, 1, rgb); + const u32 size = getImageDataSizeInBytes(); + for (u32 i=0; i> sdiv ) + bias, 0, 255 ); + r = core::s32_clamp( ( r >> sdiv ) + bias, 0, 255 ); + g = core::s32_clamp( ( g >> sdiv ) + bias, 0, 255 ); + b = core::s32_clamp( ( b >> sdiv ) + bias, 0, 255 ); + + c.set( a, r, g, b ); + return c; +} + + +// Methods for Software drivers, non-virtual and not necessary to copy into other image classes +//! draws a rectangle +void CImage::drawRectangle(const core::rect& rect, const SColor &color) +{ + Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA, + this, 0, &rect.UpperLeftCorner, 0, &rect, color.color); +} + //! draws a line from to with color void CImage::drawLine(const core::position2d& from, const core::position2d& to, const SColor &color) @@ -1312,174 +491,12 @@ void CImage::drawLine(const core::position2d& from, const core::position2d< RenderLine32_Blend( this, p[0], p[1], color.color, alpha ); } break; + default: + break; } } } - -//! copies this surface into another, scaling it to the target image size -// note: this is very very slow. (i didn't want to write a fast version. -// but hopefully, nobody wants to scale surfaces every frame. -void CImage::copyToScaling(void* target, s32 width, s32 height, ECOLOR_FORMAT format, u32 pitch) -{ - if (!target || !width || !height) - return; - - const u32 bpp=getBitsPerPixelFromFormat(format)/8; - if (0==pitch) - pitch = width*bpp; - - if (Format==format && Size.Width==width && Size.Height==height) - { - if (pitch==Pitch) - { - memcpy(target, Data, height*pitch); - return; - } - else - { - u8* tgtpos = (u8*) target; - u8* dstpos = (u8*) Data; - const u32 bwidth = width*bpp; - for (s32 y=0; y& targetSize = target->getDimension(); - - if (targetSize==Size) - { - copyTo(target); - return; - } - - copyToScaling(target->lock(), targetSize.Width, targetSize.Height, target->getColorFormat()); - target->unlock(); -} - -//! copies this surface into another, scaling it to fit it. -void CImage::copyToScalingBoxFilter(IImage* target, s32 bias) -{ - const core::dimension2d destSize = target->getDimension(); - - const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width; - const f32 sourceYStep = (f32) Size.Height / (f32) destSize.Height; - - target->lock(); - - s32 fx = core::ceil32( sourceXStep ); - s32 fy = core::ceil32( sourceYStep ); - f32 sx; - f32 sy; - - sy = 0.f; - for ( s32 y = 0; y != destSize.Height; ++y ) - { - sx = 0.f; - for ( s32 x = 0; x != destSize.Width; ++x ) - { - target->setPixel( x, y, getPixelBox( core::floor32(sx), core::floor32(sy), fx, fy, bias ) ); - sx += sourceXStep; - } - sy += sourceYStep; - } - - target->unlock(); -} - - -//! fills the surface with given color -void CImage::fill(const SColor &color) -{ - u32 c; - - switch ( Format ) - { - case ECF_A1R5G5B5: - c = video::A8R8G8B8toA1R5G5B5( color.color ); - c |= c << 16; - break; - case ECF_R5G6B5: - c = video::A8R8G8B8toR5G6B5( color.color ); - c |= c << 16; - break; - case ECF_A8R8G8B8: - c = color.color; - break; - default: -// os::Printer::log("CImage::Format not supported", ELL_ERROR); - return; - } - - memset32( Data, c, getImageDataSizeInBytes() ); -} - - -//! get a filtered pixel -inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const -{ - SColor c; - s32 a = 0, r = 0, g = 0, b = 0; - - for ( s32 dx = 0; dx != fx; ++dx ) - { - for ( s32 dy = 0; dy != fy; ++dy ) - { - c = getPixel( x + dx , y + dy ); - - a += c.getAlpha(); - r += c.getRed(); - g += c.getGreen(); - b += c.getBlue(); - } - } - - s32 sdiv = s32_log2_s32(fx * fy); - - a = core::s32_clamp( ( a >> sdiv ) + bias, 0, 255 ); - r = core::s32_clamp( ( r >> sdiv ) + bias, 0, 255 ); - g = core::s32_clamp( ( g >> sdiv ) + bias, 0, 255 ); - b = core::s32_clamp( ( b >> sdiv ) + bias, 0, 255 ); - - c.set( a, r, g, b ); - return c; -} - - } // end namespace video } // end namespace irr - diff --git a/src/dep/src/irrlicht/CImage.h b/src/dep/src/irrlicht/CImage.h index a6c6c4d..d5f8289 100644 --- a/src/dep/src/irrlicht/CImage.h +++ b/src/dep/src/irrlicht/CImage.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -19,22 +19,15 @@ class CImage : public IImage { public: - //! constructor from another image with format change - CImage(ECOLOR_FORMAT format, IImage* imageToCopy); - //! constructor from raw image data - //! \param useForeignMemory: If true, the image will use the data pointer - //! directly and own it from now on, which means it will also try to delete [] the - //! data when the image will be destructed. If false, the memory will by copied. - CImage(ECOLOR_FORMAT format, const core::dimension2d& size, + /** \param useForeignMemory: If true, the image will use the data pointer + directly and own it from now on, which means it will also try to delete [] the + data when the image will be destructed. If false, the memory will by copied. */ + CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* data, bool ownForeignMemory=true, bool deleteMemory = true); //! constructor for empty image - CImage(ECOLOR_FORMAT format, const core::dimension2d& size); - - //! constructor using a part from another image - CImage(IImage* imageToCopy, - const core::position2d& pos, const core::dimension2d& size); + CImage(ECOLOR_FORMAT format, const core::dimension2d& size); //! destructor virtual ~CImage(); @@ -49,7 +42,7 @@ public: virtual void unlock() {} //! Returns width and height of image data. - virtual const core::dimension2d& getDimension() const; + virtual const core::dimension2d& getDimension() const; //! Returns bits per pixel. virtual u32 getBitsPerPixel() const; @@ -79,7 +72,7 @@ public: virtual SColor getPixel(u32 x, u32 y) const; //! sets a pixel - virtual void setPixel(u32 x, u32 y, const SColor &color ); + virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ); //! returns the color format virtual ECOLOR_FORMAT getColorFormat() const; @@ -88,7 +81,7 @@ public: virtual u32 getPitch() const { return Pitch; } //! copies this surface into another, scaling it to fit. - virtual void copyToScaling(void* target, s32 width, s32 height, ECOLOR_FORMAT format, u32 pitch=0); + virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch=0); //! copies this surface into another, scaling it to fit. virtual void copyToScaling(IImage* target); @@ -105,7 +98,7 @@ public: const core::rect* clipRect = 0); //! copies this surface into another, scaling it to fit, appyling a box filter - void copyToScalingBoxFilter(IImage* target, s32 bias = 0); + virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false); //! fills the surface with black or white virtual void fill(const SColor &color); @@ -116,30 +109,20 @@ public: //! draws a line from to void drawLine(const core::position2d& from, const core::position2d& to, const SColor &color); - static u32 getBitsPerPixelFromFormat(ECOLOR_FORMAT format); - private: //! assumes format and size has been set and creates the rest void initData(); - void setBitMasks(); - inline SColor getPixelBox ( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const; - void* Data; - core::dimension2d Size; - u32 BitsPerPixel; + u8* Data; + core::dimension2d Size; u32 BytesPerPixel; u32 Pitch; ECOLOR_FORMAT Format; bool DeleteMemory; - - u32 RedMask; - u32 GreenMask; - u32 BlueMask; - u32 AlphaMask; }; } // end namespace video diff --git a/src/dep/src/irrlicht/CImageLoaderBMP.cpp b/src/dep/src/irrlicht/CImageLoaderBMP.cpp index 7e75441..f36c20f 100644 --- a/src/dep/src/irrlicht/CImageLoaderBMP.cpp +++ b/src/dep/src/irrlicht/CImageLoaderBMP.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -30,9 +30,9 @@ CImageLoaderBMP::CImageLoaderBMP() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderBMP::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderBMP::isALoadableFileExtension(const io::path& filename) const { - return strstr(fileName, ".bmp") != 0; + return core::hasFileExtension ( filename, "bmp" ); } @@ -307,36 +307,41 @@ IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const // create surface + // no default constructor from packed area! ARM problem! + core::dimension2d dim; + dim.Width = header.Width; + dim.Height = header.Height; + IImage* image = 0; switch(header.BPP) { case 1: - image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert1BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, pitch, true); break; case 4: - image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert4BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, paletteData, pitch, true); break; case 8: - image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert8BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, paletteData, pitch, true); break; case 16: - image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert16BitTo16Bit((s16*)bmpData, (s16*)image->lock(), header.Width, header.Height, pitch, true); break; case 24: - image = new CImage(ECF_R8G8B8, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_R8G8B8, dim); if (image) CColorConverter::convert24BitTo24Bit(bmpData, (u8*)image->lock(), header.Width, header.Height, pitch, true, true); break; case 32: // thx to Reinhard Ostermeier - image = new CImage(ECF_A8R8G8B8, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A8R8G8B8, dim); if (image) CColorConverter::convert32BitTo32Bit((s32*)bmpData, (s32*)image->lock(), header.Width, header.Height, pitch, true); break; diff --git a/src/dep/src/irrlicht/CImageLoaderBMP.h b/src/dep/src/irrlicht/CImageLoaderBMP.h index 180e0ce..29e8c66 100644 --- a/src/dep/src/irrlicht/CImageLoaderBMP.h +++ b/src/dep/src/irrlicht/CImageLoaderBMP.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,8 +7,6 @@ #include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_BMP_LOADER_ - #include "IImageLoader.h" @@ -17,9 +15,11 @@ namespace irr namespace video { +#if defined(_IRR_COMPILE_WITH_BMP_LOADER_) || defined(_IRR_COMPILE_WITH_BMP_WRITER_) + // byte-align structures -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT @@ -66,12 +66,15 @@ namespace video // Default alignment -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #endif #undef PACK_STRUCT +#endif // defined with loader or writer + +#ifdef _IRR_COMPILE_WITH_BMP_LOADER_ /*! Surface Loader for Windows bitmaps @@ -85,7 +88,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; @@ -101,10 +104,10 @@ private: }; +#endif // compiled with loader + } // end namespace video } // end namespace irr - -#endif #endif diff --git a/src/dep/src/irrlicht/CImageLoaderJPG.cpp b/src/dep/src/irrlicht/CImageLoaderJPG.cpp index 63ec1d8..e671b14 100644 --- a/src/dep/src/irrlicht/CImageLoaderJPG.cpp +++ b/src/dep/src/irrlicht/CImageLoaderJPG.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -35,9 +35,9 @@ CImageLoaderJPG::~CImageLoaderJPG() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderJPG::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderJPG::isALoadableFileExtension(const io::path& filename) const { - return strstr(fileName, ".jpg") != 0; + return core::hasFileExtension ( filename, "jpg", "jpeg" ); } @@ -197,8 +197,18 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const // read file parameters with jpeg_read_header() jpeg_read_header(&cinfo, TRUE); - cinfo.out_color_space=JCS_RGB; - cinfo.out_color_components=3; + bool useCMYK=false; + if (cinfo.jpeg_color_space==JCS_CMYK) + { + cinfo.out_color_space=JCS_CMYK; + cinfo.out_color_components=4; + useCMYK=true; + } + else + { + cinfo.out_color_space=JCS_RGB; + cinfo.out_color_components=3; + } cinfo.do_fancy_upsampling=FALSE; // Start decompressor @@ -235,8 +245,32 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const jpeg_destroy_decompress(&cinfo); // convert image - IImage* image = new CImage(ECF_R8G8B8, - core::dimension2d(width, height), output); + IImage* image = 0; + if (useCMYK) + { + image = new CImage(ECF_R8G8B8, + core::dimension2d(width, height)); + const u32 size = 3*width*height; + u8* data = (u8*)image->lock(); + if (data) + { + for (u32 i=0,j=0; iunlock(); + delete [] output; + } + else + image = new CImage(ECF_R8G8B8, + core::dimension2d(width, height), output); delete [] input; diff --git a/src/dep/src/irrlicht/CImageLoaderJPG.h b/src/dep/src/irrlicht/CImageLoaderJPG.h index fbc9cac..c3709ee 100644 --- a/src/dep/src/irrlicht/CImageLoaderJPG.h +++ b/src/dep/src/irrlicht/CImageLoaderJPG.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -43,7 +43,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/src/dep/src/irrlicht/CImageLoaderPCX.cpp b/src/dep/src/irrlicht/CImageLoaderPCX.cpp index d62e217..de5d6f4 100644 --- a/src/dep/src/irrlicht/CImageLoaderPCX.cpp +++ b/src/dep/src/irrlicht/CImageLoaderPCX.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -31,9 +31,9 @@ CImageLoaderPCX::CImageLoaderPCX() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderPCX::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderPCX::isALoadableFileExtension(const io::path& filename) const { - return (strstr(fileName, ".PCX") != 0) || (strstr(fileName, ".pcx") != 0); + return core::hasFileExtension ( filename, "pcx" ); } @@ -96,7 +96,7 @@ IImage* CImageLoaderPCX::loadImage(io::IReadFile* file) const for( s32 i=0; i<256; i++ ) { paletteData[i] = (tempPalette[i*3+0] << 16) | - (tempPalette[i*3+1] << 8) | + (tempPalette[i*3+1] << 8) | (tempPalette[i*3+2] ); } @@ -111,7 +111,7 @@ IImage* CImageLoaderPCX::loadImage(io::IReadFile* file) const for( s32 i=0; i<256; i++ ) { paletteData[i] = (header.Palette[i*3+0] << 16) | - (header.Palette[i*3+1] << 8) | + (header.Palette[i*3+1] << 8) | (header.Palette[i*3+2]); } } @@ -169,12 +169,12 @@ IImage* CImageLoaderPCX::loadImage(io::IReadFile* file) const switch(header.Planes) // TODO: Other formats { case 1: - image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); + image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); if (image) CColorConverter::convert8BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad); break; case 3: - image = new CImage(ECF_R8G8B8, core::dimension2d(width, height)); + image = new CImage(ECF_R8G8B8, core::dimension2d(width, height)); if (image) CColorConverter::convert24BitTo24Bit(PCXData, (u8*)image->lock(), width, height, pad); break; @@ -184,7 +184,7 @@ IImage* CImageLoaderPCX::loadImage(io::IReadFile* file) const { if (header.Planes==1) { - image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); + image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); if (image) CColorConverter::convert4BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad); } @@ -193,13 +193,13 @@ IImage* CImageLoaderPCX::loadImage(io::IReadFile* file) const { if (header.Planes==4) { - image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); + image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); if (image) CColorConverter::convert4BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad); } else if (header.Planes==1) { - image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); + image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); if (image) CColorConverter::convert1BitTo16Bit(PCXData, (s16*)image->lock(), width, height, pad); } diff --git a/src/dep/src/irrlicht/CImageLoaderPCX.h b/src/dep/src/irrlicht/CImageLoaderPCX.h index 8468b2a..da581a0 100644 --- a/src/dep/src/irrlicht/CImageLoaderPCX.h +++ b/src/dep/src/irrlicht/CImageLoaderPCX.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,8 +7,6 @@ #include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_PCX_LOADER_ - #include "IImageLoader.h" namespace irr @@ -16,9 +14,10 @@ namespace irr namespace video { +#if defined(_IRR_COMPILE_WITH_PCX_LOADER_) || defined(_IRR_COMPILE_WITH_PCX_WRITER_) // byte-align structures -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT @@ -52,12 +51,15 @@ namespace video // Default alignment -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #endif #undef PACK_STRUCT +#endif // compile with loader or writer + +#ifdef _IRR_COMPILE_WITH_PCX_LOADER_ /*! Image Loader for Windows PCX bitmaps. @@ -73,7 +75,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; @@ -83,10 +85,10 @@ public: }; +#endif // compile with loader } // end namespace video } // end namespace irr #endif -#endif diff --git a/src/dep/src/irrlicht/CImageLoaderPNG.cpp b/src/dep/src/irrlicht/CImageLoaderPNG.cpp index 22192fd..ae1fbe6 100644 --- a/src/dep/src/irrlicht/CImageLoaderPNG.cpp +++ b/src/dep/src/irrlicht/CImageLoaderPNG.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -38,7 +38,7 @@ void PNGAPI user_read_data_fcn(png_structp png_ptr, png_bytep data, png_size_t l // changed by zola { io::IReadFile* file=(io::IReadFile*)png_ptr->io_ptr; - check=(png_size_t) file->read((void*)data,length); + check=(png_size_t) file->read((void*)data,(u32)length); // } if (check != length) @@ -49,14 +49,10 @@ void PNGAPI user_read_data_fcn(png_structp png_ptr, png_bytep data, png_size_t l //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderPng::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderPng::isALoadableFileExtension(const io::path& filename) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ - // added fix for file extension check by jox - const c8* ext = strrchr(fileName, '.'); - if (ext == 0) - return false; - return (strcmp(ext, ".PNG") == 0) || (strcmp(ext, ".png") == 0); + return core::hasFileExtension ( filename, "png" ); #else return false; #endif // _IRR_COMPILE_WITH_LIBPNG_ @@ -184,9 +180,16 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const // Update the changes png_read_update_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, - (png_uint_32*)&Width, (png_uint_32*)&Height, - &BitDepth, &ColorType, NULL, NULL, NULL); + { + // Use temporary variables to avoid passing casted pointers + png_uint_32 w,h; + // Extract info + png_get_IHDR(png_ptr, info_ptr, + &w, &h, + &BitDepth, &ColorType, NULL, NULL, NULL); + Width=w; + Height=h; + } // Convert RGBA to BGRA if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA) @@ -199,15 +202,22 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const } // Update the changes - png_get_IHDR(png_ptr, info_ptr, - (png_uint_32*)&Width, (png_uint_32*)&Height, - &BitDepth, &ColorType, NULL, NULL, NULL); + { + // Use temporary variables to avoid passing casted pointers + png_uint_32 w,h; + // Extract info + png_get_IHDR(png_ptr, info_ptr, + &w, &h, + &BitDepth, &ColorType, NULL, NULL, NULL); + Width=w; + Height=h; + } // Create the image structure to be filled by png data if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA) - image = new CImage(ECF_A8R8G8B8, core::dimension2d(Width, Height)); + image = new CImage(ECF_A8R8G8B8, core::dimension2d(Width, Height)); else - image = new CImage(ECF_R8G8B8, core::dimension2d(Width, Height)); + image = new CImage(ECF_R8G8B8, core::dimension2d(Width, Height)); if (!image) { os::Printer::log("LOAD PNG: Internal PNG create image struct failure\n", file->getFileName(), ELL_ERROR); diff --git a/src/dep/src/irrlicht/CImageLoaderPNG.h b/src/dep/src/irrlicht/CImageLoaderPNG.h index 1b58c56..d5a32ed 100644 --- a/src/dep/src/irrlicht/CImageLoaderPNG.h +++ b/src/dep/src/irrlicht/CImageLoaderPNG.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -27,7 +27,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".png") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/src/dep/src/irrlicht/CImageLoaderPPM.cpp b/src/dep/src/irrlicht/CImageLoaderPPM.cpp index 430e944..5851413 100644 --- a/src/dep/src/irrlicht/CImageLoaderPPM.cpp +++ b/src/dep/src/irrlicht/CImageLoaderPPM.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2008 Christian Stehno +// Copyright (C) 2007-2010 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -30,16 +30,16 @@ CImageLoaderPPM::CImageLoaderPPM() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderPPM::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderPPM::isALoadableFileExtension(const io::path& filename) const { - return strstr(fileName, ".ppm") || strstr(fileName, ".pgm") || strstr(fileName, ".pbm"); + return core::hasFileExtension ( filename, "ppm", "pgm", "pbm" ); } //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderPPM::isALoadableFileFormat(io::IReadFile* file) const { - c8 id[2]; + c8 id[2]={0}; file->read(&id, 2); return (id[0]=='P' && id[1]>'0' && id[1]<'7'); } @@ -99,7 +99,7 @@ IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const shift=0; } } - image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); + image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); if (image) CColorConverter::convert1BitTo16Bit(data, (s16*)image->lock(), width, height); } @@ -120,7 +120,7 @@ IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const return 0; data = new u8[size]; file->read(data, size); - image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); + image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); if (image) { u8* ptr = (u8*)image->lock(); @@ -137,7 +137,7 @@ IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const { if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test return 0; - image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); + image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); if (image) { u8* ptr = (u8*)image->lock(); @@ -162,7 +162,7 @@ IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const return 0; data = new u8[bytesize]; file->read(data, bytesize); - image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); + image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); if (image) { u8* ptr = (u8*)image->lock(); @@ -179,7 +179,7 @@ IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const { if (file->getSize()-file->getPos() < (long)(2*bytesize)) // optimistic test return 0; - image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); + image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); if (image) { u8* ptr = (u8*)image->lock(); diff --git a/src/dep/src/irrlicht/CImageLoaderPPM.h b/src/dep/src/irrlicht/CImageLoaderPPM.h index a3bdcb4..973a8f9 100644 --- a/src/dep/src/irrlicht/CImageLoaderPPM.h +++ b/src/dep/src/irrlicht/CImageLoaderPPM.h @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2008 Christian Stehno +// Copyright (C) 2007-2010 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -31,7 +31,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/src/dep/src/irrlicht/CImageLoaderPSD.cpp b/src/dep/src/irrlicht/CImageLoaderPSD.cpp index c6b5e2e..1bd8930 100644 --- a/src/dep/src/irrlicht/CImageLoaderPSD.cpp +++ b/src/dep/src/irrlicht/CImageLoaderPSD.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -29,9 +29,9 @@ CImageLoaderPSD::CImageLoaderPSD() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderPSD::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderPSD::isALoadableFileExtension(const io::path& filename) const { - return strstr(fileName, ".psd") != 0; + return core::hasFileExtension ( filename, "psd" ); } @@ -152,7 +152,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const { // create surface image = new CImage(ECF_A8R8G8B8, - core::dimension2d(header.width, header.height), imageData); + core::dimension2d(header.width, header.height), imageData); } if (!image) diff --git a/src/dep/src/irrlicht/CImageLoaderPSD.h b/src/dep/src/irrlicht/CImageLoaderPSD.h index 2d4acd7..4da3197 100644 --- a/src/dep/src/irrlicht/CImageLoaderPSD.h +++ b/src/dep/src/irrlicht/CImageLoaderPSD.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,7 +18,7 @@ namespace video // byte-align structures -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT @@ -42,7 +42,7 @@ namespace video // Default alignment -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #endif @@ -60,7 +60,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/src/dep/src/irrlicht/CImageLoaderRGB.cpp b/src/dep/src/irrlicht/CImageLoaderRGB.cpp new file mode 100644 index 0000000..6e66557 --- /dev/null +++ b/src/dep/src/irrlicht/CImageLoaderRGB.cpp @@ -0,0 +1,651 @@ +//! Copyright (C) 2009-2010 Gary Conway +//! This file is part of the "Irrlicht Engine". +//! For conditions of distribution and use, see copyright notice in irrlicht.h + +/* + Author: Gary Conway (Viper) - co-author of the ZIP file format, Feb 1989, + see the story at http://www.idcnet.us/ziphistory.html + Website: http://idcnet.us + Email: codeslinger@vipergc.com + Created: March 1, 2009 + Version: 1.0 + Updated: + + This module will load SGI .rgb files (along with the other extensions). The module complies + with version 1.0 of the SGI Image File Format by Paul Haeberli of Silicon Graphics Computer Systems + The module handles BW, RGB and RGBA images. + + RGB images are stored with either 8 bits per COLOR VALUE, one each for red,green,blue (24bpp) + or 16 bits per COLOR VALUE, again one each for red,green,blue (48 bpp), not including the alpha channel + + + OPTIONS NOT SUPPORTED + + 1. 16 bit COLOR VALUES (48bpp modes) + 2. COLORMAP = DITHERED mode + + + +For non- run length encoded files, this is the structure + + The Header + The Image Data + +If the image is run length encoded, this is the structure: + The Header + The Offset Tables + The Image Data + +The Header consists of the following: + + Size | Type | Name | Description + + 2 bytes | short | MAGIC | IRIS image file magic number + 1 byte | char | STORAGE | Storage format + 1 byte | char | BPC | Number of bytes per pixel channel + 2 bytes | ushort | DIMENSION | Number of dimensions + 2 bytes | ushort | XSIZE | X size in pixels + 2 bytes | ushort | YSIZE | Y size in pixels + 2 bytes | ushort | ZSIZE | Number of channels + 4 bytes | long | PIXMIN | Minimum pixel value + 4 bytes | long | PIXMAX | Maximum pixel value + 4 bytes | char | DUMMY | Ignored + 80 bytes | char | IMAGENAME | Image name + 4 bytes | long | COLORMAP | Colormap ID + 404 bytes | char | DUMMY | Ignored + +Here is a description of each field in the image file Header: + +MAGIC - This is the decimal value 474 saved as a short. This identifies the file as an SGI image file. + +STORAGE - specifies whether the image is stored using run length encoding (RLE) or not (VERBATIM). + If RLE is used, the value of this byte will be 1. Otherwise the value of this byte will + be 0. The only allowed values for this field are 0 or 1. + +BPC - describes the precision that is used to store each channel of an image. This is the number of + bytes per pixel component. The majority of SGI image files use 1 byte per pixel component, + giving 256 levels. Some SGI image files use 2 bytes per component. The only allowed values + for this field are 1 or 2. + +DIMENSION - described the number of dimensions in the data stored in the image file. + The only allowed values are 1, 2, or 3. If this value is 1, the image file + consists of only 1 channel and only 1 scanline (row). The length of this + scanline is given by the value of XSIZE below. If this value is 2, the file + consists of a single channel with a number of scanlines. The width and height + of the image are given by the values of XSIZE and YSIZE below. + If this value is 3, the file consists of a number of channels. + The width and height of the image are given by the values of XSIZE and YSIZE below. + The number of channels is given by the value of ZSIZE below. + +XSIZE - The width of the image in pixels + +YSIZE - The height of the image in pixels + +ZSIZE - The number of channels in the image. B/W (greyscale) images are stored as 2 dimensional + images with a ZSIZE of 1. RGB color images are stored as 3 dimensional images with a + ZSIZE of 3. An RGB image with an ALPHA channel is stored as a 3 dimensional image with + a ZSIZE of 4. There are no inherent limitations in the SGI image file format that would + preclude the creation of image files with more than 4 channels. + +PINMIN - The minimum pixel value in the image. The value of 0 may be used if no pixel has a value + that is smaller than 0. + +PINMAX - The maximum pixel value in the image. The value of 255 may be used if no pixel has a + value that is greater than 255. This is the value that is considered to be full + brightness in the image. + +DUMMY - This 4 bytes of data should be set to 0. + +IMAGENAME - An null terminated ascii string of up to 79 characters terminated by a null may be + included here. This is not commonly used. + +COLORMAP - This controls how the pixel values in the file should be interpreted. It can have one + of these four values: + +0: NORMAL - The data in the channels represent B/W values for images with 1 channel, RGB values + for images with 3 channels, and RGBA values for images with 4 channels. Almost all + the SGI image files are of this type. + +1: DITHERED - The image will have only 1 channel of data. For each pixel, RGB data is packed + into one 8 bit value. 3 bits are used for red and green, while blue uses 2 bits. + Red data is found in bits[2..0], green data in bits[5..3], and blue data in + bits[7..6]. This format is obsolete. + +2: SCREEN - The image will have only 1 channel of data. This format was used to store + color-indexed pixels. To convert the pixel values into RGB values a colormap + must be used. The appropriate color map varies from image to image. This format is obsolete. + +3: COLORMAP - The image is used to store a color map from an SGI machine. In this case the + image is not displayable in the conventional sense. + +DUMMY - This 404 bytes of data should be set to 0. This makes the Header exactly 512 bytes. +*/ + +#include "CImageLoaderRGB.h" + +#ifdef _IRR_COMPILE_WITH_RGB_LOADER_ + +#include "IReadFile.h" +#include "SColor.h" +#include "CColorConverter.h" +#include "CImage.h" +#include "os.h" +#include "irrString.h" + + +namespace irr +{ +namespace video +{ + +//! constructor +CImageLoaderRGB::CImageLoaderRGB() +{ + #ifdef _DEBUG + setDebugName("CImageLoaderRGB"); + #endif +} + + +//! returns true if the file maybe is able to be loaded by this class +//! based on the file extensions listed here +bool CImageLoaderRGB::isALoadableFileExtension(const io::path& filename) const +{ + return core::hasFileExtension( filename, "rgb", "rgba", "sgi" ) || + core::hasFileExtension( filename, "int", "inta", "bw" ); +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CImageLoaderRGB::isALoadableFileFormat(io::IReadFile* file) const +{ + rgbStruct rgb; + return checkFormat(file, rgb); +} + + +/** The main entry point, read and format the image file. +\return Pointer to the image data on success + null pointer on fail */ +IImage* CImageLoaderRGB::loadImage(io::IReadFile* file) const +{ + IImage* image = 0; + s32* paletteData = 0; + + rgbStruct rgb; // construct our structure for holding data + + // read Header information + if (checkFormat(file, rgb)) + { + // 16 bits per COLOR VALUE, not supported, this is 48bpp mode + if (rgb.Header.BPC != 1) + { + os::Printer::log("Only one byte per pixel RGB files are supported", file->getFileName(), ELL_ERROR); + } + else if (rgb.Header.Colormap != 0) + { + os::Printer::log("Dithered, Screen and Colormap RGB files are not supported", file->getFileName(), ELL_ERROR); + } + else if (rgb.Header.Storage == 1 && !readOffsetTables(file, rgb)) + { + os::Printer::log("Failed to read RLE table in RGB file", file->getFileName(), ELL_ERROR); + } + else if (!rgb.allocateTemps()) + { + os::Printer::log("Out of memory in RGB file loader", file->getFileName(), ELL_ERROR); + } + else + { + // read and process the file to rgbData + processFile(file, rgb); + +/* + ZSIZE Description + 1 BW (grayscale) image + 3 RGB image + 4 RGBa image with one alpha channel + + When the Alpha channel is present, I am not sure with RGB files if + it's a precomputed RGB color or it needs to be completely calculated. My guess + would be that it's not precomputed for two reasons. + + 1. the loss of precision when calculating the fraction, then storing the result as an int + 2. the loss of the original color data when the image might be composited with another. Yes + the original color data could be computed, however, not without another loss in precision + + Also, I don't know where to find the background color + Pixmin and Pixmax are apparently the min and max alpha blend values (0-100%) + + Complete Alpha blending computation + The actual resulting merged color is computed this way: + (image color â—Š alpha) + (background color â—Š (100% - alpha)). + + Using precomputed blending + (image color) + (background color â—Š (100% - alpha)). + + Alternatively, the RGB files could use another blending technique entirely +*/ + + switch (rgb.Header.Zsize) + { + case 1: + // BW (grayscale) image + paletteData = new s32[256]; + for (int n=0; n<256; n++) + paletteData[n] = n; + + image = new CImage(ECF_A1R5G5B5, core::dimension2d(rgb.Header.Xsize, rgb.Header.Ysize)); + if (image) + CColorConverter::convert8BitTo16Bit(rgb.rgbData, (s16*)image->lock(), rgb.Header.Xsize, rgb.Header.Ysize, paletteData, 0, true); + break; + case 3: + // RGB image + // one byte per COLOR VALUE, eg, 24bpp + image = new CImage(ECF_R8G8B8, core::dimension2d(rgb.Header.Xsize, rgb.Header.Ysize)); + if (image) + CColorConverter::convert24BitTo24Bit(rgb.rgbData, (u8*)image->lock(), rgb.Header.Xsize, rgb.Header.Ysize, 0, true, false); + break; + case 4: + // RGBa image with one alpha channel (32bpp) + // image is stored in rgbData as RGBA + + converttoARGB(reinterpret_cast(rgb.rgbData), rgb.Header.Ysize * rgb.Header.Xsize); + + image = new CImage(ECF_A8R8G8B8, core::dimension2d(rgb.Header.Xsize, rgb.Header.Ysize)); + if (image) + CColorConverter::convert32BitTo32Bit((s32*)rgb.rgbData, (s32*)image->lock(), rgb.Header.Xsize, rgb.Header.Ysize, 0, true); + + break; + default: + // Format unknown + os::Printer::log("Unsupported pixel format in RGB file", file->getFileName(), ELL_ERROR); + } + + if (image) + image->unlock(); + } + } + + // and tidy up allocated memory + delete [] paletteData; + + return image; +} + +// returns true on success +bool CImageLoaderRGB::readHeader(io::IReadFile* file, rgbStruct& rgb) const +{ + if ( file->read(&rgb.Header, sizeof(rgb.Header)) < s32(sizeof(rgb.Header)) ) + return false; + + // test for INTEL or BIG ENDIAN processor + // if INTEL, then swap the byte order on 16 bit INT's to make them BIG ENDIAN + // because that is the native format for the .rgb file +#ifndef __BIG_ENDIAN__ + rgb.Header.Magic = os::Byteswap::byteswap(rgb.Header.Magic); + rgb.Header.Storage = os::Byteswap::byteswap(rgb.Header.Storage); + rgb.Header.Dimension = os::Byteswap::byteswap(rgb.Header.Dimension); + rgb.Header.Xsize = os::Byteswap::byteswap(rgb.Header.Xsize); + rgb.Header.Ysize = os::Byteswap::byteswap(rgb.Header.Ysize); + rgb.Header.Zsize = os::Byteswap::byteswap(rgb.Header.Zsize); + rgb.Header.Pixmin = os::Byteswap::byteswap(rgb.Header.Pixmin); + rgb.Header.Pixmax = os::Byteswap::byteswap(rgb.Header.Pixmax); + rgb.Header.Colormap = os::Byteswap::byteswap(rgb.Header.Colormap); +#endif + + // calculate the size of the buffer needed: XSIZE * YSIZE * ZSIZE * BPC + rgb.ImageSize = (rgb.Header.Xsize)*(rgb.Header.Ysize)*(rgb.Header.Zsize)*(rgb.Header.BPC); + + return true; +} + + +bool CImageLoaderRGB::checkFormat(io::IReadFile* file, rgbStruct& rgb) const +{ + if (!readHeader(file, rgb)) + return false; + + return (rgb.Header.Magic == 0x1DA); +} + +/* +If the image is stored using run length encoding, offset tables follow the Header that +describe what the file offsets are to the RLE for each scanline. This information only +applies if the value for STORAGE above is 1. + + Size | Type | Name | Description + + tablen longs | long | STARTTAB | Start table + tablen longs | long | LENGTHTAB | Length table + +One entry in each table is needed for each scanline of RLE data. The total number of scanlines in the image (tablen) is determined by the product of the YSIZE and ZSIZE. There are two tables of longs that are written. Each consists of tablen longs of data. The first table has the file offsets to the RLE data for each scanline in the image. In a file with more than 1 channel (ZSIZE > 1) this table first has all the offsets for the scanlines in the first channel, followed be offsets for the scanlines in the second channel, etc. The second table has the RLE data length for each scanline in the image. In a file with more than 1 channel (ZSIZE > 1) this table first has all the RLE data lengths for the scanlines in the first channel, followed be RLE data lengths for the scanlines in the second channel, etc. + +To find the the file offset, and the number of bytes in the RLE data for a particular scanline, these +two arrays may be read in and indexed as follows: + +To read in the tables: + + unsigned long *starttab, *lengthtab; + + tablen = YSIZE*ZSIZE*sizeof(long); + starttab = (unsigned long *)mymalloc(tablen); + lengthtab = (unsigned long *)mymalloc(tablen); + fseek(rgb->inf,512,SEEK_SET); + readlongtab(rgb->inf,starttab); + readlongtab(rgb->inf,lengthtab); + +To find the file offset and RLE data length for a scanline: + +rowno is an integer in the range 0 to YSIZE-1 channo is an integer in the range 0 to ZSIZE-1 + + rleoffset = starttab[rowno+channo*YSIZE] + rlelength = lengthtab[rowno+channo*YSIZE] + +It is possible for two identical rows (scanlines) to share compressed data. A completely +white image could be written as a single compressed row and having all table entries point +to that row. Another little hack that should work is if you are writing out a RGB RLE file, +and a particular scanline is achromatic (greyscale), you could just make the r, g and b rows +point to the same data!! + + RETURNS: on success true, else returns false +*/ + +bool CImageLoaderRGB::readOffsetTables(io::IReadFile* file, rgbStruct& rgb) const +{ + rgb.TableLen = rgb.Header.Ysize * rgb.Header.Zsize ; // calc size of tables + + // return error if unable to allocate tables + if ( !(rgb.StartTable = new u32[rgb.TableLen]) ) + return false; + if ( !(rgb.LengthTable = new u32[rgb.TableLen]) ) + return false; + + file->seek(512); + file->read(rgb.StartTable, rgb.TableLen* sizeof(u32)); + file->read(rgb.LengthTable, rgb.TableLen* sizeof(u32)); + + // if we are on an INTEL platform, swap the bytes +#ifndef __BIG_ENDIAN__ + const u32 length = rgb.TableLen; + for (u32 i=0; i=0; --i) +#endif + { + // check the number of channels and read a row of data + if (rgb.Header.Zsize >= 1) + readRGBrow( rgb.tmpR, i, 0, file, rgb); + if (rgb.Header.Zsize >= 2) + readRGBrow( rgb.tmpG, i, 1, file, rgb); + if (rgb.Header.Zsize >= 3) + readRGBrow( rgb.tmpB, i, 2, file, rgb); + if (rgb.Header.Zsize >= 4) + readRGBrow( rgb.tmpA, i, 3, file, rgb); + + // cycle thru all values for this row + for (u32 j = 0; j < rgb.Header.Xsize; ++j) + { + if(rgb.Header.BPC == 1) + { + // ONE byte per color + if (rgb.Header.Zsize >= 1) + *ptr++ = rgb.tmpR[j]; + if (rgb.Header.Zsize >= 2) + *ptr++ = rgb.tmpG[j]; + if (rgb.Header.Zsize >= 3) + *ptr++ = rgb.tmpB[j]; + if (rgb.Header.Zsize >= 4) + *ptr++ = rgb.tmpA[j]; + } + else + { + // TWO bytes per color + if( rgb.Header.Zsize >= 1 ) + { + // two bytes of color data + tempShort = (u16 *) (ptr); + *tempShort = *( (u16 *) (rgb.tmpR) + j); + tempShort++; + ptr = ( u8 *)(tempShort); + } + if( rgb.Header.Zsize >= 2 ) + { + tempShort = ( u16 *) (ptr); + *tempShort = *( ( u16 *) (rgb.tmpG) + j); + tempShort++; + ptr = ( u8 *) (tempShort); + } + if( rgb.Header.Zsize >= 3 ) + { + tempShort = ( u16 *) (ptr); + *tempShort = *( ( u16 *) (rgb.tmpB) + j); + tempShort++; + ptr = ( u8 *)(tempShort); + } + if( rgb.Header.Zsize >= 4 ) + { + tempShort = ( u16 *) (ptr); + *tempShort = *( ( u16 *) (rgb.tmpA) + j); + tempShort++; + ptr = ( u8 *)(tempShort); + } + } // end if(rgb.Header.BPC == 1) + } // end for + } // end for +} + + +/* + This information only applies if the value for STORAGE is 1. If the image is + stored using run length encoding, the image data follows the offset/length tables. + The RLE data is not in any particular order. The offset tables are used to + locate the rle data for any scanline. + + The RLE data must be read in from the file and expanded into pixel data in the following manner: + + If BPC is 1, then there is one byte per pixel. In this case the RLE data should be + read into an array of chars. To expand data, the low order seven bits of the first + byte: bits[6..0] are used to form a count. If the high order bit of the first byte + is 1: bit[7], then the count is used to specify how many bytes to copy from the RLE + data buffer to the destination. Otherwise, if the high order bit of the first byte + is 0: bit[7], then the count is used to specify how many times to repeat the value + of the following byte, in the destination. This process continues until a count + of 0 is found. This should decompress exactly XSIZE pixels. + + + One entry in each table is needed for each scanline of RLE data. The total number of + scanlines in the image (tablen) is determined by the product of the YSIZE and ZSIZE. + There are two tables of longs that are written. Each consists of tablen longs of data. + The first table has the file offsets to the RLE data for each scanline in the image. In + a file with more than 1 channel (ZSIZE > 1) this table first has all the offsets for the + scanlines in the first channel, followed be offsets for the scanlines in the second + channel, etc. The second table has the RLE data length for each scanline in the image. + In a file with more than 1 channel (ZSIZE > 1) this table first has all the RLE data + lengths for the scanlines in the first channel, followed be RLE data lengths for the + scanlines in the second channel, etc. + + Return a row of data, expanding RLE compression if necessary +*/ +void CImageLoaderRGB::readRGBrow(u8 *buf, int y, int z, io::IReadFile* file, rgbStruct& rgb) const +{ + if (rgb.Header.Storage != 1) + { + // stored VERBATIM + + file->seek(512+(y*rgb.Header.Xsize * rgb.Header.BPC)+(z* rgb.Header.Xsize * rgb.Header.Ysize * rgb.Header.BPC)); + file->read(buf, rgb.Header.Xsize * rgb.Header.BPC); + +#ifndef __BIG_ENDIAN__ + if (rgb.Header.BPC != 1) + { + u16* tmpbuf = reinterpret_cast(buf); + for (u32 i=0; iseek((long) rgb.StartTable[y+z * rgb.Header.Ysize]); + file->read(rgb.tmp, rgb.LengthTable[y+z * rgb.Header.Ysize]); + + // rgb.tmp has the data + + u16 pixel; + u16 *tempShort; + u8* iPtr = rgb.tmp; + u8* oPtr = buf; + while (true) + { + // if BPC = 1, then one byte per pixel + if (rgb.Header.BPC == 1) + { + pixel = *iPtr++; + } + else + { + // BPC = 2, so two bytes per pixel + tempShort = (u16 *) iPtr; + pixel = *tempShort; + tempShort++; + iPtr = (u8 *) tempShort; + } + +#ifndef __BIG_ENDIAN__ + if (rgb.Header.BPC != 1) + pixel = os::Byteswap::byteswap(pixel); +#endif + + s32 count = (s32)(pixel & 0x7F); + + // limit the count value to the remaining row size + if (oPtr + count*rgb.Header.BPC > buf + rgb.Header.Xsize * rgb.Header.BPC) + { + count = ( (buf + rgb.Header.Xsize * rgb.Header.BPC) - oPtr ) / rgb.Header.BPC; + } + + if (count<=0) + break; + else if (pixel & 0x80) + { + // repeat the byte pointed to by iPtr, count times + while (count--) + { + if(rgb.Header.BPC == 1) + { + *oPtr++ = *iPtr++; + } + else + { + // write pixel from iPtr to oPtr, move both two bytes ahead + tempShort = (u16 *) (iPtr); + pixel = *tempShort; + tempShort++; + iPtr = (u8 *) (tempShort); +#ifndef __BIG_ENDIAN__ + pixel = os::Byteswap::byteswap(pixel); +#endif + tempShort = (u16 *) (oPtr); + *tempShort = pixel; + tempShort++; + oPtr = (u8 *) (tempShort); + } + } + } + else + { + if (rgb.Header.BPC == 1) + { + pixel = *iPtr++; + } + else + { + tempShort = (u16 *) (iPtr); + pixel = *tempShort; + tempShort++; + iPtr = (u8 *) (tempShort); + } + +#ifndef __BIG_ENDIAN__ + if (rgb.Header.BPC != 1) + pixel = os::Byteswap::byteswap(pixel); +#endif + + while (count--) + { + if(rgb.Header.BPC == 1) + { + *oPtr++ = (u8) pixel; + } + else + { + tempShort = (u16 *) (oPtr); + *tempShort = pixel; + tempShort++; + oPtr = (u8 *) (tempShort); + } + } + } // else if (pixel & 0x80) + } // while (true) +} + + +// we have 1 byte per COLOR VALUE, eg 24bpp and 1 alpha channel +// color values are stored as RGBA, convert to ARGB +// todo: replace with CColorConverter method +void CImageLoaderRGB::converttoARGB(u32* in, const u32 size) const +{ + for (u32 x=0; x < size; ++x) + { + *in=(*in>>8)|(*in<<24); + ++in; + } +} + + +//! creates a loader which is able to load SGI RGB images +IImageLoader* createImageLoaderRGB() +{ + return new CImageLoaderRGB; +} + + +} // end namespace video +} // end namespace irr + +#endif diff --git a/src/dep/src/irrlicht/CImageLoaderRGB.h b/src/dep/src/irrlicht/CImageLoaderRGB.h new file mode 100644 index 0000000..74e4ea6 --- /dev/null +++ b/src/dep/src/irrlicht/CImageLoaderRGB.h @@ -0,0 +1,172 @@ +// Copyright (C) 2009-2010 Gary Conway +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + + +/* + Author: Gary Conway (Viper) - co-author of the ZIP file format, Feb 1989, + see the story at http://www.idcnet.us/ziphistory.html + Website: http://idcnet.us + Email: codeslinger@vipergc.com + Created: March 1, 2009 + Version: 1.0 + Updated: +*/ + +#ifndef __C_IMAGE_LOADER_RGB_H_INCLUDED__ +#define __C_IMAGE_LOADER_RGB_H_INCLUDED__ + +// define _IRR_RGB_FILE_INVERTED_IMAGE_ to preserve the inverted format of the RGB file +// commenting this out will invert the inverted image,resulting in the image being upright +#define _IRR_RGB_FILE_INVERTED_IMAGE_ + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_RGB_LOADER_ + +#include "IImageLoader.h" + +namespace irr +{ +namespace video +{ + +// byte-align structures +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( push, packing ) +# pragma pack( 1 ) +# define PACK_STRUCT +#elif defined( __GNUC__ ) +# define PACK_STRUCT __attribute__((packed)) +#else +# error compiler not supported +#endif + + // the RGB image file header structure + + struct SRGBHeader + { + u16 Magic; // IRIS image file magic number + u8 Storage; // Storage format + u8 BPC; // Number of bytes per pixel channel + u16 Dimension; // Number of dimensions + u16 Xsize; // X size in pixels + u16 Ysize; // Y size in pixels + u16 Zsize; // Z size in pixels + u32 Pixmin; // Minimum pixel value + u32 Pixmax; // Maximum pixel value + u32 Dummy1; // ignored + char Imagename[80]; // Image name + u32 Colormap; // Colormap ID +// char Dummy2[404]; // Ignored + } PACK_STRUCT; + +// Default alignment +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( pop, packing ) +#endif + +#undef PACK_STRUCT + + // this structure holds context specific data about the file being loaded. + + typedef struct _RGBdata + { + u8 *tmp, + *tmpR, + *tmpG, + *tmpB, + *tmpA; + + + u32 *StartTable; // compressed data table, holds file offsets + u32 *LengthTable; // length for the above data, hold lengths for above + u32 TableLen; // len of above tables + + SRGBHeader Header; // define the .rgb file header + u32 ImageSize; + u8 *rgbData; + + public: + _RGBdata() : tmp(0), tmpR(0), tmpG(0), tmpB(0), tmpA(0), + StartTable(0), LengthTable(0), TableLen(0), ImageSize(0), rgbData(0) + { + } + + ~_RGBdata() + { + delete [] tmp; + delete [] tmpR; + delete [] tmpG; + delete [] tmpB; + delete [] tmpA; + delete [] StartTable; + delete [] LengthTable; + delete [] rgbData; + } + + bool allocateTemps() + { + tmp = tmpR = tmpG = tmpB = tmpA = 0; + tmp = new u8 [Header.Xsize * 256 * Header.BPC]; + if (!tmp) + return false; + + if (Header.Zsize >= 1) + { + if ( !(tmpR = new u8 [Header.Xsize * Header.BPC]) ) + return false; + } + if (Header.Zsize >= 2) + { + if ( !(tmpG = new u8 [Header.Xsize * Header.BPC]) ) + return false; + } + if (Header.Zsize >= 3) + { + if ( !(tmpB = new u8 [Header.Xsize * Header.BPC]) ) + return false; + } + if (Header.Zsize >= 4) + { + if ( !(tmpA = new u8 [Header.Xsize * Header.BPC]) ) + return false; + } + return true; + } + } rgbStruct; + + +//! Surface Loader for Silicon Graphics RGB files +class CImageLoaderRGB : public IImageLoader +{ +public: + + //! constructor + CImageLoaderRGB(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".tga") + virtual bool isALoadableFileExtension(const io::path& filename) const; + + //! returns true if the file maybe is able to be loaded by this class + virtual bool isALoadableFileFormat(io::IReadFile* file) const; + + //! creates a surface from the file + virtual IImage* loadImage(io::IReadFile* file) const; + +private: + + bool readHeader(io::IReadFile* file, rgbStruct& rgb) const; + void readRGBrow(u8 *buf, int y, int z, io::IReadFile* file, rgbStruct& rgb) const; + void processFile(io::IReadFile *file, rgbStruct& rgb) const; + bool checkFormat(io::IReadFile *file, rgbStruct& rgb) const; + bool readOffsetTables(io::IReadFile* file, rgbStruct& rgb) const; + void converttoARGB(u32* in, const u32 size) const; +}; + +} // end namespace video +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_RGB_LOADER_ +#endif // __C_IMAGE_LOADER_RGB_H_INCLUDED__ diff --git a/src/dep/src/irrlicht/CImageLoaderTGA.cpp b/src/dep/src/irrlicht/CImageLoaderTGA.cpp index be96462..d48b93b 100644 --- a/src/dep/src/irrlicht/CImageLoaderTGA.cpp +++ b/src/dep/src/irrlicht/CImageLoaderTGA.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -21,9 +21,9 @@ namespace video //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderTGA::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderTGA::isALoadableFileExtension(const io::path& filename) const { - return (strstr(fileName, ".tga") != 0) || (strstr(fileName, ".TGA") != 0); + return core::hasFileExtension ( filename, "tga" ); } @@ -96,7 +96,7 @@ bool CImageLoaderTGA::isALoadableFileFormat(io::IReadFile* file) const IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const { STGAHeader header; - u8* colorMap = 0; + u32 *palette = 0; file->read(&header, sizeof(STGAHeader)); @@ -112,16 +112,37 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const if (header.ColorMapType) { + // create 32 bit palette + palette = new u32[ header.ColorMapLength]; + // read color map - colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength]; + u8 * colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength]; file->read(colorMap,header.ColorMapEntrySize/8 * header.ColorMapLength); + + // convert to 32-bit palette + switch ( header.ColorMapEntrySize ) + { + case 16: + CColorConverter::convert_A1R5G5B5toA8R8G8B8(colorMap, header.ColorMapLength, palette); + break; + case 24: + CColorConverter::convert_B8G8R8toA8R8G8B8(colorMap, header.ColorMapLength, palette); + break; + case 32: + CColorConverter::convert_B8G8R8A8toA8R8G8B8(colorMap, header.ColorMapLength, palette); + break; + } + delete [] colorMap; } // read image u8* data = 0; - if (header.ImageType == 2) + if ( header.ImageType == 1 || // Uncompressed, color-mapped images. + header.ImageType == 2 || // Uncompressed, RGB images + header.ImageType == 3 // Uncompressed, black and white images + ) { const s32 imageSize = header.ImageHeight * header.ImageWidth * header.PixelDepth/8; data = new u8[imageSize]; @@ -129,12 +150,14 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const } else if(header.ImageType == 10) + { + // Runlength encoded RGB images data = loadCompressedImage(file, header); + } else { os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR); - if (colorMap) - delete [] colorMap; + delete [] palette; return 0; } @@ -142,32 +165,37 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const switch(header.PixelDepth) { + case 8: + image = new CImage(ECF_A1R5G5B5, + core::dimension2d(header.ImageWidth, header.ImageHeight)); + if (image) + CColorConverter::convert8BitTo16Bit((u8*)data, + (s16*)image->lock(), + header.ImageWidth,header.ImageHeight, + header.ImageType == 3 ? 0 : (s32*) palette, + 0, + (header.ImageDescriptor&0x20)==0); + break; case 16: - { - image = new CImage(ECF_A1R5G5B5, - core::dimension2d(header.ImageWidth, header.ImageHeight)); - if (image) - CColorConverter::convert16BitTo16Bit((s16*)data, - (s16*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0); - } + image = new CImage(ECF_A1R5G5B5, + core::dimension2d(header.ImageWidth, header.ImageHeight)); + if (image) + CColorConverter::convert16BitTo16Bit((s16*)data, + (s16*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0); break; case 24: - { image = new CImage(ECF_R8G8B8, - core::dimension2d(header.ImageWidth, header.ImageHeight)); + core::dimension2d(header.ImageWidth, header.ImageHeight)); if (image) CColorConverter::convert24BitTo24Bit( (u8*)data, (u8*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0, true); - } break; case 32: - { image = new CImage(ECF_A8R8G8B8, - core::dimension2d(header.ImageWidth, header.ImageHeight)); + core::dimension2d(header.ImageWidth, header.ImageHeight)); if (image) CColorConverter::convert32BitTo32Bit((s32*)data, (s32*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0); - } break; default: os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR); @@ -175,15 +203,14 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const } if (image) image->unlock(); + delete [] data; - if (colorMap) - delete [] colorMap; + delete [] palette; return image; } - //! creates a loader which is able to load tgas IImageLoader* createImageLoaderTGA() { diff --git a/src/dep/src/irrlicht/CImageLoaderTGA.h b/src/dep/src/irrlicht/CImageLoaderTGA.h index 2cf5294..2073afd 100644 --- a/src/dep/src/irrlicht/CImageLoaderTGA.h +++ b/src/dep/src/irrlicht/CImageLoaderTGA.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,8 +7,6 @@ #include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_TGA_LOADER_ - #include "IImageLoader.h" @@ -17,9 +15,10 @@ namespace irr namespace video { +#if defined(_IRR_COMPILE_WITH_TGA_LOADER_) || defined(_IRR_COMPILE_WITH_TGA_WRITER_) // byte-align structures -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT @@ -53,12 +52,16 @@ namespace video } PACK_STRUCT; // Default alignment -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #endif #undef PACK_STRUCT +#endif // compiled with loader or reader + +#ifdef _IRR_COMPILE_WITH_TGA_LOADER_ + /*! Surface Loader for targa images */ @@ -68,7 +71,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; @@ -82,10 +85,10 @@ private: u8* loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const; }; +#endif // compiled with loader } // end namespace video } // end namespace irr #endif -#endif diff --git a/src/dep/src/irrlicht/CImageLoaderWAL.cpp b/src/dep/src/irrlicht/CImageLoaderWAL.cpp index ddaa9a0..27963e3 100644 --- a/src/dep/src/irrlicht/CImageLoaderWAL.cpp +++ b/src/dep/src/irrlicht/CImageLoaderWAL.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2004 Murphy McCauley -// Copyright (C) 2007-2008 Christian Stehno +// Copyright (C) 2007-2010 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -51,9 +51,9 @@ s32 CImageLoaderWAL::DefaultPaletteQ2[256] = { }; -bool CImageLoaderWAL::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderWAL::isALoadableFileExtension(const io::path& filename) const { - return strstr(fileName, ".wal") != 0; + return core::hasFileExtension ( filename, "wal" ); } @@ -123,7 +123,7 @@ IImage* CImageLoaderWAL::loadImage(irr::io::IReadFile* file) const IImage* image = 0; image = new CImage(ECF_A1R5G5B5, - core::dimension2d(header.ImageWidth, header.ImageHeight)); + core::dimension2d(header.ImageWidth, header.ImageHeight)); // I wrote an 8 to 32 converter, but this works with released Irrlicht code. CColorConverter::convert8BitTo16Bit(data, diff --git a/src/dep/src/irrlicht/CImageLoaderWAL.h b/src/dep/src/irrlicht/CImageLoaderWAL.h index e22e66b..df9cef5 100644 --- a/src/dep/src/irrlicht/CImageLoaderWAL.h +++ b/src/dep/src/irrlicht/CImageLoaderWAL.h @@ -1,5 +1,5 @@ // Copyright (C) 2004 Murphy McCauley -// Copyright (C) 2007-2008 Christian Stehno +// Copyright (C) 2007-2010 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h /* @@ -13,12 +13,12 @@ #include "IImageLoader.h" -namespace irr +namespace irr { namespace video { -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT @@ -30,7 +30,7 @@ namespace video struct SWALHeader { char FrameName[32]; - + u32 ImageWidth; u32 ImageHeight; @@ -43,7 +43,7 @@ namespace video u32 Value; // light } PACK_STRUCT; -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #endif #undef PACK_STRUCT @@ -52,7 +52,7 @@ namespace video class CImageLoaderWAL : public irr::video::IImageLoader { public: - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const; diff --git a/src/dep/src/irrlicht/CImageWriterBMP.cpp b/src/dep/src/irrlicht/CImageWriterBMP.cpp index 064c1e6..6273731 100644 --- a/src/dep/src/irrlicht/CImageWriterBMP.cpp +++ b/src/dep/src/irrlicht/CImageWriterBMP.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,9 +28,9 @@ CImageWriterBMP::CImageWriterBMP() #endif } -bool CImageWriterBMP::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterBMP::isAWriteableFileExtension(const io::path& filename) const { - return strstr(fileName, ".bmp") != 0; + return core::hasFileExtension ( filename, "bmp" ); } bool CImageWriterBMP::writeImage(io::IWriteFile* file, IImage* image, u32 param) const diff --git a/src/dep/src/irrlicht/CImageWriterBMP.h b/src/dep/src/irrlicht/CImageWriterBMP.h index 3f9deb9..8c36003 100644 --- a/src/dep/src/irrlicht/CImageWriterBMP.h +++ b/src/dep/src/irrlicht/CImageWriterBMP.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,7 +23,7 @@ public: CImageWriterBMP(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/src/dep/src/irrlicht/CImageWriterJPG.cpp b/src/dep/src/irrlicht/CImageWriterJPG.cpp index 3adbc94..a05cdce 100644 --- a/src/dep/src/irrlicht/CImageWriterJPG.cpp +++ b/src/dep/src/irrlicht/CImageWriterJPG.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -72,7 +72,7 @@ static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) static void jpeg_term_destination(j_compress_ptr cinfo) { mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; - const s32 datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + const s32 datacount = (s32)(OUTPUT_BUF_SIZE - dest->pub.free_in_buffer); // for now just exit upon file error if (dest->file->write(dest->buffer, datacount) != datacount) ERREXIT (cinfo, JERR_FILE_WRITE); @@ -127,8 +127,8 @@ static bool writeJPEGFile(io::IWriteFile* file, IImage* image, u32 quality) if ( 0 == format ) return false; - const core::dimension2di dim = image->getDimension(); - + const core::dimension2du dim = image->getDimension(); + struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); @@ -203,10 +203,9 @@ CImageWriterJPG::CImageWriterJPG() } -bool CImageWriterJPG::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterJPG::isAWriteableFileExtension(const io::path& filename) const { - const char* dot = strrchr (fileName, '.'); - return dot && (!strcmp (dot, ".jpg") || !strcmp (dot, ".jpeg")); + return core::hasFileExtension ( filename, "jpg", "jpeg" ); } diff --git a/src/dep/src/irrlicht/CImageWriterJPG.h b/src/dep/src/irrlicht/CImageWriterJPG.h index db4ffa5..0e02d22 100644 --- a/src/dep/src/irrlicht/CImageWriterJPG.h +++ b/src/dep/src/irrlicht/CImageWriterJPG.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,7 +23,7 @@ public: CImageWriterJPG(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/src/dep/src/irrlicht/CImageWriterPCX.cpp b/src/dep/src/irrlicht/CImageWriterPCX.cpp index ff0d3d0..c5489d7 100644 --- a/src/dep/src/irrlicht/CImageWriterPCX.cpp +++ b/src/dep/src/irrlicht/CImageWriterPCX.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,9 +28,9 @@ CImageWriterPCX::CImageWriterPCX() #endif } -bool CImageWriterPCX::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterPCX::isAWriteableFileExtension(const io::path& filename) const { - return strstr(fileName, ".pcx") != 0; + return core::hasFileExtension ( filename, "pcx" ); } bool CImageWriterPCX::writeImage(io::IWriteFile *file, IImage *image,u32 param) const @@ -40,7 +40,7 @@ bool CImageWriterPCX::writeImage(io::IWriteFile *file, IImage *image,u32 param) u8 d1; u16 d2; - s32 i; + u32 i; d1 = 10; // Manufacturer file->write(&d1, 1); @@ -113,7 +113,7 @@ bool CImageWriterPCX::writeImage(io::IWriteFile *file, IImage *image,u32 param) value = 0; for (u32 j=0; j<3; ++j) // color planes { - for (s32 k=0; kgetDimension().Width; ++k) + for (u32 k=0; kgetDimension().Width; ++k) { const SColor pix = image->getPixel(k,i); if ((cnt!=0) && (cnt<63) && diff --git a/src/dep/src/irrlicht/CImageWriterPCX.h b/src/dep/src/irrlicht/CImageWriterPCX.h index 152e7e6..75680ba 100644 --- a/src/dep/src/irrlicht/CImageWriterPCX.h +++ b/src/dep/src/irrlicht/CImageWriterPCX.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,7 +23,7 @@ public: CImageWriterPCX(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/src/dep/src/irrlicht/CImageWriterPNG.cpp b/src/dep/src/irrlicht/CImageWriterPNG.cpp index 4bd80b9..f4a5921 100644 --- a/src/dep/src/irrlicht/CImageWriterPNG.cpp +++ b/src/dep/src/irrlicht/CImageWriterPNG.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -44,7 +44,7 @@ void PNGAPI user_write_data_fcn(png_structp png_ptr, png_bytep data, png_size_t png_size_t check; io::IWriteFile* file=(io::IWriteFile*)png_ptr->io_ptr; - check=(png_size_t) file->write((void*)data,length); + check=(png_size_t) file->write((const void*)data,(u32)length); if (check != length) png_error(png_ptr, "Write Error"); @@ -58,10 +58,10 @@ CImageWriterPNG::CImageWriterPNG() #endif } -bool CImageWriterPNG::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterPNG::isAWriteableFileExtension(const io::path& filename) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ - return strstr(fileName, ".png") != 0; + return core::hasFileExtension ( filename, "png" ); #else return false; #endif @@ -169,7 +169,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) data=tmpImage; // Fill array of pointers to rows in image data - for (s32 i=0; igetDimension().Height; ++i) + for (u32 i=0; igetDimension().Height; ++i) { RowPointers[i]=data; data += lineWidth; diff --git a/src/dep/src/irrlicht/CImageWriterPNG.h b/src/dep/src/irrlicht/CImageWriterPNG.h index 133a59c..046657e 100644 --- a/src/dep/src/irrlicht/CImageWriterPNG.h +++ b/src/dep/src/irrlicht/CImageWriterPNG.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,7 +23,7 @@ public: CImageWriterPNG(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/src/dep/src/irrlicht/CImageWriterPPM.cpp b/src/dep/src/irrlicht/CImageWriterPPM.cpp index 1de1789..7dcf745 100644 --- a/src/dep/src/irrlicht/CImageWriterPPM.cpp +++ b/src/dep/src/irrlicht/CImageWriterPPM.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -31,9 +31,9 @@ CImageWriterPPM::CImageWriterPPM() } -bool CImageWriterPPM::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterPPM::isAWriteableFileExtension(const io::path& filename) const { - return strstr(fileName, ".ppm") != 0; + return core::hasFileExtension ( filename, "ppm" ); } @@ -42,7 +42,7 @@ bool CImageWriterPPM::writeImage(io::IWriteFile *file, IImage *image, u32 param) char cache[70]; int size; - const core::dimension2d& imageSize = image->getDimension(); + const core::dimension2d& imageSize = image->getDimension(); const bool binary = false; @@ -64,9 +64,9 @@ bool CImageWriterPPM::writeImage(io::IWriteFile *file, IImage *image, u32 param) if (binary) { - for (s32 h = 0; h < imageSize.Height; ++h) + for (u32 h = 0; h < imageSize.Height; ++h) { - for (s32 c = 0; c < imageSize.Width; ++c) + for (u32 c = 0; c < imageSize.Width; ++c) { const video::SColor& pixel = image->getPixel(c, h); const u8 r = (u8)(pixel.getRed() & 0xff); @@ -82,12 +82,12 @@ bool CImageWriterPPM::writeImage(io::IWriteFile *file, IImage *image, u32 param) { s32 n = 0; - for (s32 h = 0; h < imageSize.Height; ++h) + for (u32 h = 0; h < imageSize.Height; ++h) { - for (s32 c = 0; c < imageSize.Width; ++c, ++n) + for (u32 c = 0; c < imageSize.Width; ++c, ++n) { const video::SColor& pixel = image->getPixel(c, h); - size = snprintf(cache, 70, "%.3u %.3u %.3u%s", pixel.getRed(), pixel.getGreen(), pixel.getBlue(), n % 5 == 4 ? "\n" : " "); + size = snprintf(cache, 70, "%.3u %.3u %.3u%s", pixel.getRed(), pixel.getGreen(), pixel.getBlue(), n % 5 == 4 ? "\n" : " "); if (file->write(cache, size) != size) return false; } diff --git a/src/dep/src/irrlicht/CImageWriterPPM.h b/src/dep/src/irrlicht/CImageWriterPPM.h index 82a6ce8..d9bd066 100644 --- a/src/dep/src/irrlicht/CImageWriterPPM.h +++ b/src/dep/src/irrlicht/CImageWriterPPM.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,7 +23,7 @@ public: CImageWriterPPM(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/src/dep/src/irrlicht/CImageWriterPSD.cpp b/src/dep/src/irrlicht/CImageWriterPSD.cpp index 42fb419..3fc3c61 100644 --- a/src/dep/src/irrlicht/CImageWriterPSD.cpp +++ b/src/dep/src/irrlicht/CImageWriterPSD.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,9 +28,9 @@ CImageWriterPSD::CImageWriterPSD() #endif } -bool CImageWriterPSD::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterPSD::isAWriteableFileExtension(const io::path& filename) const { - return strstr(fileName, ".psd") != 0; + return core::hasFileExtension ( filename, "psd" ); } bool CImageWriterPSD::writeImage(io::IWriteFile *file, IImage *image,u32 param) const diff --git a/src/dep/src/irrlicht/CImageWriterPSD.h b/src/dep/src/irrlicht/CImageWriterPSD.h index b3cd238..78c98f5 100644 --- a/src/dep/src/irrlicht/CImageWriterPSD.h +++ b/src/dep/src/irrlicht/CImageWriterPSD.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,7 +23,7 @@ public: CImageWriterPSD(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image,u32 param) const; diff --git a/src/dep/src/irrlicht/CImageWriterTGA.cpp b/src/dep/src/irrlicht/CImageWriterTGA.cpp index da6d94f..ebc6b7d 100644 --- a/src/dep/src/irrlicht/CImageWriterTGA.cpp +++ b/src/dep/src/irrlicht/CImageWriterTGA.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,9 +28,9 @@ CImageWriterTGA::CImageWriterTGA() #endif } -bool CImageWriterTGA::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterTGA::isAWriteableFileExtension(const io::path& filename) const { - return strstr(fileName, ".tga") != 0; + return core::hasFileExtension ( filename, "tga" ); } bool CImageWriterTGA::writeImage(io::IWriteFile *file, IImage *image,u32 param) const diff --git a/src/dep/src/irrlicht/CImageWriterTGA.h b/src/dep/src/irrlicht/CImageWriterTGA.h index 983b8ef..b78e273 100644 --- a/src/dep/src/irrlicht/CImageWriterTGA.h +++ b/src/dep/src/irrlicht/CImageWriterTGA.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,7 +23,7 @@ public: CImageWriterTGA(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image,u32 param) const; diff --git a/src/dep/src/irrlicht/CIrrDeviceConsole.cpp b/src/dep/src/irrlicht/CIrrDeviceConsole.cpp new file mode 100644 index 0000000..8493df8 --- /dev/null +++ b/src/dep/src/irrlicht/CIrrDeviceConsole.cpp @@ -0,0 +1,474 @@ +// Copyright (C) 2009-2010 Gaz Davidson +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CIrrDeviceConsole.h" + +#ifdef _IRR_COMPILE_WITH_CONSOLE_DEVICE_ + +#include "os.h" +#include "IGUISkin.h" +#include "IGUIEnvironment.h" + +// to close the device on terminate signal +irr::CIrrDeviceConsole *DeviceToClose; + +#ifdef _IRR_WINDOWS_NT_CONSOLE_ +// Callback for Windows +BOOL WINAPI ConsoleHandler(DWORD CEvent) +{ + switch(CEvent) + { + case CTRL_C_EVENT: + irr::os::Printer::log("Closing console device", "CTRL+C"); + break; + case CTRL_BREAK_EVENT: + irr::os::Printer::log("Closing console device", "CTRL+Break"); + break; + case CTRL_CLOSE_EVENT: + irr::os::Printer::log("Closing console device", "User closed console"); + break; + case CTRL_LOGOFF_EVENT: + irr::os::Printer::log("Closing console device", "User is logging off"); + break; + case CTRL_SHUTDOWN_EVENT: + irr::os::Printer::log("Closing console device", "Computer shutting down"); + break; + } + DeviceToClose->closeDevice(); + return TRUE; +} +#elif defined(_IRR_POSIX_API_) +// sigterm handler +#include + +void sighandler(int sig) +{ + irr::core::stringc code = "Signal "; + code += sig; + code += " received"; + irr::os::Printer::log("Closing console device", code.c_str()); + + DeviceToClose->closeDevice(); +} +#endif + +namespace irr +{ + +const c8 ASCIIArtChars[] = " .,'~:;!+>=icopjtJY56SB8XDQKHNWM"; //MWNHKQDX8BS65YJtjpoci=+>!;:~',. "; +const u16 ASCIIArtCharsCount = 32; + +//const c8 ASCIIArtChars[] = " \xb0\xb1\xf9\xb2\xdb"; +//const u16 ASCIIArtCharsCount = 5; + +//! constructor +CIrrDeviceConsole::CIrrDeviceConsole(const SIrrlichtCreationParameters& params) + : CIrrDeviceStub(params), IsWindowFocused(true), ConsoleFont(0), OutFile(stdout) +{ + DeviceToClose = this; + +#ifdef _IRR_WINDOWS_NT_CONSOLE_ + MouseButtonStates = 0; + + WindowsSTDIn = GetStdHandle(STD_INPUT_HANDLE); + WindowsSTDOut = GetStdHandle(STD_OUTPUT_HANDLE); + PCOORD Dimensions = 0; + + if (CreationParams.Fullscreen) + { + if (SetConsoleDisplayMode(WindowsSTDOut, CONSOLE_FULLSCREEN_MODE, Dimensions)) + { + CreationParams.WindowSize.Width = Dimensions->X; + CreationParams.WindowSize.Width = Dimensions->Y; + } + } + else + { + COORD ConsoleSize; + ConsoleSize.X = CreationParams.WindowSize.Width; + ConsoleSize.X = CreationParams.WindowSize.Height; + SetConsoleScreenBufferSize(WindowsSTDOut, ConsoleSize); + } + + // catch windows close/break signals + SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE); + +#elif defined(_IRR_POSIX_API_) + // catch other signals + signal(SIGABRT, &sighandler); + signal(SIGTERM, &sighandler); + signal(SIGINT, &sighandler); + + // set output stream + if (params.WindowId) + OutFile = (FILE*)(params.WindowId); +#endif + +#ifdef _IRR_VT100_CONSOLE_ + // reset terminal + fprintf(OutFile, "%cc", 27); + // disable line wrapping + fprintf(OutFile, "%c[7l", 27); +#endif + + switch (params.DriverType) + { + case video::EDT_SOFTWARE: + #ifdef _IRR_COMPILE_WITH_SOFTWARE_ + VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); + #else + os::Printer::log("Software driver was not compiled in.", ELL_ERROR); + #endif + break; + + case video::EDT_BURNINGSVIDEO: + #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + VideoDriver = video::createSoftwareDriver2(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); + #else + os::Printer::log("Burning's Video driver was not compiled in.", ELL_ERROR); + #endif + break; + + case video::EDT_DIRECT3D8: + case video::EDT_DIRECT3D9: + case video::EDT_OPENGL: + os::Printer::log("The console device cannot use hardware drivers yet.", ELL_ERROR); + break; + case video::EDT_NULL: + VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); + break; + default: + break; + } + + // set up output buffer + for (u32 y=0; ygetSkin(); + if (skin) + { + for (u32 i=0; i < gui::EGDF_COUNT; ++i) + skin->setFont(ConsoleFont, gui::EGUI_DEFAULT_FONT(i)); + } + } +#endif + } +} + +//! destructor +CIrrDeviceConsole::~CIrrDeviceConsole() +{ + // GUI and scene are dropped in the stub + if (CursorControl) + { + CursorControl->drop(); + CursorControl = 0; + } + if (ConsoleFont) + { + ConsoleFont->drop(); + ConsoleFont = 0; + } +#ifdef _IRR_VT100_CONSOLE_ + // reset terminal + fprintf(OutFile, "%cc", 27); +#endif +} + +//! runs the device. Returns false if device wants to be deleted +bool CIrrDeviceConsole::run() +{ + // increment timer + os::Timer::tick(); + + // process Windows console input +#ifdef _IRR_WINDOWS_NT_CONSOLE_ + + INPUT_RECORD in; + DWORD oldMode; + DWORD count, waste; + + // get old input mode + GetConsoleMode(WindowsSTDIn, &oldMode); + SetConsoleMode(WindowsSTDIn, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT); + + GetNumberOfConsoleInputEvents(WindowsSTDIn, &count); + + // read keyboard and mouse input + while (count) + { + ReadConsoleInput(WindowsSTDIn, &in, 1, &waste ); + switch(in.EventType) + { + case KEY_EVENT: + { + SEvent e; + e.EventType = EET_KEY_INPUT_EVENT; + e.KeyInput.PressedDown = (in.Event.KeyEvent.bKeyDown == TRUE); + e.KeyInput.Control = (in.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0; + e.KeyInput.Shift = (in.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) != 0; + e.KeyInput.Key = EKEY_CODE(in.Event.KeyEvent.wVirtualKeyCode); + e.KeyInput.Char = in.Event.KeyEvent.uChar.UnicodeChar; + postEventFromUser(e); + break; + } + case MOUSE_EVENT: + { + SEvent e; + e.EventType = EET_MOUSE_INPUT_EVENT; + e.MouseInput.X = in.Event.MouseEvent.dwMousePosition.X; + e.MouseInput.Y = in.Event.MouseEvent.dwMousePosition.Y; + e.MouseInput.Wheel = 0.f; + e.MouseInput.ButtonStates = + ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) ? EMBSM_LEFT : 0 ) | + ( (in.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED) ? EMBSM_RIGHT : 0 ) | + ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) ? EMBSM_MIDDLE : 0 ) | + ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_3RD_BUTTON_PRESSED) ? EMBSM_EXTRA1 : 0 ) | + ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_4TH_BUTTON_PRESSED) ? EMBSM_EXTRA2 : 0 ); + + if (in.Event.MouseEvent.dwEventFlags & MOUSE_MOVED) + { + CursorControl->setPosition(core::position2di(e.MouseInput.X, e.MouseInput.Y)); + + // create mouse moved event + e.MouseInput.Event = EMIE_MOUSE_MOVED; + postEventFromUser(e); + } + + if (in.Event.MouseEvent.dwEventFlags & MOUSE_WHEELED) + { + e.MouseInput.Event = EMIE_MOUSE_WHEEL; + e.MouseInput.Wheel = (in.Event.MouseEvent.dwButtonState & 0xFF000000) ? -1.0f : 1.0f; + postEventFromUser(e); + } + + if ( (MouseButtonStates & EMBSM_LEFT) != (e.MouseInput.ButtonStates & EMBSM_LEFT) ) + { + e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_LEFT) ? EMIE_LMOUSE_PRESSED_DOWN : EMIE_LMOUSE_LEFT_UP; + postEventFromUser(e); + } + + if ( (MouseButtonStates & EMBSM_RIGHT) != (e.MouseInput.ButtonStates & EMBSM_RIGHT) ) + { + e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_RIGHT) ? EMIE_RMOUSE_PRESSED_DOWN : EMIE_RMOUSE_LEFT_UP; + postEventFromUser(e); + } + + if ( (MouseButtonStates & EMBSM_MIDDLE) != (e.MouseInput.ButtonStates & EMBSM_MIDDLE) ) + { + e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_MIDDLE) ? EMIE_MMOUSE_PRESSED_DOWN : EMIE_MMOUSE_LEFT_UP; + postEventFromUser(e); + } + + // save current button states + MouseButtonStates = e.MouseInput.ButtonStates; + + break; + } + case WINDOW_BUFFER_SIZE_EVENT: + VideoDriver->OnResize( + core::dimension2d(in.Event.WindowBufferSizeEvent.dwSize.X, + in.Event.WindowBufferSizeEvent.dwSize.Y)); + break; + case FOCUS_EVENT: + IsWindowFocused = (in.Event.FocusEvent.bSetFocus == TRUE); + break; + default: + break; + } + GetNumberOfConsoleInputEvents(WindowsSTDIn, &count); + } + + // set input mode + SetConsoleMode(WindowsSTDIn, oldMode); +#else + // todo: keyboard input from terminal in raw mode +#endif + + return !Close; +} + +//! Cause the device to temporarily pause execution and let other processes to run +// This should bring down processor usage without major performance loss for Irrlicht +void CIrrDeviceConsole::yield() +{ +#ifdef _IRR_WINDOWS_API_ + Sleep(1); +#else + struct timespec ts = {0,0}; + nanosleep(&ts, NULL); +#endif +} + +//! Pause execution and let other processes to run for a specified amount of time. +void CIrrDeviceConsole::sleep(u32 timeMs, bool pauseTimer) +{ + const bool wasStopped = Timer ? Timer->isStopped() : true; + +#ifdef _IRR_WINDOWS_API_ + Sleep(timeMs); +#else + struct timespec ts; + ts.tv_sec = (time_t) (timeMs / 1000); + ts.tv_nsec = (long) (timeMs % 1000) * 1000000; + + if (pauseTimer && !wasStopped) + Timer->stop(); + + nanosleep(&ts, NULL); +#endif + + if (pauseTimer && !wasStopped) + Timer->start(); +} + +//! sets the caption of the window +void CIrrDeviceConsole::setWindowCaption(const wchar_t* text) +{ +#ifdef _IRR_WINDOWS_NT_CONSOLE_ + SetConsoleTitleW(text); +#endif +} + +//! returns if window is active. if not, nothing need to be drawn +bool CIrrDeviceConsole::isWindowActive() const +{ + // there is no window, but we always assume it is active + return true; +} + +//! returns if window has focus +bool CIrrDeviceConsole::isWindowFocused() const +{ + return IsWindowFocused; +} + +//! returns if window is minimized +bool CIrrDeviceConsole::isWindowMinimized() const +{ + return false; +} + +//! presents a surface in the client area +bool CIrrDeviceConsole::present(video::IImage* surface, void* windowId, core::rect* src) +{ + + if (surface) + { + for (u32 y=0; y < surface->getDimension().Height; ++y) + { + for (u32 x=0; x< surface->getDimension().Width; ++x) + { + // get average pixel + u32 avg = surface->getPixel(x,y).getAverage() * (ASCIIArtCharsCount-1); + avg /= 255; + OutputBuffer[y] [x] = ASCIIArtChars[avg]; + } + } + } +#ifdef _IRR_USE_CONSOLE_FONT_ + for (u32 i=0; i< Text.size(); ++i) + { + s32 y = Text[i].Pos.Y; + + if ( y < (s32)OutputBuffer.size() && y > 0) + for (u32 c=0; c < Text[i].Text.size() && c + Text[i].Pos.X < OutputBuffer[y].size(); ++c) + //if (Text[i].Text[c] != ' ') + OutputBuffer[y] [c+Text[i].Pos.X] = Text[i].Text[c]; + } + Text.clear(); +#endif + + // draw output + for (u32 y=0; y +#endif +#if(_WIN32_WINNT >= 0x0500) +#define _IRR_WINDOWS_NT_CONSOLE_ +#endif +#else +#include +#endif + +// for now we assume all other terminal types are VT100 +#ifndef _IRR_WINDOWS_NT_CONSOLE_ +#define _IRR_VT100_CONSOLE_ +#endif + +namespace irr +{ + + class CIrrDeviceConsole : public CIrrDeviceStub, video::IImagePresenter + { + public: + + //! constructor + CIrrDeviceConsole(const SIrrlichtCreationParameters& params); + + //! destructor + virtual ~CIrrDeviceConsole(); + + //! runs the device. Returns false if device wants to be deleted + virtual bool run(); + + //! Cause the device to temporarily pause execution and let other processes to run + // This should bring down processor usage without major performance loss for Irrlicht + virtual void yield(); + + //! Pause execution and let other processes to run for a specified amount of time. + virtual void sleep(u32 timeMs, bool pauseTimer); + + //! sets the caption of the window + virtual void setWindowCaption(const wchar_t* text); + + //! returns if window is active. if not, nothing need to be drawn + virtual bool isWindowActive() const; + + //! returns if window has focus + virtual bool isWindowFocused() const; + + //! returns if window is minimized + virtual bool isWindowMinimized() const; + + //! presents a surface in the client area + virtual bool present(video::IImage* surface, void* windowId=0, core::rect* src=0); + + //! notifies the device that it should close itself + virtual void closeDevice(); + + //! Sets if the window should be resizable in windowed mode. + virtual void setResizable(bool resize=false); + + //! Minimizes the window. + virtual void minimizeWindow(); + + //! Maximizes the window. + virtual void maximizeWindow(); + + //! Restores the window size. + virtual void restoreWindow(); + + //! Get the device type + virtual E_DEVICE_TYPE getType() const + { + return EIDT_CONSOLE; + } + + void addPostPresentText(s16 X, s16 Y, const wchar_t *text); + + //! Implementation of the win32 console mouse cursor + class CCursorControl : public gui::ICursorControl + { + public: + + CCursorControl(const core::dimension2d& wsize) + : WindowSize(wsize), InvWindowSize(0.0f, 0.0f), IsVisible(true), UseReferenceRect(false) + { + if (WindowSize.Width!=0) + InvWindowSize.Width = 1.0f / WindowSize.Width; + + if (WindowSize.Height!=0) + InvWindowSize.Height = 1.0f / WindowSize.Height; + } + + //! Changes the visible state of the mouse cursor. + virtual void setVisible(bool visible) + { + if(visible != IsVisible) + { + IsVisible = visible; + setPosition(CursorPos.X, CursorPos.Y); + } + } + + //! Returns if the cursor is currently visible. + virtual bool isVisible() const + { + return IsVisible; + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(f32 x, f32 y) + { + if (!UseReferenceRect) + setPosition((s32)(x*WindowSize.Width), (s32)(y*WindowSize.Height)); + else + setPosition((s32)(x*ReferenceRect.getWidth()), (s32)(y*ReferenceRect.getHeight())); + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(s32 x, s32 y) + { + setInternalCursorPosition(core::position2di(x,y)); + } + + //! Returns the current position of the mouse cursor. + virtual const core::position2d& getPosition() + { + return CursorPos; + } + + //! Returns the current position of the mouse cursor. + virtual core::position2d getRelativePosition() + { + if (!UseReferenceRect) + { + return core::position2d(CursorPos.X * InvWindowSize.Width, + CursorPos.Y * InvWindowSize.Height); + } + + return core::position2d(CursorPos.X / (f32)ReferenceRect.getWidth(), + CursorPos.Y / (f32)ReferenceRect.getHeight()); + } + + //! Sets an absolute reference rect for calculating the cursor position. + virtual void setReferenceRect(core::rect* rect=0) + { + if (rect) + { + ReferenceRect = *rect; + UseReferenceRect = true; + + // prevent division through zero and uneven sizes + + if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2) + ReferenceRect.LowerRightCorner.Y += 1; + + if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2) + ReferenceRect.LowerRightCorner.X += 1; + } + else + UseReferenceRect = false; + } + + + //! Updates the internal cursor position + void setInternalCursorPosition(const core::position2di &pos) + { + CursorPos = pos; + + if (UseReferenceRect) + CursorPos -= ReferenceRect.UpperLeftCorner; + } + + private: + + core::position2d CursorPos; + core::dimension2d WindowSize; + core::dimension2d InvWindowSize; + bool IsVisible, + UseReferenceRect; + core::rect ReferenceRect; + }; + + private: + + //! Set the position of the text caret + void setTextCursorPos(s16 x, s16 y); + + // text to be added after drawing the screen + struct SPostPresentText + { + core::position2d Pos; + core::stringc Text; + }; + + bool IsWindowFocused; + + core::array OutputBuffer; + gui::IGUIFont *ConsoleFont; + core::array Text; + + FILE *OutFile; + +#ifdef _IRR_WINDOWS_NT_CONSOLE_ + HANDLE WindowsSTDIn, WindowsSTDOut; + u32 MouseButtonStates; +#endif + }; + +#ifdef _IRR_USE_CONSOLE_FONT_ + +namespace gui +{ + class CGUIConsoleFont : public IGUIFont + { + public: + + CGUIConsoleFont(CIrrDeviceConsole* device) : Device(device) { } + + //! Draws some text and clips it to the specified rectangle if wanted. + virtual void draw(const wchar_t* text, const core::rect& position, + video::SColor color, bool hcenter=false, bool vcenter=false, + const core::rect* clip=0) + { + core::rect Area = clip ? *clip : position; + + if (Area.UpperLeftCorner.X < 0) + Area.UpperLeftCorner.X = 0; + + if (Area.UpperLeftCorner.Y < 0) + Area.UpperLeftCorner.Y = 0; + + core::position2d pos; + + // centre vertically + pos.Y = vcenter ? (position.UpperLeftCorner.Y + position.LowerRightCorner.Y) / 2 : position.UpperLeftCorner.Y; + + // nothing to display? + if (pos.Y < Area.UpperLeftCorner.Y || pos.Y > Area.LowerRightCorner.Y) + return; + + tempText = text; + + // centre horizontally + pos.X = hcenter ? position.getCenter().X - ( tempText.size() / 2) : position.UpperLeftCorner.X; + + // clip + u32 xlclip = 0, + xrclip = 0; + + // get right clip + if (pos.X + (s32)tempText.size() > Area.LowerRightCorner.X) + xrclip = Area.LowerRightCorner.X - pos.X; + + // get left clip + if (pos.X < Area.UpperLeftCorner.X) + xlclip = Area.UpperLeftCorner.X - pos.X; + + // totally clipped? + if ((s32)tempText.size() - xlclip - xrclip < 0) + return; + + // null terminate the string + if (xrclip > 0) + tempText[xrclip] = L'\0'; + + Device->addPostPresentText(pos.X + xlclip, pos.Y, &(tempText.c_str()[xlclip])); + } + + //! Calculates the dimension of some text. + virtual core::dimension2d getDimension(const wchar_t* text) const + { + return core::dimension2d(wcslen(text),1); + } + + //! Calculates the index of the character in the text which is on a specific position. + virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const { return pixel_x; }; + + //! No kerning + virtual void setKerningWidth (s32 kerning) { } + virtual void setKerningHeight (s32 kerning) { } + virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const {return 0;} + virtual s32 getKerningHeight() const { return 0;} + virtual void setInvisibleCharacters( const wchar_t *s ) { } + // I guess this is an OS specific font + virtual EGUI_FONT_TYPE getType() const { return EGFT_OS; } + private: + CIrrDeviceConsole* Device; + core::stringw tempText; + }; + +} // end namespace gui + +#endif // _IRR_USE_CONSOLE_FONT_ + +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_CONSOLE_DEVICE_ +#endif // __C_IRR_DEVICE_CONSOLE_H_INCLUDED__ + diff --git a/src/dep/src/irrlicht/CIrrDeviceFB.cpp b/src/dep/src/irrlicht/CIrrDeviceFB.cpp new file mode 100644 index 0000000..a541e9b --- /dev/null +++ b/src/dep/src/irrlicht/CIrrDeviceFB.cpp @@ -0,0 +1,405 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// Copyright (C) 2007-2010 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CIrrDeviceFB.h" + +#ifdef _IRR_COMPILE_WITH_FB_DEVICE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "IEventReceiver.h" +#include "os.h" +#include "CTimer.h" +#include "irrString.h" +#include "Keycodes.h" +#include "COSOperator.h" +#include "CColorConverter.h" +#include "SIrrCreationParameters.h" + +#include + +namespace irr +{ + +//! constructor +CIrrDeviceFB::CIrrDeviceFB(const SIrrlichtCreationParameters& params) + : CIrrDeviceStub(params), Framebuffer(-1), EventDevice(-1), SoftwareImage(0), + Pitch(0), FBColorFormat(video::ECF_A8R8G8B8), Close(false) +{ + #ifdef _DEBUG + setDebugName("CIrrDeviceFB"); + #endif + + // print version, distribution etc. + // thx to LynxLuna for pointing me to the uname function + core::stringc linuxversion; + struct utsname FBInfo; + uname(&FBInfo); + + linuxversion += FBInfo.sysname; + linuxversion += " "; + linuxversion += FBInfo.release; + linuxversion += " "; + linuxversion += FBInfo.version; + linuxversion += " "; + linuxversion += FBInfo.machine; + + Operator = new COSOperator(linuxversion.c_str()); + os::Printer::log(linuxversion.c_str(), ELL_INFORMATION); + + // create window + if (params.DriverType != video::EDT_NULL) + { + // create the window, only if we do not use the null device + if (!createWindow(params.WindowSize, params.Bits)) + return; + } + + // create cursor control + CursorControl = new CCursorControl(this, params.DriverType == video::EDT_NULL); + + // create driver + createDriver(); + + if (!VideoDriver) + return; + + createGUIAndScene(); +} + + + +//! destructor +CIrrDeviceFB::~CIrrDeviceFB() +{ + if (SoftwareImage) + munmap(SoftwareImage, CreationParams.WindowSize.Height*Pitch); + // go back to previous format + if (ioctl(Framebuffer, FBIOPUT_VSCREENINFO, &oldscreeninfo) <0) + perror("Restoring old fb mode"); + + if (KeyboardDevice != -1) + if (ioctl(KeyboardDevice, KDSETMODE, &KeyboardMode) <0) + perror("Restoring keyboard mode"); + if (EventDevice != -1) + close(EventDevice); + if (KeyboardDevice != -1) + close(KeyboardDevice); + if (Framebuffer != -1) + close(Framebuffer); +} + + +bool CIrrDeviceFB::createWindow(const core::dimension2d& windowSize, u32 bits) +{ + char buf[256]; + CreationParams.WindowSize.Width = windowSize.Width; + CreationParams.WindowSize.Height = windowSize.Height; + + KeyboardDevice = open("/dev/tty", O_RDWR); + if (KeyboardDevice == -1) + perror("Open keyboard"); + if (ioctl(KeyboardDevice, KDGETMODE, &KeyboardMode) <0) + perror("Read keyboard mode"); + if (ioctl(KeyboardDevice, KDSETMODE, KD_GRAPHICS) <0) + perror("Set keyboard mode"); + + Framebuffer=open("/dev/fb/0", O_RDWR); + if (Framebuffer == -1) + { + Framebuffer=open("/dev/fb0", O_RDWR); + if (Framebuffer == -1) + { + perror("Open framebuffer"); + return false; + } + } + EventDevice = open("/dev/input/event0", O_RDONLY | O_NONBLOCK); + if (EventDevice == -1) + perror("Open event device"); + + // make format settings + ioctl(Framebuffer, FBIOGET_FSCREENINFO, &fbfixscreeninfo); + ioctl(Framebuffer, FBIOGET_VSCREENINFO, &oldscreeninfo); +snprintf(buf, 256, "Original resolution: %d x %d\nARGB%d%d%d%d\n",oldscreeninfo.xres,oldscreeninfo.yres, + oldscreeninfo.transp.length,oldscreeninfo.red.length,oldscreeninfo.green.length,oldscreeninfo.blue.length); + os::Printer::log(buf); + memcpy(&fbscreeninfo, &oldscreeninfo, sizeof(struct fb_var_screeninfo)); + if (CreationParams.DriverType != video::EDT_NULL) + { + fbscreeninfo.xres = fbscreeninfo.xres_virtual = CreationParams.WindowSize.Width; + fbscreeninfo.yres = fbscreeninfo.yres_virtual = CreationParams.WindowSize.Height; + fbscreeninfo.bits_per_pixel = 16; + fbscreeninfo.red.offset = 10; + fbscreeninfo.red.length = 5; + fbscreeninfo.green.offset = 5; + fbscreeninfo.green.length = 5; + fbscreeninfo.blue.offset = 0; + fbscreeninfo.blue.length = 5; + fbscreeninfo.transp.offset = 15; + fbscreeninfo.transp.length = 1; + ioctl(Framebuffer, FBIOPUT_VSCREENINFO, &fbscreeninfo); + ioctl(Framebuffer, FBIOGET_VSCREENINFO, &fbscreeninfo); + +snprintf(buf, 256, "New resolution: %d x %d (%d x %d)\nARGB%d%d%d%d\n",fbscreeninfo.xres,fbscreeninfo.yres,fbscreeninfo.xres_virtual,fbscreeninfo.yres_virtual, + fbscreeninfo.transp.length,fbscreeninfo.red.length,fbscreeninfo.green.length,fbscreeninfo.blue.length); + os::Printer::log(buf); + + CreationParams.WindowSize.Width = fbscreeninfo.xres; + CreationParams.WindowSize.Height = fbscreeninfo.yres; + CreationParams.Bits = fbscreeninfo.bits_per_pixel; + Pitch = fbfixscreeninfo.line_length; + if (fbscreeninfo.bits_per_pixel == 16) + { + if (fbscreeninfo.transp.length == 0) + FBColorFormat = video::ECF_R5G6B5; + else + FBColorFormat = video::ECF_A1R5G5B5; + } + else + { + if (fbscreeninfo.transp.length == 0) + FBColorFormat = video::ECF_R8G8B8; + else + FBColorFormat = video::ECF_A8R8G8B8; + } + if (MAP_FAILED==(SoftwareImage=(u8*)mmap(0, CreationParams.WindowSize.Height*Pitch, PROT_READ|PROT_WRITE, MAP_SHARED, Framebuffer, 0))) + { + perror("mmap render target"); + return false; + } + } + return true; +} + + +//! create the driver +void CIrrDeviceFB::createDriver() +{ + switch(CreationParams.DriverType) + { + case video::EDT_SOFTWARE: + #ifdef _IRR_COMPILE_WITH_SOFTWARE_ + VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); + #else + os::Printer::log("No Software driver support compiled in.", ELL_WARNING); + #endif + break; + + case video::EDT_BURNINGSVIDEO: + #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + VideoDriver = video::createSoftwareDriver2(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); + #else + os::Printer::log("Burning's video driver was not compiled in.", ELL_WARNING); + #endif + break; + + case video::EDT_OPENGL: + case video::EDT_DIRECT3D8: + case video::EDT_DIRECT3D9: + os::Printer::log("This driver is not available in FB. Try Software renderer.", + ELL_WARNING); + break; + + default: + VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); + break; + } +} + + +//! runs the device. Returns false if device wants to be deleted +bool CIrrDeviceFB::run() +{ + os::Timer::tick(); + + struct input_event ev; + if (EventDevice>=0) + { + if ((read(EventDevice, &ev, sizeof(input_event)) < 0) && + errno != EAGAIN) + perror("Read input event"); + if (ev.type == EV_KEY) + { + irr::SEvent irrevent; + irrevent.EventType = irr::EET_KEY_INPUT_EVENT; + irrevent.KeyInput.PressedDown = true; + + switch (ev.code) + { + case KEY_RIGHTCTRL: + case KEY_LEFTCTRL: + irrevent.KeyInput.Control = true; + break; + case KEY_RIGHTSHIFT: + case KEY_LEFTSHIFT: + irrevent.KeyInput.Shift = true; + break; + case KEY_ESC: + irrevent.KeyInput.Key = (EKEY_CODE)0x1B; + break; + case KEY_SPACE: + irrevent.KeyInput.Key = (EKEY_CODE)0x20; + break; + case KEY_UP: + irrevent.KeyInput.Key = (EKEY_CODE)0x26; + break; + case KEY_LEFT: + irrevent.KeyInput.Key = (EKEY_CODE)0x25; + break; + case KEY_RIGHT: + irrevent.KeyInput.Key = (EKEY_CODE)0x27; + break; + case KEY_DOWN: + irrevent.KeyInput.Key = (EKEY_CODE)0x28; + break; + default: + irrevent.KeyInput.Key = (EKEY_CODE)0; + break; + } + postEventFromUser(irrevent); + } + } + + return !Close; +} + + +//! Pause the current process for the minimum time allowed only to allow other processes to execute +void CIrrDeviceFB::yield() +{ + struct timespec ts = {0,0}; + nanosleep(&ts, NULL); +} + + +//! Pause execution and let other processes to run for a specified amount of time. +void CIrrDeviceFB::sleep(u32 timeMs, bool pauseTimer=false) +{ + bool wasStopped = Timer ? Timer->isStopped() : true; + + struct timespec ts; + ts.tv_sec = (time_t) (timeMs / 1000); + ts.tv_nsec = (long) (timeMs % 1000) * 1000000; + + if (pauseTimer && !wasStopped) + Timer->stop(); + + nanosleep(&ts, NULL); + + if (pauseTimer && !wasStopped) + Timer->start(); +} + + +//! presents a surface in the client area +bool CIrrDeviceFB::present(video::IImage* image, void* windowId, core::rect* src ) +{ + // this is only necessary for software drivers. + if (CreationParams.DriverType != video::EDT_SOFTWARE && CreationParams.DriverType != video::EDT_BURNINGSVIDEO) + return false; + + if (!SoftwareImage) + return false; + + u8* destData = SoftwareImage; + u32 srcwidth = (u32)image->getDimension().Width; + u32 srcheight = (u32)image->getDimension().Height; + // clip images + srcheight = core::min_(srcheight, CreationParams.WindowSize.Height); + srcwidth = core::min_(srcwidth, CreationParams.WindowSize.Width); + + u8* srcdata = (u8*)image->lock(); + for (u32 y=0; ygetColorFormat(), srcwidth, destData, FBColorFormat); + srcdata+=image->getPitch(); + destData+=Pitch; + } + image->unlock(); + msync(SoftwareImage,CreationParams.WindowSize.Width*CreationParams.WindowSize.Height,MS_ASYNC); + return true; +} + + +//! notifies the device that it should close itself +void CIrrDeviceFB::closeDevice() +{ + Close = true; +} + + +//! returns if window is active. if not, nothing need to be drawn +bool CIrrDeviceFB::isWindowActive() const +{ + return true; +} + + +//! returns if window has focus +bool CIrrDeviceFB::isWindowFocused() const +{ + return true; +} + + +//! returns if window is minimized +bool CIrrDeviceFB::isWindowMinimized() const +{ + return false; +} + + +//! sets the caption of the window +void CIrrDeviceFB::setWindowCaption(const wchar_t* text) +{ +} + + +//! Sets if the window should be resizeable in windowed mode. +void CIrrDeviceFB::setResizable(bool resize) +{ +} + + +//! Minimizes window +void CIrrDeviceFB::minimizeWindow() +{ +} + + +//! Maximizes window +void CIrrDeviceFB::maximizeWindow() +{ +} + + +//! Restores original window size +void CIrrDeviceFB::restoreWindow() +{ +} + + +//! Returns the type of this device +E_DEVICE_TYPE CIrrDeviceFB::getType() const +{ + return EIDT_FRAMEBUFFER; +} + + +} // end namespace irr + +#endif // _IRR_USE_FB_DEVICE_ + diff --git a/src/dep/src/irrlicht/CIrrDeviceFB.h b/src/dep/src/irrlicht/CIrrDeviceFB.h new file mode 100644 index 0000000..0c3b81f --- /dev/null +++ b/src/dep/src/irrlicht/CIrrDeviceFB.h @@ -0,0 +1,207 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// Copyright (C) 2007-2010 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_IRR_DEVICE_FB_H_INCLUDED__ +#define __C_IRR_DEVICE_FB_H_INCLUDED__ + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_FB_DEVICE_ + +#include "CIrrDeviceStub.h" +#include "SIrrCreationParameters.h" +#include "IrrlichtDevice.h" +#include "IImagePresenter.h" +#include "ICursorControl.h" + +#define KeySym s32 +#include +#include + +namespace irr +{ + class CIrrDeviceFB : public CIrrDeviceStub, public video::IImagePresenter + { + public: + + //! constructor + CIrrDeviceFB(const SIrrlichtCreationParameters& params); + + //! destructor + virtual ~CIrrDeviceFB(); + + //! runs the device. Returns false if device wants to be deleted + virtual bool run(); + + //! Cause the device to temporarily pause execution and let other processes to run + // This should bring down processor usage without major performance loss for Irrlicht + virtual void yield(); + + //! Pause execution and let other processes to run for a specified amount of time. + virtual void sleep(u32 timeMs, bool pauseTimer); + + //! sets the caption of the window + virtual void setWindowCaption(const wchar_t* text); + + //! returns if window is active. if not, nothing need to be drawn + virtual bool isWindowActive() const; + + //! returns if window has focus + virtual bool isWindowFocused() const; + + //! returns if window is minimized + virtual bool isWindowMinimized() const; + + //! Minimizes window + virtual void minimizeWindow(); + + //! Maximizes window + virtual void maximizeWindow(); + + //! Restores original window size + virtual void restoreWindow(); + + //! presents a surface in the client area + virtual bool present(video::IImage* surface, void* windowId = 0, core::rect* src=0 ); + + //! notifies the device that it should close itself + virtual void closeDevice(); + + //! Sets if the window should be resizeable in windowed mode. + virtual void setResizable(bool resize=false); + + //! Returns the type of this device + virtual E_DEVICE_TYPE getType() const; + + private: + + //! create the driver + void createDriver(); + + bool createWindow(const core::dimension2d& windowSize, u32 bits); + + //! Implementation of the cursor control + class CCursorControl : public gui::ICursorControl + { + public: + + CCursorControl(CIrrDeviceFB* dev, bool null) + : Device(dev), IsVisible(true), Null(null) + { + Device->grab(); + } + + ~CCursorControl() + { + Device->drop(); + } + + //! Changes the visible state of the mouse cursor. + virtual void setVisible(bool visible) + { + IsVisible = visible; + } + + //! Returns if the cursor is currently visible. + virtual bool isVisible() const + { + return IsVisible; + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(f32 x, f32 y) + { + setPosition((s32)(x*Device->CreationParams.WindowSize.Width), (s32)(y*Device->CreationParams.WindowSize.Height)); + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(s32 x, s32 y) + { + } + + //! Returns the current position of the mouse cursor. + virtual const core::position2d& getPosition() + { + updateCursorPos(); + return CursorPos; + } + + //! Returns the current position of the mouse cursor. + virtual core::position2d getRelativePosition() + { + updateCursorPos(); + return core::position2d(CursorPos.X / (f32)Device->CreationParams.WindowSize.Width, + CursorPos.Y / (f32)Device->CreationParams.WindowSize.Height); + } + + virtual void setReferenceRect(core::rect* rect=0) + { + } + + private: + + void updateCursorPos() + { + } + + core::position2d CursorPos; + CIrrDeviceFB* Device; + bool IsVisible; + bool Null; + }; + + friend class CCursorControl; + + int Framebuffer; + int EventDevice; + int KeyboardDevice; + struct fb_fix_screeninfo fbfixscreeninfo; + struct fb_var_screeninfo fbscreeninfo; + struct fb_var_screeninfo oldscreeninfo; + long KeyboardMode; + u8* SoftwareImage; + + u32 Pitch; + video::ECOLOR_FORMAT FBColorFormat; + bool Close; + + struct SKeyMap + { + SKeyMap() {} + SKeyMap(s32 x11, s32 win32) + : X11Key(x11), Win32Key(win32) + { + } + + KeySym X11Key; + s32 Win32Key; + + bool operator<(const SKeyMap& o) const + { + return X11Key KeyMap; + }; + + +} // end namespace irr + +#endif // _IRR_USE_FB_DEVICE_ +#endif // __C_IRR_DEVICE_FB_H_INCLUDED__ + diff --git a/src/dep/src/irrlicht/CIrrDeviceLinux.cpp b/src/dep/src/irrlicht/CIrrDeviceLinux.cpp index a106f26..d4d41f4 100644 --- a/src/dep/src/irrlicht/CIrrDeviceLinux.cpp +++ b/src/dep/src/irrlicht/CIrrDeviceLinux.cpp @@ -1,10 +1,10 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CIrrDeviceLinux.h" -#ifdef _IRR_USE_LINUX_DEVICE_ +#ifdef _IRR_COMPILE_WITH_X11_DEVICE_ #include #include @@ -19,11 +19,16 @@ #include "CColorConverter.h" #include "SIrrCreationParameters.h" #include +#include #if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #include #include +#ifdef __FREE_BSD_ +#include +#else + // linux/joystick.h includes linux/input.h, which #defines values for various KEY_FOO keys. // These override the irr::KEY_FOO equivalents, which stops key handling from working. // As a workaround, defining _INPUT_H stops linux/input.h from being included; it @@ -32,6 +37,8 @@ #include // Would normally be included in linux/input.h #include #undef _INPUT_H +#endif + #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ namespace irr @@ -39,11 +46,17 @@ namespace irr namespace video { IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, - io::IFileSystem* io); + io::IFileSystem* io, CIrrDeviceLinux* device); } } // end namespace irr - +namespace +{ + Atom X_ATOM_CLIPBOARD; + Atom X_ATOM_TARGETS; + Atom X_ATOM_UTF8_STRING; + Atom X_ATOM_TEXT; +}; namespace irr { @@ -56,13 +69,14 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param) #ifdef _IRR_COMPILE_WITH_X11_ display(0), visual(0), screennr(0), window(0), StdHints(0), SoftwareImage(0), #ifdef _IRR_COMPILE_WITH_OPENGL_ + glxWin(0), Context(0), #endif #endif Width(param.WindowSize.Width), Height(param.WindowSize.Height), - Close(false), WindowHasFocus(false), WindowMinimized(false), + WindowHasFocus(false), WindowMinimized(false), UseXVidMode(false), UseXRandR(false), UseGLXWindow(false), - AutorepeatSupport(0) + ExternalWindow(false), AutorepeatSupport(0) { #ifdef _DEBUG setDebugName("CIrrDeviceLinux"); @@ -82,7 +96,7 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param) linuxversion += " "; linuxversion += LinuxInfo.machine; - Operator = new COSOperator(linuxversion.c_str()); + Operator = new COSOperator(linuxversion.c_str(), this); os::Printer::log(linuxversion.c_str(), ELL_INFORMATION); // create keymap @@ -115,6 +129,8 @@ CIrrDeviceLinux::~CIrrDeviceLinux() #ifdef _IRR_COMPILE_WITH_X11_ if (StdHints) XFree(StdHints); + // Disable cursor and free it later on + CursorControl->setVisible(false); if (display) { #ifdef _IRR_COMPILE_WITH_OPENGL_ @@ -136,26 +152,17 @@ CIrrDeviceLinux::~CIrrDeviceLinux() } #endif // #ifdef _IRR_COMPILE_WITH_OPENGL_ - #ifdef _IRR_LINUX_X11_VIDMODE_ - if (UseXVidMode && CreationParams.Fullscreen) - { - XF86VidModeSwitchToMode(display, screennr, &oldVideoMode); - XF86VidModeSetViewPort(display, screennr, 0, 0); - } - #endif - #ifdef _IRR_LINUX_X11_RANDR_ - if (UseXRandR && CreationParams.Fullscreen) - { - XRRScreenConfiguration *config=XRRGetScreenInfo(display,DefaultRootWindow(display)); - XRRSetScreenConfig(display,config,DefaultRootWindow(display),oldRandrMode,oldRandrRotation,CurrentTime); - XRRFreeScreenConfigInfo(config); - } - #endif + // Reset fullscreen resolution change + switchToFullscreen(true); if (SoftwareImage) XDestroyImage(SoftwareImage); - XDestroyWindow(display,window); - XCloseDisplay(display); + + if (!ExternalWindow) + { + XDestroyWindow(display,window); + XCloseDisplay(display); + } } if (visual) XFree(visual); @@ -190,6 +197,147 @@ int IrrPrintXError(Display *display, XErrorEvent *event) #endif +bool CIrrDeviceLinux::switchToFullscreen(bool reset) +{ + if (!CreationParams.Fullscreen) + return true; + if (reset) + { +#ifdef _IRR_LINUX_X11_VIDMODE_ + if (UseXVidMode && CreationParams.Fullscreen) + { + XF86VidModeSwitchToMode(display, screennr, &oldVideoMode); + XF86VidModeSetViewPort(display, screennr, 0, 0); + } + #endif + #ifdef _IRR_LINUX_X11_RANDR_ + if (UseXRandR && CreationParams.Fullscreen) + { + XRRScreenConfiguration *config=XRRGetScreenInfo(display,DefaultRootWindow(display)); + XRRSetScreenConfig(display,config,DefaultRootWindow(display),oldRandrMode,oldRandrRotation,CurrentTime); + XRRFreeScreenConfigInfo(config); + } + #endif + return true; + } + + getVideoModeList(); + #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_) + s32 eventbase, errorbase; + s32 bestMode = -1; + #endif + + #ifdef _IRR_LINUX_X11_VIDMODE_ + if (XF86VidModeQueryExtension(display, &eventbase, &errorbase)) + { + // enumerate video modes + s32 modeCount; + XF86VidModeModeInfo** modes; + + XF86VidModeGetAllModeLines(display, screennr, &modeCount, &modes); + + // find fitting mode + for (s32 i = 0; ihdisplay >= Width && modes[i]->vdisplay >= Height) + bestMode = i; + else if (bestMode!=-1 && + modes[i]->hdisplay >= Width && + modes[i]->vdisplay >= Height && + modes[i]->hdisplay <= modes[bestMode]->hdisplay && + modes[i]->vdisplay <= modes[bestMode]->vdisplay) + bestMode = i; + } + if (bestMode != -1) + { + os::Printer::log("Starting vidmode fullscreen mode...", ELL_INFORMATION); + os::Printer::log("hdisplay: ", core::stringc(modes[bestMode]->hdisplay).c_str(), ELL_INFORMATION); + os::Printer::log("vdisplay: ", core::stringc(modes[bestMode]->vdisplay).c_str(), ELL_INFORMATION); + + XF86VidModeSwitchToMode(display, screennr, modes[bestMode]); + XF86VidModeSetViewPort(display, screennr, 0, 0); + UseXVidMode=true; + } + else + { + os::Printer::log("Could not find specified video mode, running windowed.", ELL_WARNING); + CreationParams.Fullscreen = false; + } + + XFree(modes); + } + else + #endif + #ifdef _IRR_LINUX_X11_RANDR_ + if (XRRQueryExtension(display, &eventbase, &errorbase)) + { + s32 modeCount; + XRRScreenConfiguration *config=XRRGetScreenInfo(display,DefaultRootWindow(display)); + XRRScreenSize *modes=XRRConfigSizes(config,&modeCount); + for (s32 i = 0; i= Width && (u32)modes[i].height >= Height) + bestMode = i; + else if (bestMode!=-1 && + (u32)modes[i].width >= Width && + (u32)modes[i].height >= Height && + modes[i].width <= modes[bestMode].width && + modes[i].height <= modes[bestMode].height) + bestMode = i; + } + if (bestMode != -1) + { + os::Printer::log("Starting randr fullscreen mode...", ELL_INFORMATION); + os::Printer::log("width: ", core::stringc(modes[bestMode].width).c_str(), ELL_INFORMATION); + os::Printer::log("height: ", core::stringc(modes[bestMode].height).c_str(), ELL_INFORMATION); + + XRRSetScreenConfig(display,config,DefaultRootWindow(display),bestMode,oldRandrRotation,CurrentTime); + UseXRandR=true; + } + XRRFreeScreenConfigInfo(config); + } + else + #endif + { + os::Printer::log("VidMode or RandR extension must be installed to allow Irrlicht " + "to switch to fullscreen mode. Running in windowed mode instead.", ELL_WARNING); + CreationParams.Fullscreen = false; + } + return CreationParams.Fullscreen; +} + + +#if defined(_IRR_COMPILE_WITH_X11_) +void IrrPrintXGrabError(int grabResult, const c8 * grabCommand ) +{ + if ( grabResult == GrabSuccess ) + { +// os::Printer::log(grabCommand, ": GrabSuccess", ELL_INFORMATION); + return; + } + + switch ( grabResult ) + { + case AlreadyGrabbed: + os::Printer::log(grabCommand, ": AlreadyGrabbed", ELL_WARNING); + break; + case GrabNotViewable: + os::Printer::log(grabCommand, ": GrabNotViewable", ELL_WARNING); + break; + case GrabFrozen: + os::Printer::log(grabCommand, ": GrabFrozen", ELL_WARNING); + break; + case GrabInvalidTime: + os::Printer::log(grabCommand, ": GrabInvalidTime", ELL_WARNING); + break; + default: + os::Printer::log(grabCommand, ": grab failed with unknown problem", ELL_WARNING); + break; + } +} +#endif + + bool CIrrDeviceLinux::createWindow() { #ifdef _IRR_COMPILE_WITH_X11_ @@ -202,92 +350,16 @@ bool CIrrDeviceLinux::createWindow() if (!display) { os::Printer::log("Error: Need running XServer to start Irrlicht Engine.", ELL_ERROR); - os::Printer::log("Could not open display", XDisplayName(0), ELL_ERROR); + if (XDisplayName(0)[0]) + os::Printer::log("Could not open display", XDisplayName(0), ELL_ERROR); + else + os::Printer::log("Could not open display, set DISPLAY variable", ELL_ERROR); return false; } screennr = DefaultScreen(display); - // query extension - - if (CreationParams.Fullscreen) - { - getVideoModeList(); - #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_) - s32 eventbase, errorbase; - s32 bestMode = -1; - #endif - - #ifdef _IRR_LINUX_X11_VIDMODE_ - if (XF86VidModeQueryExtension(display, &eventbase, &errorbase)) - { - // enumerate video modes - s32 modeCount; - XF86VidModeModeInfo** modes; - - XF86VidModeGetAllModeLines(display, screennr, &modeCount, &modes); - - // find fitting mode - for (s32 i = 0; ihdisplay >= Width && modes[i]->vdisplay >= Height) - bestMode = i; - else if (bestMode!=-1 && - modes[i]->hdisplay >= Width && - modes[i]->vdisplay >= Height && - modes[i]->hdisplay < modes[bestMode]->hdisplay && - modes[i]->vdisplay < modes[bestMode]->vdisplay) - bestMode = i; - } - if (bestMode != -1) - { - os::Printer::log("Starting fullscreen mode...", ELL_INFORMATION); - XF86VidModeSwitchToMode(display, screennr, modes[bestMode]); - XF86VidModeSetViewPort(display, screennr, 0, 0); - UseXVidMode=true; - } - else - { - os::Printer::log("Could not find specified video mode, running windowed.", ELL_WARNING); - CreationParams.Fullscreen = false; - } - - XFree(modes); - } - else - #endif - #ifdef _IRR_LINUX_X11_RANDR_ - if (XRRQueryExtension(display, &eventbase, &errorbase)) - { - s32 modeCount; - XRRScreenConfiguration *config=XRRGetScreenInfo(display,DefaultRootWindow(display)); - XRRScreenSize *modes=XRRConfigSizes(config,&modeCount); - for (s32 i = 0; i= Width && (u32)modes[i].height >= Height) - bestMode = i; - else if (bestMode!=-1 && - (u32)modes[i].width >= Width && - (u32)modes[i].height >= Height && - modes[i].width < modes[bestMode].width && - modes[i].height < modes[bestMode].height) - bestMode = i; - } - if (bestMode != -1) - { - XRRSetScreenConfig(display,config,DefaultRootWindow(display),bestMode,oldRandrRotation,CurrentTime); - UseXRandR=true; - } - XRRFreeScreenConfigInfo(config); - } - else - #endif - { - os::Printer::log("VidMode or RandR extension must be installed to allow Irrlicht " - "to switch to fullscreen mode. Running in windowed mode instead.", ELL_WARNING); - CreationParams.Fullscreen = false; - } - } + switchToFullscreen(); #ifdef _IRR_COMPILE_WITH_OPENGL_ @@ -299,9 +371,16 @@ bool CIrrDeviceLinux::createWindow() isAvailableGLX=glXQueryExtension(display,&major,&minor); if (isAvailableGLX && glXQueryVersion(display, &major, &minor)) { - if (major==1 && minor>2) +#ifdef GLX_VERSION_1_3 + typedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); + +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddress(reinterpret_cast("glXChooseFBConfig")); +#else + PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig=glXChooseFBConfig; +#endif + if (major==1 && minor>2 && glxChooseFBConfig) { - const int MAX_SAMPLES = 16; // attribute array for the draw buffer int visualAttrBuffer[] = { @@ -310,113 +389,128 @@ bool CIrrDeviceLinux::createWindow() GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0, - GLX_DEPTH_SIZE, CreationParams.ZBufferBits, - GLX_DOUBLEBUFFER, GL_TRUE, - GLX_STENCIL_SIZE, 1, + GLX_DEPTH_SIZE, CreationParams.ZBufferBits, //10,11 + GLX_DOUBLEBUFFER, CreationParams.Doublebuffer?True:False, + GLX_STENCIL_SIZE, CreationParams.Stencilbuffer?1:0, +#if defined(GLX_VERSION_1_4) && defined(GLX_SAMPLE_BUFFERS) // we need to check the extension string! + GLX_SAMPLE_BUFFERS, 1, + GLX_SAMPLES, CreationParams.AntiAlias, // 18,19 +#elif defined(GLX_ARB_multisample) GLX_SAMPLE_BUFFERS_ARB, 1, - GLX_SAMPLES_ARB, MAX_SAMPLES, + GLX_SAMPLES_ARB, CreationParams.AntiAlias, // 18,19 +#elif defined(GLX_SGIS_multisample) + GLX_SAMPLE_BUFFERS_SGIS, 1, + GLX_SAMPLES_SGIS, CreationParams.AntiAlias, // 18,19 +#endif + GLX_STEREO, CreationParams.Stereobuffer?True:False, None }; GLXFBConfig *configList=0; int nitems=0; - if (!CreationParams.AntiAlias) + if (CreationParams.AntiAlias<2) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; } - if (CreationParams.Stencilbuffer) + // first round with unchanged values { - configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); + configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (!configList && CreationParams.AntiAlias) { while (!configList && (visualAttrBuffer[19]>1)) { - visualAttrBuffer[19] >>= 1; - configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); + visualAttrBuffer[19] -= 1; + configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); } if (!configList) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; - configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); + configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (configList) { os::Printer::log("No FSAA available.", ELL_WARNING); - CreationParams.AntiAlias=false; + CreationParams.AntiAlias=0; } else { //reenable multisampling visualAttrBuffer[17] = 1; - visualAttrBuffer[19] = MAX_SAMPLES; + visualAttrBuffer[19] = CreationParams.AntiAlias; } } } } - // Next try without stencil buffer + // Next try with flipped stencil buffer value + // If the first round was with stencil flag it's now without + // Other way round also makes sense because some configs + // only have depth buffer combined with stencil buffer if (!configList) { if (CreationParams.Stencilbuffer) os::Printer::log("No stencilbuffer available, disabling stencil shadows.", ELL_WARNING); - CreationParams.Stencilbuffer = false; - visualAttrBuffer[15]=0; + CreationParams.Stencilbuffer = !CreationParams.Stencilbuffer; + visualAttrBuffer[15]=CreationParams.Stencilbuffer?1:0; - configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); + configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (!configList && CreationParams.AntiAlias) { while (!configList && (visualAttrBuffer[19]>1)) { - visualAttrBuffer[19] >>= 1; - configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); + visualAttrBuffer[19] -= 1; + configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); } if (!configList) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; - configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); + configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (configList) { os::Printer::log("No FSAA available.", ELL_WARNING); - CreationParams.AntiAlias=false; + CreationParams.AntiAlias=0; } else { //reenable multisampling visualAttrBuffer[17] = 1; - visualAttrBuffer[19] = MAX_SAMPLES; + visualAttrBuffer[19] = CreationParams.AntiAlias; } } } } // Next try without double buffer - if (!configList) + if (!configList && CreationParams.Doublebuffer) { os::Printer::log("No doublebuffering available.", ELL_WARNING); - visualAttrBuffer[13] = GL_FALSE; - configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); + CreationParams.Doublebuffer=false; + visualAttrBuffer[13] = GLX_DONT_CARE; + CreationParams.Stencilbuffer = false; + visualAttrBuffer[15]=0; + configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (!configList && CreationParams.AntiAlias) { while (!configList && (visualAttrBuffer[19]>1)) { - visualAttrBuffer[19] >>= 1; - configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); + visualAttrBuffer[19] -= 1; + configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); } if (!configList) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; - configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); + configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (configList) { os::Printer::log("No FSAA available.", ELL_WARNING); - CreationParams.AntiAlias=false; + CreationParams.AntiAlias=0; } else { //reenable multisampling visualAttrBuffer[17] = 1; - visualAttrBuffer[19] = MAX_SAMPLES; + visualAttrBuffer[19] = CreationParams.AntiAlias; } } } @@ -426,10 +520,18 @@ bool CIrrDeviceLinux::createWindow() glxFBConfig=configList[0]; XFree(configList); UseGLXWindow=true; - visual = glXGetVisualFromFBConfig(display,glxFBConfig); +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); + PFNGLXGETVISUALFROMFBCONFIGPROC glxGetVisualFromFBConfig= (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddress(reinterpret_cast("glXGetVisualFromFBConfig")); + if (glxGetVisualFromFBConfig) + visual = glxGetVisualFromFBConfig(display,glxFBConfig); +#else + visual = glXGetVisualFromFBConfig(display,glxFBConfig); +#endif } } else +#endif { // attribute array for the draw buffer int visualAttrBuffer[] = @@ -440,27 +542,29 @@ bool CIrrDeviceLinux::createWindow() GLX_BLUE_SIZE, 4, GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0, GLX_DEPTH_SIZE, CreationParams.ZBufferBits, - GLX_DOUBLEBUFFER, GL_TRUE, - GLX_STENCIL_SIZE, 1, + GLX_STENCIL_SIZE, CreationParams.Stencilbuffer?1:0, // 12,13 + // The following attributes have no flags, but are + // either present or not. As a no-op we use + // GLX_USE_GL, which is silently ignored by glXChooseVisual + CreationParams.Doublebuffer?GLX_DOUBLEBUFFER:GLX_USE_GL, // 14 + CreationParams.Stereobuffer?GLX_STEREO:GLX_USE_GL, // 15 None }; - if (CreationParams.Stencilbuffer) - visual=glXChooseVisual(display, screennr, visualAttrBuffer); + visual=glXChooseVisual(display, screennr, visualAttrBuffer); if (!visual) { if (CreationParams.Stencilbuffer) - { os::Printer::log("No stencilbuffer available, disabling.", ELL_WARNING); - CreationParams.Stencilbuffer = false; - } - visualAttrBuffer[15]=0; + CreationParams.Stencilbuffer = !CreationParams.Stencilbuffer; + visualAttrBuffer[13]=CreationParams.Stencilbuffer?1:0; visual=glXChooseVisual(display, screennr, visualAttrBuffer); - if (!visual) + if (!visual && CreationParams.Doublebuffer) { os::Printer::log("No doublebuffering available.", ELL_WARNING); - visualAttrBuffer[13] = GL_FALSE; + CreationParams.Doublebuffer=false; + visualAttrBuffer[14] = GLX_USE_GL; visual=glXChooseVisual(display, screennr, visualAttrBuffer); } } @@ -469,12 +573,14 @@ bool CIrrDeviceLinux::createWindow() else os::Printer::log("No GLX support available. OpenGL driver will not work.", ELL_WARNING); } - + // don't use the XVisual with OpenGL, because it ignores all requested + // properties of the CreationParams + else if (!visual) #endif // _IRR_COMPILE_WITH_OPENGL_ // create visual with standard X methods - if (!visual) { + os::Printer::log("Using plain X visual"); XVisualInfo visTempl; //Template to hold requested values int visNumber; // Return value of available visuals @@ -509,64 +615,64 @@ bool CIrrDeviceLinux::createWindow() attributes.colormap = colormap; attributes.border_pixel = 0; - attributes.event_mask = StructureNotifyMask | FocusChangeMask; + attributes.event_mask = StructureNotifyMask | FocusChangeMask | ExposureMask; if (!CreationParams.IgnoreInput) attributes.event_mask |= PointerMotionMask | ButtonPressMask | KeyPressMask | ButtonReleaseMask | KeyReleaseMask; - // create Window, either for Fullscreen or windowed mode - if (CreationParams.Fullscreen) + if (!CreationParams.WindowId) { - attributes.override_redirect = True; - + // create new Window + // Remove window manager decoration in fullscreen + attributes.override_redirect = CreationParams.Fullscreen; window = XCreateWindow(display, RootWindow(display, visual->screen), 0, 0, Width, Height, 0, visual->depth, InputOutput, visual->visual, CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &attributes); - CreationParams.WindowId = (void*)window; - - XWarpPointer(display, None, window, 0, 0, 0, 0, 0, 0); XMapRaised(display, window); - XGrabKeyboard(display, window, True, GrabModeAsync, - GrabModeAsync, CurrentTime); - XGrabPointer(display, window, True, ButtonPressMask, - GrabModeAsync, GrabModeAsync, window, None, CurrentTime); - } - else - { // we want windowed mode - attributes.event_mask |= ExposureMask; - attributes.event_mask |= FocusChangeMask; - - if(!CreationParams.WindowId) - { - window = XCreateWindow(display, - RootWindow(display, visual->screen), - 0, 0, Width, Height, 0, visual->depth, - InputOutput, visual->visual, - CWBorderPixel | CWColormap | CWEventMask, - &attributes); - } - else - { - window = XCreateWindow(display, - (Window)CreationParams.WindowId, - 0, 0, Width, Height, 0, visual->depth, - InputOutput, visual->visual, - CWBorderPixel | CWColormap | CWEventMask, - &attributes); - } CreationParams.WindowId = (void*)window; - Atom wmDelete; wmDelete = XInternAtom(display, wmDeleteWindow, True); XSetWMProtocols(display, window, &wmDelete, 1); - XMapRaised(display, window); + if (CreationParams.Fullscreen) + { + XSetInputFocus(display, window, RevertToParent, CurrentTime); + int grabKb = XGrabKeyboard(display, window, True, GrabModeAsync, + GrabModeAsync, CurrentTime); + IrrPrintXGrabError(grabKb, "XGrabKeyboard"); + int grabPointer = XGrabPointer(display, window, True, ButtonPressMask, + GrabModeAsync, GrabModeAsync, window, None, CurrentTime); + IrrPrintXGrabError(grabPointer, "XGrabPointer"); + XWarpPointer(display, None, window, 0, 0, 0, 0, 0, 0); + } } + else + { + // attach external window + window = (Window)CreationParams.WindowId; + if (!CreationParams.IgnoreInput) + { + XCreateWindow(display, + window, + 0, 0, Width, Height, 0, visual->depth, + InputOutput, visual->visual, + CWBorderPixel | CWColormap | CWEventMask, + &attributes); + } + XWindowAttributes wa; + XGetWindowAttributes(display, window, &wa); + CreationParams.WindowSize.Width = wa.width; + CreationParams.WindowSize.Height = wa.height; + CreationParams.Fullscreen = false; + ExternalWindow = true; + } + WindowMinimized=false; - XkbSetDetectableAutoRepeat(display, True, &AutorepeatSupport); + // Currently broken in X, see Bug ID 2795321 + // XkbSetDetectableAutoRepeat(display, True, &AutorepeatSupport); #ifdef _IRR_COMPILE_WITH_OPENGL_ @@ -625,6 +731,9 @@ bool CIrrDeviceLinux::createWindow() XGetGeometry(display, window, &tmp, &x, &y, &Width, &Height, &borderWidth, &bits); CreationParams.Bits = bits; + CreationParams.WindowSize.Width = Width; + CreationParams.WindowSize.Height = Height; + StdHints = XAllocSizeHints(); long num; XGetWMNormalHints(display, window, StdHints, &num); @@ -644,6 +753,8 @@ bool CIrrDeviceLinux::createWindow() SoftwareImage->data = (char*) malloc(SoftwareImage->bytes_per_line * SoftwareImage->height * sizeof(char)); } + initXAtoms(); + #endif // #ifdef _IRR_COMPILE_WITH_X11_ return true; } @@ -673,12 +784,12 @@ void CIrrDeviceLinux::createDriver() break; case video::EDT_OPENGL: - #ifdef _IRR_COMPILE_WITH_OPENGL_ + #ifdef _IRR_COMPILE_WITH_OPENGL_ if (Context) - VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem); - #else + VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this); + #else os::Printer::log("No OpenGL support compiled in.", ELL_ERROR); - #endif + #endif break; case video::EDT_DIRECT3D8: @@ -715,6 +826,7 @@ bool CIrrDeviceLinux::run() if ((CreationParams.DriverType != video::EDT_NULL) && display) { SEvent irrevent; + irrevent.MouseInput.ButtonStates = 0xffffffff; while (XPending(display) > 0 && !Close) { @@ -747,7 +859,7 @@ bool CIrrDeviceLinux::run() } if (VideoDriver) - VideoDriver->OnResize(core::dimension2d(Width, Height)); + VideoDriver->OnResize(core::dimension2d(Width, Height)); } break; @@ -772,6 +884,13 @@ bool CIrrDeviceLinux::run() irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED; irrevent.MouseInput.X = event.xbutton.x; irrevent.MouseInput.Y = event.xbutton.y; + irrevent.MouseInput.Control = (event.xkey.state & ControlMask) != 0; + irrevent.MouseInput.Shift = (event.xkey.state & ShiftMask) != 0; + + // mouse button states + irrevent.MouseInput.ButtonStates = (event.xbutton.state & Button1Mask) ? irr::EMBSM_LEFT : 0; + irrevent.MouseInput.ButtonStates |= (event.xbutton.state & Button3Mask) ? irr::EMBSM_RIGHT : 0; + irrevent.MouseInput.ButtonStates |= (event.xbutton.state & Button2Mask) ? irr::EMBSM_MIDDLE : 0; postEventFromUser(irrevent); break; @@ -782,6 +901,16 @@ bool CIrrDeviceLinux::run() irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT; irrevent.MouseInput.X = event.xbutton.x; irrevent.MouseInput.Y = event.xbutton.y; + irrevent.MouseInput.Control = (event.xkey.state & ControlMask) != 0; + irrevent.MouseInput.Shift = (event.xkey.state & ShiftMask) != 0; + + // mouse button states + // This sets the state which the buttons had _prior_ to the event. + // So unlike on Windows the button which just got changed has still the old state here. + // We handle that below by flipping the corresponding bit later. + irrevent.MouseInput.ButtonStates = (event.xbutton.state & Button1Mask) ? irr::EMBSM_LEFT : 0; + irrevent.MouseInput.ButtonStates |= (event.xbutton.state & Button3Mask) ? irr::EMBSM_RIGHT : 0; + irrevent.MouseInput.ButtonStates |= (event.xbutton.state & Button2Mask) ? irr::EMBSM_MIDDLE : 0; irrevent.MouseInput.Event = irr::EMIE_COUNT; @@ -790,31 +919,57 @@ bool CIrrDeviceLinux::run() case Button1: irrevent.MouseInput.Event = (event.type == ButtonPress) ? irr::EMIE_LMOUSE_PRESSED_DOWN : irr::EMIE_LMOUSE_LEFT_UP; + irrevent.MouseInput.ButtonStates ^= irr::EMBSM_LEFT; break; case Button3: irrevent.MouseInput.Event = (event.type == ButtonPress) ? irr::EMIE_RMOUSE_PRESSED_DOWN : irr::EMIE_RMOUSE_LEFT_UP; + irrevent.MouseInput.ButtonStates ^= irr::EMBSM_RIGHT; break; case Button2: irrevent.MouseInput.Event = (event.type == ButtonPress) ? irr::EMIE_MMOUSE_PRESSED_DOWN : irr::EMIE_MMOUSE_LEFT_UP; + irrevent.MouseInput.ButtonStates ^= irr::EMBSM_MIDDLE; break; case Button4: - irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; - irrevent.MouseInput.Wheel = 1.0f; + if (event.type == ButtonPress) + { + irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; + irrevent.MouseInput.Wheel = 1.0f; + } break; case Button5: - irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; - irrevent.MouseInput.Wheel = -1.0f; + if (event.type == ButtonPress) + { + irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; + irrevent.MouseInput.Wheel = -1.0f; + } break; } if (irrevent.MouseInput.Event != irr::EMIE_COUNT) + { postEventFromUser(irrevent); + + if ( irrevent.MouseInput.Event >= EMIE_LMOUSE_PRESSED_DOWN && irrevent.MouseInput.Event <= EMIE_MMOUSE_PRESSED_DOWN ) + { + u32 clicks = checkSuccessiveClicks(irrevent.MouseInput.X, irrevent.MouseInput.Y, irrevent.MouseInput.Event); + if ( clicks == 2 ) + { + irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_DOUBLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); + postEventFromUser(irrevent); + } + else if ( clicks == 3 ) + { + irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_TRIPLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); + postEventFromUser(irrevent); + } + } + } break; case MappingNotify: @@ -822,7 +977,7 @@ bool CIrrDeviceLinux::run() break; case KeyRelease: - if (0 == AutorepeatSupport) + if (0 == AutorepeatSupport && (XPending( display ) > 0) ) { // check for Autorepeat manually // We'll do the same as Windows does: Only send KeyPressed @@ -831,7 +986,7 @@ bool CIrrDeviceLinux::run() XPeekEvent (event.xkey.display, &next_event); if ((next_event.type == KeyPress) && (next_event.xkey.keycode == event.xkey.keycode) && - (next_event.xkey.time == event.xkey.time)) + (next_event.xkey.time - event.xkey.time) < 2) // usually same time, but on some systems a difference of 1 is possible { /* Ignore the key release event */ break; @@ -850,8 +1005,9 @@ bool CIrrDeviceLinux::run() irrevent.KeyInput.Key = (EKEY_CODE)KeyMap[idx].Win32Key; else { + // Usually you will check keysymdef.h and add the corresponding key to createKeyMap. irrevent.KeyInput.Key = (EKEY_CODE)0; - os::Printer::log("Could not find win32 key for x11 key.", ELL_WARNING); + os::Printer::log("Could not find win32 key for x11 key.", core::stringc((int)mp.X11Key).c_str(), ELL_WARNING); } irrevent.EventType = irr::EET_KEY_INPUT_EVENT; irrevent.KeyInput.PressedDown = (event.type == KeyPress); @@ -883,6 +1039,50 @@ bool CIrrDeviceLinux::run() } break; + case SelectionRequest: + { + XEvent respond; + XSelectionRequestEvent *req = &(event.xselectionrequest); + if ( req->target == XA_STRING) + { + XChangeProperty (display, + req->requestor, + req->property, req->target, + 8, // format + PropModeReplace, + (unsigned char*) Clipboard.c_str(), + Clipboard.size()); + respond.xselection.property = req->property; + } + else if ( req->target == X_ATOM_TARGETS ) + { + long data[2]; + + data[0] = X_ATOM_TEXT; + data[1] = XA_STRING; + + XChangeProperty (display, req->requestor, + req->property, req->target, + 8, PropModeReplace, + (unsigned char *) &data, + sizeof (data)); + respond.xselection.property = req->property; + } + else + { + respond.xselection.property= None; + } + respond.xselection.type= SelectionNotify; + respond.xselection.display= req->display; + respond.xselection.requestor= req->requestor; + respond.xselection.selection=req->selection; + respond.xselection.target= req->target; + respond.xselection.time = req->time; + XSendEvent (display, req->requestor,0,0,&respond); + XFlush (display); + } + break; + default: break; } // end switch @@ -933,10 +1133,13 @@ void CIrrDeviceLinux::setWindowCaption(const wchar_t* text) return; XTextProperty txt; - XwcTextListToTextProperty(display, const_cast(&text), 1, XStdICCTextStyle, &txt); - XSetWMName(display, window, &txt); - XSetWMIconName(display, window, &txt); - XFree(txt.value); + if (Success==XwcTextListToTextProperty(display, const_cast(&text), + 1, XStdICCTextStyle, &txt)) + { + XSetWMName(display, window, &txt); + XSetWMIconName(display, window, &txt); + XFree(txt.value); + } #endif } @@ -952,9 +1155,9 @@ bool CIrrDeviceLinux::present(video::IImage* image, void* windowId, core::rectwidth; - const int minWidth = core::min_(image->getDimension().Width, destwidth); - const int destPitch = SoftwareImage->bytes_per_line; + const u32 destwidth = SoftwareImage->width; + const u32 minWidth = core::min_(image->getDimension().Width, destwidth); + const u32 destPitch = SoftwareImage->bytes_per_line; video::ECOLOR_FORMAT destColor; switch (SoftwareImage->bits_per_pixel) @@ -975,10 +1178,10 @@ bool CIrrDeviceLinux::present(video::IImage* image, void* windowId, core::rect(image->lock()); u8* destData = reinterpret_cast(SoftwareImage->data); - const int destheight = SoftwareImage->height; - const int srcheight = core::min_(image->getDimension().Height, destheight); - const int srcPitch = image->getPitch(); - for (int y=0; y!=srcheight; ++y) + const u32 destheight = SoftwareImage->height; + const u32 srcheight = core::min_(image->getDimension().Height, destheight); + const u32 srcPitch = image->getPitch(); + for (u32 y=0; y!=srcheight; ++y) { video::CColorConverter::convert_viaFormat(srcdata,image->getColorFormat(), minWidth, destData, destColor); srcdata+=srcPitch; @@ -1036,11 +1239,11 @@ video::ECOLOR_FORMAT CIrrDeviceLinux::getColorFormat() const } -//! Sets if the window should be resizeable in windowed mode. -void CIrrDeviceLinux::setResizeAble(bool resize) +//! Sets if the window should be resizable in windowed mode. +void CIrrDeviceLinux::setResizable(bool resize) { #ifdef _IRR_COMPILE_WITH_X11_ - if (CreationParams.DriverType == video::EDT_NULL) + if (CreationParams.DriverType == video::EDT_NULL || CreationParams.Fullscreen ) return; XUnmapWindow(display, window); @@ -1098,11 +1301,11 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList() // find fitting mode - VideoModeList.setDesktop(defaultDepth, core::dimension2d( + VideoModeList.setDesktop(defaultDepth, core::dimension2d( modes[0]->hdisplay, modes[0]->vdisplay)); for (int i = 0; i( + VideoModeList.addMode(core::dimension2d( modes[i]->hdisplay, modes[i]->vdisplay), defaultDepth); } XFree(modes); @@ -1116,11 +1319,11 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList() XRRScreenConfiguration *config=XRRGetScreenInfo(display,DefaultRootWindow(display)); oldRandrMode=XRRConfigCurrentConfiguration(config,&oldRandrRotation); XRRScreenSize *modes=XRRConfigSizes(config,&modeCount); - VideoModeList.setDesktop(defaultDepth, core::dimension2d( + VideoModeList.setDesktop(defaultDepth, core::dimension2d( modes[oldRandrMode].width, modes[oldRandrMode].height)); for (int i = 0; i( + VideoModeList.addMode(core::dimension2d( modes[i].width, modes[i].height), defaultDepth); } XRRFreeScreenConfigInfo(config); @@ -1143,6 +1346,33 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList() } +//! Minimize window +void CIrrDeviceLinux::minimizeWindow() +{ +#ifdef _IRR_COMPILE_WITH_X11_ + XIconifyWindow(display, window, screennr); +#endif +} + + +//! Maximize window +void CIrrDeviceLinux::maximizeWindow() +{ +#ifdef _IRR_COMPILE_WITH_X11_ + XMapWindow(display, window); +#endif +} + + +//! Restore original window size +void CIrrDeviceLinux::restoreWindow() +{ +#ifdef _IRR_COMPILE_WITH_X11_ + XMapWindow(display, window); +#endif +} + + void CIrrDeviceLinux::createKeyMap() { // I don't know if this is the best method to create @@ -1153,6 +1383,7 @@ void CIrrDeviceLinux::createKeyMap() KeyMap.reallocate(84); KeyMap.push_back(SKeyMap(XK_BackSpace, KEY_BACK)); KeyMap.push_back(SKeyMap(XK_Tab, KEY_TAB)); + KeyMap.push_back(SKeyMap(XK_ISO_Left_Tab, KEY_TAB)); KeyMap.push_back(SKeyMap(XK_Linefeed, 0)); // ??? KeyMap.push_back(SKeyMap(XK_Clear, KEY_CLEAR)); KeyMap.push_back(SKeyMap(XK_Return, KEY_RETURN)); @@ -1173,6 +1404,7 @@ void CIrrDeviceLinux::createKeyMap() KeyMap.push_back(SKeyMap(XK_Page_Down, KEY_NEXT)); KeyMap.push_back(SKeyMap(XK_End, KEY_END)); KeyMap.push_back(SKeyMap(XK_Begin, KEY_HOME)); + KeyMap.push_back(SKeyMap(XK_Num_Lock, KEY_NUMLOCK)); KeyMap.push_back(SKeyMap(XK_KP_Space, KEY_SPACE)); KeyMap.push_back(SKeyMap(XK_KP_Tab, KEY_TAB)); KeyMap.push_back(SKeyMap(XK_KP_Enter, KEY_RETURN)); @@ -1180,10 +1412,12 @@ void CIrrDeviceLinux::createKeyMap() KeyMap.push_back(SKeyMap(XK_KP_F2, KEY_F2)); KeyMap.push_back(SKeyMap(XK_KP_F3, KEY_F3)); KeyMap.push_back(SKeyMap(XK_KP_F4, KEY_F4)); + KeyMap.push_back(SKeyMap(XK_KP_Home, KEY_HOME)); KeyMap.push_back(SKeyMap(XK_KP_Left, KEY_LEFT)); KeyMap.push_back(SKeyMap(XK_KP_Up, KEY_UP)); KeyMap.push_back(SKeyMap(XK_KP_Right, KEY_RIGHT)); KeyMap.push_back(SKeyMap(XK_KP_Down, KEY_DOWN)); + KeyMap.push_back(SKeyMap(XK_Print, KEY_PRINT)); KeyMap.push_back(SKeyMap(XK_KP_Prior, KEY_PRIOR)); KeyMap.push_back(SKeyMap(XK_KP_Page_Up, KEY_PRIOR)); KeyMap.push_back(SKeyMap(XK_KP_Next, KEY_NEXT)); @@ -1361,20 +1595,31 @@ bool CIrrDeviceLinux::activateJoysticks(core::array & joystickInf info.fd = open(devName.c_str(), O_RDONLY); if(-1 == info.fd) { - // ...but Ubuntu and possibly other distros + // ...but Ubuntu and possibly other distros // create the devices in /dev/input devName = "/dev/input/js"; devName += joystick; info.fd = open(devName.c_str(), O_RDONLY); + if(-1 == info.fd) + { + // and BSD here + devName = "/dev/joy"; + devName += joystick; + info.fd = open(devName.c_str(), O_RDONLY); + } } if(-1 == info.fd) continue; +#ifdef __FREE_BSD_ + info.axes=2; + info.buttons=2; +#else ioctl( info.fd, JSIOCGAXES, &(info.axes) ); ioctl( info.fd, JSIOCGBUTTONS, &(info.buttons) ); - fcntl( info.fd, F_SETFL, O_NONBLOCK ); +#endif (void)memset(&info.persistentData, 0, sizeof(info.persistentData)); info.persistentData.EventType = irr::EET_JOYSTICK_INPUT_EVENT; @@ -1391,10 +1636,12 @@ bool CIrrDeviceLinux::activateJoysticks(core::array & joystickInf returnInfo.Axes = info.axes; returnInfo.Buttons = info.buttons; +#ifndef __FREE_BSD_ char name[80]; ioctl( info.fd, JSIOCGNAME(80), name); returnInfo.Name = name; - +#endif + joystickInfo.push_back(returnInfo); } @@ -1402,7 +1649,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array & joystickInf { char logString[256]; (void)sprintf(logString, "Found joystick %u, %u axes, %u buttons '%s'", - joystick, joystickInfo[joystick].Axes, + joystick, joystickInfo[joystick].Axes, joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str()); os::Printer::log(logString, ELL_INFORMATION); } @@ -1420,11 +1667,19 @@ void CIrrDeviceLinux::pollJoysticks() if(0 == ActiveJoysticks.size()) return; - u32 joystick; - for(joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) + u32 j; + for(j= 0; j< ActiveJoysticks.size(); ++j) { - JoystickInfo & info = ActiveJoysticks[joystick]; + JoystickInfo & info = ActiveJoysticks[j]; +#ifdef __FREE_BSD_ + struct joystick js; + if( read( info.fd, &js, JS_RETURN ) == JS_RETURN ) + { + info.persistentData.JoystickEvent.ButtonStates = js.buttons; /* should be a two-bit field */ + info.persistentData.JoystickEvent.Axis[0] = js.x; /* X axis */ + info.persistentData.JoystickEvent.Axis[1] = js.y; /* Y axis */ +#else struct js_event event; while(sizeof(event) == read(info.fd, &event, sizeof(event))) { @@ -1432,9 +1687,9 @@ void CIrrDeviceLinux::pollJoysticks() { case JS_EVENT_BUTTON: if (event.value) - info.persistentData.JoystickEvent.ButtonStates |= (1 << event.number); + info.persistentData.JoystickEvent.ButtonStates |= (1 << event.number); else - info.persistentData.JoystickEvent.ButtonStates &= ~(1 << event.number); + info.persistentData.JoystickEvent.ButtonStates &= ~(1 << event.number); break; case JS_EVENT_AXIS: @@ -1445,29 +1700,214 @@ void CIrrDeviceLinux::pollJoysticks() break; } } +#endif // Send an irrlicht joystick event once per ::run() even if no new data were received. (void)postEventFromUser(info.persistentData); } #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ -} - - -IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx(const SIrrlichtCreationParameters& param) -{ - CIrrDeviceLinux* dev = new CIrrDeviceLinux(param); - - if (dev && !dev->getVideoDriver() && param.DriverType != video::EDT_NULL) - { - dev->drop(); - dev = 0; - } - - return dev; } +//! Set the current Gamma Value for the Display +bool CIrrDeviceLinux::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) +{ + #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_) + s32 eventbase, errorbase; + #ifdef _IRR_LINUX_X11_VIDMODE_ + if (XF86VidModeQueryExtension(display, &eventbase, &errorbase)) + { + XF86VidModeGamma gamma; + gamma.red=red; + gamma.green=green; + gamma.blue=blue; + XF86VidModeSetGamma(display, screennr, &gamma); + return true; + } + #endif + #if defined(_IRR_LINUX_X11_VIDMODE_) && defined(_IRR_LINUX_X11_RANDR_) + else + #endif + #ifdef _IRR_LINUX_X11_RANDR_ + if (XRRQueryExtension(display, &eventbase, &errorbase)) + { + XRRQueryVersion(display, &eventbase, &errorbase); // major, minor + if (eventbase>=1 && errorbase>1) + { + #if (RANDR_MAJOR>1 || RANDR_MINOR>1) + XRRCrtcGamma *gamma = XRRGetCrtcGamma(display, screennr); + if (gamma) + { + *gamma->red=(u16)red; + *gamma->green=(u16)green; + *gamma->blue=(u16)blue; + XRRSetCrtcGamma(display, screennr, gamma); + XRRFreeGamma(gamma); + return true; + } + #endif + } + } + #endif + #endif + return false; +} + + +//! Get the current Gamma Value for the Display +bool CIrrDeviceLinux::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) +{ + brightness = 0.f; + contrast = 0.f; + #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_) + s32 eventbase, errorbase; + #ifdef _IRR_LINUX_X11_VIDMODE_ + if (XF86VidModeQueryExtension(display, &eventbase, &errorbase)) + { + XF86VidModeGamma gamma; + XF86VidModeGetGamma(display, screennr, &gamma); + red = gamma.red; + green = gamma.green; + blue = gamma.blue; + return true; + } + #endif + #if defined(_IRR_LINUX_X11_VIDMODE_) && defined(_IRR_LINUX_X11_RANDR_) + else + #endif + #ifdef _IRR_LINUX_X11_RANDR_ + if (XRRQueryExtension(display, &eventbase, &errorbase)) + { + XRRQueryVersion(display, &eventbase, &errorbase); // major, minor + if (eventbase>=1 && errorbase>1) + { + #if (RANDR_MAJOR>1 || RANDR_MINOR>1) + XRRCrtcGamma *gamma = XRRGetCrtcGamma(display, screennr); + if (gamma) + { + red = *gamma->red; + green = *gamma->green; + blue= *gamma->blue; + XRRFreeGamma(gamma); + return true; + } + #endif + } + } + #endif + #endif + return false; +} + + +//! gets text from the clipboard +//! \return Returns 0 if no string is in there. +const c8* CIrrDeviceLinux::getTextFromClipboard() const +{ +#if defined(_IRR_COMPILE_WITH_X11_) + Window ownerWindow = XGetSelectionOwner (display, X_ATOM_CLIPBOARD); + if ( ownerWindow == window ) + { + return Clipboard.c_str(); + } + Clipboard = ""; + if (ownerWindow != None ) + { + XConvertSelection (display, X_ATOM_CLIPBOARD, XA_STRING, None, ownerWindow, CurrentTime); + XFlush (display); + + // check for data + Atom type; + int format; + unsigned long numItems, bytesLeft, dummy; + unsigned char *data; + XGetWindowProperty (display, ownerWindow, + XA_STRING, // property name + 0, // offset + 0, // length (we only check for data, so 0) + 0, // Delete 0==false + AnyPropertyType, // AnyPropertyType or property identifier + &type, // return type + &format, // return format + &numItems, // number items + &bytesLeft, // remaining bytes for partial reads + &data); // data + if ( bytesLeft > 0 ) + { + // there is some data to get + int result = XGetWindowProperty (display, ownerWindow, XA_STRING, 0, + bytesLeft, 0, AnyPropertyType, &type, &format, + &numItems, &dummy, &data); + if (result == Success) + Clipboard = (irr::c8*)data; + XFree (data); + } + } + + return Clipboard.c_str(); + +#else + return 0; +#endif +} + +//! copies text to the clipboard +void CIrrDeviceLinux::copyToClipboard(const c8* text) const +{ +#if defined(_IRR_COMPILE_WITH_X11_) + // Actually there is no clipboard on X but applications just say they own the clipboard and return text when asked. + // Which btw. also means that on X you lose clipboard content when closing applications. + Clipboard = text; + XSetSelectionOwner (display, X_ATOM_CLIPBOARD, window, CurrentTime); + XFlush (display); +#endif +} + +#ifdef _IRR_COMPILE_WITH_X11_ +// return true if the passed event has the type passed in parameter arg +Bool PredicateIsEventType(Display *display, XEvent *event, XPointer arg) +{ + if ( event && event->type == *(int*)arg ) + { +// os::Printer::log("remove event:", core::stringc((int)arg).c_str(), ELL_INFORMATION); + return True; + } + return False; +} +#endif //_IRR_COMPILE_WITH_X11_ + +//! Remove all messages pending in the system message loop +void CIrrDeviceLinux::clearSystemMessages() +{ +#ifdef _IRR_COMPILE_WITH_X11_ + if (CreationParams.DriverType != video::EDT_NULL) + { + XEvent event; + int usrArg = ButtonPress; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + usrArg = ButtonRelease; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + usrArg = MotionNotify; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + usrArg = KeyRelease; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + usrArg = KeyPress; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + } +#endif //_IRR_COMPILE_WITH_X11_ +} + +void CIrrDeviceLinux::initXAtoms() +{ +#ifdef _IRR_COMPILE_WITH_X11_ + X_ATOM_CLIPBOARD = XInternAtom(display, "CLIPBOARD", False); + X_ATOM_TARGETS = XInternAtom(display, "TARGETS", False); + X_ATOM_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False); + X_ATOM_TEXT = XInternAtom (display, "TEXT", False); +#endif +} + } // end namespace -#endif // _IRR_USE_LINUX_DEVICE_ +#endif // _IRR_COMPILE_WITH_X11_DEVICE_ diff --git a/src/dep/src/irrlicht/CIrrDeviceLinux.h b/src/dep/src/irrlicht/CIrrDeviceLinux.h index 0ca353b..5a2cd5d 100644 --- a/src/dep/src/irrlicht/CIrrDeviceLinux.h +++ b/src/dep/src/irrlicht/CIrrDeviceLinux.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,7 +7,7 @@ #include "IrrCompileConfig.h" -#ifdef _IRR_USE_LINUX_DEVICE_ +#ifdef _IRR_COMPILE_WITH_X11_DEVICE_ #include "CIrrDeviceStub.h" #include "IrrlichtDevice.h" @@ -87,12 +87,44 @@ namespace irr //! supported by the gfx adapter. video::IVideoModeList* getVideoModeList(); - //! Sets if the window should be resizeable in windowed mode. - virtual void setResizeAble(bool resize=false); + //! Sets if the window should be resizable in windowed mode. + virtual void setResizable(bool resize=false); + + //! Minimizes the window. + virtual void minimizeWindow(); + + //! Maximizes the window. + virtual void maximizeWindow(); + + //! Restores the window size. + virtual void restoreWindow(); //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); + //! Set the current Gamma Value for the Display + virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); + + //! Get the current Gamma Value for the Display + virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); + + //! gets text from the clipboard + //! \return Returns 0 if no string is in there. + virtual const c8* getTextFromClipboard() const; + + //! copies text to the clipboard + //! This sets the clipboard selection and _not_ the primary selection which you have on X on the middle mouse button. + virtual void copyToClipboard(const c8* text) const; + + //! Remove all messages pending in the system message loop + virtual void clearSystemMessages(); + + //! Get the device type + virtual E_DEVICE_TYPE getType() const + { + return EIDT_X11; + } + private: //! create the driver @@ -102,7 +134,11 @@ namespace irr void createKeyMap(); - void pollJoysticks(); + void pollJoysticks(); + + void initXAtoms(); + + bool switchToFullscreen(bool reset=false); //! Implementation of the linux cursor control class CCursorControl : public gui::ICursorControl @@ -147,6 +183,8 @@ namespace irr //! Changes the visible state of the mouse cursor. virtual void setVisible(bool visible) { + if (visible==IsVisible) + return; IsVisible = visible; #ifdef _IRR_COMPILE_WITH_X11_ if (!Null) @@ -217,7 +255,7 @@ namespace irr } //! Returns the current position of the mouse cursor. - virtual core::position2d getPosition() + virtual const core::position2d& getPosition() { updateCursorPos(); return CursorPos; @@ -298,6 +336,8 @@ namespace irr friend class CCursorControl; #ifdef _IRR_COMPILE_WITH_X11_ + friend class COpenGLDriver; + Display *display; XVisualInfo* visual; int screennr; @@ -305,6 +345,7 @@ namespace irr XSetWindowAttributes attributes; XSizeHints* StdHints; XImage* SoftwareImage; + mutable core::stringc Clipboard; #ifdef _IRR_LINUX_X11_VIDMODE_ XF86VidModeModeInfo oldVideoMode; #endif @@ -318,12 +359,12 @@ namespace irr #endif #endif u32 Width, Height; - bool Close; bool WindowHasFocus; bool WindowMinimized; bool UseXVidMode; bool UseXRandR; bool UseGLXWindow; + bool ExternalWindow; int AutorepeatSupport; struct SKeyMap @@ -363,6 +404,6 @@ namespace irr } // end namespace irr -#endif // _IRR_USE_LINUX_DEVICE_ +#endif // _IRR_COMPILE_WITH_X11_DEVICE_ #endif // __C_IRR_DEVICE_LINUX_H_INCLUDED__ diff --git a/src/dep/src/irrlicht/CIrrDeviceSDL.cpp b/src/dep/src/irrlicht/CIrrDeviceSDL.cpp index d5eb71d..550fbee 100644 --- a/src/dep/src/irrlicht/CIrrDeviceSDL.cpp +++ b/src/dep/src/irrlicht/CIrrDeviceSDL.cpp @@ -1,10 +1,10 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" -#ifdef _IRR_USE_SDL_DEVICE_ +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ #include "CIrrDeviceSDL.h" #include "IEventReceiver.h" @@ -18,6 +18,7 @@ #include #include "SIrrCreationParameters.h" #include +#include #ifdef _MSC_VER #pragma comment(lib, "SDL.lib") @@ -27,8 +28,23 @@ namespace irr { namespace video { + + #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ + IVideoDriver* createDirectX8Driver(const core::dimension2d& screenSize, HWND window, + u32 bits, bool fullscreen, bool stencilbuffer, io::IFileSystem* io, + bool pureSoftware, bool highPrecisionFPU, bool vsync, u8 antiAlias); + #endif + + #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ + IVideoDriver* createDirectX9Driver(const core::dimension2d& screenSize, HWND window, + u32 bits, bool fullscreen, bool stencilbuffer, io::IFileSystem* io, + bool pureSoftware, bool highPrecisionFPU, bool vsync, u8 antiAlias); + #endif + + #ifdef _IRR_COMPILE_WITH_OPENGL_ IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, - io::IFileSystem* io); + io::IFileSystem* io, CIrrDeviceSDL* device); + #endif } // end namespace video } // end namespace irr @@ -37,16 +53,13 @@ namespace irr namespace irr { -const char* wmDeleteWindow = "WM_DELETE_WINDOW"; - //! constructor CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) : CIrrDeviceStub(param), - Screen((SDL_Surface*)param.WindowId), SDL_Flags(SDL_HWSURFACE|SDL_ANYFORMAT), - MouseX(0), MouseY(0), + Screen((SDL_Surface*)param.WindowId), SDL_Flags(SDL_ANYFORMAT), + MouseX(0), MouseY(0), MouseButtonStates(0), Width(param.WindowSize.Width), Height(param.WindowSize.Height), - Close(0), Resizeable(false), - WindowHasFocus(false), WindowMinimized(false) + Resizable(false), WindowHasFocus(false), WindowMinimized(false) { #ifdef _DEBUG setDebugName("CIrrDeviceSDL"); @@ -61,19 +74,27 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) SDL_INIT_NOPARACHUTE ) < 0) { os::Printer::log( "Unable to initialize SDL!", SDL_GetError()); - Close = 1; + Close = true; } - SDL_SysWMinfo info; - SDL_VERSION(&info.version); +#if defined(_IRR_WINDOWS_) + SDL_putenv("SDL_VIDEODRIVER=directx"); +#elif defined(_IRR_OSX_PLATFORM_) + SDL_putenv("SDL_VIDEODRIVER=Quartz"); +#else + SDL_putenv("SDL_VIDEODRIVER=x11"); +#endif +// SDL_putenv("SDL_WINDOWID="); - SDL_GetWMInfo(&info); + SDL_VERSION(&Info.version); + + SDL_GetWMInfo(&Info); core::stringc sdlversion = "SDL Version "; - sdlversion += info.version.major; + sdlversion += Info.version.major; sdlversion += "."; - sdlversion += info.version.minor; + sdlversion += Info.version.minor; sdlversion += "."; - sdlversion += info.version.patch; + sdlversion += Info.version.patch; Operator = new COSOperator(sdlversion.c_str()); os::Printer::log(sdlversion.c_str(), ELL_INFORMATION); @@ -84,12 +105,12 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) 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) SDL_Flags |= SDL_OPENGL; - else + else if (CreationParams.Doublebuffer) SDL_Flags |= SDL_DOUBLEBUF; // create window if (CreationParams.DriverType != video::EDT_NULL) @@ -117,10 +138,6 @@ CIrrDeviceSDL::~CIrrDeviceSDL() for (u32 i=0; i1) + { + SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 ); + SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, CreationParams.AntiAlias ); + } + if ( !Screen ) + Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); + if ( !Screen && CreationParams.AntiAlias>1) + { + while (--CreationParams.AntiAlias>1) + { + SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, CreationParams.AntiAlias ); + Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); + if (Screen) + break; + } + if ( !Screen ) + { + SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 0 ); + SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 0 ); + Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); + if (Screen) + os::Printer::log("AntiAliasing disabled due to lack of support!" ); + } + } } - - if ( !Screen ) + else if ( !Screen ) Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); + + if ( !Screen && CreationParams.Doublebuffer) + { + // Try single buffer + if (CreationParams.DriverType == video::EDT_OPENGL) + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + SDL_Flags &= ~SDL_DOUBLEBUF; + Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); + } if ( !Screen ) { os::Printer::log( "Could not initialize display!" ); @@ -168,8 +221,39 @@ void CIrrDeviceSDL::createDriver() switch(CreationParams.DriverType) { case video::EDT_DIRECT3D8: + #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ + + VideoDriver = video::createDirectX8Driver(CreationParams.WindowSize, Info.window, + CreationParams.Bits, CreationParams.Fullscreen, CreationParams.Stencilbuffer, + FileSystem, false, CreationParams.HighPrecisionFPU, CreationParams.Vsync, + CreationParams.AntiAlias); + + if (!VideoDriver) + { + os::Printer::log("Could not create DIRECT3D8 Driver.", ELL_ERROR); + } + #else + os::Printer::log("DIRECT3D8 Driver was not compiled into this dll. Try another one.", ELL_ERROR); + #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ + + break; + case video::EDT_DIRECT3D9: - os::Printer::log("This driver is not available in SDL.", ELL_ERROR); + #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ + + VideoDriver = video::createDirectX9Driver(CreationParams.WindowSize, Info.window, + CreationParams.Bits, CreationParams.Fullscreen, CreationParams.Stencilbuffer, + FileSystem, false, CreationParams.HighPrecisionFPU, CreationParams.Vsync, + CreationParams.AntiAlias); + + if (!VideoDriver) + { + os::Printer::log("Could not create DIRECT3D9 Driver.", ELL_ERROR); + } + #else + os::Printer::log("DIRECT3D9 Driver was not compiled into this dll. Try another one.", ELL_ERROR); + #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ + break; case video::EDT_SOFTWARE: @@ -179,7 +263,7 @@ void CIrrDeviceSDL::createDriver() os::Printer::log("No Software driver support compiled in.", ELL_ERROR); #endif break; - + case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ VideoDriver = video::createSoftwareDriver2(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); @@ -189,11 +273,11 @@ void CIrrDeviceSDL::createDriver() break; case video::EDT_OPENGL: - #ifdef _IRR_COMPILE_WITH_OPENGL_ - VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem); - #else + #ifdef _IRR_COMPILE_WITH_OPENGL_ + VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this); + #else os::Printer::log("No OpenGL support compiled in.", ELL_ERROR); - #endif + #endif break; case video::EDT_NULL: @@ -224,6 +308,7 @@ bool CIrrDeviceSDL::run() irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED; MouseX = irrevent.MouseInput.X = SDL_event.motion.x; MouseY = irrevent.MouseInput.Y = SDL_event.motion.y; + irrevent.MouseInput.ButtonStates = MouseButtonStates; postEventFromUser(irrevent); break; @@ -239,24 +324,77 @@ bool CIrrDeviceSDL::run() switch(SDL_event.button.button) { - case 1: - irrevent.MouseInput.Event = - (SDL_event.type == SDL_MOUSEBUTTONDOWN) ? irr::EMIE_LMOUSE_PRESSED_DOWN : irr::EMIE_LMOUSE_LEFT_UP; + case SDL_BUTTON_LEFT: + if (SDL_event.type == SDL_MOUSEBUTTONDOWN) + { + irrevent.MouseInput.Event = irr::EMIE_LMOUSE_PRESSED_DOWN; + MouseButtonStates |= irr::EMBSM_LEFT; + } + else + { + irrevent.MouseInput.Event = irr::EMIE_LMOUSE_LEFT_UP; + MouseButtonStates &= !irr::EMBSM_LEFT; + } break; - case 2: - irrevent.MouseInput.Event = - (SDL_event.type == SDL_MOUSEBUTTONDOWN) ? irr::EMIE_RMOUSE_PRESSED_DOWN : irr::EMIE_RMOUSE_LEFT_UP; + case SDL_BUTTON_RIGHT: + if (SDL_event.type == SDL_MOUSEBUTTONDOWN) + { + irrevent.MouseInput.Event = irr::EMIE_RMOUSE_PRESSED_DOWN; + MouseButtonStates |= irr::EMBSM_RIGHT; + } + else + { + irrevent.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP; + MouseButtonStates &= !irr::EMBSM_RIGHT; + } break; - case 3: - irrevent.MouseInput.Event = - (SDL_event.type == SDL_MOUSEBUTTONDOWN) ? irr::EMIE_MMOUSE_PRESSED_DOWN : irr::EMIE_MMOUSE_LEFT_UP; + case SDL_BUTTON_MIDDLE: + if (SDL_event.type == SDL_MOUSEBUTTONDOWN) + { + irrevent.MouseInput.Event = irr::EMIE_MMOUSE_PRESSED_DOWN; + MouseButtonStates |= irr::EMBSM_MIDDLE; + } + else + { + irrevent.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP; + MouseButtonStates &= !irr::EMBSM_MIDDLE; + } + break; + + case SDL_BUTTON_WHEELUP: + irrevent.MouseInput.Event = irr::EMIE_MOUSE_WHEEL; + irrevent.MouseInput.Wheel = 1.0f; + break; + + case SDL_BUTTON_WHEELDOWN: + irrevent.MouseInput.Event = irr::EMIE_MOUSE_WHEEL; + irrevent.MouseInput.Wheel = -1.0f; break; } + irrevent.MouseInput.ButtonStates = MouseButtonStates; + if (irrevent.MouseInput.Event != irr::EMIE_MOUSE_MOVED) + { postEventFromUser(irrevent); + + if ( irrevent.MouseInput.Event >= EMIE_LMOUSE_PRESSED_DOWN && irrevent.MouseInput.Event <= EMIE_MMOUSE_PRESSED_DOWN ) + { + u32 clicks = checkSuccessiveClicks(irrevent.MouseInput.X, irrevent.MouseInput.Y, irrevent.MouseInput.Event); + if ( clicks == 2 ) + { + irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_DOUBLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); + postEventFromUser(irrevent); + } + else if ( clicks == 3 ) + { + irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_TRIPLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); + postEventFromUser(irrevent); + } + } + } break; case SDL_KEYDOWN: @@ -266,18 +404,27 @@ bool CIrrDeviceSDL::run() mp.SDLKey = SDL_event.key.keysym.sym; s32 idx = KeyMap.binary_search(mp); - if (idx != -1) - { - irrevent.EventType = irr::EET_KEY_INPUT_EVENT; - irrevent.KeyInput.Char = SDL_event.key.keysym.unicode; - irrevent.KeyInput.Key = (EKEY_CODE)KeyMap[idx].Win32Key; - irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN); - irrevent.KeyInput.Shift = SDL_event.key.keysym.mod & KMOD_SHIFT; - irrevent.KeyInput.Control = SDL_event.key.keysym.mod & KMOD_CTRL; - postEventFromUser(irrevent); - } + EKEY_CODE key; + if (idx == -1) + key = (EKEY_CODE)0; else - os::Printer::log("Could not find win32 key for SDL key."); + key = (EKEY_CODE)KeyMap[idx].Win32Key; + +#ifdef _IRR_WINDOWS_API_ + // handle alt+f4 in Windows, because SDL seems not to + if ( (SDL_event.key.keysym.mod & KMOD_LALT) && key == KEY_F4) + { + Close = true; + break; + } +#endif + irrevent.EventType = irr::EET_KEY_INPUT_EVENT; + irrevent.KeyInput.Char = SDL_event.key.keysym.unicode; + irrevent.KeyInput.Key = key; + irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN); + irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0; + irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL ) != 0; + postEventFromUser(irrevent); } break; @@ -299,18 +446,16 @@ bool CIrrDeviceSDL::run() { Width = SDL_event.resize.w; Height = SDL_event.resize.h; - if (Screen) - SDL_FreeSurface(Screen); - Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); + Screen = SDL_SetVideoMode( Width, Height, 0, SDL_Flags ); if (VideoDriver) - VideoDriver->OnResize(core::dimension2d(Width, Height)); + VideoDriver->OnResize(core::dimension2d(Width, Height)); } break; case SDL_USEREVENT: irrevent.EventType = irr::EET_USER_EVENT; - irrevent.UserEvent.UserData1 = reinterpret_cast(SDL_event.user.data1); - irrevent.UserEvent.UserData2 = reinterpret_cast(SDL_event.user.data2); + irrevent.UserEvent.UserData1 = *(reinterpret_cast(&SDL_event.user.data1)); + irrevent.UserEvent.UserData2 = *(reinterpret_cast(&SDL_event.user.data2)); postEventFromUser(irrevent); break; @@ -392,7 +537,7 @@ bool CIrrDeviceSDL::run() { joyevent.JoystickEvent.POV=65535; } - + // we map the number directly joyevent.JoystickEvent.Joystick=static_cast(i); // now post the event @@ -462,7 +607,7 @@ void CIrrDeviceSDL::sleep(u32 timeMs, bool pauseTimer) const bool wasStopped = Timer ? Timer->isStopped() : true; if (pauseTimer && !wasStopped) Timer->stop(); - + SDL_Delay(timeMs); if (pauseTimer && !wasStopped) @@ -550,7 +695,7 @@ bool CIrrDeviceSDL::present(video::IImage* surface, void* windowId, core::rectgetDimension().Width, surface->getDimension().Height); + SDL_Flip(scr); } SDL_FreeSurface(sdlSurface); @@ -581,7 +726,7 @@ video::IVideoModeList* CIrrDeviceSDL::getVideoModeList() else { for (u32 i=0; modes[i]; ++i) - VideoModeList.addMode(core::dimension2d(modes[i]->w, modes[i]->h), vi->vfmt->BitsPerPixel); + VideoModeList.addMode(core::dimension2d(modes[i]->w, modes[i]->h), vi->vfmt->BitsPerPixel); } } } @@ -590,23 +735,42 @@ video::IVideoModeList* CIrrDeviceSDL::getVideoModeList() } -//! Sets if the window should be resizeable in windowed mode. -void CIrrDeviceSDL::setResizeAble(bool resize) +//! Sets if the window should be resizable in windowed mode. +void CIrrDeviceSDL::setResizable(bool resize) { - if (resize != Resizeable) + if (resize != Resizable) { if (resize) SDL_Flags |= SDL_RESIZABLE; else SDL_Flags &= ~SDL_RESIZABLE; - if (Screen) - SDL_FreeSurface(Screen); - Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); - Resizeable = resize; + Screen = SDL_SetVideoMode( 0, 0, 0, SDL_Flags ); + Resizable = resize; } } +//! Minimizes window if possible +void CIrrDeviceSDL::minimizeWindow() +{ + SDL_WM_IconifyWindow(); +} + + +//! Maximize window +void CIrrDeviceSDL::maximizeWindow() +{ + // do nothing +} + + +//! Restore original window size +void CIrrDeviceSDL::restoreWindow() +{ + // do nothing +} + + //! returns if window is active. if not, nothing need to be drawn bool CIrrDeviceSDL::isWindowActive() const { @@ -628,6 +792,25 @@ bool CIrrDeviceSDL::isWindowMinimized() const } +//! Set the current Gamma Value for the Display +bool CIrrDeviceSDL::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) +{ + /* + // todo: Gamma in SDL takes ints, what does Irrlicht use? + return (SDL_SetGamma(red, green, blue) != -1); + */ + return false; +} + +//! Get the current Gamma Value for the Display +bool CIrrDeviceSDL::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) +{ +/* brightness = 0.f; + contrast = 0.f; + return (SDL_GetGamma(&red, &green, &blue) != -1);*/ + return false; +} + //! returns color format of the window. video::ECOLOR_FORMAT CIrrDeviceSDL::getColorFormat() const { @@ -794,21 +977,7 @@ void CIrrDeviceSDL::createKeyMap() KeyMap.sort(); } -IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx(const SIrrlichtCreationParameters& param) -{ - CIrrDeviceSDL* dev = new CIrrDeviceSDL(param); - - if (dev && !dev->getVideoDriver() && param.DriverType != video::EDT_NULL) - { - dev->drop(); - dev = 0; - } - - return dev; -} - - } // end namespace irr -#endif // _IRR_USE_SDL_DEVICE_ +#endif // _IRR_COMPILE_WITH_SDL_DEVICE_ diff --git a/src/dep/src/irrlicht/CIrrDeviceSDL.h b/src/dep/src/irrlicht/CIrrDeviceSDL.h index 2dcbf53..be36ba0 100644 --- a/src/dep/src/irrlicht/CIrrDeviceSDL.h +++ b/src/dep/src/irrlicht/CIrrDeviceSDL.h @@ -1,212 +1,235 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h -// This device code is based on the original SDL device implementation -// contributed by Shane Parker (sirshane). - -#ifndef __C_IRR_DEVICE_SDL_H_INCLUDED__ -#define __C_IRR_DEVICE_SDL_H_INCLUDED__ - -#include "IrrCompileConfig.h" - -#ifdef _IRR_USE_SDL_DEVICE_ - -#include "IrrlichtDevice.h" -#include "CIrrDeviceStub.h" -#include "IImagePresenter.h" -#include "ICursorControl.h" - -#include - -namespace irr -{ - - class CIrrDeviceSDL : public CIrrDeviceStub, video::IImagePresenter - { - public: - - //! constructor - CIrrDeviceSDL(const SIrrlichtCreationParameters& param); - - //! destructor - virtual ~CIrrDeviceSDL(); - - //! runs the device. Returns false if device wants to be deleted - virtual bool run(); - - //! pause execution temporarily - virtual void yield(); - - //! pause execution for a specified time - virtual void sleep(u32 timeMs, bool pauseTimer); - - //! sets the caption of the window - virtual void setWindowCaption(const wchar_t* text); - - //! returns if window is active. if not, nothing need to be drawn - virtual bool isWindowActive() const; - - //! returns if window has focus. - bool isWindowFocused() const; - - //! returns if window is minimized. - bool isWindowMinimized() const; - - //! returns color format of the window. - video::ECOLOR_FORMAT getColorFormat() const; - - //! presents a surface in the client area - virtual bool present(video::IImage* surface, void* windowId=0, core::rect* src=0); - - //! notifies the device that it should close itself - virtual void closeDevice(); - - //! \return Returns a pointer to a list with all video modes supported - video::IVideoModeList* getVideoModeList(); - - //! Sets if the window should be resizeable in windowed mode. - virtual void setResizeAble(bool resize=false); - - //! Activate any joysticks, and generate events for them. - virtual bool activateJoysticks(core::array & joystickInfo); - - //! Implementation of the linux cursor control - class CCursorControl : public gui::ICursorControl - { - public: - - CCursorControl(CIrrDeviceSDL* dev) - : Device(dev), IsVisible(true) - { - } - - //! Changes the visible state of the mouse cursor. - virtual void setVisible(bool visible) - { - IsVisible = visible; - if ( visible ) - SDL_ShowCursor( SDL_ENABLE ); - else - SDL_ShowCursor( SDL_DISABLE ); - } - - //! Returns if the cursor is currently visible. - virtual bool isVisible() const - { - return IsVisible; - } - - //! Sets the new position of the cursor. - virtual void setPosition(const core::position2d &pos) - { - setPosition(pos.X, pos.Y); - } - - //! Sets the new position of the cursor. - virtual void setPosition(f32 x, f32 y) - { - setPosition((s32)(x*Device->Width), (s32)(y*Device->Height)); - } - - //! Sets the new position of the cursor. - virtual void setPosition(const core::position2d &pos) - { - setPosition(pos.X, pos.Y); - } - - //! Sets the new position of the cursor. - virtual void setPosition(s32 x, s32 y) - { - SDL_WarpMouse( x, y ); - } - - //! Returns the current position of the mouse cursor. - virtual core::position2d getPosition() - { - updateCursorPos(); - return CursorPos; - } - - //! Returns the current position of the mouse cursor. - virtual core::position2d getRelativePosition() - { - updateCursorPos(); - return core::position2d(CursorPos.X / (f32)Device->Width, - CursorPos.Y / (f32)Device->Height); - } - - virtual void setReferenceRect(core::rect* rect=0) - { - } - - private: - - void updateCursorPos() - { - CursorPos.X = Device->MouseX; - CursorPos.Y = Device->MouseY; - - if (CursorPos.X < 0) - CursorPos.X = 0; - if (CursorPos.X > (s32)Device->Width) - CursorPos.X = Device->Width; - if (CursorPos.Y < 0) - CursorPos.Y = 0; - if (CursorPos.Y > (s32)Device->Height) - CursorPos.Y = Device->Height; - } - - CIrrDeviceSDL* Device; - core::position2d CursorPos; - bool IsVisible; - }; - - private: - - //! create the driver - void createDriver(); - - bool createWindow(); - - void createKeyMap(); - - SDL_Surface* Screen; - int SDL_Flags; -#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) - core::array Joysticks; -#endif - - s32 MouseX, MouseY; - - u32 Width, Height; - - bool Close; - bool Resizeable; - bool WindowHasFocus; - bool WindowMinimized; - - struct SKeyMap - { - SKeyMap() {} - SKeyMap(s32 x11, s32 win32) - : SDLKey(x11), Win32Key(win32) - { - } - - s32 SDLKey; - s32 Win32Key; - - bool operator<(const SKeyMap& o) const - { - return SDLKey KeyMap; - }; - -} // end namespace irr - -#endif // _IRR_USE_SDL_DEVICE_ -#endif // __C_IRR_DEVICE_SDL_H_INCLUDED__ - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h +// This device code is based on the original SDL device implementation +// contributed by Shane Parker (sirshane). + +#ifndef __C_IRR_DEVICE_SDL_H_INCLUDED__ +#define __C_IRR_DEVICE_SDL_H_INCLUDED__ + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ + +#include "IrrlichtDevice.h" +#include "CIrrDeviceStub.h" +#include "IImagePresenter.h" +#include "ICursorControl.h" + +#include +#include + +namespace irr +{ + + class CIrrDeviceSDL : public CIrrDeviceStub, video::IImagePresenter + { + public: + + //! constructor + CIrrDeviceSDL(const SIrrlichtCreationParameters& param); + + //! destructor + virtual ~CIrrDeviceSDL(); + + //! runs the device. Returns false if device wants to be deleted + virtual bool run(); + + //! pause execution temporarily + virtual void yield(); + + //! pause execution for a specified time + virtual void sleep(u32 timeMs, bool pauseTimer); + + //! sets the caption of the window + virtual void setWindowCaption(const wchar_t* text); + + //! returns if window is active. if not, nothing need to be drawn + virtual bool isWindowActive() const; + + //! returns if window has focus. + bool isWindowFocused() const; + + //! returns if window is minimized. + bool isWindowMinimized() const; + + //! returns color format of the window. + video::ECOLOR_FORMAT getColorFormat() const; + + //! presents a surface in the client area + virtual bool present(video::IImage* surface, void* windowId=0, core::rect* src=0); + + //! notifies the device that it should close itself + virtual void closeDevice(); + + //! \return Returns a pointer to a list with all video modes supported + video::IVideoModeList* getVideoModeList(); + + //! Sets if the window should be resizable in windowed mode. + virtual void setResizable(bool resize=false); + + //! Minimizes the window. + virtual void minimizeWindow(); + + //! Maximizes the window. + virtual void maximizeWindow(); + + //! Restores the window size. + virtual void restoreWindow(); + + //! Activate any joysticks, and generate events for them. + virtual bool activateJoysticks(core::array & joystickInfo); + + //! Set the current Gamma Value for the Display + virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); + + //! Get the current Gamma Value for the Display + virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); + + //! Get the device type + virtual E_DEVICE_TYPE getType() const + { + return EIDT_SDL; + } + + //! Implementation of the linux cursor control + class CCursorControl : public gui::ICursorControl + { + public: + + CCursorControl(CIrrDeviceSDL* dev) + : Device(dev), IsVisible(true) + { + } + + //! Changes the visible state of the mouse cursor. + virtual void setVisible(bool visible) + { + IsVisible = visible; + if ( visible ) + SDL_ShowCursor( SDL_ENABLE ); + else + SDL_ShowCursor( SDL_DISABLE ); + } + + //! Returns if the cursor is currently visible. + virtual bool isVisible() const + { + return IsVisible; + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(f32 x, f32 y) + { + setPosition((s32)(x*Device->Width), (s32)(y*Device->Height)); + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(s32 x, s32 y) + { + SDL_WarpMouse( x, y ); + } + + //! Returns the current position of the mouse cursor. + virtual const core::position2d& getPosition() + { + updateCursorPos(); + return CursorPos; + } + + //! Returns the current position of the mouse cursor. + virtual core::position2d getRelativePosition() + { + updateCursorPos(); + return core::position2d(CursorPos.X / (f32)Device->Width, + CursorPos.Y / (f32)Device->Height); + } + + virtual void setReferenceRect(core::rect* rect=0) + { + } + + private: + + void updateCursorPos() + { + CursorPos.X = Device->MouseX; + CursorPos.Y = Device->MouseY; + + if (CursorPos.X < 0) + CursorPos.X = 0; + if (CursorPos.X > (s32)Device->Width) + CursorPos.X = Device->Width; + if (CursorPos.Y < 0) + CursorPos.Y = 0; + if (CursorPos.Y > (s32)Device->Height) + CursorPos.Y = Device->Height; + } + + CIrrDeviceSDL* Device; + core::position2d CursorPos; + bool IsVisible; + }; + + private: + + //! create the driver + void createDriver(); + + bool createWindow(); + + void createKeyMap(); + + SDL_Surface* Screen; + int SDL_Flags; +#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) + core::array Joysticks; +#endif + + s32 MouseX, MouseY; + u32 MouseButtonStates; + + u32 Width, Height; + + bool Resizable; + bool WindowHasFocus; + bool WindowMinimized; + + struct SKeyMap + { + SKeyMap() {} + SKeyMap(s32 x11, s32 win32) + : SDLKey(x11), Win32Key(win32) + { + } + + s32 SDLKey; + s32 Win32Key; + + bool operator<(const SKeyMap& o) const + { + return SDLKey KeyMap; + SDL_SysWMinfo Info; + }; + +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_SDL_DEVICE_ +#endif // __C_IRR_DEVICE_SDL_H_INCLUDED__ + diff --git a/src/dep/src/irrlicht/CIrrDeviceStub.cpp b/src/dep/src/irrlicht/CIrrDeviceStub.cpp index b420da2..9f54ad2 100644 --- a/src/dep/src/irrlicht/CIrrDeviceStub.cpp +++ b/src/dep/src/irrlicht/CIrrDeviceStub.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -15,12 +15,12 @@ namespace irr { - //! constructor CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params) -: IrrlichtDevice(), VideoDriver(0), GUIEnvironment(0), SceneManager(0), +: IrrlichtDevice(), VideoDriver(0), GUIEnvironment(0), SceneManager(0), Timer(0), CursorControl(0), UserReceiver(params.EventReceiver), Logger(0), Operator(0), - FileSystem(0), InputReceivingSceneManager(0), CreationParams(params) + FileSystem(0), InputReceivingSceneManager(0), CreationParams(params), + Close(false) { Timer = new CTimer(); if (os::Printer::Logger) @@ -34,6 +34,7 @@ CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params) Logger = new CLogger(UserReceiver); os::Printer::Logger = Logger; } + Logger->setLogLevel( CreationParams.LoggingLevel ); os::Printer::Logger = Logger; @@ -82,7 +83,7 @@ void CIrrDeviceStub::createGUIAndScene() #ifdef _IRR_COMPILE_WITH_GUI_ // create gui environment GUIEnvironment = gui::createGUIEnvironment(FileSystem, VideoDriver, Operator); - #endif + #endif // create Scene manager SceneManager = scene::createSceneManager(VideoDriver, FileSystem, CursorControl, GUIEnvironment); @@ -130,7 +131,7 @@ ITimer* CIrrDeviceStub::getTimer() } -//! Returns the version of the engine. +//! Returns the version of the engine. const char* CIrrDeviceStub::getVersion() const { return IRRLICHT_SDK_VERSION; @@ -171,6 +172,36 @@ bool CIrrDeviceStub::checkVersion(const char* version) } +//! Compares to the last call of this function to return double and triple clicks. +u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) +{ + const s32 MAX_MOUSEMOVE = 3; + + irr::u32 clickTime = getTimer()->getRealTime(); + + if ( (clickTime-MouseMultiClicks.LastClickTime) < MouseMultiClicks.DoubleClickTime + && core::abs_(MouseMultiClicks.LastClick.X - mouseX ) <= MAX_MOUSEMOVE + && core::abs_(MouseMultiClicks.LastClick.Y - mouseY ) <= MAX_MOUSEMOVE + && MouseMultiClicks.CountSuccessiveClicks < 3 + && MouseMultiClicks.LastMouseInputEvent == inputEvent + ) + { + ++MouseMultiClicks.CountSuccessiveClicks; + } + else + { + MouseMultiClicks.CountSuccessiveClicks = 1; + } + + MouseMultiClicks.LastMouseInputEvent = inputEvent; + MouseMultiClicks.LastClickTime = clickTime; + MouseMultiClicks.LastClick.X = mouseX; + MouseMultiClicks.LastClick.Y = mouseY; + + return MouseMultiClicks.CountSuccessiveClicks; +} + + //! send the event to the right receiver bool CIrrDeviceStub::postEventFromUser(const SEvent& event) { @@ -225,16 +256,15 @@ IOSOperator* CIrrDeviceStub::getOSOperator() } -//! Sets the input receiving scene manager. +//! Sets the input receiving scene manager. void CIrrDeviceStub::setInputReceivingSceneManager(scene::ISceneManager* sceneManager) { + if (sceneManager) + sceneManager->grab(); if (InputReceivingSceneManager) InputReceivingSceneManager->drop(); InputReceivingSceneManager = sceneManager; - - if (InputReceivingSceneManager) - InputReceivingSceneManager->grab(); } @@ -257,5 +287,78 @@ bool CIrrDeviceStub::activateJoysticks(core::array & joystickInfo return false; } +/*! +*/ +void CIrrDeviceStub::calculateGammaRamp ( u16 *ramp, f32 gamma, f32 relativebrightness, f32 relativecontrast ) +{ + s32 i; + s32 value; + s32 rbright = (s32) ( relativebrightness * (65535.f / 4 ) ); + f32 rcontrast = 1.f / (255.f - ( relativecontrast * 127.5f ) ); + + gamma = gamma > 0.f ? 1.0f / gamma : 0.f; + + for ( i = 0; i < 256; ++i ) + { + value = (s32)(pow( rcontrast * i, gamma)*65535.f + 0.5f ); + ramp[i] = (u16) core::s32_clamp ( value + rbright, 0, 65535 ); + } + +} + +void CIrrDeviceStub::calculateGammaFromRamp ( f32 &gamma, const u16 *ramp ) +{ + /* The following is adapted from a post by Garrett Bass on OpenGL + Gamedev list, March 4, 2000. + */ + f32 sum = 0.0; + s32 i, count = 0; + + gamma = 1.0; + for ( i = 1; i < 256; ++i ) { + if ( (ramp[i] != 0) && (ramp[i] != 65535) ) { + f32 B = (f32)i / 256.f; + f32 A = ramp[i] / 65535.f; + sum += (f32) ( logf(A) / logf(B) ); + count++; + } + } + if ( count && sum ) { + gamma = 1.0f / (sum / count); + } + +} + +//! Set the current Gamma Value for the Display +bool CIrrDeviceStub::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) +{ + return false; +} + +//! Get the current Gamma Value for the Display +bool CIrrDeviceStub::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) +{ + return false; +} + +//! Set the maximal elapsed time between 2 clicks to generate doubleclicks for the mouse. It also affects tripleclick behaviour. +void CIrrDeviceStub::setDoubleClickTime( u32 timeMs ) +{ + MouseMultiClicks.DoubleClickTime = timeMs; +} + +//! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse. +u32 CIrrDeviceStub::getDoubleClickTime() const +{ + return MouseMultiClicks.DoubleClickTime; +} + +//! Remove all messages pending in the system message loop +void CIrrDeviceStub::clearSystemMessages() +{ +} + + + } // end namespace irr diff --git a/src/dep/src/irrlicht/CIrrDeviceStub.h b/src/dep/src/irrlicht/CIrrDeviceStub.h index 8cc2c54..518d887 100644 --- a/src/dep/src/irrlicht/CIrrDeviceStub.h +++ b/src/dep/src/irrlicht/CIrrDeviceStub.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -19,13 +19,13 @@ namespace irr namespace gui { class IGUIEnvironment; - IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs, + IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* Driver, IOSOperator* op); } namespace scene { - ISceneManager* createSceneManager(video::IVideoDriver* driver, + ISceneManager* createSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, gui::ICursorControl* cc, gui::IGUIEnvironment *gui); } @@ -36,13 +36,13 @@ namespace irr namespace video { - IVideoDriver* createSoftwareDriver(const core::dimension2d& windowSize, + IVideoDriver* createSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter); - IVideoDriver* createSoftwareDriver2(const core::dimension2d& windowSize, + IVideoDriver* createSoftwareDriver2(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter); - IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize); + IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize); } @@ -79,7 +79,7 @@ namespace irr //! Returns a pointer to the ITimer object. With it the current Time can be received. virtual ITimer* getTimer(); - //! Returns the version of the engine. + //! Returns the version of the engine. virtual const char* getVersion() const; //! send the event to the right receiver @@ -91,7 +91,7 @@ namespace irr //! Returns pointer to the current event receiver. Returns 0 if there is none. virtual IEventReceiver* getEventReceiver(); - //! Sets the input receiving scene manager. + //! Sets the input receiving scene manager. /** If set to null, the main scene manager (returned by GetSceneManager()) will receive the input */ virtual void setInputReceivingSceneManager(scene::ISceneManager* sceneManager); @@ -110,6 +110,23 @@ namespace irr //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); + //! Set the current Gamma Value for the Display + virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); + + //! Get the current Gamma Value for the Display + virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); + + //! Set the maximal elapsed time between 2 clicks to generate doubleclicks for the mouse. It also affects tripleclick behaviour. + //! When set to 0 no double- and tripleclicks will be generated. + virtual void setDoubleClickTime( u32 timeMs ); + + //! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse. + virtual u32 getDoubleClickTime() const; + + //! Remove all messages pending in the system message loop + virtual void clearSystemMessages(); + + protected: void createGUIAndScene(); @@ -117,6 +134,13 @@ namespace irr //! checks version of SDK and prints warning if there might be a problem bool checkVersion(const char* version); + //! Compares to the last call of this function to return double and triple clicks. + //! \return Returns only 1,2 or 3. A 4th click will start with 1 again. + virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ); + + void calculateGammaRamp ( u16 *ramp, f32 gamma, f32 relativebrightness, f32 relativecontrast ); + void calculateGammaFromRamp ( f32 &gamma, const u16 *ramp ); + video::IVideoDriver* VideoDriver; gui::IGUIEnvironment* GUIEnvironment; scene::ISceneManager* SceneManager; @@ -127,8 +151,23 @@ namespace irr IOSOperator* Operator; io::IFileSystem* FileSystem; scene::ISceneManager* InputReceivingSceneManager; + + struct SMouseMultiClicks + { + SMouseMultiClicks() + : DoubleClickTime(500), CountSuccessiveClicks(0), LastClickTime(0), LastMouseInputEvent(EMIE_COUNT) + {} + + u32 DoubleClickTime; + u32 CountSuccessiveClicks; + u32 LastClickTime; + core::position2di LastClick; + EMOUSE_INPUT_EVENT LastMouseInputEvent; + }; + SMouseMultiClicks MouseMultiClicks; video::CVideoModeList VideoModeList; SIrrlichtCreationParameters CreationParams; + bool Close; }; } // end namespace irr diff --git a/src/dep/src/irrlicht/CIrrDeviceWin32.cpp b/src/dep/src/irrlicht/CIrrDeviceWin32.cpp index 3f0e22a..8f0a6d4 100644 --- a/src/dep/src/irrlicht/CIrrDeviceWin32.cpp +++ b/src/dep/src/irrlicht/CIrrDeviceWin32.cpp @@ -1,10 +1,10 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" -#ifdef _IRR_USE_WINDOWS_DEVICE_ +#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #include "CIrrDeviceWin32.h" #include "IEventReceiver.h" @@ -16,38 +16,202 @@ #include "COSOperator.h" #include "dimension2d.h" #include -#include "irrlicht.h" namespace irr { namespace video { #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ - IVideoDriver* createDirectX8Driver(const core::dimension2d& screenSize, HWND window, + IVideoDriver* createDirectX8Driver(const core::dimension2d& screenSize, HWND window, u32 bits, bool fullscreen, bool stencilbuffer, io::IFileSystem* io, - bool pureSoftware, bool highPrecisionFPU, bool vsync, bool antiAlias); + bool pureSoftware, bool highPrecisionFPU, bool vsync, u8 antiAlias); #endif #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ - IVideoDriver* createDirectX9Driver(const core::dimension2d& screenSize, HWND window, + IVideoDriver* createDirectX9Driver(const core::dimension2d& screenSize, HWND window, u32 bits, bool fullscreen, bool stencilbuffer, io::IFileSystem* io, - bool pureSoftware, bool highPrecisionFPU, bool vsync, bool antiAlias); + bool pureSoftware, bool highPrecisionFPU, bool vsync, u8 antiAlias); #endif #ifdef _IRR_COMPILE_WITH_OPENGL_ - IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io); + IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, + io::IFileSystem* io, CIrrDeviceWin32* device); #endif } } // end namespace irr - -struct SEnvMapper +// Get the codepage from the locale language id +// Based on the table from http://www.science.co.il/Language/Locale-Codes.asp?s=decimal +static unsigned int LocaleIdToCodepage(unsigned int lcid) { - HWND hWnd; - irr::CIrrDeviceWin32* irrDev; -}; + switch ( lcid ) + { + case 1098: // Telugu + case 1095: // Gujarati + case 1094: // Punjabi + case 1103: // Sanskrit + case 1111: // Konkani + case 1114: // Syriac + case 1099: // Kannada + case 1102: // Marathi + case 1125: // Divehi + case 1067: // Armenian + case 1081: // Hindi + case 1079: // Georgian + case 1097: // Tamil + return 0; + case 1054: // Thai + return 874; + case 1041: // Japanese + return 932; + case 2052: // Chinese (PRC) + case 4100: // Chinese (Singapore) + return 936; + case 1042: // Korean + return 949; + case 5124: // Chinese (Macau S.A.R.) + case 3076: // Chinese (Hong Kong S.A.R.) + case 1028: // Chinese (Taiwan) + return 950; + case 1048: // Romanian + case 1060: // Slovenian + case 1038: // Hungarian + case 1051: // Slovak + case 1045: // Polish + case 1052: // Albanian + case 2074: // Serbian (Latin) + case 1050: // Croatian + case 1029: // Czech + return 1250; + case 1104: // Mongolian (Cyrillic) + case 1071: // FYRO Macedonian + case 2115: // Uzbek (Cyrillic) + case 1058: // Ukrainian + case 2092: // Azeri (Cyrillic) + case 1092: // Tatar + case 1087: // Kazakh + case 1059: // Belarusian + case 1088: // Kyrgyz (Cyrillic) + case 1026: // Bulgarian + case 3098: // Serbian (Cyrillic) + case 1049: // Russian + return 1251; + case 8201: // English (Jamaica) + case 3084: // French (Canada) + case 1036: // French (France) + case 5132: // French (Luxembourg) + case 5129: // English (New Zealand) + case 6153: // English (Ireland) + case 1043: // Dutch (Netherlands) + case 9225: // English (Caribbean) + case 4108: // French (Switzerland) + case 4105: // English (Canada) + case 1110: // Galician + case 10249: // English (Belize) + case 3079: // German (Austria) + case 6156: // French (Monaco) + case 12297: // English (Zimbabwe) + case 1069: // Basque + case 2067: // Dutch (Belgium) + case 2060: // French (Belgium) + case 1035: // Finnish + case 1080: // Faroese + case 1031: // German (Germany) + case 3081: // English (Australia) + case 1033: // English (United States) + case 2057: // English (United Kingdom) + case 1027: // Catalan + case 11273: // English (Trinidad) + case 7177: // English (South Africa) + case 1030: // Danish + case 13321: // English (Philippines) + case 15370: // Spanish (Paraguay) + case 9226: // Spanish (Colombia) + case 5130: // Spanish (Costa Rica) + case 7178: // Spanish (Dominican Republic) + case 12298: // Spanish (Ecuador) + case 17418: // Spanish (El Salvador) + case 4106: // Spanish (Guatemala) + case 18442: // Spanish (Honduras) + case 3082: // Spanish (International Sort) + case 13322: // Spanish (Chile) + case 19466: // Spanish (Nicaragua) + case 2058: // Spanish (Mexico) + case 10250: // Spanish (Peru) + case 20490: // Spanish (Puerto Rico) + case 1034: // Spanish (Traditional Sort) + case 14346: // Spanish (Uruguay) + case 8202: // Spanish (Venezuela) + case 1089: // Swahili + case 1053: // Swedish + case 2077: // Swedish (Finland) + case 5127: // German (Liechtenstein) + case 1078: // Afrikaans + case 6154: // Spanish (Panama) + case 4103: // German (Luxembourg) + case 16394: // Spanish (Bolivia) + case 2055: // German (Switzerland) + case 1039: // Icelandic + case 1057: // Indonesian + case 1040: // Italian (Italy) + case 2064: // Italian (Switzerland) + case 2068: // Norwegian (Nynorsk) + case 11274: // Spanish (Argentina) + case 1046: // Portuguese (Brazil) + case 1044: // Norwegian (Bokmal) + case 1086: // Malay (Malaysia) + case 2110: // Malay (Brunei Darussalam) + case 2070: // Portuguese (Portugal) + return 1252; + case 1032: // Greek + return 1253; + case 1091: // Uzbek (Latin) + case 1068: // Azeri (Latin) + case 1055: // Turkish + return 1254; + case 1037: // Hebrew + return 1255; + case 5121: // Arabic (Algeria) + case 15361: // Arabic (Bahrain) + case 9217: // Arabic (Yemen) + case 3073: // Arabic (Egypt) + case 2049: // Arabic (Iraq) + case 11265: // Arabic (Jordan) + case 13313: // Arabic (Kuwait) + case 12289: // Arabic (Lebanon) + case 4097: // Arabic (Libya) + case 6145: // Arabic (Morocco) + case 8193: // Arabic (Oman) + case 16385: // Arabic (Qatar) + case 1025: // Arabic (Saudi Arabia) + case 10241: // Arabic (Syria) + case 14337: // Arabic (U.A.E.) + case 1065: // Farsi + case 1056: // Urdu + case 7169: // Arabic (Tunisia) + return 1256; + case 1061: // Estonian + case 1062: // Latvian + case 1063: // Lithuanian + return 1257; + case 1066: // Vietnamese + return 1258; + } + return 65001; // utf-8 +} -irr::core::list EnvMap; +namespace +{ + struct SEnvMapper + { + HWND hWnd; + irr::CIrrDeviceWin32* irrDev; + }; + irr::core::list EnvMap; + + HKL KEYBOARD_INPUT_HKL=0; + unsigned int KEYBOARD_INPUT_CODEPAGE = 1252; +}; SEnvMapper* getEnvMapperFromHWnd(HWND hWnd) { @@ -87,6 +251,103 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (GetCapture() != hWnd && ClickCount > 0) ClickCount = 0; + + struct messageMap + { + irr::s32 group; + UINT winMessage; + irr::s32 irrMessage; + }; + + static messageMap mouseMap[] = + { + {0, WM_LBUTTONDOWN, irr::EMIE_LMOUSE_PRESSED_DOWN}, + {1, WM_LBUTTONUP, irr::EMIE_LMOUSE_LEFT_UP}, + {0, WM_RBUTTONDOWN, irr::EMIE_RMOUSE_PRESSED_DOWN}, + {1, WM_RBUTTONUP, irr::EMIE_RMOUSE_LEFT_UP}, + {0, WM_MBUTTONDOWN, irr::EMIE_MMOUSE_PRESSED_DOWN}, + {1, WM_MBUTTONUP, irr::EMIE_MMOUSE_LEFT_UP}, + {2, WM_MOUSEMOVE, irr::EMIE_MOUSE_MOVED}, + {3, WM_MOUSEWHEEL, irr::EMIE_MOUSE_WHEEL}, + {-1, 0, 0} + }; + + // handle grouped events + messageMap * m = mouseMap; + while ( m->group >=0 && m->winMessage != message ) + m += 1; + + if ( m->group >= 0 ) + { + if ( m->group == 0 ) // down + { + ClickCount++; + SetCapture(hWnd); + } + else + if ( m->group == 1 ) // up + { + ClickCount--; + if (ClickCount<1) + { + ClickCount=0; + ReleaseCapture(); + } + } + + event.EventType = irr::EET_MOUSE_INPUT_EVENT; + event.MouseInput.Event = (irr::EMOUSE_INPUT_EVENT) m->irrMessage; + event.MouseInput.X = (short)LOWORD(lParam); + event.MouseInput.Y = (short)HIWORD(lParam); + event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); + event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); + // left and right mouse buttons + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); + // middle and extra buttons + if (wParam & MK_MBUTTON) + event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; +#if(_WIN32_WINNT >= 0x0500) + if (wParam & MK_XBUTTON1) + event.MouseInput.ButtonStates |= irr::EMBSM_EXTRA1; + if (wParam & MK_XBUTTON2) + event.MouseInput.ButtonStates |= irr::EMBSM_EXTRA2; +#endif + event.MouseInput.Wheel = 0.f; + + // wheel + if ( m->group == 3 ) + { + POINT p; // fixed by jox + p.x = 0; p.y = 0; + ClientToScreen(hWnd, &p); + event.MouseInput.X -= p.x; + event.MouseInput.Y -= p.y; + event.MouseInput.Wheel = ((irr::f32)((short)HIWORD(wParam))) / (irr::f32)WHEEL_DELTA; + } + + dev = getDeviceFromHWnd(hWnd); + if (dev) + { + dev->postEventFromUser(event); + + if ( event.MouseInput.Event >= irr::EMIE_LMOUSE_PRESSED_DOWN && event.MouseInput.Event <= irr::EMIE_MMOUSE_PRESSED_DOWN ) + { + irr::u32 clicks = dev->checkSuccessiveClicks(event.MouseInput.X, event.MouseInput.Y, event.MouseInput.Event); + if ( clicks == 2 ) + { + event.MouseInput.Event = (irr::EMOUSE_INPUT_EVENT)(irr::EMIE_LMOUSE_DOUBLE_CLICK + event.MouseInput.Event-irr::EMIE_LMOUSE_PRESSED_DOWN); + dev->postEventFromUser(event); + } + else if ( clicks == 3 ) + { + event.MouseInput.Event = (irr::EMOUSE_INPUT_EVENT)(irr::EMIE_LMOUSE_TRIPLE_CLICK + event.MouseInput.Event-irr::EMIE_LMOUSE_PRESSED_DOWN); + dev->postEventFromUser(event); + } + } + } + return 0; + } + switch (message) { case WM_PAINT: @@ -100,129 +361,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_ERASEBKGND: return 0; - case WM_SETCURSOR: - { - SEnvMapper* envm = getEnvMapperFromHWnd(hWnd); - if (envm && !envm->irrDev->getWin32CursorControl()->isVisible()) - { - SetCursor(NULL); - return 0; - } - } - break; - - case WM_MOUSEWHEEL: - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Wheel = ((irr::f32)((short)HIWORD(wParam))) / (irr::f32)WHEEL_DELTA; - event.MouseInput.Event = irr::EMIE_MOUSE_WHEEL; - - POINT p; // fixed by jox - p.x = 0; p.y = 0; - ClientToScreen(hWnd, &p); - event.MouseInput.X = LOWORD(lParam) - p.x; - event.MouseInput.Y = HIWORD(lParam) - p.y; - - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - break; - - case WM_LBUTTONDOWN: - ClickCount++; - SetCapture(hWnd); - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_LMOUSE_PRESSED_DOWN; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_LBUTTONUP: - ClickCount--; - if (ClickCount<1) - { - ClickCount=0; - ReleaseCapture(); - } - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_LMOUSE_LEFT_UP; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_RBUTTONDOWN: - ClickCount++; - SetCapture(hWnd); - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_RMOUSE_PRESSED_DOWN; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_RBUTTONUP: - ClickCount--; - if (ClickCount<1) - { - ClickCount=0; - ReleaseCapture(); - } - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_MBUTTONDOWN: - ClickCount++; - SetCapture(hWnd); - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_MMOUSE_PRESSED_DOWN; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_MBUTTONUP: - ClickCount--; - if (ClickCount<1) - { - ClickCount=0; - ReleaseCapture(); - } - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_MOUSEMOVE: - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_MOUSE_MOVED; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - - if (dev) - dev->postEventFromUser(event); - - return 0; - + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: case WM_KEYDOWN: case WM_KEYUP: { @@ -230,21 +370,65 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) event.EventType = irr::EET_KEY_INPUT_EVENT; event.KeyInput.Key = (irr::EKEY_CODE)wParam; - event.KeyInput.PressedDown = (message==WM_KEYDOWN); - dev = getDeviceFromHWnd(hWnd); + event.KeyInput.PressedDown = (message==WM_KEYDOWN || message == WM_SYSKEYDOWN); + + const UINT MY_MAPVK_VSC_TO_VK_EX = 3; // MAPVK_VSC_TO_VK_EX should be in SDK according to MSDN, but isn't in mine. + if ( event.KeyInput.Key == irr::KEY_SHIFT ) + { + // this will fail on systems before windows NT/2000/XP, not sure _what_ will return there instead. + event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX ); + } + if ( event.KeyInput.Key == irr::KEY_CONTROL ) + { + event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX ); + // some keyboards will just return LEFT for both - left and right keys. So also check extend bit. + if (lParam & 0x1000000) + event.KeyInput.Key = irr::KEY_RCONTROL; + } + if ( event.KeyInput.Key == irr::KEY_MENU ) + { + event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX ); + if (lParam & 0x1000000) + event.KeyInput.Key = irr::KEY_RMENU; + } - WORD KeyAsc=0; GetKeyboardState(allKeys); - ToAscii((UINT)wParam,(UINT)lParam,allKeys,&KeyAsc,0); event.KeyInput.Shift = ((allKeys[VK_SHIFT] & 0x80)!=0); event.KeyInput.Control = ((allKeys[VK_CONTROL] & 0x80)!=0); - event.KeyInput.Char = (KeyAsc & 0x00ff); //KeyAsc >= 0 ? KeyAsc : 0; + // Handle unicode and deadkeys in a way that works since Windows 95 and nt4.0 + // Using ToUnicode instead would be shorter, but would to my knowledge not run on 95 and 98. + WORD keyChars[2]; + UINT scanCode = HIWORD(lParam); + int conversionResult = ToAsciiEx(wParam,scanCode,allKeys,keyChars,0,KEYBOARD_INPUT_HKL); + if (conversionResult == 1) + { + WORD unicodeChar; + MultiByteToWideChar( + KEYBOARD_INPUT_CODEPAGE, + MB_PRECOMPOSED, // default + (LPCSTR)keyChars, + sizeof(keyChars), + (WCHAR*)&unicodeChar, + 1 ); + event.KeyInput.Char = unicodeChar; + } + else + event.KeyInput.Char = 0; + + // allow composing characters like '@' with Alt Gr on non-US keyboards + if ((allKeys[VK_MENU] & 0x80) != 0) + event.KeyInput.Control = 0; + + dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); - return 0; + if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP) + return DefWindowProc(hWnd, message, wParam, lParam); + else + return 0; } case WM_SIZE: @@ -267,6 +451,18 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; break; + case WM_ACTIVATE: + // we need to take care for screen changes, e.g. Alt-Tab + dev = getDeviceFromHWnd(hWnd); + if (dev) + { + if ((wParam&0xFF)==WA_INACTIVE) + dev->switchToFullScreen(true); + else + dev->switchToFullScreen(); + } + break; + case WM_USER: event.EventType = irr::EET_USER_EVENT; event.UserEvent.UserData1 = (irr::s32)wParam; @@ -277,6 +473,19 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) dev->postEventFromUser(event); return 0; + + case WM_SETCURSOR: + // because Windows forgot about that in the meantime + dev = getDeviceFromHWnd(hWnd); + if (dev) + dev->getCursorControl()->setVisible( dev->getCursorControl()->isVisible() ); + break; + + case WM_INPUTLANGCHANGE: + // get the new codepage used for keyboard input + KEYBOARD_INPUT_HKL = GetKeyboardLayout(0); + KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) ); + return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } @@ -307,17 +516,17 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) // create the window if we need to and we do not use the null device if (!CreationParams.WindowId && CreationParams.DriverType != video::EDT_NULL) { - const c8* ClassName = "CIrrDeviceWin32"; + const fschar_t* ClassName = __TEXT("CIrrDeviceWin32"); // Register Class WNDCLASSEX wcex; - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = (WNDPROC)WndProc; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; - wcex.hIcon = NULL; + wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = 0; @@ -325,7 +534,7 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) wcex.hIconSm = 0; // if there is an icon, load it - wcex.hIcon = (HICON)LoadImage(hInstance, "irrlicht.ico", IMAGE_ICON, 0,0, LR_LOADFROMFILE); + wcex.hIcon = (HICON)LoadImage(hInstance, __TEXT("irrlicht.ico"), IMAGE_ICON, 0,0, LR_LOADFROMFILE); RegisterClassEx(&wcex); @@ -350,6 +559,11 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; + if ( windowLeft < 0 ) + windowLeft = 0; + if ( windowTop < 0 ) + windowTop = 0; // make sure window menus are in screen on creation + if (CreationParams.Fullscreen) { windowLeft = 0; @@ -358,15 +572,20 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) // create window - HWnd = CreateWindow( ClassName, "", style, windowLeft, windowTop, + HWnd = CreateWindow( ClassName, __TEXT(""), style, windowLeft, windowTop, realWidth, realHeight, NULL, NULL, hInstance, NULL); CreationParams.WindowId = HWnd; +// CreationParams.WindowSize.Width = realWidth; +// CreationParams.WindowSize.Height = realHeight; ShowWindow(HWnd, SW_SHOW); UpdateWindow(HWnd); // fix ugly ATI driver bugs. Thanks to ariaci MoveWindow(HWnd, windowLeft, windowTop, realWidth, realHeight, TRUE); + + // make sure everything gets updated to the real sizes + Resized = true; } else if (CreationParams.WindowId) { @@ -385,6 +604,9 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) Win32CursorControl = new CCursorControl(CreationParams.WindowSize, HWnd, CreationParams.Fullscreen); CursorControl = Win32CursorControl; + // initialize doubleclicks with system values + MouseMultiClicks.DoubleClickTime = GetDoubleClickTime(); + // create driver createDriver(); @@ -402,6 +624,10 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) // set this as active window SetActiveWindow(HWnd); SetForegroundWindow(HWnd); + + // get the codepage used for keyboard input + KEYBOARD_INPUT_HKL = GetKeyboardLayout(0); + KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) ); } @@ -420,8 +646,7 @@ CIrrDeviceWin32::~CIrrDeviceWin32() } } - if (ChangedToFullScreen) - ChangeDisplaySettings(NULL,0); + switchToFullScreen(true); } @@ -433,9 +658,9 @@ void CIrrDeviceWin32::createDriver() case video::EDT_DIRECT3D8: #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ - VideoDriver = video::createDirectX8Driver(CreationParams.WindowSize, HWnd, - CreationParams.Bits, CreationParams.Fullscreen, CreationParams.Stencilbuffer, - FileSystem, false, CreationParams.HighPrecisionFPU, CreationParams.Vsync, + VideoDriver = video::createDirectX8Driver(CreationParams.WindowSize, HWnd, + CreationParams.Bits, CreationParams.Fullscreen, CreationParams.Stencilbuffer, + FileSystem, false, CreationParams.HighPrecisionFPU, CreationParams.Vsync, CreationParams.AntiAlias); if (!VideoDriver) @@ -451,9 +676,9 @@ void CIrrDeviceWin32::createDriver() case video::EDT_DIRECT3D9: #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ - VideoDriver = video::createDirectX9Driver(CreationParams.WindowSize, HWnd, - CreationParams.Bits, CreationParams.Fullscreen, CreationParams.Stencilbuffer, - FileSystem, false, CreationParams.HighPrecisionFPU, CreationParams.Vsync, + VideoDriver = video::createDirectX9Driver(CreationParams.WindowSize, HWnd, + CreationParams.Bits, CreationParams.Fullscreen, CreationParams.Stencilbuffer, + FileSystem, false, CreationParams.HighPrecisionFPU, CreationParams.Vsync, CreationParams.AntiAlias); if (!VideoDriver) @@ -469,11 +694,9 @@ void CIrrDeviceWin32::createDriver() case video::EDT_OPENGL: #ifdef _IRR_COMPILE_WITH_OPENGL_ + switchToFullScreen(); - if (CreationParams.Fullscreen) - switchToFullScreen(CreationParams.WindowSize.Width, CreationParams.WindowSize.Height, CreationParams.Bits); - - VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem); + VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this); if (!VideoDriver) { os::Printer::log("Could not create OpenGL driver.", ELL_ERROR); @@ -486,8 +709,7 @@ void CIrrDeviceWin32::createDriver() case video::EDT_SOFTWARE: #ifdef _IRR_COMPILE_WITH_SOFTWARE_ - if (CreationParams.Fullscreen) - switchToFullScreen(CreationParams.WindowSize.Width, CreationParams.WindowSize.Height, CreationParams.Bits); + switchToFullScreen(); VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); #else @@ -498,13 +720,12 @@ void CIrrDeviceWin32::createDriver() case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ - if (CreationParams.Fullscreen) - switchToFullScreen(CreationParams.WindowSize.Width, CreationParams.WindowSize.Height, CreationParams.Bits); + switchToFullScreen(); VideoDriver = video::createSoftwareDriver2(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); #else os::Printer::log("Burning's Video driver was not compiled in.", ELL_ERROR); - #endif + #endif break; case video::EDT_NULL: @@ -526,11 +747,10 @@ bool CIrrDeviceWin32::run() MSG msg; - bool quit = false; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); + // No message translation because we don't use WM_CHAR and it would conflict with our + // deadkey handling. if (ExternalWindow && msg.hwnd == HWnd) WndProc(HWnd, msg.message, msg.wParam, msg.lParam); @@ -538,17 +758,17 @@ bool CIrrDeviceWin32::run() DispatchMessage(&msg); if (msg.message == WM_QUIT) - quit = true; + Close = true; } - if (!quit) + if (!Close) resizeIfNecessary(); - if(!quit) + if(!Close) pollJoysticks(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return !quit; + return !Close; } @@ -556,7 +776,6 @@ bool CIrrDeviceWin32::run() void CIrrDeviceWin32::yield() { Sleep(1); - } //! Pause execution and let other processes to run for a specified amount of time. @@ -565,7 +784,7 @@ void CIrrDeviceWin32::sleep(u32 timeMs, bool pauseTimer) const bool wasStopped = Timer ? Timer->isStopped() : true; if (pauseTimer && !wasStopped) Timer->stop(); - + Sleep(timeMs); if (pauseTimer && !wasStopped) @@ -593,7 +812,8 @@ void CIrrDeviceWin32::resizeIfNecessary() sprintf(tmp, "Resizing window (%ld %ld)", r.right, r.bottom); os::Printer::log(tmp); - getVideoDriver()->OnResize(irr::core::dimension2d(r.right, r.bottom)); + getVideoDriver()->OnResize(irr::core::dimension2du((u32)r.right, (u32)r.bottom)); + getWin32CursorControl()->OnResize(getVideoDriver()->getScreenSize()); } Resized = false; @@ -607,14 +827,24 @@ void CIrrDeviceWin32::setWindowCaption(const wchar_t* text) if (IsNonNTWindows) { const core::stringc s = text; +#if defined(_WIN64) || defined(WIN64) + SetWindowTextA(HWnd, s.c_str()); +#else SendMessageTimeout(HWnd, WM_SETTEXT, 0, reinterpret_cast(s.c_str()), SMTO_ABORTIFHUNG, 2000, &dwResult); +#endif } else + { +#if defined(_WIN64) || defined(WIN64) + SetWindowTextW(HWnd, text); +#else SendMessageTimeoutW(HWnd, WM_SETTEXT, 0, reinterpret_cast(text), SMTO_ABORTIFHUNG, 2000, &dwResult); +#endif + } } @@ -639,7 +869,7 @@ bool CIrrDeviceWin32::present(video::IImage* image, void* windowId, core::rectgetBitsPerPixel(); bi.bV4Planes = 1; bi.bV4Width = image->getDimension().Width; - bi.bV4Height = -image->getDimension().Height; + bi.bV4Height = -((s32)image->getDimension().Height); bi.bV4V4Compression = BI_BITFIELDS; bi.bV4AlphaMask = image->getAlphaMask(); bi.bV4RedMask = image->getRedMask(); @@ -676,6 +906,7 @@ void CIrrDeviceWin32::closeDevice() PostQuitMessage(0); PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE); DestroyWindow(HWnd); + Close=true; } @@ -710,16 +941,26 @@ bool CIrrDeviceWin32::isWindowMinimized() const //! switches to fullscreen -bool CIrrDeviceWin32::switchToFullScreen(s32 width, s32 height, s32 bits) +bool CIrrDeviceWin32::switchToFullScreen(bool reset) { + if (!CreationParams.Fullscreen) + return true; + if (reset) + { + if (ChangedToFullScreen) + return (ChangeDisplaySettings(NULL,0)==DISP_CHANGE_SUCCESSFUL); + else + return true; + } + DEVMODE dm; memset(&dm, 0, sizeof(dm)); dm.dmSize = sizeof(dm); // use default values from current setting EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm); - dm.dmPelsWidth = width; - dm.dmPelsHeight = height; - dm.dmBitsPerPel = bits; + dm.dmPelsWidth = CreationParams.WindowSize.Width; + dm.dmPelsHeight = CreationParams.WindowSize.Height; + dm.dmBitsPerPel = CreationParams.Bits; dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; LONG res = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); @@ -776,150 +1017,233 @@ video::IVideoModeList* CIrrDeviceWin32::getVideoModeList() // enumerate video modes. DWORD i=0; DEVMODE mode; - memset(&mode, 0, sizeof(mode)); + memset(&mode, 0, sizeof(mode)); mode.dmSize = sizeof(mode); while (EnumDisplaySettings(NULL, i, &mode)) { - VideoModeList.addMode(core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight), + VideoModeList.addMode(core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight), mode.dmBitsPerPel); ++i; } if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &mode)) - VideoModeList.setDesktop(mode.dmBitsPerPel, core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight)); + VideoModeList.setDesktop(mode.dmBitsPerPel, core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight)); } return &VideoModeList; } +typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); +// Needed for old windows apis +#define PRODUCT_ULTIMATE 0x00000001 +#define PRODUCT_HOME_BASIC 0x00000002 +#define PRODUCT_HOME_PREMIUM 0x00000003 +#define PRODUCT_ENTERPRISE 0x00000004 +#define PRODUCT_HOME_BASIC_N 0x00000005 +#define PRODUCT_BUSINESS 0x00000006 +#define PRODUCT_STARTER 0x0000000B +#define PRODUCT_BUSINESS_N 0x00000010 +#define PRODUCT_HOME_PREMIUM_N 0x0000001A +#define PRODUCT_ENTERPRISE_N 0x0000001B +#define PRODUCT_ULTIMATE_N 0x0000001C +#define PRODUCT_STARTER_N 0x0000002F +#define PRODUCT_PROFESSIONAL 0x00000030 +#define PRODUCT_PROFESSIONAL_N 0x00000031 +#define PRODUCT_STARTER_E 0x00000042 +#define PRODUCT_HOME_BASIC_E 0x00000043 +#define PRODUCT_HOME_PREMIUM_E 0x00000044 +#define PRODUCT_PROFESSIONAL_E 0x00000045 +#define PRODUCT_ENTERPRISE_E 0x00000046 +#define PRODUCT_ULTIMATE_E 0x00000047 void CIrrDeviceWin32::getWindowsVersion(core::stringc& out) { - OSVERSIONINFOEX osvi; - BOOL bOsVersionInfoEx; + OSVERSIONINFOEX osvi; + PGPI pGPI; + BOOL bOsVersionInfoEx; - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi); - if (!bOsVersionInfoEx) - { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (! GetVersionEx((OSVERSIONINFO *) &osvi)) - return; - } + bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (! GetVersionEx((OSVERSIONINFO *) &osvi)) + return; + } - switch (osvi.dwPlatformId) - { - case VER_PLATFORM_WIN32_NT: - if (osvi.dwMajorVersion <= 4) - out.append("Microsoft Windows NT "); - else - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) - out.append("Microsoft Windows 2000 "); - else - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) - out.append("Microsoft Windows XP "); - else - if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) - out.append("Microsoft Windows Vista "); + switch (osvi.dwPlatformId) + { + case VER_PLATFORM_WIN32_NT: + if (osvi.dwMajorVersion <= 4) + out.append("Microsoft Windows NT "); + else + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + out.append("Microsoft Windows 2000 "); + else + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) + out.append("Microsoft Windows XP "); + else + if (osvi.dwMajorVersion == 6 ) + { + if (osvi.dwMinorVersion == 0) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + out.append("Microsoft Windows Vista "); + else + out.append("Microsoft Windows Server 2008 "); + } + else if (osvi.dwMinorVersion == 1) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + out.append("Microsoft Windows 7 "); + else + out.append("Microsoft Windows Server 2008 R2 "); + } + } - if (bOsVersionInfoEx) - { - #ifdef VER_SUITE_ENTERPRISE - if (osvi.wProductType == VER_NT_WORKSTATION) - { + if (bOsVersionInfoEx) + { + if (osvi.dwMajorVersion == 6) + { + DWORD dwType; + pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo"); + pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType); + + switch (dwType) + { + case PRODUCT_ULTIMATE: + case PRODUCT_ULTIMATE_E: + case PRODUCT_ULTIMATE_N: + out.append("Ultimate Edition "); + break; + case PRODUCT_PROFESSIONAL: + case PRODUCT_PROFESSIONAL_E: + case PRODUCT_PROFESSIONAL_N: + out.append("Professional Edition "); + break; + case PRODUCT_HOME_BASIC: + case PRODUCT_HOME_BASIC_E: + case PRODUCT_HOME_BASIC_N: + out.append("Home Basic Edition "); + break; + case PRODUCT_HOME_PREMIUM: + case PRODUCT_HOME_PREMIUM_E: + case PRODUCT_HOME_PREMIUM_N: + out.append("Home Premium Edition "); + break; + case PRODUCT_ENTERPRISE: + case PRODUCT_ENTERPRISE_E: + case PRODUCT_ENTERPRISE_N: + out.append("Enterprise Edition "); + break; + case PRODUCT_BUSINESS: + case PRODUCT_BUSINESS_N: + out.append("Business Edition "); + break; + case PRODUCT_STARTER: + case PRODUCT_STARTER_E: + case PRODUCT_STARTER_N: + out.append("Starter Edition "); + break; + } + } +#ifdef VER_SUITE_ENTERPRISE + else + if (osvi.wProductType == VER_NT_WORKSTATION) + { #ifndef __BORLANDC__ - if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) - out.append("Personal "); - else - out.append("Professional "); + if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) + out.append("Personal "); + else + out.append("Professional "); #endif - } - else if (osvi.wProductType == VER_NT_SERVER) - { - if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) - out.append("DataCenter Server "); - else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) - out.append("Advanced Server "); - else - out.append("Server "); - } - #endif - } - else - { - HKEY hKey; - char szProductType[80]; - DWORD dwBufLen; + } + else if (osvi.wProductType == VER_NT_SERVER) + { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + out.append("DataCenter Server "); + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + out.append("Advanced Server "); + else + out.append("Server "); + } +#endif + } + else + { + HKEY hKey; + char szProductType[80]; + DWORD dwBufLen; - RegOpenKeyEx( HKEY_LOCAL_MACHINE, - "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", - 0, KEY_QUERY_VALUE, &hKey ); - RegQueryValueEx( hKey, "ProductType", NULL, NULL, - (LPBYTE) szProductType, &dwBufLen); - RegCloseKey( hKey ); + RegOpenKeyEx( HKEY_LOCAL_MACHINE, + __TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), + 0, KEY_QUERY_VALUE, &hKey ); + RegQueryValueEx( hKey, __TEXT("ProductType"), NULL, NULL, + (LPBYTE) szProductType, &dwBufLen); + RegCloseKey( hKey ); - if (lstrcmpi( "WINNT", szProductType) == 0 ) - out.append("Professional "); - if (lstrcmpi( "LANMANNT", szProductType) == 0) - out.append("Server "); - if (lstrcmpi( "SERVERNT", szProductType) == 0) - out.append("Advanced Server "); - } + if (_strcmpi( "WINNT", szProductType) == 0 ) + out.append("Professional "); + if (_strcmpi( "LANMANNT", szProductType) == 0) + out.append("Server "); + if (_strcmpi( "SERVERNT", szProductType) == 0) + out.append("Advanced Server "); + } - // Display version, service pack (if any), and build number. + // Display version, service pack (if any), and build number. - char tmp[255]; + char tmp[255]; - if (osvi.dwMajorVersion <= 4 ) - { - sprintf(tmp, "version %ld.%ld %s (Build %ld)", - osvi.dwMajorVersion, - osvi.dwMinorVersion, - osvi.szCSDVersion, - osvi.dwBuildNumber & 0xFFFF); - } - else - { - sprintf(tmp, "%s (Build %ld)", osvi.szCSDVersion, - osvi.dwBuildNumber & 0xFFFF); - } + if (osvi.dwMajorVersion <= 4 ) + { + sprintf(tmp, "version %ld.%ld %s (Build %ld)", + osvi.dwMajorVersion, + osvi.dwMinorVersion, + osvi.szCSDVersion, + osvi.dwBuildNumber & 0xFFFF); + } + else + { + sprintf(tmp, "%s (Build %ld)", osvi.szCSDVersion, + osvi.dwBuildNumber & 0xFFFF); + } - out.append(tmp); - break; + out.append(tmp); + break; - case VER_PLATFORM_WIN32_WINDOWS: + case VER_PLATFORM_WIN32_WINDOWS: - IsNonNTWindows = true; + IsNonNTWindows = true; - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) - { - out.append("Microsoft Windows 95 "); - if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' ) - out.append("OSR2 " ); - } + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) + { + out.append("Microsoft Windows 95 "); + if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' ) + out.append("OSR2 " ); + } - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) - { - out.append("Microsoft Windows 98 "); - if ( osvi.szCSDVersion[1] == 'A' ) - out.append( "SE " ); - } + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) + { + out.append("Microsoft Windows 98 "); + if ( osvi.szCSDVersion[1] == 'A' ) + out.append( "SE " ); + } - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) - out.append("Microsoft Windows Me "); + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + out.append("Microsoft Windows Me "); - break; + break; - case VER_PLATFORM_WIN32s: + case VER_PLATFORM_WIN32s: - IsNonNTWindows = true; - out.append("Microsoft Win32s "); - break; - } + IsNonNTWindows = true; + out.append("Microsoft Win32s "); + break; + } } //! Notifies the device, that it has been resized @@ -928,8 +1252,8 @@ void CIrrDeviceWin32::OnResized() Resized = true; } -//! Sets if the window should be resizeable in windowed mode. -void CIrrDeviceWin32::setResizeAble(bool resize) +//! Sets if the window should be resizable in windowed mode. +void CIrrDeviceWin32::setResizable(bool resize) { if (ExternalWindow || !getVideoDriver() || CreationParams.Fullscreen) return; @@ -960,6 +1284,41 @@ void CIrrDeviceWin32::setResizeAble(bool resize) SetWindowPos(HWnd, HWND_TOP, windowLeft, windowTop, realWidth, realHeight, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_SHOWWINDOW); + + static_cast(CursorControl)->updateBorderSize(CreationParams.Fullscreen, resize); +} + + +//! Minimizes the window. +void CIrrDeviceWin32::minimizeWindow() +{ + WINDOWPLACEMENT wndpl; + wndpl.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(HWnd, &wndpl); + wndpl.showCmd = SW_SHOWMINNOACTIVE; + SetWindowPlacement(HWnd, &wndpl); +} + + +//! Maximizes the window. +void CIrrDeviceWin32::maximizeWindow() +{ + WINDOWPLACEMENT wndpl; + wndpl.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(HWnd, &wndpl); + wndpl.showCmd = SW_SHOWMAXIMIZED; + SetWindowPlacement(HWnd, &wndpl); +} + + +//! Restores the window to its original size. +void CIrrDeviceWin32::restoreWindow() +{ + WINDOWPLACEMENT wndpl; + wndpl.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(HWnd, &wndpl); + wndpl.showCmd = SW_SHOWNORMAL; + SetWindowPlacement(HWnd, &wndpl); } @@ -985,7 +1344,7 @@ bool CIrrDeviceWin32::activateJoysticks(core::array & joystickInf { if(JOYERR_NOERROR == joyGetPosEx(joystick, &info) && - JOYERR_NOERROR == joyGetDevCaps(joystick, + JOYERR_NOERROR == joyGetDevCaps(joystick, &activeJoystick.Caps, sizeof(activeJoystick.Caps))) { @@ -1007,7 +1366,7 @@ bool CIrrDeviceWin32::activateJoysticks(core::array & joystickInf { char logString[256]; (void)sprintf(logString, "Found joystick %d, %d axes, %d buttons '%s'", - joystick, joystickInfo[joystick].Axes, + joystick, joystickInfo[joystick].Axes, joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str()); os::Printer::log(logString, ELL_INFORMATION); } @@ -1026,21 +1385,28 @@ void CIrrDeviceWin32::pollJoysticks() u32 joystick; JOYINFOEX info; - info.dwSize = sizeof(info); - info.dwFlags = JOY_RETURNALL; for(joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) { + // needs to be reset for each joystick + // request ALL values and POV as continuous if possible + info.dwSize = sizeof(info); + info.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS; + const JOYCAPS & caps = ActiveJoysticks[joystick].Caps; + // if no POV is available don't ask for POV values + if (!(caps.wCaps & JOYCAPS_HASPOV)) + info.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS); if(JOYERR_NOERROR == joyGetPosEx(ActiveJoysticks[joystick].Index, &info)) { SEvent event; - const JOYCAPS & caps = ActiveJoysticks[joystick].Caps; event.EventType = irr::EET_JOYSTICK_INPUT_EVENT; event.JoystickEvent.Joystick = (u8)joystick; event.JoystickEvent.POV = (u16)info.dwPOV; - if(event.JoystickEvent.POV > 35900) + // set to undefined if no POV value was returned or the value + // is out of range + if (!(info.dwFlags & JOY_RETURNPOV) || (event.JoystickEvent.POV > 35900)) event.JoystickEvent.POV = 65535; for(int axis = 0; axis < SEvent::SJoystickEvent::NUMBER_OF_AXES; ++axis) @@ -1050,11 +1416,11 @@ void CIrrDeviceWin32::pollJoysticks() { default: case 6: - event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_V] = + event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_V] = (s16)((65535 * (info.dwVpos - caps.wVmin)) / (caps.wVmax - caps.wVmin) - 32768); case 5: - event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_U] = + event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_U] = (s16)((65535 * (info.dwUpos - caps.wUmin)) / (caps.wUmax - caps.wUmin) - 32768); case 4: @@ -1062,44 +1428,113 @@ void CIrrDeviceWin32::pollJoysticks() (s16)((65535 * (info.dwRpos - caps.wRmin)) / (caps.wRmax - caps.wRmin) - 32768); case 3: - event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Z] = + event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Z] = (s16)((65535 * (info.dwZpos - caps.wZmin)) / (caps.wZmax - caps.wZmin) - 32768); - + case 2: event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Y] = (s16)((65535 * (info.dwYpos - caps.wYmin)) / (caps.wYmax - caps.wYmin) - 32768); case 1: - event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_X] = + event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_X] = (s16)((65535 * (info.dwXpos - caps.wXmin)) / (caps.wXmax - caps.wXmin) - 32768); } - + event.JoystickEvent.ButtonStates = info.dwButtons; (void)postEventFromUser(event); } } #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ -} - -IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( - const SIrrlichtCreationParameters& parameters) -{ - CIrrDeviceWin32* dev = new CIrrDeviceWin32(parameters); - - if (dev && !dev->getVideoDriver() && parameters.DriverType != video::EDT_NULL) - { - dev->closeDevice(); // destroy window - dev->run(); // consume quit message - dev->drop(); - dev = 0; - } - - return dev; } +//! Set the current Gamma Value for the Display +bool CIrrDeviceWin32::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) +{ + bool r; + u16 ramp[3][256]; + + calculateGammaRamp( ramp[0], red, brightness, contrast ); + calculateGammaRamp( ramp[1], green, brightness, contrast ); + calculateGammaRamp( ramp[2], blue, brightness, contrast ); + + HDC dc = GetDC(0); + r = SetDeviceGammaRamp ( dc, ramp ) == TRUE; + ReleaseDC(HWnd, dc); + return r; +} + +//! Get the current Gamma Value for the Display +bool CIrrDeviceWin32::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) +{ + bool r; + u16 ramp[3][256]; + + HDC dc = GetDC(0); + r = GetDeviceGammaRamp ( dc, ramp ) == TRUE; + ReleaseDC(HWnd, dc); + + if ( r ) + { + calculateGammaFromRamp(red, ramp[0]); + calculateGammaFromRamp(green, ramp[1]); + calculateGammaFromRamp(blue, ramp[2]); + } + + brightness = 0.f; + contrast = 0.f; + + return r; + +} + +//! Remove all messages pending in the system message loop +void CIrrDeviceWin32::clearSystemMessages() +{ + MSG msg; + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + {} + while (PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) + {} +} + +// shows last error in a messagebox to help internal debugging. +void CIrrDeviceWin32::ReportLastWinApiError() +{ + // (based on code from ovidiucucu from http://www.codeguru.com/forum/showthread.php?t=318721) + LPCTSTR pszCaption = __TEXT("Windows SDK Error Report"); + DWORD dwError = GetLastError(); + + if(NOERROR == dwError) + { + MessageBox(NULL, __TEXT("No error"), pszCaption, MB_OK); + } + else + { + const DWORD dwFormatControl = FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM; + + LPVOID pTextBuffer = NULL; + DWORD dwCount = FormatMessage(dwFormatControl, + NULL, + dwError, + 0, + (LPTSTR) &pTextBuffer, + 0, + NULL); + if(0 != dwCount) + { + MessageBox(NULL, (LPCTSTR)pTextBuffer, pszCaption, MB_OK|MB_ICONERROR); + LocalFree(pTextBuffer); + } + else + { + MessageBox(NULL, __TEXT("Unknown error"), pszCaption, MB_OK|MB_ICONERROR); + } + } +} } // end namespace -#endif // _IRR_USE_WINDOWS_DEVICE_ - +#endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ diff --git a/src/dep/src/irrlicht/CIrrDeviceWin32.h b/src/dep/src/irrlicht/CIrrDeviceWin32.h index 0eb6052..0c87c19 100644 --- a/src/dep/src/irrlicht/CIrrDeviceWin32.h +++ b/src/dep/src/irrlicht/CIrrDeviceWin32.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,17 +6,18 @@ #define __C_IRR_DEVICE_WIN32_H_INCLUDED__ #include "IrrCompileConfig.h" -#ifdef _IRR_USE_WINDOWS_DEVICE_ +#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #include "CIrrDeviceStub.h" #include "IrrlichtDevice.h" #include "IImagePresenter.h" #define WIN32_LEAN_AND_MEAN -#include - -#include // For JOYCAPS - +#if !defined(_IRR_XBOX_PLATFORM_) + #include + #include // For JOYCAPS + #include +#endif namespace irr { @@ -65,20 +66,60 @@ namespace irr //! Notifies the device, that it has been resized void OnResized(); - //! Sets if the window should be resizeable in windowed mode. - virtual void setResizeAble(bool resize=false); + //! Sets if the window should be resizable in windowed mode. + virtual void setResizable(bool resize=false); + + //! Minimizes the window. + virtual void minimizeWindow(); + + //! Maximizes the window. + virtual void maximizeWindow(); + + //! Restores the window size. + virtual void restoreWindow(); //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); + //! Set the current Gamma Value for the Display + virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); + + //! Get the current Gamma Value for the Display + virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); + + //! Remove all messages pending in the system message loop + virtual void clearSystemMessages(); + + //! Get the device type + virtual E_DEVICE_TYPE getType() const + { + return EIDT_WIN32; + } + + //! Compares to the last call of this function to return double and triple clicks. + //! \return Returns only 1,2 or 3. A 4th click will start with 1 again. + virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) + { + // we just have to make it public + return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY, inputEvent ); + } + + //! switchs to fullscreen + bool switchToFullScreen(bool reset=false); + + //! Check for and show last Windows API error to help internal debugging. + //! Does call GetLastError and on errors formats the errortext and displays it in a messagebox. + static void ReportLastWinApiError(); + //! Implementation of the win32 cursor control class CCursorControl : public gui::ICursorControl { public: - CCursorControl(const core::dimension2d& wsize, HWND hwnd, bool fullscreen) - : WindowSize(wsize), InvWindowSize(0.0f, 0.0f), IsVisible(true), - HWnd(hwnd), BorderX(0), BorderY(0), UseReferenceRect(false) + CCursorControl(const core::dimension2d& wsize, HWND hwnd, bool fullscreen) + : WindowSize(wsize), InvWindowSize(0.0f, 0.0f), + HWnd(hwnd), BorderX(0), BorderY(0), + UseReferenceRect(false), IsVisible(true) { if (WindowSize.Width!=0) InvWindowSize.Width = 1.0f / WindowSize.Width; @@ -86,19 +127,31 @@ namespace irr if (WindowSize.Height!=0) InvWindowSize.Height = 1.0f / WindowSize.Height; - if (!fullscreen) - { - BorderX = GetSystemMetrics(SM_CXDLGFRAME); - BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME); - } + updateBorderSize(fullscreen, false); } //! Changes the visible state of the mouse cursor. virtual void setVisible(bool visible) { + CURSORINFO info; + info.cbSize = sizeof(CURSORINFO); + BOOL gotCursorInfo = GetCursorInfo(&info); + while ( gotCursorInfo ) + { + if ( (visible && info.flags == CURSOR_SHOWING) // visible + || (!visible && info.flags == 0 ) ) // hidden + { + break; + } + int showResult = ShowCursor(visible); // this only increases an internal display counter in windows, so it might have to be called some more + if ( showResult < 0 ) + { + break; + } + info.cbSize = sizeof(CURSORINFO); // yes, it really must be set each time + gotCursorInfo = GetCursorInfo(&info); + } IsVisible = visible; - updateInternalCursorPosition(); - setPosition(CursorPos.X, CursorPos.Y); } //! Returns if the cursor is currently visible. @@ -118,9 +171,9 @@ namespace irr virtual void setPosition(f32 x, f32 y) { if (!UseReferenceRect) - setPosition((s32)(x*WindowSize.Width), (s32)(y*WindowSize.Height)); + setPosition(core::round32(x*WindowSize.Width), core::round32(y*WindowSize.Height)); else - setPosition((s32)(x*ReferenceRect.getWidth()), (s32)(y*ReferenceRect.getHeight())); + setPosition(core::round32(x*ReferenceRect.getWidth()), core::round32(y*ReferenceRect.getHeight())); } //! Sets the new position of the cursor. @@ -132,15 +185,14 @@ namespace irr //! Sets the new position of the cursor. virtual void setPosition(s32 x, s32 y) { - RECT rect; - if (UseReferenceRect) { - SetCursorPos(ReferenceRect.UpperLeftCorner.X + x, + SetCursorPos(ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y); } else { + RECT rect; if (GetWindowRect(HWnd, &rect)) SetCursorPos(x + rect.left + BorderX, y + rect.top + BorderY); } @@ -150,7 +202,7 @@ namespace irr } //! Returns the current position of the mouse cursor. - virtual core::position2d getPosition() + virtual const core::position2d& getPosition() { updateInternalCursorPosition(); return CursorPos; @@ -191,14 +243,55 @@ namespace irr UseReferenceRect = false; } + /** Used to notify the cursor that the window was resized. */ + virtual void OnResize(const core::dimension2d& size) + { + WindowSize = size; + if (size.Width!=0) + InvWindowSize.Width = 1.0f / size.Width; + else + InvWindowSize.Width = 0.f; + + if (size.Height!=0) + InvWindowSize.Height = 1.0f / size.Height; + else + InvWindowSize.Height = 0.f; + } + + /** Used to notify the cursor that the window resizable settings changed. */ + void updateBorderSize(bool fullscreen, bool resizable) + { + if (!fullscreen) + { + if (resizable) + { + BorderX = GetSystemMetrics(SM_CXSIZEFRAME); + BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME); + } + else + { + BorderX = GetSystemMetrics(SM_CXDLGFRAME); + BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME); + } + } + else + { + BorderX = BorderY = 0; + } + } + private: //! Updates the internal cursor position void updateInternalCursorPosition() { POINT p; - GetCursorPos(&p); - RECT rect; + if (!GetCursorPos(&p)) + { + DWORD xy = GetMessagePos(); + p.x = GET_X_LPARAM(xy); + p.y = GET_Y_LPARAM(xy); + } if (UseReferenceRect) { @@ -207,6 +300,7 @@ namespace irr } else { + RECT rect; if (GetWindowRect(HWnd, &rect)) { CursorPos.X = p.x-rect.left-BorderX; @@ -223,14 +317,14 @@ namespace irr } core::position2d CursorPos; - core::dimension2d WindowSize; + core::dimension2d WindowSize; core::dimension2d InvWindowSize; - bool IsVisible; HWND HWnd; s32 BorderX, BorderY; - bool UseReferenceRect; core::rect ReferenceRect; + bool UseReferenceRect; + bool IsVisible; }; //! returns the win32 cursor control @@ -241,14 +335,11 @@ namespace irr //! create the driver void createDriver(); - //! switchs to fullscreen - bool switchToFullScreen(s32 width, s32 height, s32 bits); - void getWindowsVersion(core::stringc& version); void resizeIfNecessary(); - void pollJoysticks(); + void pollJoysticks(); HWND HWnd; @@ -258,16 +349,17 @@ namespace irr bool ExternalWindow; CCursorControl* Win32CursorControl; +#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) struct JoystickInfo { u32 Index; JOYCAPS Caps; }; core::array ActiveJoysticks; +#endif }; } // end namespace irr -#endif -#endif - +#endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ +#endif // __C_IRR_DEVICE_WIN32_H_INCLUDED__ diff --git a/src/dep/src/irrlicht/CIrrDeviceWinCE.cpp b/src/dep/src/irrlicht/CIrrDeviceWinCE.cpp index 6085ba5..4279c1c 100644 --- a/src/dep/src/irrlicht/CIrrDeviceWinCE.cpp +++ b/src/dep/src/irrlicht/CIrrDeviceWinCE.cpp @@ -1,10 +1,10 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" -#ifdef _IRR_USE_WINDOWS_CE_DEVICE_ +#ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ #include "CIrrDeviceWinCE.h" #include "IEventReceiver.h" @@ -40,7 +40,7 @@ namespace irr #endif #ifdef _IRR_COMPILE_WITH_OPENGL_ - IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io); + IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, this); #endif } } // end namespace irr @@ -127,6 +127,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) ClientToScreen(hWnd, &p); event.MouseInput.X = LOWORD(lParam) - p.x; event.MouseInput.Y = HIWORD(lParam) - p.y; + event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); + event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); + // left and right mouse buttons + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); + // middle and extra buttons + if (wParam & MK_MBUTTON) + event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; dev = getDeviceFromHWnd(hWnd); if (dev) @@ -140,6 +147,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) event.MouseInput.Event = irr::EMIE_LMOUSE_PRESSED_DOWN; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); + event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); + event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); + // left and right mouse buttons + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); + // middle and extra buttons + if (wParam & MK_MBUTTON) + event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; + dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); @@ -156,6 +171,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) event.MouseInput.Event = irr::EMIE_LMOUSE_LEFT_UP; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); + event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); + event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); + // left and right mouse buttons + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); + // middle and extra buttons + if (wParam & MK_MBUTTON) + event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; + dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); @@ -168,6 +191,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) event.MouseInput.Event = irr::EMIE_RMOUSE_PRESSED_DOWN; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); + event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); + event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); + // left and right mouse buttons + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); + // middle and extra buttons + if (wParam & MK_MBUTTON) + event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; + dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); @@ -184,6 +215,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) event.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); + event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); + event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); + // left and right mouse buttons + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); + // middle and extra buttons + if (wParam & MK_MBUTTON) + event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; + dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); @@ -196,6 +235,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) event.MouseInput.Event = irr::EMIE_MMOUSE_PRESSED_DOWN; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); + event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); + event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); + // left and right mouse buttons + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); + // middle and extra buttons + if (wParam & MK_MBUTTON) + event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; + dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); @@ -212,6 +259,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) event.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); + event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); + event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); + // left and right mouse buttons + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); + // middle and extra buttons + if (wParam & MK_MBUTTON) + event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; + dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); @@ -222,19 +277,28 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) event.MouseInput.Event = irr::EMIE_MOUSE_MOVED; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); + event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); + event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); + // left and right mouse buttons + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); + // middle and extra buttons + if (wParam & MK_MBUTTON) + event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; + dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); return 0; + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: case WM_KEYDOWN: case WM_KEYUP: { event.EventType = irr::EET_KEY_INPUT_EVENT; event.KeyInput.Key = (irr::EKEY_CODE)wParam; - event.KeyInput.PressedDown = (message==WM_KEYDOWN); + event.KeyInput.PressedDown = (message==WM_KEYDOWN || message == WM_SYSKEYDOWN); dev = getDeviceFromHWnd(hWnd); /* WORD KeyAsc=0; @@ -297,7 +361,7 @@ CIrrDeviceWinCE::CIrrDeviceWinCE(const SIrrlichtCreationParameters& params) // Register Class WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC)WndProc; + wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; @@ -308,7 +372,7 @@ CIrrDeviceWinCE::CIrrDeviceWinCE(const SIrrlichtCreationParameters& params) wc.lpszClassName = ClassName; // if there is an icon, load it - wc.hIcon = (HICON)LoadImageW(hInstance, L"irrlicht.ico", IMAGE_ICON, 0,0, 0); + wc.hIcon = (HICON)LoadImageW(hInstance, L"irrlicht.ico", IMAGE_ICON, 0,0, 0); RegisterClass(&wc); @@ -466,7 +530,7 @@ void CIrrDeviceWinCE::createDriver() VideoDriver = video::createSoftwareDriver2(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); #else os::Printer::log("Burning's Video driver was not compiled in.", ELL_ERROR); - #endif + #endif break; case video::EDT_NULL: @@ -488,8 +552,6 @@ bool CIrrDeviceWinCE::run() MSG msg; - bool quit = false; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); @@ -500,14 +562,14 @@ bool CIrrDeviceWinCE::run() DispatchMessage(&msg); if (msg.message == WM_QUIT) - quit = true; + Close = true; } - if (!quit) + if (!Close) resizeIfNecessary(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return !quit; + return !Close; } @@ -524,7 +586,7 @@ void CIrrDeviceWinCE::sleep(u32 timeMs, bool pauseTimer) const bool wasStopped = Timer ? Timer->isStopped() : true; if (pauseTimer && !wasStopped) Timer->stop(); - + Sleep(timeMs); if (pauseTimer && !wasStopped) @@ -552,7 +614,8 @@ void CIrrDeviceWinCE::resizeIfNecessary() sprintf(tmp, "Resizing window (%ld %ld)", r.right, r.bottom); os::Printer::log(tmp); - getVideoDriver()->OnResize(irr::core::dimension2d(r.right, r.bottom)); + getVideoDriver()->OnResize(irr::core::dimension2d(r.right, r.bottom)); + getWin32CursorControl()->OnResize(getVideoDriver()->getScreenSize()); } Resized = false; @@ -585,7 +648,7 @@ typedef struct { DWORD bV4AlphaMask; DWORD bV4CSType; DWORD un[9]; -} BITMAPV4HEADER, *PBITMAPV4HEADER; +} BITMAPV4HEADER, *PBITMAPV4HEADER; #endif @@ -610,7 +673,7 @@ bool CIrrDeviceWinCE::present(video::IImage* image, void* windowId, core::rectgetBitsPerPixel(); bi.bV4Planes = 1; bi.bV4Width = image->getDimension().Width; - bi.bV4Height = -image->getDimension().Height; + bi.bV4Height = 0 - image->getDimension().Height; bi.bV4V4Compression = BI_BITFIELDS; bi.bV4AlphaMask = image->getAlphaMask (); bi.bV4RedMask = image->getRedMask (); @@ -648,6 +711,7 @@ void CIrrDeviceWinCE::closeDevice() PostQuitMessage(0); PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE); DestroyWindow(HWnd); + Close=true; } @@ -709,19 +773,19 @@ video::IVideoModeList* CIrrDeviceWinCE::getVideoModeList() // enumerate video modes. DWORD i=0; DEVMODE mode; - memset(&mode, 0, sizeof(mode)); + memset(&mode, 0, sizeof(mode)); mode.dmSize = sizeof(mode); while (EnumDisplaySettings(NULL, i, &mode)) { - VideoModeList.addMode(core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight), + VideoModeList.addMode(core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight), mode.dmBitsPerPel); ++i; } if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &mode)) - VideoModeList.setDesktop(mode.dmBitsPerPel, core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight)); + VideoModeList.setDesktop(mode.dmBitsPerPel, core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight)); } return &VideoModeList; @@ -741,8 +805,8 @@ void CIrrDeviceWinCE::OnResized() } -//! Sets if the window should be resizeable in windowed mode. -void CIrrDeviceWinCE::setResizeAble(bool resize) +//! Sets if the window should be resizable in windowed mode. +void CIrrDeviceWinCE::setResizable(bool resize) { if (ExternalWindow || !getVideoDriver() || CreationParams.Fullscreen) return; @@ -776,24 +840,27 @@ void CIrrDeviceWinCE::setResizeAble(bool resize) } -IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( - const SIrrlichtCreationParameters& parameters) +//! Minimizes the window. +void CIrrDeviceWinCE::minimizeWindow() { - CIrrDeviceWinCE* dev = new CIrrDeviceWinCE(parameters); + // do nothing +} - if (dev && !dev->getVideoDriver() && parameters.DriverType != video::EDT_NULL) - { - dev->closeDevice(); // destroy window - dev->run(); // consume quit message - dev->drop(); - dev = 0; - } +//! Maximize window +void CIrrDeviceWinCE::maximizeWindow() +{ + // do nothing +} - return dev; + +//! Restore original window size +void CIrrDeviceWinCE::restoreWindow() +{ + // do nothing } } // end namespace -#endif // _IRR_USE_WINDOWS_CE_DEVICE_ +#endif // _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ diff --git a/src/dep/src/irrlicht/CIrrDeviceWinCE.h b/src/dep/src/irrlicht/CIrrDeviceWinCE.h index a96272e..6f7b811 100644 --- a/src/dep/src/irrlicht/CIrrDeviceWinCE.h +++ b/src/dep/src/irrlicht/CIrrDeviceWinCE.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,7 +6,7 @@ #define __C_IRR_DEVICE_WINCE_H_INCLUDED__ #include "IrrCompileConfig.h" -#ifdef _IRR_USE_WINDOWS_CE_DEVICE_ +#ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ #include "CIrrDeviceStub.h" #include "IrrlichtDevice.h" @@ -66,17 +66,33 @@ namespace irr //! Notifies the device, that it has been resized void OnResized(); - //! Sets if the window should be resizeable in windowed mode. - virtual void setResizeAble(bool resize=false); + //! Sets if the window should be resizable in windowed mode. + virtual void setResizable(bool resize=false); + + //! Minimizes the window. + virtual void minimizeWindow(); + + //! Maximizes the window. + virtual void maximizeWindow(); + + //! Restores the window size. + virtual void restoreWindow(); + + //! Get the device type + virtual E_DEVICE_TYPE getType() const + { + return EIDT_WINCE; + } //! Implementation of the win32 cursor control class CCursorControl : public gui::ICursorControl { public: - CCursorControl(const core::dimension2d& wsize, HWND hwnd, bool fullscreen) - : WindowSize(wsize), InvWindowSize(0.0f, 0.0f), IsVisible(true), - HWnd(hwnd), BorderX(0), BorderY(0), UseReferenceRect(false) + CCursorControl(const core::dimension2d& wsize, HWND hwnd, bool fullscreen) + : WindowSize(wsize), InvWindowSize(0.0f, 0.0f), + HWnd(hwnd), BorderX(0), BorderY(0), + UseReferenceRect(false), IsVisible(true) { if (WindowSize.Width!=0) InvWindowSize.Width = 1.0f / WindowSize.Width; @@ -114,9 +130,9 @@ namespace irr virtual void setPosition(f32 x, f32 y) { if (!UseReferenceRect) - setPosition((s32)(x*WindowSize.Width), (s32)(y*WindowSize.Height)); + setPosition(core::round32(x*WindowSize.Width), core::round32(y*WindowSize.Height)); else - setPosition((s32)(x*ReferenceRect.getWidth()), (s32)(y*ReferenceRect.getHeight())); + setPosition(core::round32(x*ReferenceRect.getWidth()), core::round32(y*ReferenceRect.getHeight())); } //! Sets the new position of the cursor. @@ -132,7 +148,7 @@ namespace irr if (UseReferenceRect) { - SetCursorPos(ReferenceRect.UpperLeftCorner.X + x, + SetCursorPos(ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y); } else @@ -146,7 +162,7 @@ namespace irr } //! Returns the current position of the mouse cursor. - virtual core::position2d getPosition() + virtual const core::position2d& getPosition() { updateInternalCursorPosition(); return CursorPos; @@ -187,14 +203,33 @@ namespace irr UseReferenceRect = false; } + /** Used to notify the cursor that the window was resized. */ + virtual void OnResize(const core::dimension2d& size) + { + WindowSize = size; + if (size.Width!=0) + InvWindowSize.Width = 1.0f / size.Width; + else + InvWindowSize.Width = 0.f; + + if (size.Height!=0) + InvWindowSize.Height = 1.0f / size.Height; + else + InvWindowSize.Height = 0.f; + } + private: //! Updates the internal cursor position void updateInternalCursorPosition() { POINT p; - GetCursorPos(&p); - RECT rect; + if (!GetCursorPos(&p)) + { + DWORD xy = GetMessagePos(); + p.x = GET_X_LPARAM(xy); + p.y = GET_Y_LPARAM(xy); + } if (UseReferenceRect) { @@ -203,6 +238,7 @@ namespace irr } else { + RECT rect; if (GetWindowRect(HWnd, &rect)) { CursorPos.X = p.x-rect.left-BorderX; @@ -221,12 +257,12 @@ namespace irr core::position2d CursorPos; core::dimension2d WindowSize; core::dimension2d InvWindowSize; - bool IsVisible; HWND HWnd; s32 BorderX, BorderY; - bool UseReferenceRect; core::rect ReferenceRect; + bool UseReferenceRect; + bool IsVisible; }; @@ -256,6 +292,5 @@ namespace irr } // end namespace irr -#endif -#endif - +#endif // _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ +#endif // __C_IRR_DEVICE_WINCE_H_INCLUDED__ diff --git a/src/dep/src/irrlicht/CIrrMeshFileLoader.cpp b/src/dep/src/irrlicht/CIrrMeshFileLoader.cpp index eeafa6d..117ef55 100644 --- a/src/dep/src/irrlicht/CIrrMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CIrrMeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -13,6 +13,7 @@ #include "IReadFile.h" #include "IAttributes.h" #include "IMeshSceneNode.h" +#include "CDynamicMeshBuffer.h" #include "SMeshBufferLightMap.h" namespace irr @@ -36,10 +37,9 @@ CIrrMeshFileLoader::CIrrMeshFileLoader(scene::ISceneManager* smgr, //! Returns true if the file maybe is able to be loaded by this class. /** This decision should be based only on the file extension (e.g. ".cob") */ -bool CIrrMeshFileLoader::isALoadableFileExtension(const c8* fileName) const +bool CIrrMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(fileName, ".xml") || - strstr(fileName, ".irrmesh"); + return core::hasFileExtension ( filename, "xml", "irrmesh" ); } @@ -139,10 +139,7 @@ IAnimatedMesh* CIrrMeshFileLoader::readMesh(io::IXMLReader* reader) //! reads a mesh sections and creates a mesh buffer from it IMeshBuffer* CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader) { - IMeshBuffer* buffer = 0; - SMeshBuffer* sbuffer1 = 0; - SMeshBufferLightMap* sbuffer2 = 0; - SMeshBufferTangents* sbuffer3 = 0; + CDynamicMeshBuffer* buffer = 0; core::stringc verticesSectionName = "vertices"; core::stringc bbSectionName = "boundingBox"; @@ -185,38 +182,33 @@ IMeshBuffer* CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader) { // vertices section - core::stringc vertexTypeName1 = "standard"; - core::stringc vertexTypeName2 = "2tcoords"; - core::stringc vertexTypeName3 = "tangents"; + const core::stringc vertexTypeName1 = "standard"; + const core::stringc vertexTypeName2 = "2tcoords"; + const core::stringc vertexTypeName3 = "tangents"; const wchar_t* vertexType = reader->getAttributeValue(L"type"); vertexCount = reader->getAttributeValueAsInt(L"vertexCount"); insideVertexSection = true; + video::E_INDEX_TYPE itype = (vertexCount > 65536)?irr::video::EIT_32BIT:irr::video::EIT_16BIT; if (vertexTypeName1 == vertexType) { - sbuffer1 = new SMeshBuffer(); - sbuffer1->Vertices.reallocate(vertexCount); - sbuffer1->Material = material; - buffer = sbuffer1; + buffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, itype); + } else if (vertexTypeName2 == vertexType) { - sbuffer2 = new SMeshBufferLightMap(); - sbuffer2->Vertices.reallocate(vertexCount); - sbuffer2->Material = material; - buffer = sbuffer2; + buffer = new CDynamicMeshBuffer(irr::video::EVT_2TCOORDS, itype); } else if (vertexTypeName3 == vertexType) { - sbuffer3 = new SMeshBufferTangents(); - sbuffer3->Vertices.reallocate(vertexCount); - sbuffer3->Material = material; - buffer = sbuffer3; + buffer = new CDynamicMeshBuffer(irr::video::EVT_TANGENTS, itype); } + buffer->getVertexBuffer().reallocate(vertexCount); + buffer->Material = material; } else if (indicesSectionName == nodeName) @@ -234,30 +226,14 @@ IMeshBuffer* CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader) // read vertex data if (insideVertexSection) { - if (sbuffer1) - readMeshBuffer(reader, vertexCount, sbuffer1); - else - if (sbuffer2) - readMeshBuffer(reader, vertexCount, sbuffer2); - else - if (sbuffer3) - readMeshBuffer(reader, vertexCount, sbuffer3); - + readMeshBuffer(reader, vertexCount, buffer); insideVertexSection = false; } // end reading vertex array else if (insideIndexSection) { - if (sbuffer1) - readIndices(reader, indexCount, sbuffer1->Indices); - else - if (sbuffer2) - readIndices(reader, indexCount, sbuffer2->Indices); - else - if (sbuffer3) - readIndices(reader, indexCount, sbuffer3->Indices); - + readIndices(reader, indexCount, buffer->getIndexBuffer()); insideIndexSection = false; } @@ -281,7 +257,7 @@ IMeshBuffer* CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader) //! read indices -void CIrrMeshFileLoader::readIndices(io::IXMLReader* reader, int indexCount, core::array& indices) +void CIrrMeshFileLoader::readIndices(io::IXMLReader* reader, int indexCount, IIndexBuffer& indices) { indices.reallocate(indexCount); @@ -291,175 +267,169 @@ void CIrrMeshFileLoader::readIndices(io::IXMLReader* reader, int indexCount, cor for (int i=0; igetNodeData(); const c8* p = &data[0]; + scene::IVertexBuffer& Vertices = sbuffer->getVertexBuffer(); + video::E_VERTEX_TYPE vType = Vertices.getType(); if (sbuffer) { - video::S3DVertex vtx; - for (int i=0; iVertices.push_back(vtx); - } - } -} + Vertices.push_back(vtx); + } + break; + case video::EVT_2TCOORDS: + { + video::S3DVertex2TCoords vtx; + // position + findNextNoneWhiteSpace(&p); + vtx.Pos.X = readFloat(&p); + findNextNoneWhiteSpace(&p); + vtx.Pos.Y = readFloat(&p); + findNextNoneWhiteSpace(&p); + vtx.Pos.Z = readFloat(&p); -void CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader, int vertexCount, SMeshBufferLightMap* sbuffer) -{ - core::stringc data = reader->getNodeData(); - const c8* p = &data[0]; + // normal - if (sbuffer) - { - video::S3DVertex2TCoords vtx; + findNextNoneWhiteSpace(&p); + vtx.Normal.X = readFloat(&p); + findNextNoneWhiteSpace(&p); + vtx.Normal.Y = readFloat(&p); + findNextNoneWhiteSpace(&p); + vtx.Normal.Z = readFloat(&p); - for (int i=0; iVertices.push_back(vtx); - } - } -} + findNextNoneWhiteSpace(&p); + vtx.Normal.X = readFloat(&p); + findNextNoneWhiteSpace(&p); + vtx.Normal.Y = readFloat(&p); + findNextNoneWhiteSpace(&p); + vtx.Normal.Z = readFloat(&p); + // color -void CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader, int vertexCount, SMeshBufferTangents* sbuffer) -{ - core::stringc data = reader->getNodeData(); - const c8* p = &data[0]; + u32 col; + findNextNoneWhiteSpace(&p); + sscanf(p, "%08x", &col); + vtx.Color.set(col); + skipCurrentNoneWhiteSpace(&p); - if (sbuffer) - { - video::S3DVertexTangents vtx; + // tcoord1 - for (int i=0; iVertices.push_back(vtx); } } } diff --git a/src/dep/src/irrlicht/CIrrMeshFileLoader.h b/src/dep/src/irrlicht/CIrrMeshFileLoader.h index 099a6b4..033c06e 100644 --- a/src/dep/src/irrlicht/CIrrMeshFileLoader.h +++ b/src/dep/src/irrlicht/CIrrMeshFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,6 +11,7 @@ #include "irrString.h" #include "SMesh.h" #include "SMeshBuffer.h" +#include "CDynamicMeshBuffer.h" #include "ISceneManager.h" namespace irr @@ -29,7 +30,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -68,13 +69,11 @@ private: //! reads floats from inside of xml element until end of xml element void readFloatsInsideElement(io::IXMLReader* reader, f32* floats, u32 count); - //! read all 3 types of mesh buffers - void readMeshBuffer(io::IXMLReader* reader, int vertexCount, SMeshBuffer* sbuffer); - void readMeshBuffer(io::IXMLReader* reader, int vertexCount, SMeshBufferLightMap* sbuffer); - void readMeshBuffer(io::IXMLReader* reader, int vertexCount, SMeshBufferTangents* sbuffer); + //! read the mesh buffers + void readMeshBuffer(io::IXMLReader* reader, int vertexCount, CDynamicMeshBuffer* sbuffer); //! read indices - void readIndices(io::IXMLReader* reader, int indexCount, core::array& indices); + void readIndices(io::IXMLReader* reader, int indexCount, IIndexBuffer& indices); // member variables diff --git a/src/dep/src/irrlicht/CIrrMeshWriter.cpp b/src/dep/src/irrlicht/CIrrMeshWriter.cpp index 87b813c..1807af5 100644 --- a/src/dep/src/irrlicht/CIrrMeshWriter.cpp +++ b/src/dep/src/irrlicht/CIrrMeshWriter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -183,7 +183,7 @@ void CIrrMeshWriter::writeMeshBuffer(const scene::IMeshBuffer* buffer) str += getVectorAsStringLine(vtx[j].Normal); char tmp[12]; - sprintf(tmp, " %08x ", vtx[j].Color.color); + sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue()); str += tmp; str += getVectorAsStringLine(vtx[j].TCoords); @@ -203,7 +203,7 @@ void CIrrMeshWriter::writeMeshBuffer(const scene::IMeshBuffer* buffer) str += getVectorAsStringLine(vtx[j].Normal); char tmp[12]; - sprintf(tmp, " %08x ", vtx[j].Color.color); + sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue()); str += tmp; str += getVectorAsStringLine(vtx[j].TCoords); @@ -225,7 +225,7 @@ void CIrrMeshWriter::writeMeshBuffer(const scene::IMeshBuffer* buffer) str += getVectorAsStringLine(vtx[j].Normal); char tmp[12]; - sprintf(tmp, " %08x ", vtx[j].Color.color); + sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue()); str += tmp; str += getVectorAsStringLine(vtx[j].TCoords); @@ -252,13 +252,25 @@ void CIrrMeshWriter::writeMeshBuffer(const scene::IMeshBuffer* buffer) Writer->writeLineBreak(); int indexCount = (int)buffer->getIndexCount(); - const u16* idx = buffer->getIndices(); + + video::E_INDEX_TYPE iType = buffer->getIndexType(); + + const u16* idx16 = buffer->getIndices(); + const u32* idx32 = (u32*) buffer->getIndices(); const int maxIndicesPerLine = 25; for (int i=0; iwriteText(str.c_str()); + if(iType == video::EIT_16BIT) + { + core::stringw str((int)idx16[i]); + Writer->writeText(str.c_str()); + } + else + { + core::stringw str((int)idx32[i]); + Writer->writeText(str.c_str()); + } if (i % maxIndicesPerLine != maxIndicesPerLine) { diff --git a/src/dep/src/irrlicht/CIrrMeshWriter.h b/src/dep/src/irrlicht/CIrrMeshWriter.h index d3b8f41..048b915 100644 --- a/src/dep/src/irrlicht/CIrrMeshWriter.h +++ b/src/dep/src/irrlicht/CIrrMeshWriter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CLMTSMeshFileLoader.cpp b/src/dep/src/irrlicht/CLMTSMeshFileLoader.cpp index 310dea1..633af8e 100644 --- a/src/dep/src/irrlicht/CLMTSMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CLMTSMeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // This file was written by Jonas Petersen and modified by Nikolaus Gebhardt. @@ -123,9 +123,9 @@ void CLMTSMeshFileLoader::cleanup() } -bool CLMTSMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CLMTSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".lmts") != 0; + return core::hasFileExtension ( filename, "lmts" ); } @@ -178,7 +178,7 @@ IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file) for (i=0; iread(&id, sizeof(u32)); diff --git a/src/dep/src/irrlicht/CLMTSMeshFileLoader.h b/src/dep/src/irrlicht/CLMTSMeshFileLoader.h index b1868f9..e408e84 100644 --- a/src/dep/src/irrlicht/CLMTSMeshFileLoader.h +++ b/src/dep/src/irrlicht/CLMTSMeshFileLoader.h @@ -1,12 +1,12 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -// +// // I (Nikolaus Gebhardt) did some few changes to Jonas Petersen's original loader: -// - removed setTexturePath() and replaced with the ISceneManager::getStringParameter()-stuff. +// - removed setTexturePath() and replaced with the ISceneManager::getStringParameter()-stuff. // - added EAMT_LMTS enumeration value -// Thanks a lot to Jonas Petersen for his work -// on this and that he gave me his permission to add it into Irrlicht. +// Thanks a lot to Jonas Petersen for his work +// on this and that he gave me his permission to add it into Irrlicht. /* CLMTSMeshFileLoader.h @@ -35,22 +35,22 @@ class CLMTSMeshFileLoader : public IMeshLoader { public: - CLMTSMeshFileLoader(io::IFileSystem* fs, + CLMTSMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver, io::IAttributes* parameters); virtual ~CLMTSMeshFileLoader(); - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; virtual IAnimatedMesh* createMesh(io::IReadFile* file); - + private: void constructMesh(SMesh* mesh); void loadTextures(SMesh* mesh); void cleanup(); // byte-align structures -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT @@ -98,7 +98,7 @@ private: } PACK_STRUCT; // Default alignment -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #endif diff --git a/src/dep/src/irrlicht/CLWOMeshFileLoader.cpp b/src/dep/src/irrlicht/CLWOMeshFileLoader.cpp index 4bd9ab1..3c7e2e1 100644 --- a/src/dep/src/irrlicht/CLWOMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CLWOMeshFileLoader.cpp @@ -1,1790 +1,2114 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "CLWOMeshFileLoader.h" -#include "os.h" -#include "SAnimatedMesh.h" -#include "SMesh.h" -#include "IReadFile.h" -#include "ISceneManager.h" -#include "IFileSystem.h" -#include "IVideoDriver.h" -#include "IMeshManipulator.h" - -using namespace std; - -namespace irr -{ -namespace scene -{ - -#ifdef _DEBUG -#define LWO_READER_DEBUG -#endif - -#define charsToUIntD(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d) -inline unsigned int charsToUInt(const char *str) -{ - return (str[0] << 24) | (str[1] << 16) | (str[2] << 8) | str[3]; -} - - -struct tLWOTextureInfo -{ - tLWOTextureInfo() : Flags(0), WidthWrap(2), HeightWrap(2), OpacType(0), - Color(0xffffffff), Value(0.0f), AntiAliasing(1.0f), - Opacity(1.0f), TCoords(0), Active(false) {}; - core::stringc Type; - core::stringc Map; - core::stringc AlphaMap; - u16 Flags; - u16 WidthWrap; - u16 HeightWrap; - u16 OpacType; - u16 IParam[3]; - core::vector3df Size; - core::vector3df Center; - core::vector3df Falloff; - core::vector3df Velocity; - video::SColor Color; - f32 Value; - f32 AntiAliasing; - f32 Opacity; - f32 FParam[3]; - core::array* TCoords; - bool Active; -}; - -struct CLWOMeshFileLoader::tLWOMaterial -{ - tLWOMaterial() : Meshbuffer(0), TagType(0), Flags(0), ReflMode(3), TranspMode(3), - Glow(0), AlphaMode(2), Luminance(0.0f), Diffuse(1.0f), Specular(0.0f), - Reflection(0.0f), Transparency(0.0f), Translucency(0.0f), - Sharpness(0.0f), ReflSeamAngle(0.0f), ReflBlur(0.0f), - RefrIndex(1.0f), TranspBlur(0.0f), SmoothingAngle(0.0f), - EdgeTransparency(0.0f), HighlightColor(0.0f), ColorFilter(0.0f), - AdditiveTransparency(0.0f), GlowIntensity(0.0f), GlowSize(0.0f), - AlphaValue(0.0f), VertexColorIntensity(0.0f), VertexColor() {}; - - core::stringc Name; - scene::SMeshBuffer *Meshbuffer; - core::stringc ReflMap; - u16 TagType; - u16 Flags; - u16 ReflMode; - u16 TranspMode; - u16 Glow; - u16 AlphaMode; - f32 Luminance; - f32 Diffuse; - f32 Specular; - f32 Reflection; - f32 Transparency; - f32 Translucency; - f32 Sharpness; - f32 ReflSeamAngle; - f32 ReflBlur; - f32 RefrIndex; - f32 TranspBlur; - f32 SmoothingAngle; - f32 EdgeTransparency; - f32 HighlightColor; - f32 ColorFilter; - f32 AdditiveTransparency; - f32 GlowIntensity; - f32 GlowSize; - f32 AlphaValue; - f32 VertexColorIntensity; - video::SColorf VertexColor; - u32 Envelope[23]; - tLWOTextureInfo Texture[7]; -}; - -struct tLWOLayerInfo -{ - u16 Number; - u16 Parent; - u16 Flags; - bool Active; - core::stringc Name; - core::vector3df Pivot; -}; - - -//! Constructor -CLWOMeshFileLoader::CLWOMeshFileLoader(scene::ISceneManager* smgr, - io::IFileSystem* fs) -: SceneManager(smgr), FileSystem(fs), File(0), Mesh(0) -{ - #ifdef _DEBUG - setDebugName("CLWOMeshFileLoader"); - #endif -} - - -//! destructor -CLWOMeshFileLoader::~CLWOMeshFileLoader() -{ - if (Mesh) - Mesh->drop(); -} - - -//! returns true if the file maybe is able to be loaded by this class -//! based on the file extension (e.g. ".bsp") -bool CLWOMeshFileLoader::isALoadableFileExtension(const c8* filename) const -{ - return strstr(filename, ".lwo")!=0; -} - - - -//! creates/loads an animated mesh from the file. -//! \return Pointer to the created mesh. Returns 0 if loading failed. -//! If you no longer need the mesh, you should call IAnimatedMesh::drop(). -//! See IUnknown::drop() for more information. -IAnimatedMesh* CLWOMeshFileLoader::createMesh(io::IReadFile* file) -{ - File = file; - - if (Mesh) - Mesh->drop(); - - Mesh = new SMesh(); - - if (!readFileHeader()) - return false; - - if (!readChunks()) - return false; - - SAnimatedMesh* am = new SAnimatedMesh(); - am->Type = EAMT_3DS; - - for (u32 polyIndex=0; polyIndexMeshbuffer; - const s32 vertCount=mb->Vertices.size(); - const core::array& poly = Indices[polyIndex]; - const u32 polySize=poly.size(); - video::S3DVertex vertex; - for (u32 i=0; iTexture[0].TCoords && (Materials[tag]->Texture[0].TCoords->size()>0)) - vertex.TCoords=(*Materials[tag]->Texture[0].TCoords)[j]; - mb->Vertices.push_back(vertex); - } - if (polySize>2) - { - for (u32 i=1; iVertices[vertCount].Pos,mb->Vertices[vertCount+i].Pos,mb->Vertices[vertCount+i+1].Pos).Normal.normalize(); - mb->Vertices[vertCount].Normal=normal; - mb->Vertices[vertCount+i].Normal=normal; - mb->Vertices[vertCount+i+1].Normal=normal; - mb->Indices.push_back(vertCount); - mb->Indices.push_back(vertCount+i); - mb->Indices.push_back(vertCount+i+1); - } - } - } - for (u32 i=0; iMeshbuffer->Vertices.size(); ++j) - Materials[i]->Meshbuffer->Vertices[j].Color=Materials[i]->Meshbuffer->Material.DiffuseColor; - Materials[i]->Meshbuffer->recalculateBoundingBox(); - if (Materials[i]->Meshbuffer->Material.MaterialType==video::EMT_NORMAL_MAP_SOLID) - { - SMesh tmpmesh; - tmpmesh.addMeshBuffer(Materials[i]->Meshbuffer); - SceneManager->getMeshManipulator()->createMeshWithTangents(&tmpmesh); - Mesh->addMeshBuffer(tmpmesh.getMeshBuffer(0)); - } - else - Mesh->addMeshBuffer(Materials[i]->Meshbuffer); - Mesh->getMeshBuffer(Mesh->getMeshBufferCount()-1)->drop(); - } - - Mesh->recalculateBoundingBox(); - - am->addMesh(Mesh); - am->recalculateBoundingBox(); - Mesh->drop(); - Mesh = 0; - - Points.clear(); - Indices.clear(); - MaterialMapping.clear(); - VMap.clear(); - TCoords.clear(); - Materials.clear(); - Images.clear(); - - return am; -} - - -bool CLWOMeshFileLoader::readChunks() -{ - s32 lastPos; - u32 size; - unsigned int uiType; - char type[5]; - type[4]=0; - tLWOLayerInfo layer; - - while(File->getPos()getSize()) - { - File->read(&type, 4); - //Convert 4-char string to 4-byte integer - //Makes it possible to do a switch statement - uiType = charsToUInt(type); - File->read(&size, 4); -#ifndef __BIG_ENDIAN__ - size=os::Byteswap::byteswap(size); -#endif - lastPos=File->getPos(); - - switch(uiType) - { - case charsToUIntD('L','A','Y','R'): - { -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading layer."); -#endif - u16 tmp16; - File->read(&tmp16, 2); // number - File->read(&tmp16, 2); // flags - size -= 4; -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - if (((FormatVersion==1)&&(tmp16!=1)) || - ((FormatVersion==2)&&(tmp16&1))) - layer.Active=false; - else - layer.Active=true; - if (FormatVersion==2) - size -= readVec(layer.Pivot); - size -= readString(layer.Name); - if (size) - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - layer.Parent = tmp16; - } - } - break; - case charsToUIntD('P','N','T','S'): - { -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading points."); -#endif - core::vector3df vec; - Points.clear(); - const u32 tmpsize = size/12; - Points.reallocate(tmpsize); - for (u32 i=0; iName=""; - mat->Meshbuffer=new scene::SMeshBuffer(); - size -= readString(mat->Name); - if (FormatVersion!=2) - mat->TagType = 1; // format 2 has more types - Materials.push_back(mat); - } - } - break; - case charsToUIntD('P','T','A','G'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading tag mapping."); -#endif - readTagMapping(size); - break; -// case charsToUIntD('V','M','A','D'): // dicontinuous vertex mapping, i.e. additional texcoords -// case charsToUIntD('V','M','P','A'): -// case charsToUIntD('E','N','V','L'): -// break; - case charsToUIntD('C','L','I','P'): - { -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading clips."); -#endif - u32 index; - u16 subsize; - File->read(&index, 4); -#ifndef __BIG_ENDIAN__ - index=os::Byteswap::byteswap(index); -#endif - size -= 4; - while (size != 0) - { - File->read(&type, 4); - File->read(&subsize, 2); -#ifndef __BIG_ENDIAN__ - subsize=os::Byteswap::byteswap(subsize); -#endif - size -= 6; - if (strncmp(type, "STIL", 4)) - { - File->seek(subsize, true); - size -= subsize; - continue; - } - core::stringc path; - size -= readString(path, subsize); - #ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loaded clip", path.c_str()); - #endif - Images.push_back(path); - } - } - break; - case charsToUIntD('S','U','R','F'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading material."); -#endif - readMat(size); - break; - case charsToUIntD('B','B','O','X'): - { -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading bbox."); -#endif - // not stored - core::vector3df vec; - for (u32 i=0; i<2; ++i) - readVec(vec); - size -= 24; - } - break; - case charsToUIntD('D','E','S','C'): - case charsToUIntD('T','E','X','T'): - { -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading text."); -#endif - core::stringc text; - size -= readString(text, size); - } - break; - // not needed - case charsToUIntD('I','C','O','N'): - // not yet supported - case charsToUIntD('P','C','H','S'): - case charsToUIntD('C','R','V','S'): - default: -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: skipping ", type); -#endif - //Go to next chunk - File->seek(lastPos + size, false); - break; - } - } - return true; -} - - -void CLWOMeshFileLoader::readObj1(u32 size) -{ - u32 pos; - u16 numVerts, vertIndex; - s16 material; - video::S3DVertex vertex; - - while (size!=0) - { - File->read(&numVerts, 2); -#ifndef __BIG_ENDIAN__ - numVerts=os::Byteswap::byteswap(numVerts); -#endif - pos=File->getPos(); - File->seek(2*numVerts, true); - File->read(&material, 2); -#ifndef __BIG_ENDIAN__ - material=os::Byteswap::byteswap(material); -#endif - size -=2*numVerts+4; - // detail meshes ? - scene::SMeshBuffer *mb; - if (material<0) - mb=Materials[-material-1]->Meshbuffer; - else - mb=Materials[material-1]->Meshbuffer; - File->seek(pos, false); - - u16 vertCount=mb->Vertices.size(); - for (u16 i=0; iread(&vertIndex, 2); -#ifndef __BIG_ENDIAN__ - vertIndex=os::Byteswap::byteswap(vertIndex); -#endif - vertex.Pos=Points[vertIndex]; - mb->Vertices.push_back(vertex); - } - for (u16 i=1; iVertices[vertCount].Pos,mb->Vertices[vertCount+i].Pos,mb->Vertices[vertCount+i+1].Pos).Normal.normalize(); - mb->Vertices[vertCount].Normal=normal; - mb->Vertices[vertCount+i].Normal=normal; - mb->Vertices[vertCount+i+1].Normal=normal; - mb->Indices.push_back(vertCount); - mb->Indices.push_back(vertCount+i); - mb->Indices.push_back(vertCount+i+1); - } - // skip material number and detail surface count - if (material<0) - File->read(&material, 2); - File->read(&material, 2); - } -} - -void CLWOMeshFileLoader::readVertexMapping(u32 size) -{ - char type[5]; - type[4]=0; - u16 dimension; - core::stringc name; - File->read(&type, 4); -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: Vertex map type", type); -#endif - File->read(&dimension, 2); -#ifndef __BIG_ENDIAN__ - dimension=os::Byteswap::byteswap(dimension); -#endif - size -= 6; - size -= readString(name); -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: Vertex map", name.c_str()); -#endif - if (strncmp(type, "TXUV", 4)) // also support RGB, RGBA, WGHT, ... - { - File->seek(size, true); - return; - } - VMap.insert(name,TCoords.size()); - TCoords.push_back(core::array()); - - u32 index; - core::vector2df tcoord; - core::array& tcArray = TCoords.getLast(); - tcArray.set_used(Points.size()); - while (size!=0) - { - size -= readVX(index); - File->read(&tcoord.X, 4); -#ifndef __BIG_ENDIAN__ - tcoord.X=os::Byteswap::byteswap(tcoord.X); -#endif - File->read(&tcoord.Y, 4); -#ifndef __BIG_ENDIAN__ - tcoord.Y=os::Byteswap::byteswap(tcoord.Y); -#endif - tcoord.Y=tcoord.Y; - tcArray[index]=tcoord; - size -= 8; - } -} - -void CLWOMeshFileLoader::readTagMapping(u32 size) -{ - char type[5]; - type[4]=0; - File->read(&type, 4); - size -= 4; - if ((strncmp(type, "SURF", 4))||(Indices.size()==0)) - { - File->seek(size, true); - return; - } - - while (size!=0) - { - u16 tag; - u32 polyIndex; - size-=readVX(polyIndex); - File->read(&tag, 2); -#ifndef __BIG_ENDIAN__ - tag=os::Byteswap::byteswap(tag); -#endif - size -= 2; - MaterialMapping[polyIndex]=tag; - Materials[tag]->TagType=1; - } -} - -void CLWOMeshFileLoader::readObj2(u32 size) -{ - char type[5]; - type[4]=0; - File->read(&type, 4); - size -= 4; - Indices.clear(); - if (strncmp(type, "FACE", 4)) // also possible are splines, subdivision patches, metaballs, and bones - { - File->seek(size, true); - return; - } - u16 numVerts=0; - while (size!=0) - { - File->read(&numVerts, 2); -#ifndef __BIG_ENDIAN__ - numVerts=os::Byteswap::byteswap(numVerts); -#endif - // mask out flags - numVerts &= 0x03FF; - - size -= 2; - Indices.push_back(core::array()); - u32 vertIndex; - core::array& polyArray = Indices.getLast(); - polyArray.reallocate(numVerts); - for (u16 i=0; iTagType==1) && (Materials[i]->Name==name)) - { - mat=Materials[i]; - break; - } - } - if (!mat) - { - File->seek(size, true); - return; - } - if (FormatVersion==2) - size -= readString(name); - - video::SMaterial *irrMat=&mat->Meshbuffer->Material; - - u8 currTexture=0; - while (size!=0) - { - char type[5]; - type[4]=0; - u32 uiType; - u32 tmp32; - u16 subsize, tmp16; - f32 tmpf32; - File->read(&type, 4); - //Convert 4-char string to 4-byte integer - //Makes it possible to do a switch statement - uiType = charsToUInt(type); - File->read(&subsize, 2); -#ifndef __BIG_ENDIAN__ - subsize=os::Byteswap::byteswap(subsize); -#endif - size -= 6; - switch (uiType) - { - case charsToUIntD('C','O','L','R'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading Ambient color."); -#endif - { - s32 colSize = readColor(irrMat->DiffuseColor); - irrMat->AmbientColor=irrMat->DiffuseColor; - size -= colSize; - subsize -= colSize; - if (FormatVersion==2) - size -= readVX(mat->Envelope[0]); - } - break; - case charsToUIntD('D','I','F','F'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading Diffuse color."); -#endif - { - if (FormatVersion==2) - { - File->read(&mat->Diffuse, 4); -#ifndef __BIG_ENDIAN__ - mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse); -#endif - size -= 4; - subsize -= 4; - size -= readVX(mat->Envelope[1]); - } - else - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - mat->Diffuse=tmp16/256.0f; - size -= 2; - subsize -= 2; - } - } - break; - case charsToUIntD('V','D','I','F'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading Diffuse color."); -#endif - { - File->read(&mat->Diffuse, 4); -#ifndef __BIG_ENDIAN__ - mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse); -#endif - size -= 4; - } - break; - case charsToUIntD('L','U','M','I'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading luminance."); -#endif - { - if (FormatVersion==2) - { - File->read(&mat->Luminance, 4); -#ifndef __BIG_ENDIAN__ - mat->Luminance=os::Byteswap::byteswap(mat->Luminance); -#endif - size -= 4; - subsize -= 4; - size -= readVX(mat->Envelope[2]); - } - else - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - mat->Luminance=tmp16/256.0f; - size -= 2; - subsize -= 2; - } } - break; - case charsToUIntD('V','L','U','M'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading luminance."); -#endif - { - File->read(&mat->Luminance, 4); -#ifndef __BIG_ENDIAN__ - mat->Luminance=os::Byteswap::byteswap(mat->Luminance); -#endif - size -= 4; - } - break; - case charsToUIntD('S','P','E','C'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading specular."); -#endif - { - if (FormatVersion==2) - { - File->read(&mat->Specular, 4); -#ifndef __BIG_ENDIAN__ - mat->Specular=os::Byteswap::byteswap(mat->Specular); -#endif - size -= 4; - subsize -= 4; - size -= readVX(mat->Envelope[3]); - } - else - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - mat->Specular=tmp16/256.0f;; - size -= 2; - subsize -= 2; - } - } - break; - case charsToUIntD('V','S','P','C'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading specular."); -#endif - { - File->read(&mat->Specular, 4); -#ifndef __BIG_ENDIAN__ - mat->Specular=os::Byteswap::byteswap(mat->Specular); -#endif - size -= 4; - } - break; - case charsToUIntD('R','E','F','L'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading reflection."); -#endif - { - if (FormatVersion==2) - { - File->read(&mat->Reflection, 4); -#ifndef __BIG_ENDIAN__ - mat->Reflection=os::Byteswap::byteswap(mat->Reflection); -#endif - size -= 4; - subsize -= 4; - size -= readVX(mat->Envelope[4]); - } - else - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - mat->Reflection=tmp16/256.0f; - size -= 2; - subsize -= 2; - } - } - break; - case charsToUIntD('V','R','F','L'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading reflection."); -#endif - { - File->read(&mat->Reflection, 4); -#ifndef __BIG_ENDIAN__ - mat->Reflection=os::Byteswap::byteswap(mat->Reflection); -#endif - size -= 4; - } - break; - case charsToUIntD('T','R','A','N'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading transparency."); -#endif - { - if (FormatVersion==2) - { - File->read(&mat->Transparency, 4); -#ifndef __BIG_ENDIAN__ - mat->Transparency=os::Byteswap::byteswap(mat->Transparency); -#endif - size -= 4; - subsize -= 4; - size -= readVX(mat->Envelope[5]); - } - else - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - mat->Transparency=tmp16/256.0f; - size -= 2; - subsize -= 2; - } - } - break; - case charsToUIntD('V','T','R','N'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading transparency."); -#endif - { - File->read(&mat->Transparency, 4); -#ifndef __BIG_ENDIAN__ - mat->Transparency=os::Byteswap::byteswap(mat->Transparency); -#endif - size -= 4; - } - break; - case charsToUIntD('T','R','N','L'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading translucency."); -#endif - { - File->read(&mat->Translucency, 4); -#ifndef __BIG_ENDIAN__ - mat->Translucency=os::Byteswap::byteswap(mat->Translucency); -#endif - size -= 4; - subsize -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[6]); - } - break; - case charsToUIntD('G','L','O','S'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading glossy."); -#endif - { - if (FormatVersion == 2) - { - File->read(&irrMat->Shininess, 4); -#ifndef __BIG_ENDIAN__ - irrMat->Shininess=os::Byteswap::byteswap(irrMat->Shininess); -#endif - size -= 4; - subsize -= 4; - size -= readVX(mat->Envelope[7]); - } - else - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - irrMat->Shininess=tmp16/16.f; - size -= 2; - subsize -= 2; - } - } - break; - case charsToUIntD('S','H','R','P'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading sharpness."); -#endif - { - File->read(&mat->Sharpness, 4); -#ifndef __BIG_ENDIAN__ - mat->Sharpness=os::Byteswap::byteswap(mat->Sharpness); -#endif - size -= 4; - subsize -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[8]); - } - break; - case charsToUIntD('B','U','M','P'): - case charsToUIntD('T','A','M','P'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading bumpiness."); -#endif - { - File->read(&tmpf32, 4); -#ifndef __BIG_ENDIAN__ - tmpf32=os::Byteswap::byteswap(tmpf32); -#endif - if (currTexture==6) - irrMat->MaterialTypeParam=tmpf32; - size -= 4; - subsize -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[9]); - } - break; - case charsToUIntD('S','I','D','E'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading backface culled."); -#endif - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - if (tmp16==1) - irrMat->BackfaceCulling=true; - if (tmp16==3) - irrMat->BackfaceCulling=false; - size -= 2; - } - break; - case charsToUIntD('S','M','A','N'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading smoothing angle."); -#endif - { - File->read(&mat->SmoothingAngle, 4); -#ifndef __BIG_ENDIAN__ - mat->SmoothingAngle=os::Byteswap::byteswap(mat->SmoothingAngle); -#endif - size -= 4; - } - break; - case charsToUIntD('R','F','O','P'): - case charsToUIntD('R','F','L','T'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading reflection mode."); -#endif - { - File->read(&mat->ReflMode, 2); -#ifndef __BIG_ENDIAN__ - mat->ReflMode=os::Byteswap::byteswap(mat->ReflMode); -#endif - size -= 2; - } - break; - case charsToUIntD('R','I','M','G'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading reflection map."); -#endif - { - if (FormatVersion==2) - { - size -= readVX(tmp32); - if (tmp32) - mat->ReflMap=Images[tmp32-1]; - } - else - size -= readString(mat->ReflMap, size); - } - break; - case charsToUIntD('R','S','A','N'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading reflection seam angle."); -#endif - { - File->read(&mat->ReflSeamAngle, 4); -#ifndef __BIG_ENDIAN__ - mat->ReflSeamAngle=os::Byteswap::byteswap(mat->ReflSeamAngle); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[10]); - } - break; - case charsToUIntD('R','B','L','R'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading reflection blur."); -#endif - { - File->read(&mat->ReflBlur, 4); -#ifndef __BIG_ENDIAN__ - mat->ReflBlur=os::Byteswap::byteswap(mat->ReflBlur); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[11]); - } - break; - case charsToUIntD('R','I','N','D'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading refraction index."); -#endif - { - File->read(&mat->RefrIndex, 4); -#ifndef __BIG_ENDIAN__ - mat->RefrIndex=os::Byteswap::byteswap(mat->RefrIndex); -#endif - size -= 4; - subsize -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[12]); - } - break; - case charsToUIntD('T','R','O','P'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading transparency mode."); -#endif - { - File->read(&mat->TranspMode, 2); -#ifndef __BIG_ENDIAN__ - mat->TranspMode=os::Byteswap::byteswap(mat->TranspMode); -#endif - size -= 2; - } - break; - case charsToUIntD('T','I','M','G'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading refraction map."); -#endif - { - if (FormatVersion==2) - { - size -= readVX(tmp32); -#ifndef __BIG_ENDIAN__ - tmp32=os::Byteswap::byteswap(tmp32); -#endif - if (tmp32) - mat->Texture[currTexture].Map=Images[tmp32-1]; - } - else - size -= readString(mat->Texture[currTexture].Map, size); - } - break; - case charsToUIntD('T','B','L','R'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading transparency blur."); -#endif - { - File->read(&mat->TranspBlur, 4); -#ifndef __BIG_ENDIAN__ - mat->TranspBlur=os::Byteswap::byteswap(mat->TranspBlur); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[13]); - } - break; - case charsToUIntD('C','L','R','H'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading highlight color."); -#endif - { - File->read(&mat->HighlightColor, 4); -#ifndef __BIG_ENDIAN__ - mat->HighlightColor=os::Byteswap::byteswap(mat->HighlightColor); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[14]); - } - break; - case charsToUIntD('C','L','R','F'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading color filter."); -#endif - { - File->read(&mat->ColorFilter, 4); -#ifndef __BIG_ENDIAN__ - mat->ColorFilter=os::Byteswap::byteswap(mat->ColorFilter); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[15]); - } - break; - case charsToUIntD('A','D','T','R'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading additive transparency."); -#endif - { - File->read(&mat->AdditiveTransparency, 4); -#ifndef __BIG_ENDIAN__ - mat->AdditiveTransparency=os::Byteswap::byteswap(mat->AdditiveTransparency); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[16]); - } - break; - case charsToUIntD('G','L','O','W'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading glow."); -#endif - { - File->read(&mat->Glow, 2); -#ifndef __BIG_ENDIAN__ - mat->Glow=os::Byteswap::byteswap(mat->Glow); -#endif - size -= 2; - File->read(&mat->GlowIntensity, 4); -#ifndef __BIG_ENDIAN__ - mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[17]); - File->read(&mat->GlowSize, 4); -#ifndef __BIG_ENDIAN__ - mat->GlowSize=os::Byteswap::byteswap(mat->GlowSize); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[18]); - } - break; - case charsToUIntD('G','V','A','L'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading glow intensity."); -#endif - { - File->read(&mat->GlowIntensity, 4); -#ifndef __BIG_ENDIAN__ - mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[17]); - } - break; - case charsToUIntD('L','I','N','E'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading isWireframe."); -#endif - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - if (tmp16&1) - irrMat->Wireframe=true; - size -= 2; - if (size!=0) - { - File->read(&irrMat->Thickness, 4); -#ifndef __BIG_ENDIAN__ - irrMat->Thickness=os::Byteswap::byteswap(irrMat->Thickness); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[19]); - } - if (size!=0) - { - video::SColor lineColor; - size -= readColor(lineColor); - if (FormatVersion==2) - size -= readVX(mat->Envelope[20]); - } - } - break; - case charsToUIntD('A','L','P','H'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading alpha mode."); -#endif - { - File->read(&mat->AlphaMode, 2); -#ifndef __BIG_ENDIAN__ - mat->AlphaMode=os::Byteswap::byteswap(mat->AlphaMode); -#endif - size -= 2; - File->read(&mat->AlphaValue, 4); -#ifndef __BIG_ENDIAN__ - mat->AlphaValue=os::Byteswap::byteswap(mat->AlphaValue); -#endif - size -= 4; - } - break; - case charsToUIntD('V','C','O','L'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading vertex color."); -#endif - { - File->read(&mat->VertexColorIntensity, 4); -#ifndef __BIG_ENDIAN__ - mat->VertexColorIntensity=os::Byteswap::byteswap(mat->VertexColorIntensity); -#endif - size -= 4; - if (FormatVersion==2) - size -= readVX(mat->Envelope[21]); - File->read(&tmp32, 4); // skip type - size -= 4; - core::stringc tmpname; - size -= readString(tmpname, size); -// mat->VertexColor = getColorVMAP(tmpname); - } - break; - case charsToUIntD('F','L','A','G'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading flag."); -#endif - { - File->read(&mat->Flags, 2); -#ifndef __BIG_ENDIAN__ - mat->Flags=os::Byteswap::byteswap(mat->Flags); -#endif - if (mat->Flags&1) - mat->Luminance=1.0f; - if (mat->Flags&256) - irrMat->BackfaceCulling=false; - size -= 2; - } - break; - case charsToUIntD('E','D','G','E'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading edge."); -#endif - { - File->read(&mat->EdgeTransparency, 4); -#ifndef __BIG_ENDIAN__ - mat->EdgeTransparency=os::Byteswap::byteswap(mat->EdgeTransparency); -#endif - size -= 4; - } - break; - case charsToUIntD('C','T','E','X'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading ctex."); -#endif - currTexture=0; - size -= readString(mat->Texture[currTexture].Type, size); - break; - case charsToUIntD('D','T','E','X'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading dtex."); -#endif - currTexture=1; - size -= readString(mat->Texture[currTexture].Type, size); - break; - case charsToUIntD('S','T','E','X'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading stex."); -#endif - currTexture=2; - size -= readString(mat->Texture[currTexture].Type, size); - break; - case charsToUIntD('R','T','E','X'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading rtex."); -#endif - currTexture=3; - size -= readString(mat->Texture[currTexture].Type, size); - break; - case charsToUIntD('T','T','E','X'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading ttex."); -#endif - currTexture=4; - size -= readString(mat->Texture[currTexture].Type, size); - break; - case charsToUIntD('L','T','E','X'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading ltex."); -#endif - currTexture=5; - size -= readString(mat->Texture[currTexture].Type, size); - break; - case charsToUIntD('B','T','E','X'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading btex."); -#endif - currTexture=6; - size -= readString(mat->Texture[currTexture].Type, size); - break; - case charsToUIntD('T','A','L','P'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading alpha map."); -#endif - size -= readString(mat->Texture[currTexture].AlphaMap, size); - break; - case charsToUIntD('T','F','L','G'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture flag."); -#endif - { - File->read(&mat->Texture[currTexture].Flags, 2); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].Flags=os::Byteswap::byteswap(mat->Texture[currTexture].Flags); -#endif - size -= 2; - } - break; - case charsToUIntD('E','N','A','B'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading isEnabled."); -#endif - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - mat->Texture[currTexture].Active=(tmp16!=0); - size -= 2; - } - break; - case charsToUIntD('W','R','A','P'): - case charsToUIntD('T','W','R','P'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture wrap."); -#endif - { - File->read(&mat->Texture[currTexture].WidthWrap, 2); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].WidthWrap=os::Byteswap::byteswap(mat->Texture[currTexture].WidthWrap); -#endif - File->read(&mat->Texture[currTexture].HeightWrap, 2); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].HeightWrap=os::Byteswap::byteswap(mat->Texture[currTexture].HeightWrap); -#endif - size -= 4; - } - break; - case charsToUIntD('T','S','I','Z'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture size."); -#endif - size -= readVec(mat->Texture[currTexture].Size); - break; - case charsToUIntD('T','C','T','R'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture center."); -#endif - size -= readVec(mat->Texture[currTexture].Center); - break; - case charsToUIntD('T','F','A','L'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture falloff."); -#endif - size -= readVec(mat->Texture[currTexture].Falloff); - break; - case charsToUIntD('T','V','E','L'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture velocity."); -#endif - size -= readVec(mat->Texture[currTexture].Velocity); - break; - case charsToUIntD('T','C','L','R'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture color."); -#endif - size -= readColor(mat->Texture[currTexture].Color); - break; - case charsToUIntD('A','A','S','T'): - case charsToUIntD('T','A','A','S'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture antialias."); -#endif - { - tmp16=0; - if (FormatVersion==2) - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - size -= 2; - } - File->read(&mat->Texture[currTexture].AntiAliasing, 4); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].AntiAliasing=os::Byteswap::byteswap(mat->Texture[currTexture].AntiAliasing); -#endif - if (tmp16 & ~0x01) - mat->Texture[currTexture].AntiAliasing=0.0f; // disabled - size -= 4; - } - break; - case charsToUIntD('T','O','P','C'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture opacity."); -#endif - { - File->read(&mat->Texture[currTexture].Opacity, 4); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity); -#endif - size -= 4; - } - break; - case charsToUIntD('O','P','A','C'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture opacity and type."); -#endif - { - File->read(&mat->Texture[currTexture].OpacType, 2); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].OpacType=os::Byteswap::byteswap(mat->Texture[currTexture].OpacType); -#endif - File->read(&mat->Texture[currTexture].Opacity, 4); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity); -#endif - size -= 6; - subsize -= 6; - if (FormatVersion==2) - size -= readVX(mat->Envelope[22]); - } - break; - case charsToUIntD('T','V','A','L'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture value."); -#endif - { - File->read(&tmp16, 2); -#ifndef __BIG_ENDIAN__ - tmp16=os::Byteswap::byteswap(tmp16); -#endif - mat->Texture[currTexture].Value=tmp16/256.0f; - size -= 2; - } - break; - case charsToUIntD('T','F','P','0'): - case charsToUIntD('T','S','P','0'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture param 0."); -#endif - { - File->read(&mat->Texture[currTexture].FParam[0], 4); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].FParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[0]); -#endif - size -= 4; - } - break; - case charsToUIntD('T','F','P','1'): - case charsToUIntD('T','S','P','1'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture param 1."); -#endif - { - File->read(&mat->Texture[currTexture].FParam[1], 4); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].FParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[1]); -#endif - size -= 4; - } - break; - case charsToUIntD('T','F','P','2'): - case charsToUIntD('T','S','P','2'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture param 2."); -#endif - { - File->read(&mat->Texture[currTexture].FParam[2], 4); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].FParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[2]); -#endif - size -= 4; - } - break; - case charsToUIntD('T','F','R','Q'): - case charsToUIntD('T','I','P','0'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture iparam 0."); -#endif - { - File->read(&mat->Texture[currTexture].IParam[0], 2); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].IParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[0]); -#endif - size -= 2; - } - break; - case charsToUIntD('T','I','P','1'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture param 1."); -#endif - { - File->read(&mat->Texture[currTexture].IParam[1], 2); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].IParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[1]); -#endif - size -= 2; - } - break; - case charsToUIntD('T','I','P','2'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading texture param 2."); -#endif - { - File->read(&mat->Texture[currTexture].IParam[2], 2); -#ifndef __BIG_ENDIAN__ - mat->Texture[currTexture].IParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[2]); -#endif - size -= 2; - } - break; - case charsToUIntD('V','M','A','P'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading material vmap binding."); -#endif - { - core::stringc tmpname; - size -= readString(tmpname); - if (VMap.find(tmpname) != 0) - mat->Texture[currTexture].TCoords = &TCoords[VMap.find(tmpname)->getValue()]; - } - break; - case charsToUIntD('B','L','O','K'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading blok."); -#endif - { - core::stringc ordinal; - File->read(&type, 4); - File->read(&subsize, 2); -#ifndef __BIG_ENDIAN__ - subsize=os::Byteswap::byteswap(subsize); -#endif - size -= 6; - size -= readString(ordinal, size); - } - break; - case charsToUIntD('C','H','A','N'): - { - File->read(&type, 4); - size -= 4; - if (!strncmp(type, "COLR", 4)) - currTexture=0; - else if (!strncmp(type, "DIFF", 4)) - currTexture=1; - else if (!strncmp(type, "LUMI", 4)) - currTexture=5; - else if (!strncmp(type, "SPEC", 4)) - currTexture=2; - else if (!strncmp(type, "REFL", 4)) - currTexture=3; - else if (!strncmp(type, "TRAN", 4)) - currTexture=4; - else if (!strncmp(type, "BUMP", 4)) - currTexture=6; - } -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading channel ", type); -#endif - break; - case charsToUIntD('I','M','A','G'): -#ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: loading channel map."); -#endif - { - u16 index; - File->read(&index, 2); -#ifndef __BIG_ENDIAN__ - index=os::Byteswap::byteswap(index); -#endif - size -= 2; - if (index) - mat->Texture[currTexture].Map=Images[index-1]; - } - break; - default: - { - File->seek(subsize, true); - size -= subsize; - } - } - } - - if (mat->Texture[0].Map != "") // diffuse - irrMat->setTexture(0,loadTexture(mat->Texture[0].Map)); - if (mat->Texture[3].Map != "") // reflection - { - video::ITexture* reflTexture = loadTexture(mat->Texture[3].Map); - if (reflTexture) - { - irrMat->setTexture(1, irrMat->getTexture(0)); - irrMat->setTexture(0, reflTexture); - irrMat->MaterialType=video::EMT_REFLECTION_2_LAYER; - } - } - if (mat->Texture[4].Map != "") // transparency - { - video::ITexture* transTexture = loadTexture(mat->Texture[4].Map); - if (transTexture) - { - irrMat->setTexture(1, irrMat->getTexture(0)); - irrMat->setTexture(0, transTexture); - irrMat->MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; - } - } - if (mat->Texture[6].Map != "") // bump - { - irrMat->setTexture(1, loadTexture(mat->Texture[6].Map)); - if (irrMat->getTexture(1)) - { -// SceneManager->getVideoDriver()->makeNormalMapTexture(irrMat->getTexture(1)); - irrMat->MaterialType=video::EMT_NORMAL_MAP_SOLID; - } - } -} - - -u32 CLWOMeshFileLoader::readColor(video::SColor& color) -{ - if (FormatVersion!=2) - { - u8 colorComponent; - File->read(&colorComponent, 1); - color.setRed(colorComponent); - File->read(&colorComponent, 1); - color.setGreen(colorComponent); - File->read(&colorComponent, 1); - color.setBlue(colorComponent); - // unknown value - File->read(&colorComponent, 1); - return 4; - } - else - { - video::SColorf col; - File->read(&col.r, 4); -#ifndef __BIG_ENDIAN__ - col.r=os::Byteswap::byteswap(col.r); -#endif - File->read(&col.g, 4); -#ifndef __BIG_ENDIAN__ - col.g=os::Byteswap::byteswap(col.g); -#endif - File->read(&col.b, 4); -#ifndef __BIG_ENDIAN__ - col.b=os::Byteswap::byteswap(col.b); -#endif - color=col.toSColor(); - return 12; - } -} - -u32 CLWOMeshFileLoader::readString(core::stringc& name, u32 size) -{ - c8 c; - - name=""; - if (size) - name.reserve(size); - File->read(&c, 1); - while (c) - { - name.append(c); - File->read(&c, 1); - } - // read extra 0 upon odd file position - if (File->getPos() & 0x1) - { - File->read(&c, 1); - return (name.size()+2); - } - return (name.size()+1); -} - - -u32 CLWOMeshFileLoader::readVec(core::vector3df& vec) -{ - File->read(&vec.X, 4); -#ifndef __BIG_ENDIAN__ - vec.X=os::Byteswap::byteswap(vec.X); -#endif - File->read(&vec.Y, 4); -#ifndef __BIG_ENDIAN__ - vec.Y=os::Byteswap::byteswap(vec.Y); -#endif - File->read(&vec.Z, 4); -#ifndef __BIG_ENDIAN__ - vec.Z=os::Byteswap::byteswap(vec.Z); -#endif - return 12; -} - - -u32 CLWOMeshFileLoader::readVX(u32& num) -{ - u16 tmpIndex; - - File->read(&tmpIndex, 2); -#ifndef __BIG_ENDIAN__ - tmpIndex=os::Byteswap::byteswap(tmpIndex); -#endif - num=tmpIndex; - if (num >= 0xFF00) - { - File->read(&tmpIndex, 2); -#ifndef __BIG_ENDIAN__ - tmpIndex=os::Byteswap::byteswap(tmpIndex); -#endif - num=((num << 16)|tmpIndex) & ~0xFF000000; - return 4; - } - return 2; -} - - -bool CLWOMeshFileLoader::readFileHeader() -{ - u32 Id; - - File->read(&Id, 4); -#ifndef __BIG_ENDIAN__ - Id=os::Byteswap::byteswap(Id); -#endif - if (Id != 0x464f524d) // FORM - return false; - - //skip the file length - File->read(&Id, 4); - - File->read(&Id, 4); -#ifndef __BIG_ENDIAN__ - Id=os::Byteswap::byteswap(Id); -#endif - // Currently supported: LWOB, LWLO, LWO2 - switch (Id) - { - case 0x4c574f42: - FormatVersion = 0; // LWOB - break; - case 0x4c574c4f: - FormatVersion = 1; // LWLO - break; - case 0x4c574f32: - FormatVersion = 2; // LWO2 - break; - default: - return false; // unsupported - } - - return true; -} - - -video::ITexture* CLWOMeshFileLoader::loadTexture(const core::stringc& file) -{ - video::IVideoDriver* driver = SceneManager->getVideoDriver(); - - if (FileSystem->existFile(file.c_str())) - return driver->getTexture(file.c_str()); - - core::stringc strippedName; - s32 stringPos = file.findLast('/'); - if (stringPos==-1) - stringPos = file.findLast('\\'); - if (stringPos != -1) - { - strippedName = file.subString(stringPos+1, file.size()-stringPos); - if (FileSystem->existFile(strippedName.c_str())) - return driver->getTexture(strippedName.c_str()); - } - else - strippedName = file; - core::stringc newpath = File->getFileName(); - stringPos = newpath.findLast('/'); - if (stringPos==-1) - stringPos = newpath.findLast('\\'); - if (stringPos != -1) - { - newpath = newpath.subString(0,stringPos+1); - newpath.append(strippedName); - if (FileSystem->existFile(newpath.c_str())) - return driver->getTexture(newpath.c_str()); - } - os::Printer::log("Could not load texture", file.c_str(), ELL_WARNING); - - return 0; -} - - -} // end namespace scene -} // end namespace irr +// Copyright (C) 2007-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CLWOMeshFileLoader.h" +#include "os.h" +#include "SAnimatedMesh.h" +#include "SMesh.h" +#include "IReadFile.h" +#include "ISceneManager.h" +#include "IFileSystem.h" +#include "IVideoDriver.h" +#include "IMeshManipulator.h" + +namespace irr +{ +namespace scene +{ + +#ifdef _DEBUG +#define LWO_READER_DEBUG +#endif + +#define charsToUIntD(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d) +inline unsigned int charsToUInt(const char *str) +{ + return (str[0] << 24) | (str[1] << 16) | (str[2] << 8) | str[3]; +} + + +struct tLWOTextureInfo +{ + tLWOTextureInfo() : UVTag(0), DUVTag(0), Flags(0), WidthWrap(2), + HeightWrap(2), OpacType(0), Color(0xffffffff), + Value(0.0f), AntiAliasing(1.0f), Opacity(1.0f), + Axis(255), Projection(0), Active(false) {} + core::stringc Type; + core::stringc Map; + core::stringc AlphaMap; + core::stringc UVname; + u16 UVTag; + u16 DUVTag; + u16 Flags; + u16 WidthWrap; + u16 HeightWrap; + u16 OpacType; + u16 IParam[3]; + core::vector3df Size; + core::vector3df Center; + core::vector3df Falloff; + core::vector3df Velocity; + video::SColor Color; + f32 Value; + f32 AntiAliasing; + f32 Opacity; + f32 FParam[3]; + u8 Axis; + u8 Projection; + bool Active; +}; + +struct CLWOMeshFileLoader::tLWOMaterial +{ + tLWOMaterial() : Meshbuffer(0), TagType(0), Flags(0), ReflMode(3), TranspMode(3), + Glow(0), AlphaMode(2), Luminance(0.0f), Diffuse(1.0f), Specular(0.0f), + Reflection(0.0f), Transparency(0.0f), Translucency(0.0f), + Sharpness(0.0f), ReflSeamAngle(0.0f), ReflBlur(0.0f), + RefrIndex(1.0f), TranspBlur(0.0f), SmoothingAngle(0.0f), + EdgeTransparency(0.0f), HighlightColor(0.0f), ColorFilter(0.0f), + AdditiveTransparency(0.0f), GlowIntensity(0.0f), GlowSize(0.0f), + AlphaValue(0.0f), VertexColorIntensity(0.0f), VertexColor() {} + + core::stringc Name; + scene::SMeshBuffer *Meshbuffer; + core::stringc ReflMap; + u16 TagType; + u16 Flags; + u16 ReflMode; + u16 TranspMode; + u16 Glow; + u16 AlphaMode; + f32 Luminance; + f32 Diffuse; + f32 Specular; + f32 Reflection; + f32 Transparency; + f32 Translucency; + f32 Sharpness; + f32 ReflSeamAngle; + f32 ReflBlur; + f32 RefrIndex; + f32 TranspBlur; + f32 SmoothingAngle; + f32 EdgeTransparency; + f32 HighlightColor; + f32 ColorFilter; + f32 AdditiveTransparency; + f32 GlowIntensity; + f32 GlowSize; + f32 AlphaValue; + f32 VertexColorIntensity; + video::SColorf VertexColor; + u32 Envelope[23]; + tLWOTextureInfo Texture[7]; +}; + +struct tLWOLayerInfo +{ + u16 Number; + u16 Parent; + u16 Flags; + bool Active; + core::stringc Name; + core::vector3df Pivot; +}; + + +//! Constructor +CLWOMeshFileLoader::CLWOMeshFileLoader(scene::ISceneManager* smgr, + io::IFileSystem* fs) +: SceneManager(smgr), FileSystem(fs), File(0), Mesh(0) +{ + #ifdef _DEBUG + setDebugName("CLWOMeshFileLoader"); + #endif +} + + +//! destructor +CLWOMeshFileLoader::~CLWOMeshFileLoader() +{ + if (Mesh) + Mesh->drop(); +} + + +//! returns true if the file maybe is able to be loaded by this class +//! based on the file extension (e.g. ".bsp") +bool CLWOMeshFileLoader::isALoadableFileExtension(const io::path& filename) const +{ + return core::hasFileExtension(filename, "lwo"); +} + + +//! creates/loads an animated mesh from the file. +IAnimatedMesh* CLWOMeshFileLoader::createMesh(io::IReadFile* file) +{ + File = file; + + if (Mesh) + Mesh->drop(); + + Mesh = new SMesh(); + + if (!readFileHeader()) + return 0; + + if (!readChunks()) + return 0; + +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: Creating geometry."); + os::Printer::log("LWO loader: Assigning UV maps."); +#endif + u32 i; + for (i=0; iTexture[j].UVname.size()) + { + for (uvTag=0; uvTagTexture[j].UVname == UvName[uvTag]) + { + Materials[i]->Texture[j].UVTag=uvTag; + break; + } + } + for (uvTag=0; uvTagTexture[j].UVname == DUvName[uvTag]) + { + Materials[i]->Texture[j].DUVTag=uvTag; + break; + } + } + } + } + } +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: Creating polys."); +#endif + // create actual geometry for lwo2 + if (FormatVersion==2) + { + core::arrayvertexCount; + vertexCount.reallocate(Materials.size()); + for (i=0; iMeshbuffer->Vertices.reallocate(vertexCount[i]); + Materials[i]->Meshbuffer->Indices.reallocate(vertexCount[i]); + } + } + // create actual geometry for lwo2 + for (u32 polyIndex=0; polyIndexMeshbuffer; + const core::array& poly = Indices[polyIndex]; + const u32 polySize=poly.size(); + const u16 uvTag = Materials[tag]->Texture[0].UVTag; + const u16 duvTag = Materials[tag]->Texture[0].DUVTag; + video::S3DVertex vertex; + vertex.Color=0xffffffff; + const u32 vertCount=mb->Vertices.size(); + for (u32 i=0; iVertices.push_back(vertex); + } + // triangulate as trifan + if (polySize>2) + { + for (u32 i=1; iIndices.push_back(vertCount); + mb->Indices.push_back(vertCount+i); + mb->Indices.push_back(vertCount+i+1); + } + } + } +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: Fixing meshbuffers."); +#endif + for (u32 i=0; iName); + os::Printer::log("LWO loader: Vertex count", core::stringc(Materials[i]->Meshbuffer->Vertices.size())); +#endif + if (!Materials[i]->Meshbuffer->Vertices.size()) + { + Materials[i]->Meshbuffer->drop(); + delete Materials[i]; + continue; + } + for (u32 j=0; jMeshbuffer->Vertices.size(); ++j) + Materials[i]->Meshbuffer->Vertices[j].Color=Materials[i]->Meshbuffer->Material.DiffuseColor; + Materials[i]->Meshbuffer->recalculateBoundingBox(); + + // load textures + video::SMaterial& irrMat=Materials[i]->Meshbuffer->Material; + if (Materials[i]->Texture[0].Map != "") // diffuse + irrMat.setTexture(0,loadTexture(Materials[i]->Texture[0].Map)); + if (Materials[i]->Texture[3].Map != "") // reflection + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading reflection texture."); +#endif + video::ITexture* reflTexture = loadTexture(Materials[i]->Texture[3].Map); + if (reflTexture && irrMat.getTexture(0)) + irrMat.setTexture(1, irrMat.getTexture(0)); + irrMat.setTexture(0, reflTexture); + irrMat.MaterialType=video::EMT_REFLECTION_2_LAYER; + } + if (Materials[i]->Texture[4].Map != "") // transparency + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading transparency texture."); +#endif + video::ITexture* transTexture = loadTexture(Materials[i]->Texture[4].Map); + if (transTexture && irrMat.getTexture(0)) + irrMat.setTexture(1, irrMat.getTexture(0)); + irrMat.setTexture(0, transTexture); + irrMat.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; + } + if (Materials[i]->Texture[6].Map != "") // bump + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading bump texture."); +#endif + const u8 pos = irrMat.getTexture(0)?1:0; + irrMat.setTexture(pos, loadTexture(Materials[i]->Texture[6].Map)); + if (irrMat.getTexture(pos)) + { + // SceneManager->getVideoDriver()->makeNormalMapTexture(irrMat.getTexture(1)); + // irrMat.MaterialType=video::EMT_NORMAL_MAP_SOLID; + } + } + + // cope with planar mapping texture coords + if (Materials[i]->Texture[0].Projection != 5) + { + if (FormatVersion!=2) + { + if (Materials[i]->Texture[0].Flags&1) + Materials[i]->Texture[0].Axis=0; + else if (Materials[i]->Texture[0].Flags&2) + Materials[i]->Texture[0].Axis=1; + else if (Materials[i]->Texture[0].Flags&4) + Materials[i]->Texture[0].Axis=2; + } + // if no axis given choose the dominant one + else if (Materials[i]->Texture[0].Axis>2) + { + if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().YMeshbuffer->getBoundingBox().getExtent().X) + { + if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().YMeshbuffer->getBoundingBox().getExtent().Z) + Materials[i]->Texture[0].Axis=1; + else + Materials[i]->Texture[0].Axis=2; + } + else + { + if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().XMeshbuffer->getBoundingBox().getExtent().Z) + Materials[i]->Texture[0].Axis=0; + else + Materials[i]->Texture[0].Axis=2; + } + } + // get the resolution for this axis + f32 resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.Z); + f32 resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Y); + if (Materials[i]->Texture[0].Axis==1) + { + resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.X); + resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Z); + } + else if (Materials[i]->Texture[0].Axis==2) + { + resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.X); + resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Y); + } + // use the two-way planar mapping + SceneManager->getMeshManipulator()->makePlanarTextureMapping(Materials[i]->Meshbuffer, resolutionS, resolutionT, Materials[i]->Texture[0].Axis, Materials[i]->Texture[0].Center); + } + + // add bump maps + if (Materials[i]->Meshbuffer->Material.MaterialType==video::EMT_NORMAL_MAP_SOLID) + { + SMesh* tmpmesh = new SMesh(); + tmpmesh->addMeshBuffer(Materials[i]->Meshbuffer); + SceneManager->getMeshManipulator()->createMeshWithTangents(tmpmesh, true, true); + Mesh->addMeshBuffer(tmpmesh->getMeshBuffer(0)); + tmpmesh->getMeshBuffer(0)->drop(); + tmpmesh->drop(); + } + else + { + SceneManager->getMeshManipulator()->recalculateNormals(Materials[i]->Meshbuffer); + Mesh->addMeshBuffer(Materials[i]->Meshbuffer); + } + Materials[i]->Meshbuffer->drop(); + // clear the material array elements + delete Materials[i]; + } + Mesh->recalculateBoundingBox(); + + SAnimatedMesh* am = new SAnimatedMesh(); + am->Type = EAMT_3DS; + am->addMesh(Mesh); + am->recalculateBoundingBox(); + Mesh->drop(); + Mesh = 0; + + Points.clear(); + Indices.clear(); + MaterialMapping.clear(); + TCoords.clear(); + Materials.clear(); + Images.clear(); + VmPolyPointsIndex.clear(); + VmCoordsIndex.clear(); + UvIndex.clear(); + UvName.clear(); + + return am; +} + + +bool CLWOMeshFileLoader::readChunks() +{ + s32 lastPos; + u32 size; + unsigned int uiType; + char type[5]; + type[4]=0; + tLWOLayerInfo layer; + + while(File->getPos()getSize()) + { + File->read(&type, 4); + //Convert 4-char string to 4-byte integer + //Makes it possible to do a switch statement + uiType = charsToUInt(type); + File->read(&size, 4); +#ifndef __BIG_ENDIAN__ + size=os::Byteswap::byteswap(size); +#endif + lastPos=File->getPos(); + + switch(uiType) + { + case charsToUIntD('L','A','Y','R'): + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading layer."); +#endif + u16 tmp16; + File->read(&tmp16, 2); // number + File->read(&tmp16, 2); // flags + size -= 4; +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + if (((FormatVersion==1)&&(tmp16!=1)) || + ((FormatVersion==2)&&(tmp16&1))) + layer.Active=false; + else + layer.Active=true; + if (FormatVersion==2) + size -= readVec(layer.Pivot); + size -= readString(layer.Name); + if (size) + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + layer.Parent = tmp16; + } + } + break; + case charsToUIntD('P','N','T','S'): + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading points."); +#endif + core::vector3df vec; + Points.clear(); + const u32 tmpsize = size/12; + Points.reallocate(tmpsize); + for (u32 i=0; iName=""; + mat->Meshbuffer=new scene::SMeshBuffer(); + size -= readString(mat->Name); + if (FormatVersion!=2) + mat->TagType = 1; // format 2 has more types + Materials.push_back(mat); + } + } + break; + case charsToUIntD('P','T','A','G'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading tag mapping."); +#endif + readTagMapping(size); + break; + case charsToUIntD('V','M','A','D'): // discontinuous vertex mapping, i.e. additional texcoords +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading Vertex mapping VMAD."); +#endif + readDiscVertexMapping(size); +// case charsToUIntD('V','M','P','A'): +// case charsToUIntD('E','N','V','L'): + break; + case charsToUIntD('C','L','I','P'): + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading clips."); +#endif + u32 index; + u16 subsize; + File->read(&index, 4); +#ifndef __BIG_ENDIAN__ + index=os::Byteswap::byteswap(index); +#endif + size -= 4; + while (size != 0) + { + File->read(&type, 4); + File->read(&subsize, 2); +#ifndef __BIG_ENDIAN__ + subsize=os::Byteswap::byteswap(subsize); +#endif + size -= 6; + if (strncmp(type, "STIL", 4)) + { + File->seek(subsize, true); + size -= subsize; + continue; + } + core::stringc path; + size -= readString(path, subsize); + #ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loaded clip", path.c_str()); + #endif + Images.push_back(path); + } + } + break; + case charsToUIntD('S','U','R','F'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading material."); +#endif + readMat(size); + break; + case charsToUIntD('B','B','O','X'): + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading bbox."); +#endif + // not stored + core::vector3df vec; + for (u32 i=0; i<2; ++i) + readVec(vec); + size -= 24; + } + break; + case charsToUIntD('D','E','S','C'): + case charsToUIntD('T','E','X','T'): + { + core::stringc text; + size -= readString(text, size); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader text", text); +#endif + } + break; + // not needed + case charsToUIntD('I','C','O','N'): + // not yet supported + case charsToUIntD('P','C','H','S'): + case charsToUIntD('C','R','V','S'): + default: +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: skipping ", type); +#endif + //Go to next chunk + File->seek(lastPos + size, false); + break; + } + } + return true; +} + + +void CLWOMeshFileLoader::readObj1(u32 size) +{ + u32 pos; + u16 numVerts, vertIndex; + s16 material; + video::S3DVertex vertex; + vertex.Color=0xffffffff; + + while (size!=0) + { + File->read(&numVerts, 2); +#ifndef __BIG_ENDIAN__ + numVerts=os::Byteswap::byteswap(numVerts); +#endif + pos=File->getPos(); + // skip forward to material number + File->seek(2*numVerts, true); + File->read(&material, 2); +#ifndef __BIG_ENDIAN__ + material=os::Byteswap::byteswap(material); +#endif + size -=2*numVerts+4; + // detail meshes ? + scene::SMeshBuffer *mb; + if (material<0) + mb=Materials[-material-1]->Meshbuffer; + else + mb=Materials[material-1]->Meshbuffer; + // back to vertex list start + File->seek(pos, false); + + const u16 vertCount=mb->Vertices.size(); + for (u16 i=0; iread(&vertIndex, 2); +#ifndef __BIG_ENDIAN__ + vertIndex=os::Byteswap::byteswap(vertIndex); +#endif + vertex.Pos=Points[vertIndex]; + mb->Vertices.push_back(vertex); + } + for (u16 i=1; iIndices.push_back(vertCount); + mb->Indices.push_back(vertCount+i); + mb->Indices.push_back(vertCount+i+1); + } + // skip material number and detail surface count + // detail surface can be read just as a normal one now + if (material<0) + File->read(&material, 2); + File->read(&material, 2); + } +} + + +void CLWOMeshFileLoader::readVertexMapping(u32 size) +{ + char type[5]={0}; + u16 dimension; + core::stringc name; + File->read(&type, 4); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: Vertex map type", type); +#endif + File->read(&dimension,2); +#ifndef __BIG_ENDIAN__ + dimension=os::Byteswap::byteswap(dimension); +#endif + size -= 6; + size -= readString(name); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: Vertex map", name.c_str()); +#endif + if (strncmp(type, "TXUV", 4)) // also support RGB, RGBA, WGHT, ... + { + File->seek(size, true); + return; + } + UvName.push_back(name); + + TCoords.push_back(core::array()); + core::array& UvCoords=TCoords.getLast(); + UvCoords.reallocate(Points.size()); + UvIndex.push_back(core::array()); + core::array& UvPointsArray=UvIndex.getLast(); + UvPointsArray.reallocate(Points.size()); + + u32 index; + core::vector2df tcoord; + while (size) + { + size -= readVX(index); + File->read(&tcoord.X, 4); + File->read(&tcoord.Y, 4); + size -= 8; +#ifndef __BIG_ENDIAN__ + index=os::Byteswap::byteswap(index); + tcoord.X=os::Byteswap::byteswap(tcoord.X); + tcoord.Y=os::Byteswap::byteswap(tcoord.Y); +#endif + UvCoords.push_back(tcoord); + UvPointsArray.push_back(index); + } +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: UvCoords", core::stringc(UvCoords.size())); +#endif +} + + +void CLWOMeshFileLoader::readDiscVertexMapping(u32 size) +{ + char type[5]={0}; + u16 dimension; + core::stringc name; + File->read(&type, 4); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: Discontinuous vertex map type", type); +#endif + File->read(&dimension,2); +#ifndef __BIG_ENDIAN__ + dimension=os::Byteswap::byteswap(dimension); +#endif + size -= 6; + size -= readString(name); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: Discontinuous vertex map", name.c_str()); +#endif + if (strncmp(type, "TXUV", 4)) + { + File->seek(size, true); + return; + } + DUvName.push_back(name); + VmPolyPointsIndex.push_back(core::array()); + core::array& VmPolyPoints=VmPolyPointsIndex.getLast(); + + VmCoordsIndex.push_back(core::array()); + core::array& VmCoords=VmCoordsIndex.getLast(); + + u32 vmpolys; + u32 vmpoints; + core::vector2df vmcoords; + while (size) + { + size-=readVX(vmpoints); + size-=readVX(vmpolys); + File->read(&vmcoords.X, 4); + File->read(&vmcoords.Y, 4); + size -= 8; +#ifndef __BIG_ENDIAN__ + vmpoints=os::Byteswap::byteswap(vmpoints); + vmpolys=os::Byteswap::byteswap(vmpolys); + vmcoords.X=os::Byteswap::byteswap(vmcoords.X); + vmcoords.Y=os::Byteswap::byteswap(vmcoords.Y); +#endif + VmCoords.push_back(vmcoords); + VmPolyPoints.push_back(vmpolys); + VmPolyPoints.push_back(vmpoints); + } +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: VmCoords", core::stringc(VmCoords.size())); +#endif +} + + +void CLWOMeshFileLoader::readTagMapping(u32 size) +{ + char type[5]; + type[4]=0; + File->read(&type, 4); + size -= 4; + if ((strncmp(type, "SURF", 4))||(Indices.size()==0)) + { + File->seek(size, true); + return; + } + + while (size!=0) + { + u16 tag; + u32 polyIndex; + size-=readVX(polyIndex); + File->read(&tag, 2); +#ifndef __BIG_ENDIAN__ + tag=os::Byteswap::byteswap(tag); +#endif + size -= 2; + MaterialMapping[polyIndex]=tag; + Materials[tag]->TagType=1; + } +} + + +void CLWOMeshFileLoader::readObj2(u32 size) +{ + char type[5]; + type[4]=0; + File->read(&type, 4); + size -= 4; + Indices.clear(); + if (strncmp(type, "FACE", 4)) // also possible are splines, subdivision patches, metaballs, and bones + { + File->seek(size, true); + return; + } + u16 numVerts=0; + while (size!=0) + { + File->read(&numVerts, 2); +#ifndef __BIG_ENDIAN__ + numVerts=os::Byteswap::byteswap(numVerts); +#endif + // mask out flags + numVerts &= 0x03FF; + + size -= 2; + Indices.push_back(core::array()); + u32 vertIndex; + core::array& polyArray = Indices.getLast(); + polyArray.reallocate(numVerts); + for (u16 i=0; iTagType==1) && (Materials[i]->Name==name)) + { + mat=Materials[i]; + break; + } + } + if (!mat) + { + File->seek(size, true); + return; + } + if (FormatVersion==2) + size -= readString(name); + + video::SMaterial& irrMat=mat->Meshbuffer->Material; + + u8 currTexture=0; + while (size!=0) + { + char type[5]; + type[4]=0; + u32 uiType; + u32 tmp32; + u16 subsize, tmp16; + f32 tmpf32; + File->read(&type, 4); + //Convert 4-char string to 4-byte integer + //Makes it possible to do a switch statement + uiType = charsToUInt(type); + File->read(&subsize, 2); +#ifndef __BIG_ENDIAN__ + subsize=os::Byteswap::byteswap(subsize); +#endif + size -= 6; + switch (uiType) + { + case charsToUIntD('C','O','L','R'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading Ambient color."); +#endif + { + s32 colSize = readColor(irrMat.DiffuseColor); + irrMat.AmbientColor=irrMat.DiffuseColor; + size -= colSize; + subsize -= colSize; + if (FormatVersion==2) + size -= readVX(mat->Envelope[0]); + } + break; + case charsToUIntD('D','I','F','F'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading Diffuse color."); +#endif + { + if (FormatVersion==2) + { + File->read(&mat->Diffuse, 4); +#ifndef __BIG_ENDIAN__ + mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse); +#endif + size -= 4; + subsize -= 4; + size -= readVX(mat->Envelope[1]); + } + else + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + mat->Diffuse=tmp16/256.0f; + size -= 2; + subsize -= 2; + } + } + break; + case charsToUIntD('V','D','I','F'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading Diffuse color."); +#endif + { + File->read(&mat->Diffuse, 4); +#ifndef __BIG_ENDIAN__ + mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse); +#endif + size -= 4; + } + break; + case charsToUIntD('L','U','M','I'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading luminance."); +#endif + { + if (FormatVersion==2) + { + File->read(&mat->Luminance, 4); +#ifndef __BIG_ENDIAN__ + mat->Luminance=os::Byteswap::byteswap(mat->Luminance); +#endif + size -= 4; + subsize -= 4; + size -= readVX(mat->Envelope[2]); + } + else + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + mat->Luminance=tmp16/256.0f; + size -= 2; + subsize -= 2; + } } + break; + case charsToUIntD('V','L','U','M'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading luminance."); +#endif + { + File->read(&mat->Luminance, 4); +#ifndef __BIG_ENDIAN__ + mat->Luminance=os::Byteswap::byteswap(mat->Luminance); +#endif + size -= 4; + } + break; + case charsToUIntD('S','P','E','C'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading specular."); +#endif + { + if (FormatVersion==2) + { + File->read(&mat->Specular, 4); +#ifndef __BIG_ENDIAN__ + mat->Specular=os::Byteswap::byteswap(mat->Specular); +#endif + size -= 4; + subsize -= 4; + size -= readVX(mat->Envelope[3]); + } + else + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + mat->Specular=tmp16/256.0f;; + size -= 2; + subsize -= 2; + } + } + break; + case charsToUIntD('V','S','P','C'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading specular."); +#endif + { + File->read(&mat->Specular, 4); +#ifndef __BIG_ENDIAN__ + mat->Specular=os::Byteswap::byteswap(mat->Specular); +#endif + size -= 4; + } + break; + case charsToUIntD('R','E','F','L'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading reflection."); +#endif + { + if (FormatVersion==2) + { + File->read(&mat->Reflection, 4); +#ifndef __BIG_ENDIAN__ + mat->Reflection=os::Byteswap::byteswap(mat->Reflection); +#endif + size -= 4; + subsize -= 4; + size -= readVX(mat->Envelope[4]); + } + else + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + mat->Reflection=tmp16/256.0f; + size -= 2; + subsize -= 2; + } + } + break; + case charsToUIntD('V','R','F','L'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading reflection."); +#endif + { + File->read(&mat->Reflection, 4); +#ifndef __BIG_ENDIAN__ + mat->Reflection=os::Byteswap::byteswap(mat->Reflection); +#endif + size -= 4; + } + break; + case charsToUIntD('T','R','A','N'): + { + if (FormatVersion==2) + { + File->read(&mat->Transparency, 4); +#ifndef __BIG_ENDIAN__ + mat->Transparency=os::Byteswap::byteswap(mat->Transparency); +#endif + size -= 4; + subsize -= 4; + size -= readVX(mat->Envelope[5]); + } + else + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + mat->Transparency=tmp16/256.0f; + size -= 2; + subsize -= 2; + } +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading transparency", core::stringc(mat->Transparency).c_str()); +#endif + } + break; + case charsToUIntD('V','T','R','N'): + { + File->read(&mat->Transparency, 4); +#ifndef __BIG_ENDIAN__ + mat->Transparency=os::Byteswap::byteswap(mat->Transparency); +#endif + size -= 4; + } +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading transparency", core::stringc(mat->Transparency).c_str()); +#endif + break; + case charsToUIntD('T','R','N','L'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading translucency."); +#endif + { + File->read(&mat->Translucency, 4); +#ifndef __BIG_ENDIAN__ + mat->Translucency=os::Byteswap::byteswap(mat->Translucency); +#endif + size -= 4; + subsize -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[6]); + } + break; + case charsToUIntD('G','L','O','S'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading glossy."); +#endif + { + if (FormatVersion == 2) + { + File->read(&irrMat.Shininess, 4); +#ifndef __BIG_ENDIAN__ + irrMat.Shininess=os::Byteswap::byteswap(irrMat.Shininess); +#endif + size -= 4; + subsize -= 4; + size -= readVX(mat->Envelope[7]); + } + else + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + irrMat.Shininess=tmp16/16.f; + size -= 2; + subsize -= 2; + } + } + break; + case charsToUIntD('S','H','R','P'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading sharpness."); +#endif + { + File->read(&mat->Sharpness, 4); +#ifndef __BIG_ENDIAN__ + mat->Sharpness=os::Byteswap::byteswap(mat->Sharpness); +#endif + size -= 4; + subsize -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[8]); + } + break; + case charsToUIntD('B','U','M','P'): + case charsToUIntD('T','A','M','P'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading bumpiness."); +#endif + { + File->read(&tmpf32, 4); +#ifndef __BIG_ENDIAN__ + tmpf32=os::Byteswap::byteswap(tmpf32); +#endif + if (currTexture==6) + irrMat.MaterialTypeParam=tmpf32; + size -= 4; + subsize -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[9]); + } + break; + case charsToUIntD('S','I','D','E'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading backface culled."); +#endif + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + if (tmp16==1) + irrMat.BackfaceCulling=true; + else if (tmp16==3) + irrMat.BackfaceCulling=false; + size -= 2; + } + break; + case charsToUIntD('S','M','A','N'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading smoothing angle."); +#endif + { + File->read(&mat->SmoothingAngle, 4); +#ifndef __BIG_ENDIAN__ + mat->SmoothingAngle=os::Byteswap::byteswap(mat->SmoothingAngle); +#endif + size -= 4; + } + break; + case charsToUIntD('R','F','O','P'): + case charsToUIntD('R','F','L','T'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading reflection mode."); +#endif + { + File->read(&mat->ReflMode, 2); +#ifndef __BIG_ENDIAN__ + mat->ReflMode=os::Byteswap::byteswap(mat->ReflMode); +#endif + size -= 2; + } + break; + case charsToUIntD('R','I','M','G'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading reflection map."); +#endif + { + if (FormatVersion==2) + { + size -= readVX(tmp32); + if (tmp32) + mat->ReflMap=Images[tmp32-1]; + } + else + size -= readString(mat->ReflMap, size); + } + break; + case charsToUIntD('R','S','A','N'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading reflection seam angle."); +#endif + { + File->read(&mat->ReflSeamAngle, 4); +#ifndef __BIG_ENDIAN__ + mat->ReflSeamAngle=os::Byteswap::byteswap(mat->ReflSeamAngle); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[10]); + } + break; + case charsToUIntD('R','B','L','R'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading reflection blur."); +#endif + { + File->read(&mat->ReflBlur, 4); +#ifndef __BIG_ENDIAN__ + mat->ReflBlur=os::Byteswap::byteswap(mat->ReflBlur); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[11]); + } + break; + case charsToUIntD('R','I','N','D'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading refraction index."); +#endif + { + File->read(&mat->RefrIndex, 4); +#ifndef __BIG_ENDIAN__ + mat->RefrIndex=os::Byteswap::byteswap(mat->RefrIndex); +#endif + size -= 4; + subsize -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[12]); + } + break; + case charsToUIntD('T','R','O','P'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading refraction options."); +#endif + { + File->read(&mat->TranspMode, 2); +#ifndef __BIG_ENDIAN__ + mat->TranspMode=os::Byteswap::byteswap(mat->TranspMode); +#endif + size -= 2; + } + break; + case charsToUIntD('T','I','M','G'): + { + if (FormatVersion==2) + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading refraction map."); +#endif + size -= readVX(tmp32); +#ifndef __BIG_ENDIAN__ + tmp32=os::Byteswap::byteswap(tmp32); +#endif + if (tmp32) + mat->Texture[currTexture].Map=Images[tmp32-1]; + } + else + { + size -= readString(mat->Texture[currTexture].Map, size); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading image", mat->Texture[currTexture].Map.c_str()); +#endif + } + } + break; + case charsToUIntD('T','B','L','R'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading transparency blur."); +#endif + { + File->read(&mat->TranspBlur, 4); +#ifndef __BIG_ENDIAN__ + mat->TranspBlur=os::Byteswap::byteswap(mat->TranspBlur); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[13]); + } + break; + case charsToUIntD('C','L','R','H'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading highlight color."); +#endif + { + File->read(&mat->HighlightColor, 4); +#ifndef __BIG_ENDIAN__ + mat->HighlightColor=os::Byteswap::byteswap(mat->HighlightColor); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[14]); + } + break; + case charsToUIntD('C','L','R','F'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading color filter."); +#endif + { + File->read(&mat->ColorFilter, 4); +#ifndef __BIG_ENDIAN__ + mat->ColorFilter=os::Byteswap::byteswap(mat->ColorFilter); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[15]); + } + break; + case charsToUIntD('A','D','T','R'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading additive transparency."); +#endif + { + File->read(&mat->AdditiveTransparency, 4); +#ifndef __BIG_ENDIAN__ + mat->AdditiveTransparency=os::Byteswap::byteswap(mat->AdditiveTransparency); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[16]); + } + break; + case charsToUIntD('G','L','O','W'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading glow."); +#endif + { + if (FormatVersion==0) + { + File->read(&mat->GlowIntensity, 4); +#ifndef __BIG_ENDIAN__ + mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity); +#endif + size -= 4; + } + else + { + File->read(&mat->Glow, 2); +#ifndef __BIG_ENDIAN__ + mat->Glow=os::Byteswap::byteswap(mat->Glow); +#endif + size -= 2; + File->read(&mat->GlowIntensity, 4); +#ifndef __BIG_ENDIAN__ + mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[17]); + File->read(&mat->GlowSize, 4); +#ifndef __BIG_ENDIAN__ + mat->GlowSize=os::Byteswap::byteswap(mat->GlowSize); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[18]); + } + } + break; + case charsToUIntD('G','V','A','L'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading glow intensity."); +#endif + { + File->read(&mat->GlowIntensity, 4); +#ifndef __BIG_ENDIAN__ + mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[17]); + } + break; + case charsToUIntD('L','I','N','E'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading isWireframe."); +#endif + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + if (tmp16&1) + irrMat.Wireframe=true; + size -= 2; + if (size!=0) + { + File->read(&irrMat.Thickness, 4); +#ifndef __BIG_ENDIAN__ + irrMat.Thickness=os::Byteswap::byteswap(irrMat.Thickness); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[19]); + } + if (size!=0) + { + video::SColor lineColor; + size -= readColor(lineColor); + if (FormatVersion==2) + size -= readVX(mat->Envelope[20]); + } + } + break; + case charsToUIntD('A','L','P','H'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading alpha mode."); +#endif + { + File->read(&mat->AlphaMode, 2); +#ifndef __BIG_ENDIAN__ + mat->AlphaMode=os::Byteswap::byteswap(mat->AlphaMode); +#endif + size -= 2; + File->read(&mat->AlphaValue, 4); +#ifndef __BIG_ENDIAN__ + mat->AlphaValue=os::Byteswap::byteswap(mat->AlphaValue); +#endif + size -= 4; + } + break; + case charsToUIntD('V','C','O','L'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading vertex color."); +#endif + { + File->read(&mat->VertexColorIntensity, 4); +#ifndef __BIG_ENDIAN__ + mat->VertexColorIntensity=os::Byteswap::byteswap(mat->VertexColorIntensity); +#endif + size -= 4; + if (FormatVersion==2) + size -= readVX(mat->Envelope[21]); + File->read(&tmp32, 4); // skip type + size -= 4; + core::stringc tmpname; + size -= readString(tmpname, size); +// mat->VertexColor = getColorVMAP(tmpname); + } + break; + case charsToUIntD('F','L','A','G'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading flag."); +#endif + { + File->read(&mat->Flags, 2); +#ifndef __BIG_ENDIAN__ + mat->Flags=os::Byteswap::byteswap(mat->Flags); +#endif + if (mat->Flags&1) + mat->Luminance=1.0f; + if (mat->Flags&256) + irrMat.BackfaceCulling=false; + size -= 2; + } + break; + case charsToUIntD('E','D','G','E'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading edge."); +#endif + { + File->read(&mat->EdgeTransparency, 4); +#ifndef __BIG_ENDIAN__ + mat->EdgeTransparency=os::Byteswap::byteswap(mat->EdgeTransparency); +#endif + size -= 4; + } + break; + case charsToUIntD('C','T','E','X'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading ctex."); +#endif + currTexture=0; + size -= readString(mat->Texture[currTexture].Type, size); + break; + case charsToUIntD('D','T','E','X'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading dtex."); +#endif + currTexture=1; + size -= readString(mat->Texture[currTexture].Type, size); + break; + case charsToUIntD('S','T','E','X'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading stex."); +#endif + currTexture=2; + size -= readString(mat->Texture[currTexture].Type, size); + break; + case charsToUIntD('R','T','E','X'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading rtex."); +#endif + currTexture=3; + size -= readString(mat->Texture[currTexture].Type, size); + break; + case charsToUIntD('T','T','E','X'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading ttex."); +#endif + currTexture=4; + size -= readString(mat->Texture[currTexture].Type, size); + break; + case charsToUIntD('L','T','E','X'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading ltex."); +#endif + currTexture=5; + size -= readString(mat->Texture[currTexture].Type, size); + break; + case charsToUIntD('B','T','E','X'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading btex."); +#endif + currTexture=6; + size -= readString(mat->Texture[currTexture].Type, size); + break; + case charsToUIntD('T','A','L','P'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading alpha map."); +#endif + size -= readString(mat->Texture[currTexture].AlphaMap, size); + break; + case charsToUIntD('T','F','L','G'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture flag."); +#endif + { + File->read(&mat->Texture[currTexture].Flags, 2); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].Flags=os::Byteswap::byteswap(mat->Texture[currTexture].Flags); +#endif + size -= 2; + } + break; + case charsToUIntD('E','N','A','B'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading isEnabled."); +#endif + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + mat->Texture[currTexture].Active=(tmp16!=0); + size -= 2; + } + break; + case charsToUIntD('W','R','A','P'): + case charsToUIntD('T','W','R','P'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture wrap."); +#endif + { + File->read(&mat->Texture[currTexture].WidthWrap, 2); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].WidthWrap=os::Byteswap::byteswap(mat->Texture[currTexture].WidthWrap); +#endif + File->read(&mat->Texture[currTexture].HeightWrap, 2); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].HeightWrap=os::Byteswap::byteswap(mat->Texture[currTexture].HeightWrap); +#endif + size -= 4; + } + break; + case charsToUIntD('T','V','E','L'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture velocity."); +#endif + size -= readVec(mat->Texture[currTexture].Velocity); + break; + case charsToUIntD('T','C','L','R'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture color."); +#endif + size -= readColor(mat->Texture[currTexture].Color); + break; + case charsToUIntD('A','A','S','T'): + case charsToUIntD('T','A','A','S'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture antialias."); +#endif + { + tmp16=0; + if (FormatVersion==2) + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + size -= 2; + } + File->read(&mat->Texture[currTexture].AntiAliasing, 4); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].AntiAliasing=os::Byteswap::byteswap(mat->Texture[currTexture].AntiAliasing); +#endif + if (tmp16 & ~0x01) + mat->Texture[currTexture].AntiAliasing=0.0f; // disabled + size -= 4; + } + break; + case charsToUIntD('T','O','P','C'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture opacity."); +#endif + { + File->read(&mat->Texture[currTexture].Opacity, 4); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity); +#endif + size -= 4; + } + break; + case charsToUIntD('O','P','A','C'): + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture opacity and type."); +#endif + File->read(&mat->Texture[currTexture].OpacType, 2); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].OpacType=os::Byteswap::byteswap(mat->Texture[currTexture].OpacType); +#endif + File->read(&mat->Texture[currTexture].Opacity, 4); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity); +#endif + size -= 6; + subsize -= 6; + if (FormatVersion==2) + size -= readVX(mat->Envelope[22]); + } + break; + case charsToUIntD('A','X','I','S'): + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + mat->Texture[currTexture].Axis=(u8)tmp16; + size -= 2; +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading axis value", core::stringc(tmp16).c_str()); +#endif + } + break; + case charsToUIntD('T','M','A','P'): // empty separation chunk + break; + case charsToUIntD('T','C','T','R'): + case charsToUIntD('C','N','T','R'): + { + core::vector3df& center=mat->Texture[currTexture].Center; + size -= readVec(center); + if (FormatVersion==2) + size -= readVX(mat->Envelope[22]); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture center", (core::stringc(center.X)+" "+core::stringc(center.Y)+" "+core::stringc(center.Z)).c_str()); +#endif + } + break; + case charsToUIntD('T','S','I','Z'): + case charsToUIntD('S','I','Z','E'): + { + core::vector3df& tsize=mat->Texture[currTexture].Size; + size -= readVec(tsize); + if (FormatVersion==2) + size -= readVX(mat->Envelope[22]); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture size", (core::stringc(tsize.X)+" "+core::stringc(tsize.Y)+" "+core::stringc(tsize.Z)).c_str()); +#endif + } + break; + case charsToUIntD('R','O','T','A'): + { + core::vector3df rotation; + size -= readVec(rotation); + if (FormatVersion==2) + size -= readVX(mat->Envelope[22]); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture rotation", (core::stringc(rotation.X)+" "+core::stringc(rotation.Y)+" "+core::stringc(rotation.Z)).c_str()); +#endif + } + break; + case charsToUIntD('O','R','E','F'): + { + core::stringc tmpname; + size -= readString(tmpname); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: texture reference object", tmpname.c_str()); +#endif + } + break; + case charsToUIntD('T','F','A','L'): + case charsToUIntD('F','A','L','L'): + { + if (FormatVersion==2) + { + u16 tmp16; + File->read(&tmp16, 2); + size -= 2; +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + } + + core::vector3df& falloff=mat->Texture[currTexture].Falloff; + size -= readVec(falloff); + if (FormatVersion==2) + size -= readVX(mat->Envelope[22]); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture falloff"); +#endif + } + break; + case charsToUIntD('C','S','Y','S'): + { + u16 tmp16; + File->read(&tmp16, 2); + size -= 2; +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: texture coordinate system", tmp16==0?"object coords":"world coords"); +#endif + } + break; + case charsToUIntD('T','V','A','L'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture value."); +#endif + { + File->read(&tmp16, 2); +#ifndef __BIG_ENDIAN__ + tmp16=os::Byteswap::byteswap(tmp16); +#endif + mat->Texture[currTexture].Value=tmp16/256.0f; + size -= 2; + } + break; + case charsToUIntD('T','F','P','0'): + case charsToUIntD('T','S','P','0'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture param 0."); +#endif + { + File->read(&mat->Texture[currTexture].FParam[0], 4); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].FParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[0]); +#endif + size -= 4; + } + break; + case charsToUIntD('T','F','P','1'): + case charsToUIntD('T','S','P','1'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture param 1."); +#endif + { + File->read(&mat->Texture[currTexture].FParam[1], 4); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].FParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[1]); +#endif + size -= 4; + } + break; + case charsToUIntD('T','F','P','2'): + case charsToUIntD('T','S','P','2'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture param 2."); +#endif + { + File->read(&mat->Texture[currTexture].FParam[2], 4); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].FParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[2]); +#endif + size -= 4; + } + break; + case charsToUIntD('T','F','R','Q'): + case charsToUIntD('T','I','P','0'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture iparam 0."); +#endif + { + File->read(&mat->Texture[currTexture].IParam[0], 2); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].IParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[0]); +#endif + size -= 2; + } + break; + case charsToUIntD('T','I','P','1'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture param 1."); +#endif + { + File->read(&mat->Texture[currTexture].IParam[1], 2); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].IParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[1]); +#endif + size -= 2; + } + break; + case charsToUIntD('T','I','P','2'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading texture param 2."); +#endif + { + File->read(&mat->Texture[currTexture].IParam[2], 2); +#ifndef __BIG_ENDIAN__ + mat->Texture[currTexture].IParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[2]); +#endif + size -= 2; + } + break; + case charsToUIntD('V','M','A','P'): + { + size -= readString(mat->Texture[currTexture].UVname); +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading material vmap binding",mat->Texture[currTexture].UVname.c_str()); +#endif + } + break; + case charsToUIntD('B','L','O','K'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading blok."); +#endif + { + core::stringc ordinal; + File->read(&type, 4); + File->read(&subsize, 2); +#ifndef __BIG_ENDIAN__ + subsize=os::Byteswap::byteswap(subsize); +#endif + size -= 6; + size -= readString(ordinal, size); + } + break; + case charsToUIntD('C','H','A','N'): + { + File->read(&type, 4); + size -= 4; + if (!strncmp(type, "COLR", 4)) + currTexture=0; + else if (!strncmp(type, "DIFF", 4)) + currTexture=1; + else if (!strncmp(type, "LUMI", 4)) + currTexture=5; + else if (!strncmp(type, "SPEC", 4)) + currTexture=2; + else if (!strncmp(type, "REFL", 4)) + currTexture=3; + else if (!strncmp(type, "TRAN", 4)) + currTexture=4; + else if (!strncmp(type, "BUMP", 4)) + currTexture=6; + } +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading channel ", type); +#endif + break; + case charsToUIntD('I','M','A','G'): +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading channel map."); +#endif + { + u16 index; + File->read(&index, 2); +#ifndef __BIG_ENDIAN__ + index=os::Byteswap::byteswap(index); +#endif + size -= 2; + if (index) + mat->Texture[currTexture].Map=Images[index-1]; + } + break; + case charsToUIntD('P','R','O','J'): // define the projection type +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: loading channel projection type."); +#endif + { + u16 index; + File->read(&index, 2); +#ifndef __BIG_ENDIAN__ + index=os::Byteswap::byteswap(index); +#endif + size -= 2; +#ifdef LWO_READER_DEBUG + if (index != 5) + os::Printer::log("LWO loader: wrong channel projection type", core::stringc(index).c_str()); +#endif + mat->Texture[currTexture].Projection=(u8)index; + } + break; + case charsToUIntD('W','R','P','W'): // for cylindrical and spherical projections + case charsToUIntD('W','R','P','H'): // for cylindrical and spherical projections + default: + { +#ifdef LWO_READER_DEBUG + os::Printer::log("LWO loader: skipping ", core::stringc((char*)&uiType, 4)); +#endif + File->seek(subsize, true); + size -= subsize; + } + } + } + + if (mat->Transparency != 0.f) + { + irrMat.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; + } +} + + +u32 CLWOMeshFileLoader::readColor(video::SColor& color) +{ + if (FormatVersion!=2) + { + u8 colorComponent; + File->read(&colorComponent, 1); + color.setRed(colorComponent); + File->read(&colorComponent, 1); + color.setGreen(colorComponent); + File->read(&colorComponent, 1); + color.setBlue(colorComponent); + // unknown value + File->read(&colorComponent, 1); + return 4; + } + else + { + video::SColorf col; + File->read(&col.r, 4); +#ifndef __BIG_ENDIAN__ + col.r=os::Byteswap::byteswap(col.r); +#endif + File->read(&col.g, 4); +#ifndef __BIG_ENDIAN__ + col.g=os::Byteswap::byteswap(col.g); +#endif + File->read(&col.b, 4); +#ifndef __BIG_ENDIAN__ + col.b=os::Byteswap::byteswap(col.b); +#endif + color=col.toSColor(); + return 12; + } +} + +u32 CLWOMeshFileLoader::readString(core::stringc& name, u32 size) +{ + c8 c; + + name=""; + if (size) + name.reserve(size); + File->read(&c, 1); + while (c) + { + name.append(c); + File->read(&c, 1); + } + // read extra 0 upon odd file position + if (File->getPos() & 0x1) + { + File->read(&c, 1); + return (name.size()+2); + } + return (name.size()+1); +} + + +u32 CLWOMeshFileLoader::readVec(core::vector3df& vec) +{ + File->read(&vec.X, 4); +#ifndef __BIG_ENDIAN__ + vec.X=os::Byteswap::byteswap(vec.X); +#endif + File->read(&vec.Y, 4); +#ifndef __BIG_ENDIAN__ + vec.Y=os::Byteswap::byteswap(vec.Y); +#endif + File->read(&vec.Z, 4); +#ifndef __BIG_ENDIAN__ + vec.Z=os::Byteswap::byteswap(vec.Z); +#endif + return 12; +} + + +u32 CLWOMeshFileLoader::readVX(u32& num) +{ + u16 tmpIndex; + + File->read(&tmpIndex, 2); +#ifndef __BIG_ENDIAN__ + tmpIndex=os::Byteswap::byteswap(tmpIndex); +#endif + num=tmpIndex; + if (num >= 0xFF00) + { + File->read(&tmpIndex, 2); +#ifndef __BIG_ENDIAN__ + tmpIndex=os::Byteswap::byteswap(tmpIndex); +#endif + num=((num << 16)|tmpIndex) & ~0xFF000000; + return 4; + } + return 2; +} + + +bool CLWOMeshFileLoader::readFileHeader() +{ + u32 Id; + + File->read(&Id, 4); +#ifndef __BIG_ENDIAN__ + Id=os::Byteswap::byteswap(Id); +#endif + if (Id != 0x464f524d) // FORM + return false; + + //skip the file length + File->read(&Id, 4); + + File->read(&Id, 4); +#ifndef __BIG_ENDIAN__ + Id=os::Byteswap::byteswap(Id); +#endif + // Currently supported: LWOB, LWLO, LWO2 + switch (Id) + { + case 0x4c574f42: + FormatVersion = 0; // LWOB + break; + case 0x4c574c4f: + FormatVersion = 1; // LWLO + break; + case 0x4c574f32: + FormatVersion = 2; // LWO2 + break; + default: + return false; // unsupported + } + + return true; +} + + +video::ITexture* CLWOMeshFileLoader::loadTexture(const core::stringc& file) +{ + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + + if (FileSystem->existFile(file)) + return driver->getTexture(file); + + core::stringc strippedName=FileSystem->getFileBasename(file); + if (FileSystem->existFile(strippedName)) + return driver->getTexture(strippedName); + core::stringc newpath = FileSystem->getFileDir(File->getFileName()); + newpath.append("/"); + newpath.append(strippedName); + if (FileSystem->existFile(newpath)) + return driver->getTexture(newpath); + os::Printer::log("Could not load texture", file.c_str(), ELL_WARNING); + + return 0; +} + + +} // end namespace scene +} // end namespace irr + diff --git a/src/dep/src/irrlicht/CLWOMeshFileLoader.h b/src/dep/src/irrlicht/CLWOMeshFileLoader.h index 674690b..edef071 100644 --- a/src/dep/src/irrlicht/CLWOMeshFileLoader.h +++ b/src/dep/src/irrlicht/CLWOMeshFileLoader.h @@ -1,82 +1,87 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __C_LWO_MESH_FILE_LOADER_H_INCLUDED__ -#define __C_LWO_MESH_FILE_LOADER_H_INCLUDED__ - -#include "IMeshLoader.h" -#include "SMeshBuffer.h" -#include "irrString.h" -#include "irrMap.h" - -namespace irr -{ -namespace io -{ - class IReadFile; - class IFileSystem; -} // end namespace io -namespace scene -{ - - struct SMesh; - class ISceneManager; - -//! Meshloader capable of loading Lightwave 3D meshes. -class CLWOMeshFileLoader : public IMeshLoader -{ -public: - - //! Constructor - CLWOMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); - - //! destructor - virtual ~CLWOMeshFileLoader(); - - //! returns true if the file maybe is able to be loaded by this class - //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; - - //! creates/loads an animated mesh from the file. - //! \return Pointer to the created mesh. Returns 0 if loading failed. - //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). - //! See IUnknown::drop() for more information. - virtual IAnimatedMesh* createMesh(io::IReadFile* file); - -private: - - struct tLWOMaterial; - - bool readFileHeader(); - bool readChunks(); - void readObj1(u32 size); - void readTagMapping(u32 size); - void readVertexMapping(u32 size); - void readObj2(u32 size); - void readMat(u32 size); - u32 readString(core::stringc& name, u32 size=0); - u32 readVec(core::vector3df& vec); - u32 readVX(u32& num); - u32 readColor(video::SColor& color); - video::ITexture* loadTexture(const core::stringc& file); - - scene::ISceneManager* SceneManager; - io::IFileSystem* FileSystem; - io::IReadFile* File; - SMesh* Mesh; - - core::array Points; - core::array > Indices; - core::array MaterialMapping; - core::map VMap; - core::array > TCoords; - core::array Materials; - core::array Images; - u8 FormatVersion; -}; - -} // end namespace scene -} // end namespace irr - -#endif +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_LWO_MESH_FILE_LOADER_H_INCLUDED__ +#define __C_LWO_MESH_FILE_LOADER_H_INCLUDED__ + +#include "IMeshLoader.h" +#include "SMeshBuffer.h" +#include "irrString.h" + +namespace irr +{ +namespace io +{ + class IReadFile; + class IFileSystem; +} // end namespace io +namespace scene +{ + + struct SMesh; + class ISceneManager; + +//! Meshloader capable of loading Lightwave 3D meshes. +class CLWOMeshFileLoader : public IMeshLoader +{ +public: + + //! Constructor + CLWOMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); + + //! destructor + virtual ~CLWOMeshFileLoader(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".bsp") + virtual bool isALoadableFileExtension(const io::path& filename) const; + + //! creates/loads an animated mesh from the file. + //! \return Pointer to the created mesh. Returns 0 if loading failed. + //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). + //! See IUnknown::drop() for more information. + virtual IAnimatedMesh* createMesh(io::IReadFile* file); + +private: + + struct tLWOMaterial; + + bool readFileHeader(); + bool readChunks(); + void readObj1(u32 size); + void readTagMapping(u32 size); + void readVertexMapping(u32 size); + void readDiscVertexMapping (u32 size); + void readObj2(u32 size); + void readMat(u32 size); + u32 readString(core::stringc& name, u32 size=0); + u32 readVec(core::vector3df& vec); + u32 readVX(u32& num); + u32 readColor(video::SColor& color); + video::ITexture* loadTexture(const core::stringc& file); + + scene::ISceneManager* SceneManager; + io::IFileSystem* FileSystem; + io::IReadFile* File; + SMesh* Mesh; + + core::array Points; + core::array > Indices; + core::array UvName; + core::array > UvIndex; + core::array DUvName; + core::array > VmPolyPointsIndex; + core::array > VmCoordsIndex; + + core::array MaterialMapping; + core::array > TCoords; + core::array Materials; + core::array Images; + u8 FormatVersion; +}; + +} // end namespace scene +} // end namespace irr + +#endif diff --git a/src/dep/src/irrlicht/CLightSceneNode.cpp b/src/dep/src/irrlicht/CLightSceneNode.cpp index ec6cf75..9b04ae1 100644 --- a/src/dep/src/irrlicht/CLightSceneNode.cpp +++ b/src/dep/src/irrlicht/CLightSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,7 +17,7 @@ namespace scene //! constructor CLightSceneNode::CLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, video::SColorf color, f32 radius) -: ILightSceneNode(parent, mgr, id, position) +: ILightSceneNode(parent, mgr, id, position), DriverLightIndex(-1), LightIsOn(true) { #ifdef _DEBUG setDebugName("CLightSceneNode"); @@ -28,7 +28,6 @@ CLightSceneNode::CLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, LightData.SpecularColor = color.getInterpolated(video::SColor(255,255,255,255),0.7f); setRadius(radius); - doLightRecalc(); } @@ -72,7 +71,9 @@ void CLightSceneNode::render() break; } } - driver->addDynamicLight(LightData); + + DriverLightIndex = driver->addDynamicLight(LightData); + setVisible(LightIsOn); } @@ -96,6 +97,19 @@ video::SLight& CLightSceneNode::getLightData() return LightData; } +void CLightSceneNode::setVisible(bool isVisible) +{ + ISceneNode::setVisible(isVisible); + + if(DriverLightIndex < 0) + return; + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + if (!driver) + return; + + LightIsOn = isVisible; + driver->turnLightOn((u32)DriverLightIndex, LightIsOn); +} //! returns the axis aligned bounding box of this node const core::aabbox3d& CLightSceneNode::getBoundingBox() const @@ -114,6 +128,7 @@ void CLightSceneNode::setRadius(f32 radius) { LightData.Radius=radius; LightData.Attenuation.set(0.f, 1.f/radius, 0.f); + doLightRecalc(); } @@ -207,18 +222,28 @@ void CLightSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeR LightData.AmbientColor = in->getAttributeAsColorf("AmbientColor"); LightData.DiffuseColor = in->getAttributeAsColorf("DiffuseColor"); LightData.SpecularColor = in->getAttributeAsColorf("SpecularColor"); + + //TODO: clearify Radius and Linear Attenuation +#if 0 + setRadius ( in->getAttributeAsFloat("Radius") ); +#else + LightData.Radius = in->getAttributeAsFloat("Radius"); +#endif + if (in->existsAttribute("Attenuation")) // might not exist in older files LightData.Attenuation = in->getAttributeAsVector3d("Attenuation"); + if (in->existsAttribute("OuterCone")) // might not exist in older files LightData.OuterCone = in->getAttributeAsFloat("OuterCone"); if (in->existsAttribute("InnerCone")) // might not exist in older files LightData.InnerCone = in->getAttributeAsFloat("InnerCone"); if (in->existsAttribute("Falloff")) // might not exist in older files LightData.Falloff = in->getAttributeAsFloat("Falloff"); - LightData.Radius = in->getAttributeAsFloat("Radius"); LightData.CastShadows = in->getAttributeAsBool("CastShadows"); LightData.Type = (video::E_LIGHT_TYPE)in->getAttributeAsEnumeration("LightType", video::LightTypeNames); + doLightRecalc (); + ILightSceneNode::deserializeAttributes(in, options); } @@ -237,7 +262,8 @@ ISceneNode* CLightSceneNode::clone(ISceneNode* newParent, ISceneManager* newMana nb->LightData = LightData; nb->BBox = BBox; - nb->drop(); + if ( newParent ) + nb->drop(); return nb; } diff --git a/src/dep/src/irrlicht/CLightSceneNode.h b/src/dep/src/irrlicht/CLightSceneNode.h index 689e3f6..d7fd520 100644 --- a/src/dep/src/irrlicht/CLightSceneNode.h +++ b/src/dep/src/irrlicht/CLightSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -39,6 +39,12 @@ public: //! \return Returns the light data. virtual video::SLight& getLightData(); + //! Sets if the node should be visible or not. + /** All children of this node won't be visible either, when set + to true. + \param isVisible If the node shall be visible. */ + virtual void setVisible(bool isVisible); + //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; @@ -89,6 +95,8 @@ private: video::SLight LightData; core::aabbox3d BBox; + s32 DriverLightIndex; + bool LightIsOn; void doLightRecalc(); }; diff --git a/src/dep/src/irrlicht/CLimitReadFile.cpp b/src/dep/src/irrlicht/CLimitReadFile.cpp index f192141..3e73e83 100644 --- a/src/dep/src/irrlicht/CLimitReadFile.cpp +++ b/src/dep/src/irrlicht/CLimitReadFile.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,31 +11,24 @@ namespace io { -CLimitReadFile::CLimitReadFile(IReadFile* alreadyOpenedFile, long areaSize, const c8* name) -: Filename(name), AreaSize(areaSize), AreaStart(0), AreaEnd(0), File(alreadyOpenedFile) +CLimitReadFile::CLimitReadFile(IReadFile* alreadyOpenedFile, long pos, + long areaSize, const io::path& name) + : Filename(name), AreaStart(0), AreaEnd(0), Pos(0), + File(alreadyOpenedFile) { #ifdef _DEBUG setDebugName("CLimitReadFile"); #endif if (File) + { File->grab(); - - init(); + AreaStart = pos; + AreaEnd = AreaStart + areaSize; + } } -void CLimitReadFile::init() -{ - if (!File) - return; - - AreaStart = File->getPos(); - AreaEnd = AreaStart + AreaSize; -} - - - CLimitReadFile::~CLimitReadFile() { if (File) @@ -43,10 +36,22 @@ CLimitReadFile::~CLimitReadFile() } - //! returns how much was read s32 CLimitReadFile::read(void* buffer, u32 sizeToRead) { +#if 1 + if (0 == File) + return 0; + + s32 r = AreaStart + Pos; + s32 toRead = core::s32_min(AreaEnd, r + sizeToRead) - core::s32_max(AreaStart, r); + if (toRead < 0) + return 0; + File->seek(r); + r = File->read(buffer, toRead); + Pos += r; + return r; +#else const long pos = File->getPos(); if (pos >= AreaEnd) @@ -56,15 +61,17 @@ s32 CLimitReadFile::read(void* buffer, u32 sizeToRead) sizeToRead = AreaEnd - pos; return File->read(buffer, sizeToRead); +#endif } - //! changes position in file, returns true if successful -//! if relativeMovement==true, the pos is changed relative to current pos, -//! otherwise from begin of file bool CLimitReadFile::seek(long finalPos, bool relativeMovement) { +#if 1 + Pos = core::s32_clamp(finalPos + (relativeMovement ? Pos : 0 ), 0, AreaEnd - AreaStart); + return true; +#else const long pos = File->getPos(); if (relativeMovement) @@ -79,36 +86,39 @@ bool CLimitReadFile::seek(long finalPos, bool relativeMovement) return false; } - return File->seek(finalPos, relativeMovement); + return File->seek(finalPos, relativeMovement); +#endif } //! returns size of file long CLimitReadFile::getSize() const { - return AreaSize; + return AreaEnd - AreaStart; } - //! returns where in the file we are. long CLimitReadFile::getPos() const { +#if 1 + return Pos; +#else return File->getPos() - AreaStart; +#endif } - //! returns name of file -const c8* CLimitReadFile::getFileName() const +const io::path& CLimitReadFile::getFileName() const { - return Filename.c_str(); + return Filename; } -IReadFile* createLimitReadFile(const c8* fileName, IReadFile* alreadyOpenedFile, long areaSize) +IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize) { - return new CLimitReadFile(alreadyOpenedFile, areaSize, fileName); + return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName); } diff --git a/src/dep/src/irrlicht/CLimitReadFile.h b/src/dep/src/irrlicht/CLimitReadFile.h index 0f3c543..d2ca826 100644 --- a/src/dep/src/irrlicht/CLimitReadFile.h +++ b/src/dep/src/irrlicht/CLimitReadFile.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -15,17 +15,17 @@ namespace irr namespace io { - /*! this is a read file, which is limited to some boundaries, + /*! this is a read file, which is limited to some boundaries, so that it may only start from a certain file position and may only read until a certain file position. This can be useful, for example for reading uncompressed files - in an archive (zip). + in an archive (zip, tar). !*/ class CLimitReadFile : public IReadFile { public: - CLimitReadFile(IReadFile* alreadyOpenedFile, long areaSize, const c8* name); + CLimitReadFile(IReadFile* alreadyOpenedFile, long pos, long areaSize, const io::path& name); virtual ~CLimitReadFile(); @@ -44,16 +44,14 @@ namespace io virtual long getPos() const; //! returns name of file - virtual const c8* getFileName() const; + virtual const io::path& getFileName() const; private: - void init(); - - core::stringc Filename; - long AreaSize; + io::path Filename; long AreaStart; long AreaEnd; + long Pos; IReadFile* File; }; diff --git a/src/dep/src/irrlicht/CLogger.cpp b/src/dep/src/irrlicht/CLogger.cpp index 84eaa9a..8b489c5 100644 --- a/src/dep/src/irrlicht/CLogger.cpp +++ b/src/dep/src/irrlicht/CLogger.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -81,6 +81,16 @@ namespace irr log(s1.c_str(), s2.c_str(), ll); } + //! Prints out a text into the log + void CLogger::log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll) + { + if (ll < LogLevel) + return; + + core::stringc s2 = hint; + log( text, s2.c_str(), ll); + } + //! Sets a new event receiver void CLogger::setReceiver(IEventReceiver* r) { diff --git a/src/dep/src/irrlicht/CLogger.h b/src/dep/src/irrlicht/CLogger.h index d9be303..340ebab 100644 --- a/src/dep/src/irrlicht/CLogger.h +++ b/src/dep/src/irrlicht/CLogger.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -35,6 +35,9 @@ public: //! Prints out a text into the log virtual void log(const c8* text, const c8* hint, ELOG_LEVEL ll=ELL_INFORMATION); + //! Prints out a text into the log + virtual void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION); + //! Prints out a text into the log virtual void log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION); diff --git a/src/dep/src/irrlicht/CMD2MeshFileLoader.cpp b/src/dep/src/irrlicht/CMD2MeshFileLoader.cpp index 5652d57..544de99 100644 --- a/src/dep/src/irrlicht/CMD2MeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CMD2MeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,28 +7,104 @@ #include "CMD2MeshFileLoader.h" #include "CAnimatedMeshMD2.h" +#include "os.h" namespace irr { namespace scene { + +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( push, packing ) +# pragma pack( 1 ) +# define PACK_STRUCT +#elif defined( __GNUC__ ) +# define PACK_STRUCT __attribute__((packed)) +#else +# error compiler not supported +#endif + + // structs needed to load the md2-format + + const s32 MD2_MAGIC_NUMBER = 844121161; + const s32 MD2_VERSION = 8; + const s32 MD2_MAX_VERTS = 2048; + + struct SMD2Header + { + s32 magic; // four character code "IDP2" + s32 version; // must be 8 + s32 skinWidth; // width of the texture + s32 skinHeight; // height of the texture + s32 frameSize; // size in bytes of an animation frame + s32 numSkins; // number of textures + s32 numVertices; // total number of vertices + s32 numTexcoords; // number of vertices with texture coords + s32 numTriangles; // number of triangles + s32 numGlCommands; // number of opengl commands (triangle strip or triangle fan) + s32 numFrames; // animation keyframe count + s32 offsetSkins; // offset in bytes to 64 character skin names + s32 offsetTexcoords; // offset in bytes to texture coordinate list + s32 offsetTriangles; // offset in bytes to triangle list + s32 offsetFrames; // offset in bytes to frame list + s32 offsetGlCommands;// offset in bytes to opengl commands + s32 offsetEnd; // offset in bytes to end of file + } PACK_STRUCT; + + struct SMD2Vertex + { + u8 vertex[3]; // [0] = X, [1] = Z, [2] = Y + u8 lightNormalIndex; // index in the normal table + } PACK_STRUCT; + + struct SMD2Frame + { + f32 scale[3]; // first scale the vertex position + f32 translate[3]; // then translate the position + c8 name[16]; // the name of the animation that this key belongs to + SMD2Vertex vertices[1]; // vertex 1 of SMD2Header.numVertices + } PACK_STRUCT; + + struct SMD2Triangle + { + u16 vertexIndices[3]; + u16 textureIndices[3]; + } PACK_STRUCT; + + struct SMD2TextureCoordinate + { + s16 s; + s16 t; + } PACK_STRUCT; + + struct SMD2GLCommand + { + f32 s, t; + s32 vertexIndex; + } PACK_STRUCT; + +// Default alignment +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( pop, packing ) +#endif + +#undef PACK_STRUCT + //! Constructor CMD2MeshFileLoader::CMD2MeshFileLoader() { - #ifdef _DEBUG setDebugName("CMD2MeshFileLoader"); #endif - } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CMD2MeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CMD2MeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".md2")!=0; + return core::hasFileExtension ( filename, "md2" ); } @@ -41,7 +117,7 @@ IAnimatedMesh* CMD2MeshFileLoader::createMesh(io::IReadFile* file) IAnimatedMesh* msh = new CAnimatedMeshMD2(); if (msh) { - if (((CAnimatedMeshMD2*)msh)->loadFile(file)) + if (loadFile(file, (CAnimatedMeshMD2*)msh) ) return msh; msh->drop(); @@ -50,6 +126,248 @@ IAnimatedMesh* CMD2MeshFileLoader::createMesh(io::IReadFile* file) return 0; } +//! loads an md2 file +bool CMD2MeshFileLoader::loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh) +{ + if (!file) + return false; + + SMD2Header header; + + file->read(&header, sizeof(SMD2Header)); + +#ifdef __BIG_ENDIAN__ + header.magic = os::Byteswap::byteswap(header.magic); + header.version = os::Byteswap::byteswap(header.version); + header.skinWidth = os::Byteswap::byteswap(header.skinWidth); + header.skinHeight = os::Byteswap::byteswap(header.skinHeight); + header.frameSize = os::Byteswap::byteswap(header.frameSize); + header.numSkins = os::Byteswap::byteswap(header.numSkins); + header.numVertices = os::Byteswap::byteswap(header.numVertices); + header.numTexcoords = os::Byteswap::byteswap(header.numTexcoords); + header.numTriangles = os::Byteswap::byteswap(header.numTriangles); + header.numGlCommands = os::Byteswap::byteswap(header.numGlCommands); + header.numFrames = os::Byteswap::byteswap(header.numFrames); + header.offsetSkins = os::Byteswap::byteswap(header.offsetSkins); + header.offsetTexcoords = os::Byteswap::byteswap(header.offsetTexcoords); + header.offsetTriangles = os::Byteswap::byteswap(header.offsetTriangles); + header.offsetFrames = os::Byteswap::byteswap(header.offsetFrames); + header.offsetGlCommands = os::Byteswap::byteswap(header.offsetGlCommands); + header.offsetEnd = os::Byteswap::byteswap(header.offsetEnd); +#endif + + if (header.magic != MD2_MAGIC_NUMBER || header.version != MD2_VERSION) + { + os::Printer::log("MD2 Loader: Wrong file header", file->getFileName(), ELL_WARNING); + return false; + } + + // + // prepare mesh and allocate memory + // + + mesh->FrameCount = header.numFrames; + + // create keyframes + mesh->FrameTransforms.set_used(header.numFrames); + + // create vertex arrays for each keyframe + if (mesh->FrameList) + delete [] mesh->FrameList; + mesh->FrameList = new core::array[header.numFrames]; + + // allocate space in vertex arrays + s32 i; + for (i=0; iFrameList[i].reallocate(header.numVertices); + + // allocate interpolation buffer vertices + mesh->InterpolationBuffer->Vertices.set_used(header.numTriangles*3); + + // populate triangles + mesh->InterpolationBuffer->Indices.reallocate(header.numTriangles*3); + const s32 count = header.numTriangles*3; + for (i=0; iInterpolationBuffer->Indices.push_back(i); + mesh->InterpolationBuffer->Indices.push_back(i+1); + mesh->InterpolationBuffer->Indices.push_back(i+2); + } + + // + // read texture coordinates + // + + file->seek(header.offsetTexcoords); + SMD2TextureCoordinate* textureCoords = new SMD2TextureCoordinate[header.numTexcoords]; + + if (!file->read(textureCoords, sizeof(SMD2TextureCoordinate)*header.numTexcoords)) + { + delete[] textureCoords; + os::Printer::log("MD2 Loader: Error reading TextureCoords.", file->getFileName(), ELL_ERROR); + return false; + } + +#ifdef __BIG_ENDIAN__ + for (i=0; iseek(header.offsetTriangles); + + SMD2Triangle *triangles = new SMD2Triangle[header.numTriangles]; + if (!file->read(triangles, header.numTriangles *sizeof(SMD2Triangle))) + { + delete[] triangles; + delete[] textureCoords; + + os::Printer::log("MD2 Loader: Error reading triangles.", file->getFileName(), ELL_ERROR); + return false; + } + +#ifdef __BIG_ENDIAN__ + for (i=0; iseek(header.offsetFrames); + + for (i = 0; iread(frame, header.frameSize); + +#ifdef __BIG_ENDIAN__ + frame->scale[0] = os::Byteswap::byteswap(frame->scale[0]); + frame->scale[1] = os::Byteswap::byteswap(frame->scale[1]); + frame->scale[2] = os::Byteswap::byteswap(frame->scale[2]); + frame->translate[0] = os::Byteswap::byteswap(frame->translate[0]); + frame->translate[1] = os::Byteswap::byteswap(frame->translate[1]); + frame->translate[2] = os::Byteswap::byteswap(frame->translate[2]); +#endif + // + // store frame data + // + + CAnimatedMeshMD2::SAnimationData adata; + adata.begin = i; + adata.end = i; + adata.fps = 7; + + // Add new named animation if necessary + if (frame->name[0]) + { + // get animation name + for (s32 s = 0; s < 16 && frame->name[s]!=0 && (frame->name[s] < '0' || frame->name[s] > '9'); ++s) + { + adata.name += frame->name[s]; + } + + // Does this keyframe have the same animation name as the current animation? + if (!mesh->AnimationData.empty() && mesh->AnimationData[mesh->AnimationData.size()-1].name == adata.name) + { + // Increase the length of the animation + ++mesh->AnimationData[mesh->AnimationData.size() - 1].end; + } + else + { + // Add the new animation + mesh->AnimationData.push_back(adata); + } + } + + // save keyframe scale and translation + + mesh->FrameTransforms[i].scale.X = frame->scale[0]; + mesh->FrameTransforms[i].scale.Z = frame->scale[1]; + mesh->FrameTransforms[i].scale.Y = frame->scale[2]; + mesh->FrameTransforms[i].translate.X = frame->translate[0]; + mesh->FrameTransforms[i].translate.Z = frame->translate[1]; + mesh->FrameTransforms[i].translate.Y = frame->translate[2]; + + // add vertices + for (s32 j=0; jvertices[num].vertex[0]; + v.Pos.Z = frame->vertices[num].vertex[1]; + v.Pos.Y = frame->vertices[num].vertex[2]; + v.NormalIdx = frame->vertices[num].lightNormalIndex; + + mesh->FrameList[i].push_back(v); + } + } + + // calculate bounding boxes + if (header.numVertices) + { + core::aabbox3d box; + core::vector3df pos; + pos.X = f32(mesh->FrameList[i] [0].Pos.X) * mesh->FrameTransforms[i].scale.X + mesh->FrameTransforms[i].translate.X; + pos.Y = f32(mesh->FrameList[i] [0].Pos.Y) * mesh->FrameTransforms[i].scale.Y + mesh->FrameTransforms[i].translate.Y; + pos.Z = f32(mesh->FrameList[i] [0].Pos.Z) * mesh->FrameTransforms[i].scale.Z + mesh->FrameTransforms[i].translate.Z; + + box.reset(pos); + + for (s32 j=1; jFrameList[i] [j].Pos.X) * mesh->FrameTransforms[i].scale.X + mesh->FrameTransforms[i].translate.X; + pos.Y = f32(mesh->FrameList[i] [j].Pos.Y) * mesh->FrameTransforms[i].scale.Y + mesh->FrameTransforms[i].translate.Y; + pos.Z = f32(mesh->FrameList[i] [j].Pos.Z) * mesh->FrameTransforms[i].scale.Z + mesh->FrameTransforms[i].translate.Z; + + box.addInternalPoint(pos); + } + mesh->BoxList.push_back(box); + } + } + + // populate interpolation buffer with texture coordinates and colours + if (header.numFrames) + { + f32 dmaxs = 1.0f/(header.skinWidth); + f32 dmaxt = 1.0f/(header.skinHeight); + + for (s32 t=0; tInterpolationBuffer->Vertices[t*3 + n].TCoords.X = (textureCoords[triangles[t].textureIndices[n]].s + 0.5f) * dmaxs; + mesh->InterpolationBuffer->Vertices[t*3 + n].TCoords.Y = (textureCoords[triangles[t].textureIndices[n]].t + 0.5f) * dmaxt; + mesh->InterpolationBuffer->Vertices[t*3 + n].Color = video::SColor(255,255,255,255); + } + } + } + + // clean up + delete [] triangles; + delete [] textureCoords; + + // init buffer with start frame. + mesh->getMesh(0); + return true; +} + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CMD2MeshFileLoader.h b/src/dep/src/irrlicht/CMD2MeshFileLoader.h index 24ec8d5..382a35e 100644 --- a/src/dep/src/irrlicht/CMD2MeshFileLoader.h +++ b/src/dep/src/irrlicht/CMD2MeshFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,6 +12,8 @@ namespace irr namespace scene { +class CAnimatedMeshMD2; + //! Meshloader capable of loading MD2 files class CMD2MeshFileLoader : public IMeshLoader { @@ -22,7 +24,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -30,6 +32,10 @@ public: //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); +private: + //! Loads the file data into the mesh + bool loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh); + }; } // end namespace scene diff --git a/src/dep/src/irrlicht/CMD3MeshFileLoader.cpp b/src/dep/src/irrlicht/CMD3MeshFileLoader.cpp index 7405e3a..acea5ec 100644 --- a/src/dep/src/irrlicht/CMD3MeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CMD3MeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -14,11 +14,24 @@ namespace irr namespace scene { +//! Constructor +CMD3MeshFileLoader::CMD3MeshFileLoader( scene::ISceneManager* smgr) +: SceneManager(smgr) +{ +} + + +//! destructor +CMD3MeshFileLoader::~CMD3MeshFileLoader() +{ +} + + //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CMD3MeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CMD3MeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".md3") != 0; + return core::hasFileExtension ( filename, "md3" ); } @@ -26,9 +39,9 @@ IAnimatedMesh* CMD3MeshFileLoader::createMesh(io::IReadFile* file) { CAnimatedMeshMD3 * mesh = new CAnimatedMeshMD3(); - if ( mesh->loadModelFile ( 0, file ) ) + if ( mesh->loadModelFile ( 0, file, SceneManager->getFileSystem(), SceneManager->getVideoDriver() ) ) return mesh; - + mesh->drop (); return 0; } @@ -38,4 +51,3 @@ IAnimatedMesh* CMD3MeshFileLoader::createMesh(io::IReadFile* file) } // end namespace irr #endif // _IRR_COMPILE_WITH_MD3_LOADER_ - diff --git a/src/dep/src/irrlicht/CMD3MeshFileLoader.h b/src/dep/src/irrlicht/CMD3MeshFileLoader.h index 845992c..5341eb1 100644 --- a/src/dep/src/irrlicht/CMD3MeshFileLoader.h +++ b/src/dep/src/irrlicht/CMD3MeshFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,6 +6,10 @@ #define __C_MD3_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" +#include "IFileSystem.h" +#include "IVideoDriver.h" +#include "ISceneManager.h" +#include "IQ3Shader.h" namespace irr { @@ -17,9 +21,15 @@ class CMD3MeshFileLoader : public IMeshLoader { public: + //! Constructor + CMD3MeshFileLoader( scene::ISceneManager* smgr ); + + //! destructor + virtual ~CMD3MeshFileLoader(); + //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -27,6 +37,9 @@ public: //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); +private: + scene::ISceneManager* SceneManager; + }; } // end namespace scene diff --git a/src/dep/src/irrlicht/CMS3DMeshFileLoader.cpp b/src/dep/src/irrlicht/CMS3DMeshFileLoader.cpp index 6f35d20..350fd69 100644 --- a/src/dep/src/irrlicht/CMS3DMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CMS3DMeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -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 ) @@ -27,6 +31,7 @@ namespace scene # error compiler not supported #endif +namespace { // File header struct MS3DHeader { @@ -95,6 +100,8 @@ struct MS3DVertexWeights u8 weights[3]; } PACK_STRUCT; +} // end namespace + // Default alignment #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) @@ -121,13 +128,12 @@ CMS3DMeshFileLoader::CMS3DMeshFileLoader(video::IVideoDriver *driver) //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CMS3DMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CMS3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".ms3d")!=0; + return core::hasFileExtension ( filename, "ms3d" ); } - //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). @@ -195,6 +201,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 +211,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 +239,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,9 +276,12 @@ 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); - + core::array groups; groups.reallocate(numGroups); @@ -313,6 +331,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); @@ -322,7 +343,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if(numMaterials == 0) { // if there are no materials, add at least one buffer - AnimatedMesh->createBuffer(); + AnimatedMesh->addMeshBuffer(); } for (i=0; icreateBuffer(); + scene::SSkinMeshBuffer *tmpBuffer = AnimatedMesh->addMeshBuffer(); tmpBuffer->Material.MaterialType = video::EMT_SOLID; @@ -362,14 +383,14 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (TexturePath.trim()!="") { TexturePath=stripPathFromString(file->getFileName(),true) + stripPathFromString(TexturePath,false); - tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath.c_str()) ); + tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath) ); } core::stringc AlphamapPath=(const c8*)material->Alphamap; if (AlphamapPath.trim()!="") { AlphamapPath=stripPathFromString(file->getFileName(),true) + stripPathFromString(AlphamapPath,false); - tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath.c_str()) ); + tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath) ); } } @@ -378,6 +399,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 +418,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) @@ -427,9 +454,14 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) return false; } - ISkinnedMesh::SJoint *jnt = AnimatedMesh->createJoint(); + ISkinnedMesh::SJoint *jnt = AnimatedMesh->addJoint(); 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]) ); @@ -467,8 +499,8 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) return false; } - ISkinnedMesh::SRotationKey *k=AnimatedMesh->createRotationKey(jnt); - k->frame = kf->Time * framesPerSecond; + ISkinnedMesh::SRotationKey *k=AnimatedMesh->addRotationKey(jnt); + k->frame = kf->Time * framesPerSecond-1; core::matrix4 tmpMatrix; @@ -503,8 +535,8 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) return false; } - ISkinnedMesh::SPositionKey *k=AnimatedMesh->createPositionKey(jnt); - k->frame = kf->Time * framesPerSecond; + ISkinnedMesh::SPositionKey *k=AnimatedMesh->addPositionKey(jnt); + k->frame = kf->Time * framesPerSecond-1; k->position = core::vector3df (kf->Parameter[0]+pJoint->Translation[0], @@ -525,6 +557,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); @@ -532,7 +567,11 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) pPtr += sizeof(u32); for (i=0; i buffer+fileSize) @@ -599,6 +644,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 } @@ -668,7 +716,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) const s32 boneid = vertices[vertidx].BoneID; if ((u32)boneid < AnimatedMesh->getAllJoints().size()) { - ISkinnedMesh::SWeight *w=AnimatedMesh->createWeight(AnimatedMesh->getAllJoints()[boneid]); + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; w->strength = 1.0f; w->vertex_id = index; @@ -680,7 +728,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) s32 boneid = vertices[vertidx].BoneID; if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[0] != 0)) { - ISkinnedMesh::SWeight *w=AnimatedMesh->createWeight(AnimatedMesh->getAllJoints()[boneid]); + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; sum -= (w->strength = vertexWeights[vertidx].weights[0]/100.f); w->vertex_id = index; @@ -688,7 +736,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) boneid = vertexWeights[vertidx].boneIds[0]; if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[1] != 0)) { - ISkinnedMesh::SWeight *w=AnimatedMesh->createWeight(AnimatedMesh->getAllJoints()[boneid]); + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; sum -= (w->strength = vertexWeights[vertidx].weights[1]/100.f); w->vertex_id = index; @@ -696,7 +744,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) boneid = vertexWeights[vertidx].boneIds[1]; if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[2] != 0)) { - ISkinnedMesh::SWeight *w=AnimatedMesh->createWeight(AnimatedMesh->getAllJoints()[boneid]); + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; sum -= (w->strength = vertexWeights[vertidx].weights[2]/100.f); w->vertex_id = index; @@ -704,7 +752,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) boneid = vertexWeights[vertidx].boneIds[2]; if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (sum > 0.f)) { - ISkinnedMesh::SWeight *w=AnimatedMesh->createWeight(AnimatedMesh->getAllJoints()[boneid]); + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; w->strength = sum; w->vertex_id = index; @@ -713,7 +761,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) boneid = vertices[vertidx].BoneID; if ((sum == 1.f) && ((u32)boneid < AnimatedMesh->getAllJoints().size())) { - ISkinnedMesh::SWeight *w=AnimatedMesh->createWeight(AnimatedMesh->getAllJoints()[boneid]); + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; w->strength = 1.f; w->vertex_id = index; diff --git a/src/dep/src/irrlicht/CMS3DMeshFileLoader.h b/src/dep/src/irrlicht/CMS3DMeshFileLoader.h index 84ff7a3..d0e0b10 100644 --- a/src/dep/src/irrlicht/CMS3DMeshFileLoader.h +++ b/src/dep/src/irrlicht/CMS3DMeshFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,7 +24,7 @@ public: //! returns true if the file might be loadable by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/src/dep/src/irrlicht/CMY3DHelper.h b/src/dep/src/irrlicht/CMY3DHelper.h index dc54df3..cd90626 100644 --- a/src/dep/src/irrlicht/CMY3DHelper.h +++ b/src/dep/src/irrlicht/CMY3DHelper.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // diff --git a/src/dep/src/irrlicht/CMY3DMeshFileLoader.cpp b/src/dep/src/irrlicht/CMY3DMeshFileLoader.cpp index 909696b..86e7836 100644 --- a/src/dep/src/irrlicht/CMY3DMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CMY3DMeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // @@ -8,7 +8,7 @@ // This tool created by ZDimitor everyone can use it as wants //----------------------------------------------------------------------------- -#include "IrrCompileConfig.h" +#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_MY3D_LOADER_ #include "CMY3DMeshFileLoader.h" @@ -59,7 +59,7 @@ CMY3DMeshFileLoader::CMY3DMeshFileLoader(ISceneManager* scmgr, io::IFileSystem* #ifdef _DEBUG setDebugName("CMY3DMeshFileLoader"); #endif - + if (FileSystem) FileSystem->grab(); } @@ -72,9 +72,9 @@ CMY3DMeshFileLoader::~CMY3DMeshFileLoader() } -bool CMY3DMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CMY3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".my3d") != 0; + return core::hasFileExtension ( filename, "my3d" ); } @@ -195,7 +195,7 @@ IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) me.Texture2FileName.append(name); if (name.size()) - me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName.c_str()); + me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName); me.MaterialType = video::EMT_LIGHTMAP_M2; gotLightMap = true; @@ -209,7 +209,7 @@ IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) me.Texture2FileName.append(name); if (name.size()) - me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName.c_str()); + me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName); me.MaterialType = video::EMT_REFLECTION_2_LAYER; } @@ -219,7 +219,7 @@ IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) me.Texture1FileName = filepath; me.Texture1FileName.append(name); if (name.size()) - me.Texture1 = SceneManager->getVideoDriver()->getTexture(me.Texture1FileName.c_str()); + me.Texture1 = SceneManager->getVideoDriver()->getTexture(me.Texture1FileName); gotMainMap = true; me.MaterialType = video::EMT_SOLID; @@ -246,8 +246,6 @@ IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) // loading meshes - SMesh* mesh = new SMesh(); - if (id!=MY3D_MESH_LIST_ID) { os::Printer::log("Can not find MY3D_MESH_LIST_ID, loading failed!", ELL_ERROR); @@ -637,6 +635,7 @@ IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) } // creating mesh + SMesh* mesh = new SMesh(); for (u32 num=0; numgetVideoDriver()->createImageFromData( - video::ECF_R8G8B8, - core::dimension2d(texDataHeader.Width, texDataHeader.Height), + video::ECF_R8G8B8, + core::dimension2d(texDataHeader.Width, texDataHeader.Height), data, true); } else @@ -836,7 +835,7 @@ video::ITexture* CMY3DMeshFileLoader::readEmbeddedLightmap(io::IReadFile* file, // 16 bit lightmap format light_img = SceneManager->getVideoDriver()->createImageFromData( video::ECF_A1R5G5B5, - core::dimension2d(texDataHeader.Width, texDataHeader.Height), + core::dimension2d(texDataHeader.Width, texDataHeader.Height), data, true); } diff --git a/src/dep/src/irrlicht/CMY3DMeshFileLoader.h b/src/dep/src/irrlicht/CMY3DMeshFileLoader.h index 0cb7849..25e2b57 100644 --- a/src/dep/src/irrlicht/CMY3DMeshFileLoader.h +++ b/src/dep/src/irrlicht/CMY3DMeshFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // @@ -87,7 +87,7 @@ public: CMY3DMeshFileLoader(ISceneManager *scmgr, io::IFileSystem* fs); virtual ~CMY3DMeshFileLoader(); - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; virtual IAnimatedMesh* createMesh(io::IReadFile* file); diff --git a/src/dep/src/irrlicht/CMY3DStuff.h b/src/dep/src/irrlicht/CMY3DStuff.h deleted file mode 100644 index e69de29..0000000 diff --git a/src/dep/src/irrlicht/CMakeLists.txt b/src/dep/src/irrlicht/CMakeLists.txt index b8aa873..4cf3b90 100644 --- a/src/dep/src/irrlicht/CMakeLists.txt +++ b/src/dep/src/irrlicht/CMakeLists.txt @@ -9,6 +9,25 @@ include_directories(${INCLUDE_DIRS}) add_library(irrlicht ${LIBTYPE} # this may be considered a hack. +aesGladman/aescrypt.cpp +aesGladman/aeskey.cpp +aesGladman/aestab.cpp +aesGladman/fileenc.cpp +aesGladman/hmac.cpp +aesGladman/prng.cpp +aesGladman/pwd2key.cpp +aesGladman/sha1.cpp +aesGladman/sha2.cpp + +bzip2/blocksort.c +bzip2/bzlib.c +bzip2/crctable.c +bzip2/decompress.c +bzip2/bzcompress.c +bzip2/huffman.c +bzip2/randtable.c + + zlib/adler32.c zlib/compress.c zlib/crc32.c @@ -22,28 +41,38 @@ zlib/trees.c zlib/uncompr.c zlib/zutil.c -libpng/example.c -libpng/pnggccrd.c -libpng/pngpread.c -libpng/pngrtran.c -libpng/pngtest.c -libpng/pngwio.c -libpng/pngwutil.c -libpng/png.c -libpng/pngget.c -libpng/pngread.c -libpng/pngrutil.c -libpng/pngtrans.c -libpng/pngwrite.c -libpng/pngerror.c -libpng/pngmem.c -libpng/pngrio.c -libpng/pngset.c -libpng/pngvcrd.c -libpng/pngwtran.c +lzma/LzmaDec.c +libpng/example.c +libpng/png.c +libpng/pngerror.c +libpng/pnggccrd.c +libpng/pngget.c +libpng/pngmem.c +libpng/pngpread.c +libpng/pngread.c +libpng/pngrio.c +libpng/pngrtran.c +libpng/pngrutil.c +libpng/pngset.c +libpng/pngtest.c +libpng/pngtrans.c +libpng/pngvcrd.c +libpng/pngwio.c +libpng/pngwrite.c +libpng/pngwtran.c +libpng/pngwutil.c + +# jpeglib/ansi2knr.c +# # jpeglib/cdjpeg.c +# jpeglib/cjpeg.c +# jpeglib/ckconfig.c +# jpeglib/djpeg.c +# jpeglib/example.c +jpeglib/jaricom.c jpeglib/jcapimin.c jpeglib/jcapistd.c +jpeglib/jcarith.c jpeglib/jccoefct.c jpeglib/jccolor.c jpeglib/jcdctmgr.c @@ -54,12 +83,12 @@ jpeglib/jcmarker.c jpeglib/jcmaster.c jpeglib/jcomapi.c jpeglib/jcparam.c -jpeglib/jcphuff.c jpeglib/jcprepct.c jpeglib/jcsample.c jpeglib/jctrans.c jpeglib/jdapimin.c jpeglib/jdapistd.c +jpeglib/jdarith.c jpeglib/jdatadst.c jpeglib/jdatasrc.c jpeglib/jdcoefct.c @@ -71,7 +100,6 @@ jpeglib/jdmainct.c jpeglib/jdmarker.c jpeglib/jdmaster.c jpeglib/jdmerge.c -jpeglib/jdphuff.c jpeglib/jdpostct.c jpeglib/jdsample.c jpeglib/jdtrans.c @@ -82,12 +110,31 @@ jpeglib/jfdctint.c jpeglib/jidctflt.c jpeglib/jidctfst.c jpeglib/jidctint.c -jpeglib/jidctred.c +# jpeglib/jmemansi.c +# # jpeglib/jmemdos.c +# # jpeglib/jmemmac.c jpeglib/jmemmgr.c +# jpeglib/jmemname.c jpeglib/jmemnobs.c +# jpeglib/jpegtran.c jpeglib/jquant1.c jpeglib/jquant2.c jpeglib/jutils.c +# jpeglib/rdbmp.c +# jpeglib/rdcolmap.c +# jpeglib/rdgif.c +# # jpeglib/rdjpgcom.c +# jpeglib/rdppm.c +# jpeglib/rdrle.c +# jpeglib/rdswitch.c +# jpeglib/rdtarga.c +# jpeglib/transupp.c +# jpeglib/wrbmp.c +# jpeglib/wrgif.c +# # jpeglib/wrjpgcom.c +# jpeglib/wrppm.c +# jpeglib/wrrle.c +# jpeglib/wrtarga.c C3DSMeshFileLoader.cpp @@ -100,8 +147,6 @@ CBillboardSceneNode.cpp CBoneSceneNode.cpp CBSPMeshFileLoader.cpp CBurningShader_Raster_Reference.cpp -CCameraFPSSceneNode.cpp -CCameraMayaSceneNode.cpp CCameraSceneNode.cpp CColladaFileLoader.cpp CColladaMeshWriter.cpp @@ -140,6 +185,7 @@ CGUIEnvironment.cpp CGUIFileOpenDialog.cpp CGUIFont.cpp CGUIImage.cpp +CGUIImageList.cpp CGUIInOutFader.cpp CGUIListBox.cpp CGUIMenu.cpp @@ -154,6 +200,7 @@ CGUIStaticText.cpp CGUITabControl.cpp CGUITable.cpp CGUIToolBar.cpp +CGUITreeView.cpp CGUIWindow.cpp CImage.cpp CImageLoaderBMP.cpp @@ -162,6 +209,7 @@ CImageLoaderPCX.cpp CImageLoaderPNG.cpp CImageLoaderPPM.cpp CImageLoaderPSD.cpp +CImageLoaderRGB.cpp CImageLoaderTGA.cpp CImageLoaderWAL.cpp CImageWriterBMP.cpp @@ -171,6 +219,8 @@ CImageWriterPNG.cpp CImageWriterPPM.cpp CImageWriterPSD.cpp CImageWriterTGA.cpp +CIrrDeviceConsole.cpp +CIrrDeviceFB.cpp CIrrDeviceLinux.cpp CIrrDeviceSDL.cpp CIrrDeviceStub.cpp @@ -185,19 +235,21 @@ CLogger.cpp CLWOMeshFileLoader.cpp CMD2MeshFileLoader.cpp CMD3MeshFileLoader.cpp -CMemoryReadFile.cpp +CMemoryFile.cpp CMeshCache.cpp CMeshManipulator.cpp CMeshSceneNode.cpp CMetaTriangleSelector.cpp +CMountPointReader.cpp CMS3DMeshFileLoader.cpp CMY3DMeshFileLoader.cpp +CNPKReader.cpp CNullDriver.cpp COBJMeshFileLoader.cpp COBJMeshWriter.cpp COCTLoader.cpp -COctTreeSceneNode.cpp -COctTreeTriangleSelector.cpp +COctreeSceneNode.cpp +COctreeTriangleSelector.cpp COgreMeshFileLoader.cpp COpenGLDriver.cpp COpenGLExtensionHandler.cpp @@ -221,6 +273,8 @@ CParticleRotationAffector.cpp CParticleScaleAffector.cpp CParticleSphereEmitter.cpp CParticleSystemSceneNode.cpp +CPLYMeshFileLoader.cpp +CPLYMeshWriter.cpp CQ3LevelMesh.cpp CQuake3ShaderSceneNode.cpp CReadFile.cpp @@ -239,22 +293,23 @@ CShadowVolumeSceneNode.cpp CSkinnedMesh.cpp CSkyBoxSceneNode.cpp CSkyDomeSceneNode.cpp -CSoftwareDriver2.cpp CSoftwareDriver.cpp -CSoftwareTexture2.cpp +CSoftwareDriver2.cpp CSoftwareTexture.cpp +CSoftwareTexture2.cpp CSphereSceneNode.cpp CSTLMeshFileLoader.cpp CSTLMeshWriter.cpp +CTarReader.cpp CTerrainSceneNode.cpp CTerrainTriangleSelector.cpp CTextSceneNode.cpp CTRFlat.cpp CTRFlatWire.cpp +CTRGouraud.cpp CTRGouraud2.cpp CTRGouraudAlpha2.cpp CTRGouraudAlphaNoZ2.cpp -CTRGouraud.cpp CTRGouraudWire.cpp CTriangleBBSelector.cpp CTriangleSelector.cpp @@ -262,15 +317,15 @@ CTRTextureBlend.cpp CTRTextureDetailMap2.cpp CTRTextureFlat.cpp CTRTextureFlatWire.cpp +CTRTextureGouraud.cpp CTRTextureGouraud2.cpp -CTRTextureGouraudAdd2.cpp CTRTextureGouraudAdd.cpp +CTRTextureGouraudAdd2.cpp CTRTextureGouraudAddNoZ2.cpp CTRTextureGouraudAlpha.cpp CTRTextureGouraudAlphaNoZ.cpp -CTRTextureGouraud.cpp -CTRTextureGouraudNoZ2.cpp CTRTextureGouraudNoZ.cpp +CTRTextureGouraudNoZ2.cpp CTRTextureGouraudVertexAlpha2.cpp CTRTextureGouraudWire.cpp CTRTextureLightMap2_Add.cpp @@ -289,11 +344,12 @@ CXMLWriter.cpp CZBuffer.cpp CZipReader.cpp IBurningShader.cpp +Irrlicht-gcc.cbp Irrlicht.cpp irrXML.cpp os.cpp ) if(WIN32) SET_TARGET_PROPERTIES (irrlicht PROPERTIES DEFINE_SYMBOL "IRRLICHT_EXPORTS" ) - target_link_libraries (irrlicht ${DirectX_D3D9_LIBRARY} ${DirectX_D3DX9_LIBRARY} Winmm) + target_link_libraries (irrlicht ${DirectX_D3D9_LIBRARY} ${DirectX_D3DX9_LIBRARY} Winmm) endif() diff --git a/src/dep/src/irrlicht/CMemoryReadFile.cpp b/src/dep/src/irrlicht/CMemoryFile.cpp similarity index 53% rename from src/dep/src/irrlicht/CMemoryReadFile.cpp rename to src/dep/src/irrlicht/CMemoryFile.cpp index 05e6d9f..0196d30 100644 --- a/src/dep/src/irrlicht/CMemoryReadFile.cpp +++ b/src/dep/src/irrlicht/CMemoryFile.cpp @@ -2,7 +2,7 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "CMemoryReadFile.h" +#include "CMemoryFile.h" #include "irrString.h" namespace irr @@ -11,16 +11,16 @@ namespace io { -CMemoryReadFile::CMemoryReadFile(void* memory, long len, const c8* fileName, bool d) +CMemoryFile::CMemoryFile(void* memory, long len, const io::path& fileName, bool d) : Buffer(memory), Len(len), Pos(0), Filename(fileName), deleteMemoryWhenDropped(d) { #ifdef _DEBUG - setDebugName("CMemoryReadFile"); + setDebugName("CMemoryFile"); #endif } -CMemoryReadFile::~CMemoryReadFile() +CMemoryFile::~CMemoryFile() { if (deleteMemoryWhenDropped) delete [] (c8*)Buffer; @@ -28,7 +28,7 @@ CMemoryReadFile::~CMemoryReadFile() //! returns how much was read -s32 CMemoryReadFile::read(void* buffer, u32 sizeToRead) +s32 CMemoryFile::read(void* buffer, u32 sizeToRead) { s32 amount = static_cast(sizeToRead); if (Pos + amount > Len) @@ -39,17 +39,36 @@ s32 CMemoryReadFile::read(void* buffer, u32 sizeToRead) c8* p = (c8*)Buffer; memcpy(buffer, p + Pos, amount); - + + Pos += amount; + + return amount; +} + +//! returns how much was written +s32 CMemoryFile::write(const void* buffer, u32 sizeToWrite) +{ + s32 amount = static_cast(sizeToWrite); + if (Pos + amount > Len) + amount -= Pos + amount - Len; + + if (amount <= 0) + return 0; + + c8* p = (c8*)Buffer; + memcpy(p + Pos, buffer, amount); + Pos += amount; return amount; } + //! changes position in file, returns true if successful //! if relativeMovement==true, the pos is changed relative to current pos, //! otherwise from begin of file -bool CMemoryReadFile::seek(long finalPos, bool relativeMovement) +bool CMemoryFile::seek(long finalPos, bool relativeMovement) { if (relativeMovement) { @@ -62,7 +81,7 @@ bool CMemoryReadFile::seek(long finalPos, bool relativeMovement) { if (finalPos > Len) return false; - + Pos = finalPos; } @@ -71,29 +90,29 @@ bool CMemoryReadFile::seek(long finalPos, bool relativeMovement) //! returns size of file -long CMemoryReadFile::getSize() const +long CMemoryFile::getSize() const { return Len; } //! returns where in the file we are. -long CMemoryReadFile::getPos() const +long CMemoryFile::getPos() const { return Pos; } //! returns name of file -const c8* CMemoryReadFile::getFileName() const +const io::path& CMemoryFile::getFileName() const { - return Filename.c_str(); + return Filename; } -IReadFile* createMemoryReadFile(void* memory, long size, const c8* fileName, bool deleteMemoryWhenDropped) +IReadFile* createMemoryReadFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped) { - CMemoryReadFile* file = new CMemoryReadFile(memory, size, fileName, deleteMemoryWhenDropped); + CMemoryFile* file = new CMemoryFile(memory, size, fileName, deleteMemoryWhenDropped); return file; } diff --git a/src/dep/src/irrlicht/CMemoryReadFile.h b/src/dep/src/irrlicht/CMemoryFile.h similarity index 65% rename from src/dep/src/irrlicht/CMemoryReadFile.h rename to src/dep/src/irrlicht/CMemoryFile.h index 32124b8..91098ab 100644 --- a/src/dep/src/irrlicht/CMemoryReadFile.h +++ b/src/dep/src/irrlicht/CMemoryFile.h @@ -6,6 +6,7 @@ #define __C_MEMORY_READ_FILE_H_INCLUDED__ #include "IReadFile.h" +#include "IWriteFile.h" #include "irrString.h" namespace irr @@ -15,21 +16,24 @@ namespace io { /*! - Class for reading from memory. + Class for reading and writing from memory. */ - class CMemoryReadFile : public IReadFile + class CMemoryFile : public IReadFile, public IWriteFile { public: //! Constructor - CMemoryReadFile(void* memory, long len, const c8* fileName, bool deleteMemoryWhenDropped); + CMemoryFile(void* memory, long len, const io::path& fileName, bool deleteMemoryWhenDropped); //! Destructor - virtual ~CMemoryReadFile(); + virtual ~CMemoryFile(); //! returns how much was read virtual s32 read(void* buffer, u32 sizeToRead); + //! returns how much was written + virtual s32 write(const void* buffer, u32 sizeToWrite); + //! changes position in file, returns true if successful virtual bool seek(long finalPos, bool relativeMovement = false); @@ -40,14 +44,14 @@ namespace io virtual long getPos() const; //! returns name of file - virtual const c8* getFileName() const; + virtual const io::path& getFileName() const; private: void *Buffer; long Len; long Pos; - core::stringc Filename; + io::path Filename; bool deleteMemoryWhenDropped; }; diff --git a/src/dep/src/irrlicht/CMeshCache.cpp b/src/dep/src/irrlicht/CMeshCache.cpp index bb3fbf9..cc698b8 100644 --- a/src/dep/src/irrlicht/CMeshCache.cpp +++ b/src/dep/src/irrlicht/CMeshCache.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,6 +11,8 @@ namespace irr namespace scene { +static const io::SNamedPath emptyNamedPath; + CMeshCache::~CMeshCache() { @@ -19,14 +21,12 @@ CMeshCache::~CMeshCache() //! adds a mesh to the list -void CMeshCache::addMesh(const c8* filename, IAnimatedMesh* mesh) +void CMeshCache::addMesh(const io::path& filename, IAnimatedMesh* mesh) { mesh->grab(); - MeshEntry e; + MeshEntry e ( filename ); e.Mesh = mesh; - e.Name = filename; - e.Name.make_lower(); Meshes.push_back(e); } @@ -108,83 +108,74 @@ IAnimatedMesh* CMeshCache::getMeshByIndex(u32 number) } -//! Returns a mesh based on its file name. -IAnimatedMesh* CMeshCache::getMeshByFilename(const c8* filename) +//! Returns a mesh based on its name. +IAnimatedMesh* CMeshCache::getMeshByName(const io::path& name) { - MeshEntry e; - e.Name = filename; - e.Name.make_lower(); + MeshEntry e ( name ); s32 id = Meshes.binary_search(e); return (id != -1) ? Meshes[id].Mesh : 0; } - -//! Returns name of a mesh based on its index number -const c8* CMeshCache::getMeshFilename(u32 number) const +//! Get the name of a loaded mesh, based on its index. +const io::SNamedPath& CMeshCache::getMeshName(u32 index) const { - if (number >= Meshes.size()) - return 0; + if (index >= Meshes.size()) + return emptyNamedPath; - return Meshes[number].Name.c_str(); + return Meshes[index].NamedPath; } - - -//! Returns the filename of a loaded mesh, if there is any. Returns 0 if there is none. -const c8* CMeshCache::getMeshFilename(const IAnimatedMesh* const mesh) const +//! Get the name of a loaded mesh, if there is any. +const io::SNamedPath& CMeshCache::getMeshName(const IAnimatedMesh* const mesh) const { if(!mesh) - return 0; + return emptyNamedPath; for (u32 i=0; igetMesh(0) == mesh)) - return Meshes[i].Name.c_str(); + return Meshes[i].NamedPath; } - return 0; + return emptyNamedPath; } - - -//! Renames a loaded mesh, if possible. -bool CMeshCache::setMeshFilename(u32 index, const c8* filename) +//! Renames a loaded mesh. +bool CMeshCache::renameMesh(u32 index, const io::path& name) { if (index >= Meshes.size()) return false; - Meshes[index].Name = filename; + Meshes[index].NamedPath.setPath(name); Meshes.sort(); return true; } - -//! Renames a loaded mesh, if possible. -bool CMeshCache::setMeshFilename(const IAnimatedMesh* const mesh, const c8* filename) +//! Renames a loaded mesh. +bool CMeshCache::renameMesh(const IAnimatedMesh* const mesh, const io::path& name) { for (u32 i=0; igetMesh(0) == mesh) { - Meshes[i].Name = filename; + Meshes[i].NamedPath.setPath(name); Meshes.sort(); return true; } @@ -212,9 +202,9 @@ bool CMeshCache::setMeshFilename(const IMesh* const mesh, const c8* filename) //! returns if a mesh already was loaded -bool CMeshCache::isMeshLoaded(const c8* filename) +bool CMeshCache::isMeshLoaded(const io::path& name) { - return getMeshByFilename(filename) != 0; + return getMeshByName(name) != 0; } diff --git a/src/dep/src/irrlicht/CMeshCache.h b/src/dep/src/irrlicht/CMeshCache.h index dea2ba5..c79d390 100644 --- a/src/dep/src/irrlicht/CMeshCache.h +++ b/src/dep/src/irrlicht/CMeshCache.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -30,7 +30,7 @@ namespace scene \param filename: Filename of the mesh. When called ISceneManager::getMesh() with this parameter, the method will return the mesh parameter given with this method. \param mesh: Pointer to a mesh which will now be referenced by this name. */ - virtual void addMesh(const c8* filename, IAnimatedMesh* mesh); + virtual void addMesh(const io::path& filename, IAnimatedMesh* mesh); //! Removes a mesh from the cache. /** After loading a mesh with getMesh(), the mesh can be removed from the cache @@ -60,34 +60,55 @@ namespace scene \return Returns pointer to the mesh or 0 if there is none with this number. */ virtual IAnimatedMesh* getMeshByIndex(u32 index); - //! Returns a mesh based on its file name. - /** \return Returns pointer to the mesh or 0 if there is none with this number. */ - virtual IAnimatedMesh* getMeshByFilename(const c8* filename); + //! Returns a mesh based on its name. + /** \param name Name of the mesh. Usually a filename. + \return Pointer to the mesh or 0 if there is none with this number. */ + virtual IAnimatedMesh* getMeshByName(const io::path& name); - //! Returns name of a mesh based on its index number. + //! Get the name of a loaded mesh, based on its index. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. - Note that this is only valid until a new mesh is loaded */ - virtual const c8* getMeshFilename(u32 index) const; + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(u32 index) const; - //! Returns the filename of a loaded mesh, if there is any. - /** Returns 0 if there is none. */ - virtual const c8* getMeshFilename(const IAnimatedMesh* const mesh) const; + //! Get the name of a loaded mesh, if there is any. + /** \param mesh Pointer to mesh to query. + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(const IAnimatedMesh* const mesh) const; - //! Returns the filename of a loaded mesh, if there is any. - /* Returns 0 if there is none.*/ - virtual const c8* getMeshFilename(const IMesh* const mesh) const; + //! Get the name of a loaded mesh, if there is any. + /** \param mesh Pointer to mesh to query. + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(const IMesh* const mesh) const; - //! Renames a loaded mesh, if possible. - virtual bool setMeshFilename(u32 index, const c8* filename); + //! Renames a loaded mesh. + /** Note that renaming meshes might change the ordering of the + meshes, and so the index of the meshes as returned by + getMeshIndex() or taken by some methods will change. + \param index The index of the mesh in the cache. + \param name New name for the mesh. + \return True if mesh was renamed. */ + virtual bool renameMesh(u32 index, const io::path& name); - //! Renames a loaded mesh, if possible. - virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const c8* filename); + //! Renames a loaded mesh. + /** Note that renaming meshes might change the ordering of the + meshes, and so the index of the meshes as returned by + getMeshIndex() or taken by some methods will change. + \param mesh Mesh to be renamed. + \param name New name for the mesh. + \return True if mesh was renamed. */ + virtual bool renameMesh(const IAnimatedMesh* const mesh, const io::path& name); - //! Renames a loaded mesh, if possible. - virtual bool setMeshFilename(const IMesh* const mesh, const c8* filename); + //! Renames a loaded mesh. + /** Note that renaming meshes might change the ordering of the + meshes, and so the index of the meshes as returned by + getMeshIndex() or taken by some methods will change. + \param mesh Mesh to be renamed. + \param name New name for the mesh. + \return True if mesh was renamed. */ + virtual bool renameMesh(const IMesh* const mesh, const io::path& name); //! returns if a mesh already was loaded - virtual bool isMeshLoaded(const c8* filename); + virtual bool isMeshLoaded(const io::path& name); //! Clears the whole mesh cache, removing all meshes. virtual void clear(); @@ -99,12 +120,16 @@ namespace scene struct MeshEntry { - core::stringc Name; + MeshEntry ( const io::path& name ) + : NamedPath ( name ) + { + } + io::SNamedPath NamedPath; IAnimatedMesh* Mesh; bool operator < (const MeshEntry& other) const { - return (Name < other.Name); + return (NamedPath < other.NamedPath); } }; diff --git a/src/dep/src/irrlicht/CMeshManipulator.cpp b/src/dep/src/irrlicht/CMeshManipulator.cpp index 1b22d15..a79f483 100644 --- a/src/dep/src/irrlicht/CMeshManipulator.cpp +++ b/src/dep/src/irrlicht/CMeshManipulator.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,6 +7,7 @@ #include "CMeshBuffer.h" #include "SAnimatedMesh.h" #include "os.h" +#include "irrMap.h" namespace irr { @@ -60,86 +61,6 @@ void CMeshManipulator::flipSurfaces(scene::IMesh* mesh) const } -//! Sets the alpha vertex color value of the whole mesh to a new value -//! \param mesh: Mesh on which the operation is performed. -void CMeshManipulator::setVertexColorAlpha(scene::IMesh* mesh, s32 alpha) const -{ - if (!mesh) - return; - - u32 i; - - const u32 bcount = mesh->getMeshBufferCount(); - for ( u32 b=0; bgetMeshBuffer(b); - void* v = buffer->getVertices(); - u32 vtxcnt = buffer->getVertexCount(); - - switch(buffer->getVertexType()) - { - case video::EVT_STANDARD: - { - for ( i=0; igetMeshBufferCount(); - for (u32 b=0; bgetMeshBuffer(b); - void* v = buffer->getVertices(); - const u32 vtxcnt = buffer->getVertexCount(); - u32 i; - - switch(buffer->getVertexType()) - { - case video::EVT_STANDARD: - { - for ( i=0; igetVertexCount(); - if (!vtxcnt) + if (!mesh || !mesh->getMeshBufferCount() || (mesh->getMeshBuffer(0)->getVertexType()!= video::EVT_TANGENTS)) return; - core::aabbox3df bufferbox; - // first transform + const u32 meshBufferCount = mesh->getMeshBufferCount(); + for (u32 b=0; bgetPosition(0)); - m.rotateVect(buffer->getNormal(0)); - buffer->getNormal(0).normalize(); + IMeshBuffer* clone = mesh->getMeshBuffer(b); + const u32 vtxCnt = clone->getVertexCount(); + const u32 idxCnt = clone->getIndexCount(); - bufferbox.reset(buffer->getPosition(0)); - } + u16* idx = clone->getIndices(); + video::S3DVertexTangents* v = + (video::S3DVertexTangents*)clone->getVertices(); - for ( u32 i=1 ;i < vtxcnt; ++i) - { - m.transformVect(buffer->getPosition(i)); - m.rotateVect(buffer->getNormal(i)); - buffer->getNormal(i).normalize(); + if (smooth) + { + u32 i; - bufferbox.addInternalPoint(buffer->getPosition(i)); - } + for ( i = 0; i!= vtxCnt; ++i ) + { + if (recalculateNormals) + v[i].Normal.set( 0.f, 0.f, 0.f ); + v[i].Tangent.set( 0.f, 0.f, 0.f ); + v[i].Binormal.set( 0.f, 0.f, 0.f ); + } - buffer->setBoundingBox(bufferbox); -} + //Each vertex gets the sum of the tangents and binormals from the faces around it + for ( i=0; igetMeshBufferCount(); - for ( u32 b=0; bgetMeshBuffer(b); - transform(buffer, m); + if (recalculateNormals) + v[idx[i+1]].Normal += localNormal * weight.Y; + v[idx[i+1]].Tangent += localTangent * weight.Y; + v[idx[i+1]].Binormal += localBinormal * weight.Y; - if (b == 0) - meshbox.reset(buffer->getBoundingBox()); + calculateTangents( + localNormal, + localTangent, + localBinormal, + v[idx[i+2]].Pos, + v[idx[i+0]].Pos, + v[idx[i+1]].Pos, + v[idx[i+2]].TCoords, + v[idx[i+0]].TCoords, + v[idx[i+1]].TCoords); + + if (recalculateNormals) + v[idx[i+2]].Normal += localNormal * weight.Z; + v[idx[i+2]].Tangent += localTangent * weight.Z; + v[idx[i+2]].Binormal += localBinormal * weight.Z; + } + + // Normalize the tangents and binormals + if (recalculateNormals) + { + for ( i = 0; i!= vtxCnt; ++i ) + v[i].Normal.normalize(); + } + for ( i = 0; i!= vtxCnt; ++i ) + { + v[i].Tangent.normalize(); + v[i].Binormal.normalize(); + } + } else - meshbox.addInternalBox(buffer->getBoundingBox()); - } + { + core::vector3df localNormal; + for (u32 i=0; isetBoundingBox( meshbox ); -} + calculateTangents( + localNormal, + v[idx[i+1]].Tangent, + v[idx[i+1]].Binormal, + v[idx[i+1]].Pos, + v[idx[i+2]].Pos, + v[idx[i+0]].Pos, + v[idx[i+1]].TCoords, + v[idx[i+2]].TCoords, + v[idx[i+0]].TCoords); + if (recalculateNormals) + v[idx[i+1]].Normal=localNormal; - -//! Scales the actual mesh, not a scene node. -void CMeshManipulator::scale(scene::IMesh* mesh, const core::vector3df& factor) const -{ - if (!mesh) - return; - - core::aabbox3df meshbox; - - const u32 bcount = mesh->getMeshBufferCount(); - for ( u32 b=0; bgetMeshBuffer(b); - scale(buffer, factor); - - if (b == 0) - meshbox.reset(buffer->getBoundingBox()); - else - meshbox.addInternalBox(buffer->getBoundingBox()); - } - - mesh->setBoundingBox( meshbox ); -} - - -//! Scales the actual meshbuffer, not a scene node. -void CMeshManipulator::scale(scene::IMeshBuffer* buffer, const core::vector3df& factor) const -{ - if (!buffer) - return; - - const u32 vtxcnt = buffer->getVertexCount(); - core::aabbox3df bufferbox; - - if (vtxcnt != 0) - bufferbox.reset(buffer->getPosition(0) * factor); - - for (u32 i=0; igetPosition(i) *= factor; - bufferbox.addInternalPoint(buffer->getPosition(i)); - } - - buffer->setBoundingBox(bufferbox); -} - - -//! Scale the texture coords of a mesh. -void CMeshManipulator::scaleTCoords(scene::IMesh* mesh, const core::vector2df& factor, u32 layer) const -{ - if (!mesh) - return; - - const u32 bcount = mesh->getMeshBufferCount(); - for (u32 b=0; bgetMeshBuffer(b), factor, layer); -} - - -//! Scale the level-th texture coords of a meshbuffer. -void CMeshManipulator::scaleTCoords(scene::IMeshBuffer* buffer, const core::vector2df& factor, u32 level) const -{ - if (!buffer || ((level>1) && (buffer->getVertexType() != video::EVT_2TCOORDS))) - return; - - const u32 vtxcnt = buffer->getVertexCount(); - - if (level==1) - { - for (u32 i=0; igetTCoords(i) *= factor; - } - else - { - for (u32 i=0; iVertices[i].TCoords2 *= factor; + calculateTangents( + localNormal, + v[idx[i+2]].Tangent, + v[idx[i+2]].Binormal, + v[idx[i+2]].Pos, + v[idx[i+0]].Pos, + v[idx[i+1]].Pos, + v[idx[i+2]].TCoords, + v[idx[i+0]].TCoords, + v[idx[i+1]].TCoords); + if (recalculateNormals) + v[idx[i+2]].Normal=localNormal; + } + } } } @@ -358,21 +303,51 @@ SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const { case video::EVT_STANDARD: { - SMeshBuffer* buffer = new SMeshBuffer(*(SMeshBuffer*)mesh->getMeshBuffer(b)); + SMeshBuffer* buffer = new SMeshBuffer(); + const u32 vcount = mesh->getMeshBuffer(b)->getVertexCount(); + buffer->Vertices.reallocate(vcount); + video::S3DVertex* vertices = (video::S3DVertex*)mesh->getMeshBuffer(b)->getVertices(); + for (u32 i=0; i < vcount; ++i) + buffer->Vertices.push_back(vertices[i]); + const u32 icount = mesh->getMeshBuffer(b)->getIndexCount(); + buffer->Indices.reallocate(icount); + u16* indices = mesh->getMeshBuffer(b)->getIndices(); + for (u32 i=0; i < icount; ++i) + buffer->Indices.push_back(indices[i]); clone->addMeshBuffer(buffer); buffer->drop(); } break; case video::EVT_2TCOORDS: { - SMeshBufferLightMap* buffer = new SMeshBufferLightMap(*(SMeshBufferLightMap*)mesh->getMeshBuffer(b)); + SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); + const u32 vcount = mesh->getMeshBuffer(b)->getVertexCount(); + buffer->Vertices.reallocate(vcount); + video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)mesh->getMeshBuffer(b)->getVertices(); + for (u32 i=0; i < vcount; ++i) + buffer->Vertices.push_back(vertices[i]); + const u32 icount = mesh->getMeshBuffer(b)->getIndexCount(); + buffer->Indices.reallocate(icount); + u16* indices = mesh->getMeshBuffer(b)->getIndices(); + for (u32 i=0; i < icount; ++i) + buffer->Indices.push_back(indices[i]); clone->addMeshBuffer(buffer); buffer->drop(); } break; case video::EVT_TANGENTS: { - SMeshBufferTangents* buffer = new SMeshBufferTangents(*(SMeshBufferTangents*)mesh->getMeshBuffer(b)); + SMeshBufferTangents* buffer = new SMeshBufferTangents(); + const u32 vcount = mesh->getMeshBuffer(b)->getVertexCount(); + buffer->Vertices.reallocate(vcount); + video::S3DVertexTangents* vertices = (video::S3DVertexTangents*)mesh->getMeshBuffer(b)->getVertices(); + for (u32 i=0; i < vcount; ++i) + buffer->Vertices.push_back(vertices[i]); + const u32 icount = mesh->getMeshBuffer(b)->getIndexCount(); + buffer->Indices.reallocate(icount); + u16* indices = mesh->getMeshBuffer(b)->getIndices(); + for (u32 i=0; i < icount; ++i) + buffer->Indices.push_back(indices[i]); clone->addMeshBuffer(buffer); buffer->drop(); } @@ -387,10 +362,6 @@ SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const //! Creates a planar texture mapping on the mesh -//! \param mesh: Mesh on which the operation is performed. -//! \param resolution: resolution of the planar mapping. This is the value -//! specifying which is the releation between world space and -//! texture coordinate space. void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resolution=0.01f) const { if (!mesh) @@ -399,42 +370,85 @@ void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resoluti const u32 bcount = mesh->getMeshBufferCount(); for ( u32 b=0; bgetMeshBuffer(b); - u32 idxcnt = buffer->getIndexCount(); - u16* idx = buffer->getIndices(); + makePlanarTextureMapping(mesh->getMeshBuffer(b), resolution); + } +} - for (u32 i=0; igetIndexCount(); + u16* idx = buffer->getIndices(); + + for (u32 i=0; igetPosition(idx[i+0]), buffer->getPosition(idx[i+1]), buffer->getPosition(idx[i+2])); + p.Normal.X = fabsf(p.Normal.X); + p.Normal.Y = fabsf(p.Normal.Y); + p.Normal.Z = fabsf(p.Normal.Z); + // calculate planar mapping worldspace coordinates + + if (p.Normal.X > p.Normal.Y && p.Normal.X > p.Normal.Z) { - core::plane3df p(buffer->getPosition(idx[i+0]), buffer->getPosition(idx[i+1]), buffer->getPosition(idx[i+2])); - p.Normal.X = fabsf(p.Normal.X); - p.Normal.Y = fabsf(p.Normal.Y); - p.Normal.Z = fabsf(p.Normal.Z); - // calculate planar mapping worldspace coordinates + for (u32 o=0; o!=3; ++o) + { + buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).Y * resolution; + buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution; + } + } + else + if (p.Normal.Y > p.Normal.X && p.Normal.Y > p.Normal.Z) + { + for (u32 o=0; o!=3; ++o) + { + buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution; + buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution; + } + } + else + { + for (u32 o=0; o!=3; ++o) + { + buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution; + buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Y * resolution; + } + } + } +} - if (p.Normal.X > p.Normal.Y && p.Normal.X > p.Normal.Z) + +//! Creates a planar texture mapping on the meshbuffer +void CMeshManipulator::makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const +{ + u32 idxcnt = buffer->getIndexCount(); + u16* idx = buffer->getIndices(); + + for (u32 i=0; igetTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).Y * resolution; - buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution; - } + buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).Z + offset.Z) * resolutionS; + buffer->getTCoords(idx[i+o]).Y = 0.5f-(buffer->getPosition(idx[i+o]).Y + offset.Y) * resolutionT; } - else - if (p.Normal.Y > p.Normal.X && p.Normal.Y > p.Normal.Z) + } + else if (axis==1) + { + for (u32 o=0; o!=3; ++o) { - for (u32 o=0; o!=3; ++o) - { - buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution; - buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution; - } + buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).X + offset.X) * resolutionS; + buffer->getTCoords(idx[i+o]).Y = 1.f-(buffer->getPosition(idx[i+o]).Z + offset.Z) * resolutionT; } - else + } + else if (axis==2) + { + for (u32 o=0; o!=3; ++o) { - for (u32 o=0; o!=3; ++o) - { - buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution; - buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Y * resolution; - } + buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).X + offset.X) * resolutionS; + buffer->getTCoords(idx[i+o]).Y = 0.5f-(buffer->getPosition(idx[i+o]).Y + offset.Y) * resolutionT; } } } @@ -711,7 +725,7 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const //! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices. -IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const +IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted, bool calculateTangents) const { if (!mesh) return 0; @@ -720,218 +734,79 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNor SMesh* clone = new SMesh(); const u32 meshBufferCount = mesh->getMeshBufferCount(); - u32 b; - for (b=0; bgetMeshBuffer(b)->getIndexCount(); - const u16* idx = mesh->getMeshBuffer(b)->getIndices(); + const IMeshBuffer* original = mesh->getMeshBuffer(b); + const u32 idxCnt = original->getIndexCount(); + const u16* idx = original->getIndices(); SMeshBufferTangents* buffer = new SMeshBufferTangents(); - buffer->Material = mesh->getMeshBuffer(b)->getMaterial(); + + buffer->Material = original->getMaterial(); + buffer->Vertices.reallocate(idxCnt); + buffer->Indices.set_used(idxCnt); + + core::map vertMap; + int vertLocation; // copy vertices - buffer->Vertices.reallocate(idxCnt); - switch(mesh->getMeshBuffer(b)->getVertexType()) - { - case video::EVT_STANDARD: - { - video::S3DVertex* v = - (video::S3DVertex*)mesh->getMeshBuffer(b)->getVertices(); - - for (u32 i=0; iVertices.push_back( - video::S3DVertexTangents( - v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords)); - } - break; - case video::EVT_2TCOORDS: - { - video::S3DVertex2TCoords* v = - (video::S3DVertex2TCoords*)mesh->getMeshBuffer(b)->getVertices(); - - for (u32 i=0; iVertices.push_back(video::S3DVertexTangents( - v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords)); - } - break; - case video::EVT_TANGENTS: - { - video::S3DVertexTangents* v = - (video::S3DVertexTangents*)mesh->getMeshBuffer(b)->getVertices(); - - for (u32 i=0; iVertices.push_back(v[idx[i]]); - } - break; - } - - // create new indices - - buffer->Indices.set_used(idxCnt); + const video::E_VERTEX_TYPE vType = original->getVertexType(); + video::S3DVertexTangents vNew; for (u32 i=0; iIndices[i] = i; + { + switch(vType) + { + case video::EVT_STANDARD: + { + const video::S3DVertex* v = + (const video::S3DVertex*)original->getVertices(); + vNew = video::S3DVertexTangents( + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); + } + break; + case video::EVT_2TCOORDS: + { + const video::S3DVertex2TCoords* v = + (const video::S3DVertex2TCoords*)original->getVertices(); + vNew = video::S3DVertexTangents( + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); + } + break; + case video::EVT_TANGENTS: + { + const video::S3DVertexTangents* v = + (const video::S3DVertexTangents*)original->getVertices(); + vNew = v[idx[i]]; + } + break; + } + core::map::Node* n = vertMap.find(vNew); + if (n) + { + vertLocation = n->getValue(); + } + else + { + vertLocation = buffer->Vertices.size(); + buffer->Vertices.push_back(vNew); + vertMap.insert(vNew, vertLocation); + } + + // create new indices + buffer->Indices[i] = vertLocation; + } + buffer->recalculateBoundingBox(); - buffer->setBoundingBox(mesh->getMeshBuffer(b)->getBoundingBox()); // add new buffer clone->addMeshBuffer(buffer); buffer->drop(); } - clone->BoundingBox = mesh->getBoundingBox(); - - // now calculate tangents - for (b=0; bgetMeshBuffer(b)->getVertexCount(); - const u32 idxCnt = clone->getMeshBuffer(b)->getIndexCount(); - - u16* idx = clone->getMeshBuffer(b)->getIndices(); - video::S3DVertexTangents* v = - (video::S3DVertexTangents*)clone->getMeshBuffer(b)->getVertices(); - - if (smooth) - { - u32 i; - - for ( i = 0; i!= vtxCnt; ++i ) - { - if (recalculateNormals) - v[i].Normal.set( 0.f, 0.f, 0.f ); - v[i].Tangent.set( 0.f, 0.f, 0.f ); - v[i].Binormal.set( 0.f, 0.f, 0.f ); - } - - //Each vertex gets the sum of the tangents and binormals from the faces around it - for ( i=0; irecalculateBoundingBox(); + if (calculateTangents) + recalculateTangents(clone, recalculateNormals, smooth, angleWeighted); return clone; } @@ -947,67 +822,157 @@ IMesh* CMeshManipulator::createMeshWith2TCoords(IMesh* mesh) const SMesh* clone = new SMesh(); const u32 meshBufferCount = mesh->getMeshBufferCount(); - u32 b; - for (b=0; bgetMeshBuffer(b)->getIndexCount(); - const u16* idx = mesh->getMeshBuffer(b)->getIndices(); + const IMeshBuffer* original = mesh->getMeshBuffer(b); + const u32 idxCnt = original->getIndexCount(); + const u16* idx = original->getIndices(); SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); - buffer->Material = mesh->getMeshBuffer(b)->getMaterial(); + buffer->Material = original->getMaterial(); + buffer->Vertices.reallocate(idxCnt); + buffer->Indices.set_used(idxCnt); + + core::map vertMap; + int vertLocation; // copy vertices - buffer->Vertices.reallocate(idxCnt); - switch(mesh->getMeshBuffer(b)->getVertexType()) - { - case video::EVT_STANDARD: - { - video::S3DVertex* v = - (video::S3DVertex*)mesh->getMeshBuffer(b)->getVertices(); - - for (u32 i=0; iVertices.push_back( - video::S3DVertex2TCoords( - v[idx[i]].Pos, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords)); - } - break; - case video::EVT_2TCOORDS: - { - video::S3DVertex2TCoords* v = - (video::S3DVertex2TCoords*)mesh->getMeshBuffer(b)->getVertices(); - - for (u32 i=0; iVertices.push_back(v[idx[i]]); - } - break; - case video::EVT_TANGENTS: - { - video::S3DVertexTangents* v = - (video::S3DVertexTangents*)mesh->getMeshBuffer(b)->getVertices(); - - for (u32 i=0; iVertices.push_back(video::S3DVertex2TCoords( - v[idx[i]].Pos, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords)); - } - break; - } - - // create new indices - - buffer->Indices.set_used(idxCnt); + const video::E_VERTEX_TYPE vType = original->getVertexType(); + video::S3DVertex2TCoords vNew; for (u32 i=0; iIndices[i] = i; + { + switch(vType) + { + case video::EVT_STANDARD: + { + const video::S3DVertex* v = + (const video::S3DVertex*)original->getVertices(); + vNew = video::S3DVertex2TCoords( + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords); + } + break; + case video::EVT_2TCOORDS: + { + const video::S3DVertex2TCoords* v = + (const video::S3DVertex2TCoords*)original->getVertices(); + vNew = v[idx[i]]; + } + break; + case video::EVT_TANGENTS: + { + const video::S3DVertexTangents* v = + (const video::S3DVertexTangents*)original->getVertices(); + vNew = video::S3DVertex2TCoords( + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords); + } + break; + } + core::map::Node* n = vertMap.find(vNew); + if (n) + { + vertLocation = n->getValue(); + } + else + { + vertLocation = buffer->Vertices.size(); + buffer->Vertices.push_back(vNew); + vertMap.insert(vNew, vertLocation); + } + + // create new indices + buffer->Indices[i] = vertLocation; + } + buffer->recalculateBoundingBox(); - buffer->setBoundingBox(mesh->getMeshBuffer(b)->getBoundingBox()); // add new buffer clone->addMeshBuffer(buffer); buffer->drop(); } - clone->BoundingBox = mesh->getBoundingBox(); + clone->recalculateBoundingBox(); + return clone; +} +//! Creates a copy of the mesh, which will only consist of S3DVertex vertices. +IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const +{ + if (!mesh) + return 0; + + // copy mesh and fill data into SMeshBuffer + SMesh* clone = new SMesh(); + const u32 meshBufferCount = mesh->getMeshBufferCount(); + + for (u32 b=0; bgetMeshBuffer(b); + const u32 idxCnt = original->getIndexCount(); + const u16* idx = original->getIndices(); + + SMeshBuffer* buffer = new SMeshBuffer(); + buffer->Material = original->getMaterial(); + buffer->Vertices.reallocate(idxCnt); + buffer->Indices.set_used(idxCnt); + + core::map vertMap; + int vertLocation; + + // copy vertices + const video::E_VERTEX_TYPE vType = original->getVertexType(); + video::S3DVertex vNew; + for (u32 i=0; igetVertices(); + vNew = v[idx[i]]; + } + break; + case video::EVT_2TCOORDS: + { + video::S3DVertex2TCoords* v = + (video::S3DVertex2TCoords*)original->getVertices(); + vNew = video::S3DVertex( + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); + } + break; + case video::EVT_TANGENTS: + { + video::S3DVertexTangents* v = + (video::S3DVertexTangents*)original->getVertices(); + vNew = video::S3DVertex( + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); + } + break; + } + core::map::Node* n = vertMap.find(vNew); + if (n) + { + vertLocation = n->getValue(); + } + else + { + vertLocation = buffer->Vertices.size(); + buffer->Vertices.push_back(vNew); + vertMap.insert(vNew, vertLocation); + } + + // create new indices + buffer->Indices[i] = vertLocation; + } + buffer->recalculateBoundingBox(); + + // add new buffer + clone->addMeshBuffer(buffer); + buffer->drop(); + } + + clone->recalculateBoundingBox(); return clone; } diff --git a/src/dep/src/irrlicht/CMeshManipulator.h b/src/dep/src/irrlicht/CMeshManipulator.h index 59a6bdc..83916a5 100644 --- a/src/dep/src/irrlicht/CMeshManipulator.h +++ b/src/dep/src/irrlicht/CMeshManipulator.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -25,14 +25,6 @@ public: \param mesh: Mesh on which the operation is performed. */ virtual void flipSurfaces(scene::IMesh* mesh) const; - //! Sets the alpha vertex color value of the whole mesh to a new value - /** \param mesh: Mesh on which the operation is performed. - \param alpha: New alpha for the vertex color. */ - virtual void setVertexColorAlpha(scene::IMesh* mesh, s32 alpha) const; - - //! Sets the colors of all vertices to one color - virtual void setVertexColors(IMesh* mesh, video::SColor color) const; - //! Recalculates all normals of the mesh. /** \param mesh: Mesh on which the operation is performed. \param smooth: Whether to use smoothed normals. */ @@ -43,38 +35,6 @@ public: \param smooth: Whether to use smoothed normals. */ virtual void recalculateNormals(IMeshBuffer* buffer, bool smooth = false, bool angleWeighted = false) const; - //! Scales the actual mesh, not the scene node. - /** \param mesh Mesh on which the operation is performed. - \param factor Vector which defines the scale for each axis. */ - virtual void scale(scene::IMesh* mesh, const core::vector3df& factor) const; - - //! Scales the actual meshbuffer, not the scene node. - /** \param buffer MeshBuffer on which the operation is performed. - \param factor Vector which defines the scale for each axis. */ - virtual void scale(scene::IMeshBuffer* buffer, const core::vector3df& factor) const; - - //! Scale the texture coords of a mesh. - /** \param mesh Mesh on which the operation is performed. - \param factor Vector which defines the scale for each axis. - \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */ - virtual void scaleTCoords(scene::IMesh* mesh, const core::vector2df& factor, u32 layer=1) const; - - //! Scale the texture coords of a meshbuffer. - /** \param mesh Mesh on which the operation is performed. - \param factor Vector which defines the scale for each axis. - \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */ - virtual void scaleTCoords(scene::IMeshBuffer* buffer, const core::vector2df& factor, u32 level=1) const; - - //! Applies a transformation to a meshbuffer - /** \param buffer: Meshbuffer on which the operation is performed. - \param m: matrix. */ - void transform(scene::IMeshBuffer* buffer, const core::matrix4& m) const; - - //! Applies a transformation to a mesh - /** \param mesh: Mesh on which the operation is performed. - \param m: transformation matrix. */ - virtual void transform(scene::IMesh* mesh, const core::matrix4& m) const; - //! Clones a static IMesh into a modifiable SMesh. virtual SMesh* createMeshCopy(scene::IMesh* mesh) const; @@ -85,17 +45,29 @@ public: texture coordinate space. */ virtual void makePlanarTextureMapping(scene::IMesh* mesh, f32 resolution) const; + //! Creates a planar texture mapping on the meshbuffer + virtual void makePlanarTextureMapping(scene::IMeshBuffer* meshbuffer, f32 resolution=0.001f) const; + + //! Creates a planar texture mapping on the meshbuffer + void makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const; + + //! Recalculates tangents, requires a tangent mesh + virtual void recalculateTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const; + //! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices. - virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const; + virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false, bool recalculateTangents=true) const; //! Creates a copy of the mesh, which will only consist of S3D2TCoords vertices. virtual IMesh* createMeshWith2TCoords(IMesh* mesh) const; + //! Creates a copy of the mesh, which will only consist of S3DVertex vertices. + virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const; + //! Creates a copy of the mesh, which will only consist of unique triangles, i.e. no vertices are shared. virtual IMesh* createMeshUniquePrimitives(IMesh* mesh) const; //! Creates a copy of the mesh, which will have all duplicated vertices removed, i.e. maximal amount of vertices are shared via indexing. - virtual IMesh* createMeshWelded(IMesh *mesh, f32 tolerance=core::ROUNDING_ERROR_32) const; + virtual IMesh* createMeshWelded(IMesh *mesh, f32 tolerance=core::ROUNDING_ERROR_f32) const; //! Returns amount of polygons in mesh. virtual s32 getPolyCount(scene::IMesh* mesh) const; @@ -120,4 +92,3 @@ private: #endif - diff --git a/src/dep/src/irrlicht/CMeshSceneNode.cpp b/src/dep/src/irrlicht/CMeshSceneNode.cpp index bb57b64..e23e87d 100644 --- a/src/dep/src/irrlicht/CMeshSceneNode.cpp +++ b/src/dep/src/irrlicht/CMeshSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -48,8 +48,8 @@ void CMeshSceneNode::OnRegisterSceneNode() { if (IsVisible) { - // because this node supports rendering of mixed mode meshes consisting of - // transparent and solid material at the same time, we need to go through all + // because this node supports rendering of mixed mode meshes consisting of + // transparent and solid material at the same time, we need to go through all // materials, check of what type they are and register this node for the right // render pass according to that. @@ -62,16 +62,16 @@ void CMeshSceneNode::OnRegisterSceneNode() // count transparent and solid materials in this scene node if (ReadOnlyMaterials && Mesh) { - // count mesh materials + // count mesh materials for (u32 i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); video::IMaterialRenderer* rnd = mb ? driver->getMaterialRenderer(mb->getMaterial().MaterialType) : 0; - if (rnd && rnd->isTransparent()) + if (rnd && rnd->isTransparent()) ++transparentCount; - else + else ++solidCount; if (solidCount && transparentCount) @@ -80,21 +80,21 @@ void CMeshSceneNode::OnRegisterSceneNode() } else { - // count copied materials + // count copied materials for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); - if (rnd && rnd->isTransparent()) + if (rnd && rnd->isTransparent()) ++transparentCount; - else + else ++solidCount; if (solidCount && transparentCount) break; - } + } } // register according to material types counted @@ -119,7 +119,7 @@ void CMeshSceneNode::render() if (!Mesh || !driver) return; - bool isTransparentPass = + bool isTransparentPass = SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; ++PassCount; @@ -134,7 +134,7 @@ void CMeshSceneNode::render() if (DebugDataVisible && PassCount==1) { // overwrite half transparency - if ( DebugDataVisible & scene::EDS_HALF_TRANSPARENCY ) + if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) { for (u32 g=0; ggetMeshBufferCount(); ++g) { @@ -148,7 +148,7 @@ void CMeshSceneNode::render() } // render original meshes - if ( renderMeshes ) + if (renderMeshes) { for (u32 i=0; igetMeshBufferCount(); ++i) { @@ -162,7 +162,7 @@ void CMeshSceneNode::render() // only render transparent buffer if this is the transparent render pass // and solid only in solid pass - if (transparent == isTransparentPass) + if (transparent == isTransparentPass) { driver->setMaterial(material); driver->drawMeshBuffer(mb); @@ -174,17 +174,18 @@ void CMeshSceneNode::render() driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); // for debug purposes only: - if ( DebugDataVisible && PassCount==1) + if (DebugDataVisible && PassCount==1) { video::SMaterial m; m.Lighting = false; + m.AntiAliasing=0; driver->setMaterial(m); - if ( DebugDataVisible & scene::EDS_BBOX ) + if (DebugDataVisible & scene::EDS_BBOX) { driver->draw3DBox(Box, video::SColor(255,255,255,255)); } - if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) + if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) { for (u32 g=0; ggetMeshBufferCount(); ++g) { @@ -194,50 +195,37 @@ void CMeshSceneNode::render() } } - if ( DebugDataVisible & scene::EDS_NORMALS ) + if (DebugDataVisible & scene::EDS_NORMALS) { - IAnimatedMesh * arrow = SceneManager->addArrowMesh ( - "__debugnormal", 0xFFECEC00, - 0xFF999900, 4, 8, 1.f, 0.6f, 0.05f, - 0.3f); - if ( 0 == arrow ) - { - arrow = SceneManager->getMesh ( "__debugnormal" ); - } - IMesh *mesh = arrow->getMesh(0); - - // find a good scaling factor - - core::matrix4 m2; // draw normals + core::vector3df normalizedNormal; + const f32 DebugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); + const video::SColor DebugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); + for (u32 g=0; ggetMeshBufferCount(); ++g) { const scene::IMeshBuffer* mb = Mesh->getMeshBuffer(g); const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); - for ( u32 i=0; i != mb->getVertexCount(); ++i ) + const bool normalize = mb->getMaterial().NormalizeNormals; + + for (u32 i=0; i != mb->getVertexCount(); ++i) { - // align to v->Normal - core::quaternion quatRot(v->Normal.X, 0.f, -v->Normal.X, 1+v->Normal.Y); - quatRot.normalize(); - quatRot.getMatrix(m2); + normalizedNormal = v->Normal; + if (normalize) + normalizedNormal.normalize(); - m2.setTranslation(v->Pos); - m2*=AbsoluteTransformation; + driver->draw3DLine(v->Pos, v->Pos + (normalizedNormal * DebugNormalLength), DebugNormalColor); - driver->setTransform(video::ETS_WORLD, m2); - for (u32 a = 0; a != mesh->getMeshBufferCount(); ++a) - driver->drawMeshBuffer(mesh->getMeshBuffer(a)); - - v = (const video::S3DVertex*) ( (u8*) v + vSize ); + v = (const video::S3DVertex*) ( (u8*) v+vSize ); } } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); } // show mesh - if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) + if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) { m.Wireframe = true; driver->setMaterial(m); @@ -271,7 +259,7 @@ video::SMaterial& CMeshSceneNode::getMaterial(u32 i) return tmpReadOnlyMaterial; } - if ( i >= Materials.size()) + if (i >= Materials.size()) return ISceneNode::getMaterial(i); return Materials[i]; @@ -296,14 +284,12 @@ void CMeshSceneNode::setMesh(IMesh* mesh) if (!mesh) return; // won't set null mesh + mesh->grab(); if (Mesh) Mesh->drop(); Mesh = mesh; copyMaterials(); - - if (Mesh) - Mesh->grab(); } @@ -332,15 +318,15 @@ void CMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeRea { IMeshSceneNode::serializeAttributes(out, options); - out->addString("Mesh", SceneManager->getMeshCache()->getMeshFilename(Mesh)); + out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str()); out->addBool("ReadOnlyMaterials", ReadOnlyMaterials); } //! Reads attributes of the scene node. void CMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - core::stringc oldMeshStr = SceneManager->getMeshCache()->getMeshFilename(Mesh); - core::stringc newMeshStr = in->getAttributeAsString("Mesh"); + io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh); + io::path newMeshStr = in->getAttributeAsString("Mesh"); ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials"); if (newMeshStr != "" && oldMeshStr != newMeshStr) @@ -359,7 +345,7 @@ void CMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeRe } //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. -/* In this way it is possible to change the materials a mesh causing all mesh scene nodes +/* In this way it is possible to change the materials a mesh causing all mesh scene nodes referencing this mesh to change too. */ void CMeshSceneNode::setReadOnlyMaterials(bool readonly) { @@ -379,14 +365,15 @@ ISceneNode* CMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; - CMeshSceneNode* nb = new CMeshSceneNode(Mesh, newParent, + CMeshSceneNode* nb = new CMeshSceneNode(Mesh, newParent, newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale); nb->cloneMembers(this, newManager); nb->ReadOnlyMaterials = ReadOnlyMaterials; nb->Materials = Materials; - nb->drop(); + if ( newParent ) + nb->drop(); return nb; } diff --git a/src/dep/src/irrlicht/CMeshSceneNode.h b/src/dep/src/irrlicht/CMeshSceneNode.h index cc76ff3..a8eff19 100644 --- a/src/dep/src/irrlicht/CMeshSceneNode.h +++ b/src/dep/src/irrlicht/CMeshSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CMetaTriangleSelector.cpp b/src/dep/src/irrlicht/CMetaTriangleSelector.cpp index 6641360..aefe493 100644 --- a/src/dep/src/irrlicht/CMetaTriangleSelector.cpp +++ b/src/dep/src/irrlicht/CMetaTriangleSelector.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -41,12 +41,14 @@ void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 array s32& outTriangleCount, const core::matrix4* transform) const { s32 outWritten = 0; - for (u32 i=0; igetTriangles(triangles + outWritten, arraySize - outWritten, t, transform); + TriangleSelectors[i]->getTriangles(triangles + outWritten, + arraySize - outWritten, t, transform); outWritten += t; + if (outWritten==arraySize) + break; } outTriangleCount = outWritten; @@ -59,13 +61,14 @@ void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 array const core::matrix4* transform) const { s32 outWritten = 0; - for (u32 i=0; igetTriangles(triangles + outWritten, arraySize - outWritten, t, - box, transform); + TriangleSelectors[i]->getTriangles(triangles + outWritten, + arraySize - outWritten, t, box, transform); outWritten += t; + if (outWritten==arraySize) + break; } outTriangleCount = outWritten; @@ -78,13 +81,14 @@ void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 array const core::matrix4* transform) const { s32 outWritten = 0; - for (u32 i=0; igetTriangles(triangles + outWritten, arraySize - outWritten, t, - line, transform); + TriangleSelectors[i]->getTriangles(triangles + outWritten, + arraySize - outWritten, t, line, transform); outWritten += t; + if (outWritten==arraySize) + break; } outTriangleCount = outWritten; @@ -130,6 +134,24 @@ void CMetaTriangleSelector::removeAllTriangleSelectors() } +//! Return the scene node associated with a given triangle. +const ISceneNode* CMetaTriangleSelector::getSceneNodeForTriangle(u32 triangleIndex) const +{ + u32 totalTriangles = 0; + + for (u32 i=0; igetTriangleCount(); + + if(totalTriangles > triangleIndex) + return TriangleSelectors[i]->getSceneNodeForTriangle(0); + } + + // For lack of anything more sensible, return the first selector. + return TriangleSelectors[0]->getSceneNodeForTriangle(0); +} + + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CMetaTriangleSelector.h b/src/dep/src/irrlicht/CMetaTriangleSelector.h index e995aec..02fd46b 100644 --- a/src/dep/src/irrlicht/CMetaTriangleSelector.h +++ b/src/dep/src/irrlicht/CMetaTriangleSelector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -51,6 +51,9 @@ public: //! Removes all triangle selectors from the collection. virtual void removeAllTriangleSelectors(); + //! Return the scene node associated with a given triangle. + virtual const ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const; + private: core::array TriangleSelectors; diff --git a/src/dep/src/irrlicht/CMountPointReader.cpp b/src/dep/src/irrlicht/CMountPointReader.cpp new file mode 100644 index 0000000..a5a4b91 --- /dev/null +++ b/src/dep/src/irrlicht/CMountPointReader.cpp @@ -0,0 +1,168 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CMountPointReader.h" + +#ifdef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ + +#include "CReadFile.h" +#include "os.h" + +namespace irr +{ +namespace io +{ + +//! Constructor +CArchiveLoaderMount::CArchiveLoaderMount( io::IFileSystem* fs) +: FileSystem(fs) +{ + #ifdef _DEBUG + setDebugName("CArchiveLoaderMount"); + #endif +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderMount::isALoadableFileFormat(const io::path& filename) const +{ + bool ret = false; + io::path fname(filename); + deletePathFromFilename(fname); + + if (!fname.size()) + { + ret = true; + } + + return ret; +} + +//! Check to see if the loader can create archives of this type. +bool CArchiveLoaderMount::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const +{ + return fileType == EFAT_FOLDER; +} + +//! Check if the file might be loaded by this class +bool CArchiveLoaderMount::isALoadableFileFormat(io::IReadFile* file) const +{ + return false; +} + +//! Creates an archive from the filename +IFileArchive* CArchiveLoaderMount::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + + EFileSystemType current = FileSystem->setFileListSystem(FILESYSTEM_NATIVE); + + io::path save = FileSystem->getWorkingDirectory(); + io::path fullPath = FileSystem->getAbsolutePath(filename); + FileSystem->flattenFilename(fullPath); + + if ( FileSystem->changeWorkingDirectoryTo ( fullPath ) ) + { + archive = new CMountPointReader(FileSystem, fullPath, ignoreCase, ignorePaths); + } + + FileSystem->changeWorkingDirectoryTo(save); + FileSystem->setFileListSystem(current); + + return archive; +} + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderMount::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + return 0; +} + +//! compatible Folder Architecture +CMountPointReader::CMountPointReader(IFileSystem * parent, const io::path& basename, bool ignoreCase, bool ignorePaths) + : CFileList(basename, ignoreCase, ignorePaths), Parent(parent) +{ + //! ensure CFileList path ends in a slash + if (Path.lastChar() != '/' ) + Path.append('/'); + + const io::path work = Parent->getWorkingDirectory(); + + Parent->changeWorkingDirectoryTo(basename); + buildDirectory(); + Parent->changeWorkingDirectoryTo(work); + + sort(); +} + + +//! returns the list of files +const IFileList* CMountPointReader::getFileList() const +{ + return this; +} + +void CMountPointReader::buildDirectory() +{ + IFileList * list = Parent->createFileList(); + if (!list) + return; + + const u32 size = list->getFileCount(); + for (u32 i=0; i < size; ++i) + { + io::path full = list->getFullFileName(i); + full = full.subString(Path.size(), full.size() - Path.size()); + + if (!list->isDirectory(i)) + { + addItem(full, list->getFileSize(i), false, RealFileNames.size()); + RealFileNames.push_back(list->getFullFileName(i)); + } + else + { + const io::path rel = list->getFileName(i); + io::path pwd = Parent->getWorkingDirectory(); + if (pwd.lastChar() != '/') + pwd.append('/'); + pwd.append(rel); + + if ( rel != "." && rel != ".." ) + { + addItem(full, 0, true, 0); + Parent->changeWorkingDirectoryTo(pwd); + buildDirectory(); + Parent->changeWorkingDirectoryTo(".."); + } + } + } + + list->drop(); +} + +//! opens a file by index +IReadFile* CMountPointReader::createAndOpenFile(u32 index) +{ + if (index >= Files.size()) + return 0; + + return createReadFile(RealFileNames[Files[index].ID]); +} + +//! opens a file by file name +IReadFile* CMountPointReader::createAndOpenFile(const io::path& filename) +{ + s32 index = findFile(filename, false); + if (index != -1) + return createAndOpenFile(index); + else + return 0; +} + + +} // io +} // irr + +#endif // __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ diff --git a/src/dep/src/irrlicht/CMountPointReader.h b/src/dep/src/irrlicht/CMountPointReader.h new file mode 100644 index 0000000..0a4f0eb --- /dev/null +++ b/src/dep/src/irrlicht/CMountPointReader.h @@ -0,0 +1,89 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_MOUNT_READER_H_INCLUDED__ +#define __C_MOUNT_READER_H_INCLUDED__ + +#include "IrrCompileConfig.h" + +#ifdef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ + +#include "IFileSystem.h" +#include "CFileList.h" + +namespace irr +{ +namespace io +{ + + //! Archiveloader capable of loading MountPoint Archives + class CArchiveLoaderMount : public IArchiveLoader + { + public: + + //! Constructor + CArchiveLoaderMount(io::IFileSystem* fs); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".zip") + virtual bool isALoadableFileFormat(const io::path& filename) const; + + //! Check if the file might be loaded by this class + /** Check might look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const; + + //! Check to see if the loader can create archives of this type. + /** Check based on the archive type. + \param fileType The archive type to check. + \return True if the archile loader supports this type, false if not */ + virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const; + + //! Creates an archive from the filename + /** \param file File handle to check. + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const; + + //! creates/loads an archive from the file. + //! \return Pointer to the created archive. Returns 0 if loading failed. + virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; + + private: + io::IFileSystem* FileSystem; + }; + + //! A File Archive which uses a mountpoint + class CMountPointReader : public virtual IFileArchive, virtual CFileList + { + public: + + //! Constructor + CMountPointReader(IFileSystem *parent, const io::path& basename, + bool ignoreCase, bool ignorePaths); + + //! opens a file by index + virtual IReadFile* createAndOpenFile(u32 index); + + //! opens a file by file name + virtual IReadFile* createAndOpenFile(const io::path& filename); + + //! returns the list of files + virtual const IFileList* getFileList() const; + + //! get the class Type + virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_FOLDER; } + + private: + + core::array RealFileNames; + + IFileSystem *Parent; + void buildDirectory(); + }; +} // io +} // irr + +#endif // __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ +#endif // __C_MOUNT_READER_H_INCLUDED__ diff --git a/src/dep/src/irrlicht/CNPKReader.cpp b/src/dep/src/irrlicht/CNPKReader.cpp new file mode 100644 index 0000000..3cfb7f4 --- /dev/null +++ b/src/dep/src/irrlicht/CNPKReader.cpp @@ -0,0 +1,279 @@ +// Copyright (C) 2002-2009 Nikolaus Gebhardt +// Copyright (C) 2009-2010 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h +// Based on the NPK reader from Irrlicht + +#include "CNPKReader.h" + +#ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ + +#include "os.h" +#include "coreutil.h" + +#ifdef _DEBUG +#define IRR_DEBUG_NPK_READER +#endif + +namespace irr +{ +namespace io +{ + +namespace +{ + bool isHeaderValid(const SNPKHeader& header) + { + const c8* const tag = header.Tag; + return tag[0] == '0' && + tag[1] == 'K' && + tag[2] == 'P' && + tag[3] == 'N'; + } +} // end namespace + + +//! Constructor +CArchiveLoaderNPK::CArchiveLoaderNPK( io::IFileSystem* fs) +: FileSystem(fs) +{ +#ifdef _DEBUG + setDebugName("CArchiveLoaderNPK"); +#endif +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderNPK::isALoadableFileFormat(const io::path& filename) const +{ + return core::hasFileExtension(filename, "npk"); +} + +//! Check to see if the loader can create archives of this type. +bool CArchiveLoaderNPK::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const +{ + return fileType == EFAT_NPK; +} + +//! Creates an archive from the filename +/** \param file File handle to check. +\return Pointer to newly created archive, or 0 upon error. */ +IFileArchive* CArchiveLoaderNPK::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + io::IReadFile* file = FileSystem->createAndOpenFile(filename); + + if (file) + { + archive = createArchive(file, ignoreCase, ignorePaths); + file->drop (); + } + + return archive; +} + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderNPK::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + if ( file ) + { + file->seek ( 0 ); + archive = new CNPKReader(file, ignoreCase, ignorePaths); + } + return archive; +} + + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderNPK::isALoadableFileFormat(io::IReadFile* file) const +{ + SNPKHeader header; + + file->read(&header, sizeof(header)); + + return isHeaderValid(header); +} + + +/*! + NPK Reader +*/ +CNPKReader::CNPKReader(IReadFile* file, bool ignoreCase, bool ignorePaths) +: CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file) +{ +#ifdef _DEBUG + setDebugName("CNPKReader"); +#endif + + if (File) + { + File->grab(); + if (scanLocalHeader()) + sort(); + else + os::Printer::log("Failed to load NPK archive."); + } +} + + +CNPKReader::~CNPKReader() +{ + if (File) + File->drop(); +} + + +const IFileList* CNPKReader::getFileList() const +{ + return this; +} + + +bool CNPKReader::scanLocalHeader() +{ + SNPKHeader header; + + // Read and validate the header + File->read(&header, sizeof(header)); + if (!isHeaderValid(header)) + return false; + + // Seek to the table of contents +#ifdef __BIG_ENDIAN__ + header.Offset = os::Byteswap::byteswap(header.Offset); + header.Length = os::Byteswap::byteswap(header.Length); +#endif + header.Offset += 8; + core::stringc dirName; + bool inTOC=true; + // Loop through each entry in the table of contents + while (inTOC && (File->getPos() < File->getSize())) + { + // read an entry + char tag[4]={0}; + SNPKFileEntry entry; + File->read(tag, 4); + const int numTag = MAKE_IRR_ID(tag[3],tag[2],tag[1],tag[0]); + int size; + + bool isDir=true; + + switch (numTag) + { + case MAKE_IRR_ID('D','I','R','_'): + { + File->read(&size, 4); + readString(entry.Name); + entry.Length=0; + entry.Offset=0; +#ifdef IRR_DEBUG_NPK_READER + os::Printer::log("Dir", entry.Name); +#endif + } + break; + case MAKE_IRR_ID('F','I','L','E'): + { + File->read(&size, 4); + File->read(&entry.Offset, 4); + File->read(&entry.Length, 4); + readString(entry.Name); + isDir=false; +#ifdef IRR_DEBUG_NPK_READER + os::Printer::log("File", entry.Name); +#endif +#ifdef __BIG_ENDIAN__ + entry.Offset = os::Byteswap::byteswap(entry.Offset); + entry.Length = os::Byteswap::byteswap(entry.Length); +#endif + } + break; + case MAKE_IRR_ID('D','E','N','D'): + { + File->read(&size, 4); + entry.Name=""; + entry.Length=0; + entry.Offset=0; + const s32 pos = dirName.findLast('/', dirName.size()-2); + if (pos==-1) + dirName=""; + else + dirName=dirName.subString(0, pos); +#ifdef IRR_DEBUG_NPK_READER + os::Printer::log("Dirend", dirName); +#endif + } + break; + default: + inTOC=false; + } + // skip root dir + if (isDir) + { + if (!entry.Name.size() || (entry.Name==".") || (entry.Name=="")) + continue; + dirName += entry.Name; + dirName += "/"; + } +#ifdef IRR_DEBUG_NPK_READER + os::Printer::log("Name", entry.Name); +#endif + addItem((isDir?dirName:dirName+entry.Name), entry.Length, isDir, Offsets.size()); + Offsets.push_back(entry.Offset+header.Offset); + } + return true; +} + + +//! opens a file by file name +IReadFile* CNPKReader::createAndOpenFile(const io::path& filename) +{ + s32 index = findFile(filename, false); + + if (index != -1) + return createAndOpenFile(index); + + return 0; +} + + +//! opens a file by index +IReadFile* CNPKReader::createAndOpenFile(u32 index) +{ + if (index < Files.size()) + { + return createLimitReadFile(Files[index].FullName, File, Offsets[Files[index].ID], Files[index].Size); + } + else + return 0; +} + +void CNPKReader::readString(core::stringc& name) +{ + short stringSize; + char buf[256]; + File->read(&stringSize, 2); +#ifdef __BIG_ENDIAN__ + stringSize = os::Byteswap::byteswap(stringSize); +#endif + name.reserve(stringSize); + while(stringSize) + { + const short next = core::min_(stringSize, (short)255); + File->read(buf,next); + buf[next]=0; + name.append(buf); + stringSize -= next; + } +} + + +} // end namespace io +} // end namespace irr + +#endif // __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ + diff --git a/src/dep/src/irrlicht/CNPKReader.h b/src/dep/src/irrlicht/CNPKReader.h new file mode 100644 index 0000000..1f3f6d0 --- /dev/null +++ b/src/dep/src/irrlicht/CNPKReader.h @@ -0,0 +1,131 @@ +// Copyright (C) 2002-2009 Nikolaus Gebhardt +// Copyright (C) 2009-2010 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_NPK_READER_H_INCLUDED__ +#define __C_NPK_READER_H_INCLUDED__ + +#include "IrrCompileConfig.h" + +#ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ + +#include "IReferenceCounted.h" +#include "IReadFile.h" +#include "irrArray.h" +#include "irrString.h" +#include "IFileSystem.h" +#include "CFileList.h" + +namespace irr +{ +namespace io +{ + namespace + { + //! File header containing location and size of the table of contents + struct SNPKHeader + { + // Don't change the order of these fields! They must match the order stored on disk. + c8 Tag[4]; + u32 Length; + u32 Offset; + }; + + //! An entry in the NPK file's table of contents. + struct SNPKFileEntry + { + core::stringc Name; + u32 Offset; + u32 Length; + }; + } // end namespace + + //! Archiveloader capable of loading Nebula Device 2 NPK Archives + class CArchiveLoaderNPK : public IArchiveLoader + { + public: + + //! Constructor + CArchiveLoaderNPK(io::IFileSystem* fs); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".zip") + virtual bool isALoadableFileFormat(const io::path& filename) const; + + //! Check if the file might be loaded by this class + /** Check might look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const; + + //! Check to see if the loader can create archives of this type. + /** Check based on the archive type. + \param fileType The archive type to check. + \return True if the archile loader supports this type, false if not */ + virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const; + + //! Creates an archive from the filename + /** \param file File handle to check. + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const; + + //! creates/loads an archive from the file. + //! \return Pointer to the created archive. Returns 0 if loading failed. + virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; + + //! Returns the type of archive created by this loader + virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_NPK; } + + private: + io::IFileSystem* FileSystem; + }; + + + //! reads from NPK + class CNPKReader : public virtual IFileArchive, virtual CFileList + { + public: + + CNPKReader(IReadFile* file, bool ignoreCase, bool ignorePaths); + virtual ~CNPKReader(); + + // file archive methods + + //! return the id of the file Archive + virtual const io::path& getArchiveName() const + { + return File->getFileName(); + } + + //! opens a file by file name + virtual IReadFile* createAndOpenFile(const io::path& filename); + + //! opens a file by index + virtual IReadFile* createAndOpenFile(u32 index); + + //! returns the list of files + virtual const IFileList* getFileList() const; + + //! get the class Type + virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_NPK; } + + private: + + //! scans for a local header, returns false if the header is invalid + bool scanLocalHeader(); + void readString(core::stringc& name); + + IReadFile* File; + + //! Contains offsets of the files from the start of the archive file + core::array Offsets; + }; + +} // end namespace io +} // end namespace irr + +#endif // __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ + +#endif // __C_NPK_READER_H_INCLUDED__ + diff --git a/src/dep/src/irrlicht/CNullDriver.cpp b/src/dep/src/irrlicht/CNullDriver.cpp index 645d0d6..62a2fd0 100644 --- a/src/dep/src/irrlicht/CNullDriver.cpp +++ b/src/dep/src/irrlicht/CNullDriver.cpp @@ -1,9 +1,8 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CNullDriver.h" -#include "CSoftwareTexture.h" #include "os.h" #include "CImage.h" #include "CAttributes.h" @@ -13,6 +12,7 @@ #include "IImageWriter.h" #include "IMaterialRenderer.h" #include "CMeshManipulator.h" +#include "CColorConverter.h" namespace irr @@ -44,33 +44,37 @@ IImageLoader* createImageLoaderWAL(); //! creates a loader which is able to load ppm/pgm/pbm images IImageLoader* createImageLoaderPPM(); -//! creates a loader which is able to load bmp images +//! creates a loader which is able to load rgb images +IImageLoader* createImageLoaderRGB(); + + +//! creates a writer which is able to save bmp images IImageWriter* createImageWriterBMP(); -//! creates a loader which is able to load jpg images +//! creates a writer which is able to save jpg images IImageWriter* createImageWriterJPG(); -//! creates a loader which is able to load tga images +//! creates a writer which is able to save tga images IImageWriter* createImageWriterTGA(); -//! creates a loader which is able to load psd images +//! creates a writer which is able to save psd images IImageWriter* createImageWriterPSD(); -//! creates a loader which is able to load pcx images +//! creates a writer which is able to save pcx images IImageWriter* createImageWriterPCX(); -//! creates a loader which is able to load png images +//! creates a writer which is able to save png images IImageWriter* createImageWriterPNG(); -//! creates a loader which is able to load ppm images +//! creates a writer which is able to save ppm images IImageWriter* createImageWriterPPM(); - //! constructor -CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize) +CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize) : FileSystem(io), MeshManipulator(0), ViewPort(0,0,0,0), ScreenSize(screenSize), - PrimitivesDrawn(0), TextureCreationFlags(0), AllowZWriteOnTransparent(false) + PrimitivesDrawn(0), MinVertexCountForVBO(500), TextureCreationFlags(0), + OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false) { #ifdef _DEBUG setDebugName("CNullDriver"); @@ -81,7 +85,7 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d& scre setTextureCreationFlag(ETCF_ALWAYS_32_BIT, true); setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true); - ViewPort = core::rect(core::position2d(0,0), screenSize); + ViewPort = core::rect(core::position2d(0,0), core::dimension2di(screenSize)); // create manipulator MeshManipulator = new scene::CMeshManipulator(); @@ -115,6 +119,10 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d& scre #ifdef _IRR_COMPILE_WITH_PPM_LOADER_ SurfaceLoader.push_back(video::createImageLoaderPPM()); #endif +#ifdef _IRR_COMPILE_WITH_RGB_LOADER_ + SurfaceLoader.push_back(video::createImageLoaderRGB()); +#endif + #ifdef _IRR_COMPILE_WITH_BMP_WRITER_ SurfaceWriter.push_back(video::createImageWriterBMP()); @@ -142,6 +150,18 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d& scre memset(&ExposedData, 0, sizeof(ExposedData)); for (u32 i=0; idrop(); @@ -205,7 +261,7 @@ void CNullDriver::deleteAllTextures() //! applications must call this method before performing any rendering. returns false if failed. bool CNullDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, - void* windowId, core::rect* sourceRect) + const SExposedVideoData& videoData, core::rect* sourceRect) { core::clearFPUException(); PrimitivesDrawn = 0; @@ -227,7 +283,7 @@ void CNullDriver::disableFeature(E_VIDEO_DRIVER_FEATURE feature, bool flag) { FeatureEnabled[feature]=!flag; } - + //! queries the features of the driver, returns true if feature is available bool CNullDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const @@ -236,7 +292,6 @@ bool CNullDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const } - //! sets transformation void CNullDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { @@ -250,14 +305,12 @@ const core::matrix4& CNullDriver::getTransform(E_TRANSFORMATION_STATE state) con } - //! sets a material void CNullDriver::setMaterial(const SMaterial& material) { } - //! Removes a texture from the texture cache and deletes it, freeing lot of //! memory. void CNullDriver::removeTexture(ITexture* texture) @@ -280,6 +333,7 @@ void CNullDriver::removeTexture(ITexture* texture) //! memory. void CNullDriver::removeAllTextures() { + setMaterial ( SMaterial() ); deleteAllTextures(); } @@ -302,26 +356,26 @@ u32 CNullDriver::getTextureCount() const //! Renames a texture -void CNullDriver::renameTexture(ITexture* texture, const c8* newName) +void CNullDriver::renameTexture(ITexture* texture, const io::path& newName) { // we can do a const_cast here safely, the name of the ITexture interface // is just readonly to prevent the user changing the texture name without invoking // this method, because the textures will need resorting afterwards - core::stringc& name = const_cast(texture->getName()); - name = newName; + io::SNamedPath& name = const_cast(texture->getName()); + name.setPath(newName); Textures.sort(); } //! loads a Texture -ITexture* CNullDriver::getTexture(const c8* filename) +ITexture* CNullDriver::getTexture(const io::path& filename) { // Identify textures by their absolute filenames if possible. - core::stringc absolutePath = FileSystem->getAbsolutePath(filename); + const io::path absolutePath = FileSystem->getAbsolutePath(filename); - ITexture* texture = findTexture(absolutePath.c_str()); + ITexture* texture = findTexture(absolutePath); if (texture) return texture; @@ -331,7 +385,7 @@ ITexture* CNullDriver::getTexture(const c8* filename) return texture; // Now try to open the file using the complete path. - io::IReadFile* file = FileSystem->createAndOpenFile(absolutePath.c_str()); + io::IReadFile* file = FileSystem->createAndOpenFile(absolutePath); if(!file) { @@ -341,6 +395,14 @@ ITexture* CNullDriver::getTexture(const c8* filename) if (file) { + // Re-check name for actual archive names + texture = findTexture(file->getFileName()); + if (texture) + { + file->drop(); + return texture; + } + texture = loadTextureFromFile(file); file->drop(); @@ -390,7 +452,7 @@ ITexture* CNullDriver::getTexture(io::IReadFile* file) //! opens the file and loads it into the surface -video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const c8 *hashName ) +video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const io::path& hashName ) { ITexture* texture = 0; IImage* image = createImageFromFile(file); @@ -398,7 +460,7 @@ video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const c8 if (image) { // create texture from surface - texture = createDeviceDependentTexture(image, hashName ? hashName : file->getFileName() ); + texture = createDeviceDependentTexture(image, hashName.size() ? hashName : file->getFileName() ); os::Printer::log("Loaded texture", file->getFileName()); image->drop(); } @@ -407,7 +469,6 @@ video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const c8 } - //! adds a surface, not loaded or created by the Irrlicht Engine void CNullDriver::addTexture(video::ITexture* texture) { @@ -429,13 +490,9 @@ void CNullDriver::addTexture(video::ITexture* texture) } - //! looks if the image is already loaded -video::ITexture* CNullDriver::findTexture(const c8* filename) +video::ITexture* CNullDriver::findTexture(const io::path& filename) { - if (!filename) - filename = ""; - SSurface s; SDummyTexture dummy(filename); s.Surface = &dummy; @@ -448,14 +505,13 @@ video::ITexture* CNullDriver::findTexture(const c8* filename) } - //! Creates a texture from a loaded IImage. -ITexture* CNullDriver::addTexture(const c8* name, IImage* image) +ITexture* CNullDriver::addTexture(const io::path& name, IImage* image, void* mipmapData) { - if (!name || !image) + if ( 0 == name.size() || !image) return 0; - ITexture* t = createDeviceDependentTexture(image, name); + ITexture* t = createDeviceDependentTexture(image, name, mipmapData); if (t) { addTexture(t); @@ -465,12 +521,17 @@ ITexture* CNullDriver::addTexture(const c8* name, IImage* image) } - //! creates a Texture -ITexture* CNullDriver::addTexture(const core::dimension2d& size, - const c8* name, ECOLOR_FORMAT format) +ITexture* CNullDriver::addTexture(const core::dimension2d& size, + const io::path& name, ECOLOR_FORMAT format) { - if (!name) + if(IImage::isRenderTargetOnlyFormat(format)) + { + os::Printer::log("Could not create ITexture, format only supported for render target textures.", ELL_WARNING); + return 0; + } + + if ( 0 == name.size () ) return 0; IImage* image = new CImage(format, size); @@ -488,16 +549,22 @@ ITexture* CNullDriver::addTexture(const core::dimension2d& size, //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES -ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const char* name) +ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { - #ifdef _IRR_COMPILE_WITH_SOFTWARE_ - return new CSoftwareTexture(surface, name); - #else - return 0; - #endif + return new SDummyTexture(name); } +//! set or reset special render targets +bool CNullDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, + bool clearZBuffer, SColor color) +{ + if (ERT_FRAME_BUFFER==target) + return setRenderTarget(0,clearTarget, clearZBuffer, color); + else + return false; +} + //! sets a render target bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, @@ -507,6 +574,13 @@ bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer } +//! Sets multiple render targets +bool CNullDriver::setRenderTarget(const core::array& texture, + bool clearBackBuffer, bool clearZBuffer, SColor color) +{ + return false; +} + //! sets a viewport void CNullDriver::setViewPort(const core::rect& area) @@ -514,7 +588,6 @@ void CNullDriver::setViewPort(const core::rect& area) } - //! gets the area of the current viewport const core::rect& CNullDriver::getViewPort() const { @@ -522,66 +595,24 @@ const core::rect& CNullDriver::getViewPort() const } - //! draws a vertex primitive list void CNullDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { + if ((iType==EIT_16BIT) && (vertexCount>65536)) + os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur."); PrimitivesDrawn += primitiveCount; } - -//! draws an indexed triangle list -inline void CNullDriver::drawIndexedTriangleList(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) +//! draws a vertex primitive list in 2d +void CNullDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { - drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); + if ((iType==EIT_16BIT) && (vertexCount>65536)) + os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur."); + PrimitivesDrawn += primitiveCount; } - -//! draws an indexed triangle list -inline void CNullDriver::drawIndexedTriangleList(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) -{ - drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_2TCOORDS, scene::EPT_TRIANGLES, EIT_16BIT); -} - - -//! Draws an indexed triangle list. -inline void CNullDriver::drawIndexedTriangleList(const S3DVertexTangents* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount) -{ - drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_TANGENTS, scene::EPT_TRIANGLES, EIT_16BIT); -} - - - -//! Draws an indexed triangle fan. -inline void CNullDriver::drawIndexedTriangleFan(const S3DVertex* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount) -{ - drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_STANDARD, scene::EPT_TRIANGLE_FAN, EIT_16BIT); -} - - - -//! Draws an indexed triangle fan. -inline void CNullDriver::drawIndexedTriangleFan(const S3DVertex2TCoords* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount) -{ - drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_2TCOORDS, scene::EPT_TRIANGLE_FAN, EIT_16BIT); -} - - - -//! Draws an indexed triangle fan. -inline void CNullDriver::drawIndexedTriangleFan(const S3DVertexTangents* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount) -{ - drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_TANGENTS, scene::EPT_TRIANGLE_FAN, EIT_16BIT); -} - - - //! Draws a 3d line. void CNullDriver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) @@ -589,17 +620,27 @@ void CNullDriver::draw3DLine(const core::vector3df& start, } - //! Draws a 3d triangle. void CNullDriver::draw3DTriangle(const core::triangle3df& triangle, SColor color) { - draw3DLine(triangle.pointA, triangle.pointB, color); - draw3DLine(triangle.pointB, triangle.pointC, color); - draw3DLine(triangle.pointC, triangle.pointA, color); + S3DVertex vertices[3]; + vertices[0].Pos=triangle.pointA; + vertices[0].Color=color; + vertices[0].Normal=triangle.getNormal().normalize(); + vertices[0].TCoords.set(0.f,0.f); + vertices[1].Pos=triangle.pointB; + vertices[1].Color=color; + vertices[1].Normal=vertices[0].Normal; + vertices[1].TCoords.set(0.5f,1.f); + vertices[2].Pos=triangle.pointC; + vertices[2].Color=color; + vertices[2].Normal=vertices[0].Normal; + vertices[2].TCoords.set(1.f,0.f); + const u16 indexList[] = {0,1,2}; + drawVertexPrimitiveList(vertices, 3, indexList, 1, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); } - //! Draws a 3d axis aligned box. void CNullDriver::draw3DBox(const core::aabbox3d& box, SColor color) { @@ -630,7 +671,8 @@ void CNullDriver::draw2DImage(const video::ITexture* texture, const core::positi if (!texture) return; - draw2DImage(texture,destPos, core::rect(core::position2d(0,0), texture->getOriginalSize())); + draw2DImage(texture,destPos, core::rect(core::position2d(0,0), + core::dimension2di(texture->getOriginalSize()))); } @@ -640,7 +682,7 @@ void CNullDriver::draw2DImage(const video::ITexture* texture, const core::positi //! in one line. All drawings are clipped against clipRect (if != 0). //! The subtextures are defined by the array of sourceRects and are chosen //! by the indices given. -void CNullDriver::draw2DImage(const video::ITexture* texture, +void CNullDriver::draw2DImageBatch(const video::ITexture* texture, const core::position2d& pos, const core::array >& sourceRects, const core::array& indices, @@ -659,6 +701,23 @@ void CNullDriver::draw2DImage(const video::ITexture* texture, } } +//! draws a set of 2d images, using a color and the alpha channel of the +//! texture if desired. +void CNullDriver::draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect, + SColor color, + bool useAlphaChannelOfTexture) +{ + const irr::u32 drawCount = core::min_(positions.size(), sourceRects.size()); + + for (u32 i=0; i& sourceRect, const core::rect* clipRect, const video::SColor* const colors, bool useAlphaChannelOfTexture) { + draw2DImage(texture, core::position2d(destRect.UpperLeftCorner), + sourceRect, clipRect, colors?colors[0]:video::SColor(0xffffffff), + useAlphaChannelOfTexture); } -//! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. +//! Draws a 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect, SColor color, @@ -678,8 +740,17 @@ void CNullDriver::draw2DImage(const video::ITexture* texture, const core::positi } +//! Draws the outline of a 2d rectangle +void CNullDriver::draw2DRectangleOutline(const core::recti& pos, SColor color) +{ + draw2DLine(pos.UpperLeftCorner, core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), color); + draw2DLine(core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), pos.LowerRightCorner, color); + draw2DLine(pos.LowerRightCorner, core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), color); + draw2DLine(core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), pos.UpperLeftCorner, color); +} -//! draw an 2d rectangle + +//! Draw a 2d rectangle void CNullDriver::draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip) { draw2DRectangle(pos, color, color, color, color, clip); @@ -687,7 +758,7 @@ void CNullDriver::draw2DRectangle(SColor color, const core::rect& pos, cons -//!Draws an 2d rectangle with a gradient. +//! Draws a 2d rectangle with a gradient. void CNullDriver::draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip) @@ -743,7 +814,7 @@ ECOLOR_FORMAT CNullDriver::getColorFormat() const //! returns screen size -const core::dimension2d& CNullDriver::getScreenSize() const +const core::dimension2d& CNullDriver::getScreenSize() const { return ScreenSize; } @@ -751,7 +822,7 @@ const core::dimension2d& CNullDriver::getScreenSize() const //! returns the current render target size, //! or the screen size if render targets are not implemented -const core::dimension2d& CNullDriver::getCurrentRenderTargetSize() const +const core::dimension2d& CNullDriver::getCurrentRenderTargetSize() const { return ScreenSize; } @@ -818,11 +889,19 @@ void CNullDriver::deleteAllDynamicLights() //! adds a dynamic light -void CNullDriver::addDynamicLight(const SLight& light) +s32 CNullDriver::addDynamicLight(const SLight& light) { Lights.push_back(light); + return Lights.size() - 1; } +//! Turns a dynamic light on or off +//! \param lightIndex: the index returned by addDynamicLight +//! \param turnOn: true to turn the light on, false to turn it off +void CNullDriver::turnLightOn(s32 lightIndex, bool turnOn) +{ + // Do nothing +} //! returns the maximal amount of dynamic lights the device can handle @@ -853,8 +932,10 @@ const SLight& CNullDriver::getDynamicLight(u32 idx) const } -//! Creates an 1bit alpha channel of the texture based of an color key. -void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor color) const +//! Creates a boolean alpha channel of the texture based of an color key. +void CNullDriver::makeColorKeyTexture(video::ITexture* texture, + video::SColor color, + bool zeroTexels) const { if (!texture) return; @@ -868,7 +949,7 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor co if (texture->getColorFormat() == ECF_A1R5G5B5) { - s16 *p = (s16*)texture->lock(); + u16 *p = (u16*)texture->lock(); if (!p) { @@ -876,26 +957,34 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor co return; } - core::dimension2d dim = texture->getSize(); - s32 pitch = texture->getPitch() / 2; + const core::dimension2d dim = texture->getSize(); + const u32 pitch = texture->getPitch() / 2; - // color with alpha enabled (color opaque) - s16 ref = (0x1<<15) | (0x7fff & color.toA1R5G5B5()); + // color with alpha disabled (i.e. fully transparent) + const u16 refZeroAlpha = (0x7fff & color.toA1R5G5B5()); - for (s32 y=0; yunlock(); } else { - s32 *p = (s32*)texture->lock(); + u32 *p = (u32*)texture->lock(); if (!p) { @@ -903,19 +992,26 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor co return; } - core::dimension2d dim = texture->getSize(); - s32 pitch = texture->getPitch() / 4; + core::dimension2d dim = texture->getSize(); + u32 pitch = texture->getPitch() / 4; - // color with alpha enabled (color opaque) - s32 ref = 0xff000000 | (0x00ffffff & color.color); + // color with alpha disabled (fully transparent) + const u32 refZeroAlpha = 0x00ffffff & color.color; - for (s32 y=0; yunlock(); @@ -924,9 +1020,10 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor co -//! Creates an 1bit alpha channel of the texture based of an color key position. +//! Creates an boolean alpha channel of the texture based of an color key position. void CNullDriver::makeColorKeyTexture(video::ITexture* texture, - core::position2d colorKeyPixelPos) const + core::position2d colorKeyPixelPos, + bool zeroTexels) const { if (!texture) return; @@ -938,9 +1035,11 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, return; } + SColor colorKey; + if (texture->getColorFormat() == ECF_A1R5G5B5) { - s16 *p = (s16*)texture->lock(); + u16 *p = (u16*)texture->lock(true); if (!p) { @@ -948,25 +1047,15 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, return; } - core::dimension2d dim = texture->getSize(); - s32 pitch = texture->getPitch() / 2; + u32 pitch = texture->getPitch() / 2; - s16 ref = (0x1<<15) | (0x7fff & p[colorKeyPixelPos.Y*dim.Width + colorKeyPixelPos.X]); + const u16 key16Bit = 0x7fff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X]; - for (s32 y=0; yunlock(); + colorKey = video::A1R5G5B5toA8R8G8B8(key16Bit); } else { - s32 *p = (s32*)texture->lock(); + u32 *p = (u32*)texture->lock(true); if (!p) { @@ -974,22 +1063,12 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, return; } - core::dimension2d dim = texture->getSize(); - s32 pitch = texture->getPitch() / 4; - - s32 ref = (0xff<<24) | (0x00ffffff & p[colorKeyPixelPos.Y*dim.Width + colorKeyPixelPos.X]); - - for (s32 y=0; yunlock(); + u32 pitch = texture->getPitch() / 4; + colorKey = 0x00ffffff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X]; } + + texture->unlock(); + makeColorKeyTexture(texture, colorKey, zeroTexels); } @@ -1008,7 +1087,7 @@ void CNullDriver::makeNormalMapTexture(video::ITexture* texture, f32 amplitude) return; } - core::dimension2d dim = texture->getSize(); + core::dimension2d dim = texture->getSize(); amplitude = amplitude / 255.0f; f32 vh = dim.Height / (f32)dim.Width; f32 hh = dim.Width / (f32)dim.Height; @@ -1027,13 +1106,13 @@ void CNullDriver::makeNormalMapTexture(video::ITexture* texture, f32 amplitude) // copy texture - s32 pitch = texture->getPitch() / 4; + u32 pitch = texture->getPitch() / 4; s32* in = new s32[dim.Height * pitch]; memcpy(in, p, dim.Height * pitch * 4); - for (s32 x=0; xgetPitch() / 2; + u32 pitch = texture->getPitch() / 2; // copy texture s16* in = new s16[dim.Height * pitch]; memcpy(in, p, dim.Height * pitch * 2); - for (s32 x=0; xcreateAndWriteFile(filename); + if(!file) + return false; + + bool result = writeImageToFile(image, file, param); + file->drop(); + + return result; +} + +//! Writes the provided image to a file. +bool CNullDriver::writeImageToFile(IImage* image, io::IWriteFile * file, u32 param) +{ + if(!file) + return false; + for (u32 i=0; iisAWriteableFileExtension(filename)) + if (SurfaceWriter[i]->isAWriteableFileExtension(file->getFileName())) { - io::IWriteFile* file = FileSystem->createAndWriteFile(filename); - if (file) - { - bool written = SurfaceWriter[i]->writeImage(file, image, param); - file->drop(); - if (written) - return true; - } + bool written = SurfaceWriter[i]->writeImage(file, image, param); + if (written) + return true; } } return false; // failed to write } - //! Creates a software image from a byte array. IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format, - const core::dimension2d& size, + const core::dimension2d& size, void *data, bool ownForeignMemory, bool deleteMemory) { + if(IImage::isRenderTargetOnlyFormat(format)) + { + os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING); + return 0; + } + return new CImage(format, size, data, ownForeignMemory, deleteMemory); } //! Creates an empty software image. -IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d& size) +IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d& size) { - return new CImage(format, size); + if(IImage::isRenderTargetOnlyFormat(format)) + { + os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING); + return 0; + } + + return new CImage(format, size); } //! Creates a software image from another image. IImage* CNullDriver::createImage(ECOLOR_FORMAT format, IImage *imageToCopy) { - return new CImage(format, imageToCopy); + os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING); + if(IImage::isRenderTargetOnlyFormat(format)) + { + os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING); + return 0; + } + + CImage* tmp = new CImage(format, imageToCopy->getDimension()); + imageToCopy->copyTo(tmp); + return tmp; } //! Creates a software image from part of another image. -IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d& pos, const core::dimension2d& size) +IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d& pos, const core::dimension2d& size) { - return new CImage(imageToCopy, pos, size); + os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING); + CImage* tmp = new CImage(imageToCopy->getColorFormat(), imageToCopy->getDimension()); + imageToCopy->copyTo(tmp, core::position2di(0,0), core::recti(pos,size)); + return tmp; +} + + +//! Creates a software image from part of a texture. +IImage* CNullDriver::createImage(ITexture* texture, const core::position2d& pos, const core::dimension2d& size) +{ + if ((pos==core::position2di(0,0)) && (size == texture->getSize())) + { + IImage* image = new CImage(texture->getColorFormat(), size, texture->lock(true), false); + texture->unlock(); + return image; + } + else + { + // make sure to avoid buffer overruns + // make the vector a separate variable for g++ 3.x + const core::vector2d leftUpper(core::clamp(static_cast(pos.X), 0u, texture->getSize().Width), + core::clamp(static_cast(pos.Y), 0u, texture->getSize().Height)); + const core::rect clamped(leftUpper, + core::dimension2du(core::clamp(static_cast(size.Width), 0u, texture->getSize().Width), + core::clamp(static_cast(size.Height), 0u, texture->getSize().Height))); + if (!clamped.isValid()) + return 0; + u8* src = static_cast(texture->lock(true)); + if (!src) + return 0; + IImage* image = new CImage(texture->getColorFormat(), clamped.getSize()); + u8* dst = static_cast(image->lock()); + for (u32 i=clamped.UpperLeftCorner.Y; igetColorFormat(), clamped.getWidth(), dst, image->getColorFormat()); + src += texture->getPitch(); + dst += image->getPitch(); + } + image->unlock(); + texture->unlock(); + return image; + } } //! Sets the fog mode. -void CNullDriver::setFog(SColor color, bool linearFog, f32 start, f32 end, +void CNullDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { FogColor = color; - LinearFog = linearFog; + FogType = fogType; FogStart = start; FogEnd = end; FogDensity = density; @@ -1291,6 +1441,18 @@ void CNullDriver::setFog(SColor color, bool linearFog, f32 start, f32 end, RangeFog = rangeFog; } +//! Gets the fog mode. +void CNullDriver::getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end, + f32& density, bool& pixelFog, bool& rangeFog) +{ + color = FogColor; + fogType = FogType; + start = FogStart; + end = FogEnd; + density = FogDensity; + pixelFog = PixelFog; + rangeFog = RangeFog; +} //! Draws a mesh buffer void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer* mb) @@ -1307,6 +1469,7 @@ void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer* mb) drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType()); } + CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer* mb) { if (!mb || !isHardwareBufferRecommend(mb)) @@ -1314,11 +1477,13 @@ CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer* //search for hardware links core::map< const scene::IMeshBuffer*,SHWBufferLink* >::Node* node = HWBufferMap.find(mb); - if (node) return node->getValue(); + if (node) + return node->getValue(); return createHardwareBuffer(mb); //no hardware links, and mesh wants one, create it } + //! Update all hardware buffers, remove unused ones void CNullDriver::updateAllHardwareBuffers() { @@ -1342,18 +1507,22 @@ void CNullDriver::updateAllHardwareBuffers() void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer) { - if (!HWBuffer) return; - HWBufferMap.remove( HWBuffer->MeshBuffer ); + if (!HWBuffer) + return; + HWBufferMap.remove(HWBuffer->MeshBuffer); delete HWBuffer; } + //! Remove hardware buffer void CNullDriver::removeHardwareBuffer(const scene::IMeshBuffer* mb) { core::map::Node* node = HWBufferMap.find(mb); - if (node) deleteHardwareBuffer( node->getValue() ); + if (node) + deleteHardwareBuffer(node->getValue()); } + //! Remove all hardware buffers void CNullDriver::removeAllHardwareBuffers() { @@ -1361,28 +1530,32 @@ void CNullDriver::removeAllHardwareBuffers() deleteHardwareBuffer(HWBufferMap.getRoot()->getValue()); } + bool CNullDriver::isHardwareBufferRecommend(const scene::IMeshBuffer* mb) { if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER)) return false; - if (mb->getVertexCount()<500) //todo: tweak and make user definable + if (mb->getVertexCount()& size) +void CNullDriver::OnResize(const core::dimension2d& size) { - if (ViewPort.getWidth() == ScreenSize.Width && - ViewPort.getHeight() == ScreenSize.Height) - ViewPort = core::rect(core::position2d(0,0), size); + if (ViewPort.getWidth() == (s32)ScreenSize.Width && + ViewPort.getHeight() == (s32)ScreenSize.Height) + ViewPort = core::rect(core::position2d(0,0), + core::dimension2di(size)); ScreenSize = size; } + // adds a material renderer and drops it afterwards. To be used for internal creation s32 CNullDriver::addAndDropMaterialRenderer(IMaterialRenderer* m) { @@ -1460,6 +1633,8 @@ io::IAttributes* CNullDriver::createAttributesFromMaterial(const video::SMateria attr->addBool("FrontfaceCulling", material.FrontfaceCulling); attr->addBool("FogEnable", material.FogEnable); attr->addBool("NormalizeNormals", material.NormalizeNormals); + attr->addInt("AntiAliasing", material.AntiAliasing); + attr->addInt("ColorMask", material.ColorMask); prefix = "BilinearFilter"; for (i=0; iaddBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TrilinearFilter); prefix = "AnisotropicFilter"; for (i=0; iaddBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].AnisotropicFilter); - prefix="TextureWrap"; + attr->addInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].AnisotropicFilter); + prefix="TextureWrapU"; for (i=0; iaddEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrap, aTextureClampNames); + attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapU, aTextureClampNames); + prefix="TextureWrapV"; + for (i=0; iaddEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapV, aTextureClampNames); + prefix="LODBias"; + for (i=0; iaddInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].LODBias); return attr; } @@ -1511,11 +1692,15 @@ void CNullDriver::fillMaterialStructureFromAttributes(video::SMaterial& outMater outMaterial.GouraudShading = attr->getAttributeAsBool("GouraudShading"); outMaterial.Lighting = attr->getAttributeAsBool("Lighting"); outMaterial.ZWriteEnable = attr->getAttributeAsBool("ZWriteEnable"); - outMaterial.ZBuffer = (char)attr->getAttributeAsInt("ZBuffer"); + outMaterial.ZBuffer = (u8)attr->getAttributeAsInt("ZBuffer"); outMaterial.BackfaceCulling = attr->getAttributeAsBool("BackfaceCulling"); outMaterial.FrontfaceCulling = attr->getAttributeAsBool("FrontfaceCulling"); outMaterial.FogEnable = attr->getAttributeAsBool("FogEnable"); outMaterial.NormalizeNormals = attr->getAttributeAsBool("NormalizeNormals"); + // default 0 is ok + outMaterial.AntiAliasing = attr->getAttributeAsInt("AntiAliasing"); + if (attr->existsAttribute("ColorMask")) + outMaterial.ColorMask = attr->getAttributeAsInt("ColorMask"); prefix = "BilinearFilter"; if (attr->existsAttribute(prefix.c_str())) // legacy outMaterial.setFlag(EMF_BILINEAR_FILTER, attr->getAttributeAsBool(prefix.c_str())); @@ -1535,11 +1720,30 @@ void CNullDriver::fillMaterialStructureFromAttributes(video::SMaterial& outMater outMaterial.setFlag(EMF_ANISOTROPIC_FILTER, attr->getAttributeAsBool(prefix.c_str())); else for (i=0; igetAttributeAsBool((prefix+core::stringc(i+1)).c_str()); + outMaterial.TextureLayer[i].AnisotropicFilter = attr->getAttributeAsInt((prefix+core::stringc(i+1)).c_str()); prefix = "TextureWrap"; + if (attr->existsAttribute(prefix.c_str())) // legacy + { + for (i=0; igetAttributeAsEnumeration((prefix+core::stringc(i+1)).c_str(), aTextureClampNames); + outMaterial.TextureLayer[i].TextureWrapV = outMaterial.TextureLayer[i].TextureWrapU; + } + } + else + { + for (i=0; igetAttributeAsEnumeration((prefix+"U"+core::stringc(i+1)).c_str(), aTextureClampNames); + outMaterial.TextureLayer[i].TextureWrapV = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"V"+core::stringc(i+1)).c_str(), aTextureClampNames); + } + } + + // default 0 is ok + prefix="LODBias"; for (i=0; igetAttributeAsEnumeration((prefix+core::stringc(i+1)).c_str(), aTextureClampNames); + outMaterial.TextureLayer[i].LODBias = attr->getAttributeAsInt((prefix+core::stringc(i+1)).c_str()); } @@ -1556,6 +1760,7 @@ E_DRIVER_TYPE CNullDriver::getDriverType() const return EDT_NULL; } + //! deletes all material renderers void CNullDriver::deleteMaterialRenders() { @@ -1598,11 +1803,11 @@ const char* CNullDriver::getMaterialRendererName(u32 idx) const //! Returns pointer to the IGPUProgrammingServices interface. IGPUProgrammingServices* CNullDriver::getGPUProgrammingServices() { - return 0; + return this; } -//! Adds a new material renderer to the VideoDriver, based on a high level shading -//! language. Currently only HLSL in D3D9 is supported. + +//! Adds a new material renderer to the VideoDriver, based on a high level shading language. s32 CNullDriver::addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, @@ -1610,6 +1815,11 @@ s32 CNullDriver::addHighLevelShaderMaterial( const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) @@ -1618,49 +1828,64 @@ s32 CNullDriver::addHighLevelShaderMaterial( return -1; } + //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. s32 CNullDriver::addHighLevelShaderMaterialFromFiles( - const c8* vertexShaderProgram, - const c8* vertexShaderEntryPointName, - E_VERTEX_SHADER_TYPE vsCompileTarget, - const c8* pixelShaderProgram, - const c8* pixelShaderEntryPointName, - E_PIXEL_SHADER_TYPE psCompileTarget, - IShaderConstantSetCallBack* callback, - E_MATERIAL_TYPE baseMaterial, - s32 userData) + const io::path& vertexShaderProgramFileName, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const io::path& pixelShaderProgramFileName, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const io::path& geometryShaderProgramFileName, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, + s32 userData) { io::IReadFile* vsfile = 0; io::IReadFile* psfile = 0; + io::IReadFile* gsfile = 0; - if (vertexShaderProgram) + if (vertexShaderProgramFileName.size() ) { - vsfile = FileSystem->createAndOpenFile(vertexShaderProgram); + vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName); if (!vsfile) { os::Printer::log("Could not open vertex shader program file", - vertexShaderProgram, ELL_WARNING); - return -1; + vertexShaderProgramFileName, ELL_WARNING); } } - if (pixelShaderProgram) + if (pixelShaderProgramFileName.size() ) { - psfile = FileSystem->createAndOpenFile(pixelShaderProgram); + psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName); if (!psfile) { os::Printer::log("Could not open pixel shader program file", - pixelShaderProgram, ELL_WARNING); - if (vsfile) - vsfile->drop(); - return -1; + pixelShaderProgramFileName, ELL_WARNING); + } + } + + if (geometryShaderProgramFileName.size() ) + { + gsfile = FileSystem->createAndOpenFile(geometryShaderProgramFileName); + if (!gsfile) + { + os::Printer::log("Could not open geometry shader program file", + geometryShaderProgramFileName, ELL_WARNING); } } s32 result = addHighLevelShaderMaterialFromFiles( vsfile, vertexShaderEntryPointName, vsCompileTarget, psfile, pixelShaderEntryPointName, psCompileTarget, + gsfile, geometryShaderEntryPointName, gsCompileTarget, + inType, outType, verticesOut, callback, baseMaterial, userData); if (psfile) @@ -1669,24 +1894,34 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles( if (vsfile) vsfile->drop(); + if (gsfile) + gsfile->drop(); + return result; } + //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. s32 CNullDriver::addHighLevelShaderMaterialFromFiles( - io::IReadFile* vertexShaderProgram, - const c8* vertexShaderEntryPointName, - E_VERTEX_SHADER_TYPE vsCompileTarget, - io::IReadFile* pixelShaderProgram, - const c8* pixelShaderEntryPointName, - E_PIXEL_SHADER_TYPE psCompileTarget, - IShaderConstantSetCallBack* callback, - E_MATERIAL_TYPE baseMaterial, - s32 userData) + io::IReadFile* vertexShaderProgram, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + io::IReadFile* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + io::IReadFile* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, + s32 userData) { c8* vs = 0; c8* ps = 0; + c8* gs = 0; if (vertexShaderProgram) { @@ -1713,17 +1948,36 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles( } } + if (geometryShaderProgram) + { + const long size = geometryShaderProgram->getSize(); + if (size) + { + // if both handles are the same we must reset the file + if ((geometryShaderProgram==vertexShaderProgram) || + (geometryShaderProgram==pixelShaderProgram)) + geometryShaderProgram->seek(0); + gs = new c8[size+1]; + geometryShaderProgram->read(gs, size); + gs[size] = 0; + } + } + s32 result = this->addHighLevelShaderMaterial( vs, vertexShaderEntryPointName, vsCompileTarget, ps, pixelShaderEntryPointName, psCompileTarget, + gs, geometryShaderEntryPointName, gsCompileTarget, + inType, outType, verticesOut, callback, baseMaterial, userData); delete [] vs; delete [] ps; + delete [] gs; return result; } + //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 CNullDriver::addShaderMaterial(const c8* vertexShaderProgram, @@ -1736,6 +1990,7 @@ s32 CNullDriver::addShaderMaterial(const c8* vertexShaderProgram, return -1; } + //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the //! programs from files. s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram, @@ -1778,11 +2033,10 @@ s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram, } - //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the //! programs from files. -s32 CNullDriver::addShaderMaterialFromFiles(const c8* vertexShaderProgramFileName, - const c8* pixelShaderProgramFileName, +s32 CNullDriver::addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, + const io::path& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) @@ -1790,7 +2044,7 @@ s32 CNullDriver::addShaderMaterialFromFiles(const c8* vertexShaderProgramFileNam io::IReadFile* vsfile = 0; io::IReadFile* psfile = 0; - if (vertexShaderProgramFileName) + if (vertexShaderProgramFileName.size()) { vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName); if (!vsfile) @@ -1801,7 +2055,7 @@ s32 CNullDriver::addShaderMaterialFromFiles(const c8* vertexShaderProgramFileNam } } - if (pixelShaderProgramFileName) + if (pixelShaderProgramFileName.size()) { psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName); if (!psfile) @@ -1828,8 +2082,8 @@ s32 CNullDriver::addShaderMaterialFromFiles(const c8* vertexShaderProgramFileNam //! Creates a render target texture. -ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d& size, - const c8* name) +ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d& size, + const io::path&name, const ECOLOR_FORMAT format) { return 0; } @@ -1865,7 +2119,7 @@ void CNullDriver::printVersion() //! creates a video driver -IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize) +IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize) { CNullDriver* nullDriver = new CNullDriver(io, screenSize); @@ -1891,17 +2145,15 @@ bool CNullDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enab return false; } + //! Enable/disable a clipping plane. -//! There are at least 6 clipping planes available for the user to set at will. -//! \param index: The plane index. Must be between 0 and MaxUserClipPlanes. -//! \param enable: If true, enable the clipping plane else disable it. void CNullDriver::enableClipPlane(u32 index, bool enable) { // not necessary } -ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d& size, +ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d& size, const c8* name) { os::Printer::log("createRenderTargetTexture is deprecated, use addRenderTargetTexture instead"); @@ -1910,7 +2162,38 @@ ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d& s return tex; } -} // end namespace -} // end namespace + +void CNullDriver::setMinHardwareBufferVertexCount(u32 count) +{ + MinVertexCountForVBO = count; +} +SOverrideMaterial& CNullDriver::getOverrideMaterial() +{ + return OverrideMaterial; +} + + +//! Get the 2d override material for altering its values +SMaterial& CNullDriver::getMaterial2D() +{ + return OverrideMaterial2D; +} + + +//! Enable the 2d override material +void CNullDriver::enableMaterial2D(bool enable) +{ + OverrideMaterial2DEnabled=enable; +} + + +core::dimension2du CNullDriver::getMaxTextureSize() const +{ + return core::dimension2du(0x10000,0x10000); // maybe large enough +} + + +} // end namespace +} // end namespace diff --git a/src/dep/src/irrlicht/CNullDriver.h b/src/dep/src/irrlicht/CNullDriver.h index 8a40f8b..58fcdd2 100644 --- a/src/dep/src/irrlicht/CNullDriver.h +++ b/src/dep/src/irrlicht/CNullDriver.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -32,21 +32,19 @@ namespace video class IImageLoader; class IImageWriter; - - class CNullDriver : public IVideoDriver, public IGPUProgrammingServices { public: //! constructor - CNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize); + CNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize); //! destructor virtual ~CNullDriver(); virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); virtual bool endScene(); @@ -60,15 +58,23 @@ namespace video //! sets transformation virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat); + //! Retrieve the number of image loaders + virtual u32 getImageLoaderCount() const; + + //! Retrieve the given image loader + virtual IImageLoader* getImageLoader(u32 n); + + //! Retrieve the number of image writers + virtual u32 getImageWriterCount() const; + + //! Retrieve the given image writer + virtual IImageWriter* getImageWriter(u32 n); + //! sets a material virtual void setMaterial(const SMaterial& material); //! loads a Texture - virtual ITexture* getTexture(const c8* filename); - - //! loads a Texture - virtual ITexture* getTexture(const core::stringc& filename) - { return getTexture(filename.c_str()); } + virtual ITexture* getTexture(const io::path& filename); //! loads a Texture virtual ITexture* getTexture(io::IReadFile* file); @@ -80,15 +86,23 @@ namespace video virtual u32 getTextureCount() const; //! Renames a texture - virtual void renameTexture(ITexture* texture, const c8* newName); + virtual void renameTexture(ITexture* texture, const io::path& newName); //! creates a Texture - virtual ITexture* addTexture(const core::dimension2d& size, const c8* name, ECOLOR_FORMAT format = ECF_A8R8G8B8); + virtual ITexture* addTexture(const core::dimension2d& size, const io::path& name, ECOLOR_FORMAT format = ECF_A8R8G8B8); //! sets a render target virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color); + //! set or reset special render targets + virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, + bool clearZBuffer, SColor color); + + //! Sets multiple render targets + virtual bool setRenderTarget(const core::array& texture, + bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=SColor(0,0,0,0)); + //! sets a viewport virtual void setViewPort(const core::rect& area); @@ -98,29 +112,12 @@ namespace video //! draws a vertex primitive list virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, - E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); + E_VERTEX_TYPE vType=EVT_STANDARD, scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, E_INDEX_TYPE iType=EIT_16BIT); - //! draws an indexed triangle list - virtual void drawIndexedTriangleList(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount); - - //! draws an indexed triangle list - virtual void drawIndexedTriangleList(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount); - - //! Draws an indexed triangle list. - virtual void drawIndexedTriangleList(const S3DVertexTangents* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount); - - //! Draws an indexed triangle fan. - virtual void drawIndexedTriangleFan(const S3DVertex* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount); - - //! Draws an indexed triangle list. - virtual void drawIndexedTriangleFan(const S3DVertex2TCoords* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount); - - //! Draws an indexed triangle fan. - inline void drawIndexedTriangleFan(const S3DVertexTangents* vertices, - u32 vertexCount, const u16* indexList, u32 triangleCount); + //! draws a vertex primitive list in 2d + virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType=EVT_STANDARD, scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, E_INDEX_TYPE iType=EIT_16BIT); //! Draws a 3d line. virtual void draw3DLine(const core::vector3df& start, @@ -154,7 +151,7 @@ namespace video Note that the alpha component is used: If alpha is other than 255, the image will be transparent. \param useAlphaChannelOfTexture: If true, the alpha channel of the texture is used to draw the image. */ - virtual void draw2DImage(const video::ITexture* texture, + virtual void draw2DImageBatch(const video::ITexture* texture, const core::position2d& pos, const core::array >& sourceRects, const core::array& indices, @@ -163,7 +160,30 @@ namespace video SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); - //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. + //! Draws a set of 2d images, using a color and the alpha channel of the texture. + /** All drawings are clipped against clipRect (if != 0). + The subtextures are defined by the array of sourceRects and are + positioned using the array of positions. + \param texture Texture to be drawn. + \param pos Array of upper left 2d destinations where the images + will be drawn. + \param sourceRects Source rectangles of the image. + \param clipRect Pointer to rectangle on the screen where the + images are clipped to. + If this pointer is 0 then the image is not clipped. + \param color Color with which the image is drawn. + Note that the alpha component is used. If alpha is other than + 255, the image will be transparent. + \param useAlphaChannelOfTexture: If true, the alpha channel of + the texture is used to draw the image. */ + virtual void draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect=0, + SColor color=SColor(255,255,255,255), + bool useAlphaChannelOfTexture=false); + + //! Draws a 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); @@ -173,38 +193,46 @@ namespace video const core::rect& sourceRect, const core::rect* clipRect = 0, const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false); - //! draw an 2d rectangle + //! Draws a 2d rectangle virtual void draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip = 0); - //!Draws an 2d rectangle with a gradient. + //! Draws a 2d rectangle with a gradient. virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip = 0); + //! Draws the outline of a 2d rectangle + virtual void draw2DRectangleOutline(const core::recti& pos, SColor color=SColor(255,255,255,255)); + //! Draws a 2d line. virtual void draw2DLine(const core::position2d& start, const core::position2d& end, SColor color=SColor(255,255,255,255)); //! Draws a pixel - virtual void drawPixel(u32 x, u32 y, const SColor & color); + virtual void drawPixel(u32 x, u32 y, const SColor & color); //! Draws a non filled concyclic reqular 2d polyon. virtual void draw2DPolygon(core::position2d center, f32 radius, video::SColor Color, s32 vertexCount); - virtual void setFog(SColor color=SColor(0,255,255,255), bool linearFog=true, - f32 start=50.0f, f32 end=100.0f, - f32 density=0.01f, bool pixelFog=false, bool rangeFog=false); + virtual void setFog(SColor color=SColor(0,255,255,255), + E_FOG_TYPE fogType=EFT_FOG_LINEAR, + f32 start=50.0f, f32 end=100.0f, f32 density=0.01f, + bool pixelFog=false, bool rangeFog=false); + + virtual void getFog(SColor& color, E_FOG_TYPE& fogType, + f32& start, f32& end, f32& density, + bool& pixelFog, bool& rangeFog); //! get color format of the current color buffer virtual ECOLOR_FORMAT getColorFormat() const; //! get screen size - virtual const core::dimension2d& getScreenSize() const; + virtual const core::dimension2d& getScreenSize() const; //! get render target size - virtual const core::dimension2d& getCurrentRenderTargetSize() const; + virtual const core::dimension2d& getCurrentRenderTargetSize() const; // get current frames per second value virtual s32 getFPS() const; @@ -216,8 +244,15 @@ namespace video //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); - //! adds a dynamic light - virtual void addDynamicLight(const SLight& light); + //! adds a dynamic light, returning an index to the light + //! \param light: the light data to use to create the light + //! \return An index to the light, or -1 if an error occurs + virtual s32 addDynamicLight(const SLight& light); + + //! Turns a dynamic light on or off + //! \param lightIndex: the index returned by addDynamicLight + //! \param turnOn: true to turn the light on, false to turn it off + virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; @@ -270,14 +305,14 @@ namespace video virtual void removeAllTextures(); //! Creates a render target texture. - virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Creates an 1bit alpha channel of the texture based of an color key. - virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color) const; + virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color, bool zeroTexels) const; //! Creates an 1bit alpha channel of the texture based of an color key position. - virtual void makeColorKeyTexture(video::ITexture* texture, core::position2d colorKeyPixelPos) const; + virtual void makeColorKeyTexture(video::ITexture* texture, core::position2d colorKeyPixelPos, bool zeroTexels) const; //! Creates a normal map from a height map texture. //! \param amplitude: Constant value by which the height information is multiplied. @@ -295,7 +330,7 @@ namespace video virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const; //! Creates a software image from a file. - virtual IImage* createImageFromFile(const char* filename); + virtual IImage* createImageFromFile(const io::path& filename); //! Creates a software image from a file. virtual IImage* createImageFromFile(io::IReadFile* file); @@ -305,11 +340,11 @@ namespace video directly and own it from now on, which means it will also try to delete [] the data when the image will be destructed. If false, the memory will by copied. */ virtual IImage* createImageFromData(ECOLOR_FORMAT format, - const core::dimension2d& size, void *data, + const core::dimension2d& size, void *data, bool ownForeignMemory=true, bool deleteForeignMemory = true); //! Creates an empty software image. - virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size); + virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size); //! Creates a software image from another image. @@ -318,7 +353,12 @@ namespace video //! Creates a software image from part of another image. virtual IImage* createImage(IImage* imageToCopy, const core::position2d& pos, - const core::dimension2d& size); + const core::dimension2d& size); + + //! Creates a software image from part of a texture. + virtual IImage* createImage(ITexture* texture, + const core::position2d& pos, + const core::dimension2d& size); //! Draws a mesh buffer virtual void drawMeshBuffer(const scene::IMeshBuffer* mb); @@ -326,7 +366,10 @@ namespace video protected: struct SHWBufferLink { - SHWBufferLink(const scene::IMeshBuffer *_MeshBuffer):MeshBuffer(_MeshBuffer),ChangedID_Vertex(0),ChangedID_Index(0),LastUsed(0),Mapped_Vertex(scene::EHM_NEVER),Mapped_Index(scene::EHM_NEVER) + SHWBufferLink(const scene::IMeshBuffer *_MeshBuffer) + :MeshBuffer(_MeshBuffer), + ChangedID_Vertex(0),ChangedID_Index(0),LastUsed(0), + Mapped_Vertex(scene::EHM_NEVER),Mapped_Index(scene::EHM_NEVER) { if (MeshBuffer) MeshBuffer->grab(); @@ -338,7 +381,6 @@ namespace video MeshBuffer->drop(); } - scene::E_BUFFER_TYPE Contains; const scene::IMeshBuffer *MeshBuffer; u32 ChangedID_Vertex; u32 ChangedID_Index; @@ -377,7 +419,7 @@ namespace video public: //! Only used by the engine internally. /** Used to notify the driver that the window was resized. */ - virtual void OnResize(const core::dimension2d& size); + virtual void OnResize(const core::dimension2d& size); //! Adds a new material renderer to the video device. virtual s32 addMaterialRenderer(IMaterialRenderer* renderer, @@ -413,8 +455,8 @@ namespace video //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the //! programs from files. - virtual s32 addShaderMaterialFromFiles(const c8* vertexShaderProgramFileName = 0, - const c8* pixelShaderProgramFileName = 0, + virtual s32 addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, + const io::path& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); @@ -437,6 +479,12 @@ namespace video const c8* pixelShaderProgram = 0, const c8* pixelShaderEntryPointName = 0, E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const c8* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); @@ -444,12 +492,18 @@ namespace video //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. virtual s32 addHighLevelShaderMaterialFromFiles( - const c8* vertexShaderProgram, + const io::path& vertexShaderProgramFile, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, - const c8* pixelShaderProgram = 0, + const io::path& pixelShaderProgramFile = "", const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const io::path& geometryShaderProgramFileName="", + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); @@ -463,6 +517,12 @@ namespace video io::IReadFile* pixelShaderProgram = 0, const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + io::IReadFile* geometryShaderProgram= 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); @@ -477,7 +537,10 @@ namespace video virtual IImage* createScreenShot(); //! Writes the provided image to disk file - virtual bool writeImageToFile(IImage* image, const char* filename, u32 param = 0); + virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0); + + //! Writes the provided image to a file. + virtual bool writeImageToFile(IImage* image, io::IWriteFile * file, u32 param = 0); //! Sets the name of a material renderer. virtual void setMaterialRendererName(s32 idx, const char* name); @@ -489,7 +552,7 @@ namespace video virtual void fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attributes); //! looks if the image is already loaded - virtual video::ITexture* findTexture(const c8* filename); + virtual video::ITexture* findTexture(const io::path& filename); //! Set/unset a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. @@ -507,12 +570,31 @@ namespace video //! Returns the graphics card vendor name. virtual core::stringc getVendorInfo() {return "Not available on this driver.";} + //! Set the minimum number of vertices for which a hw buffer will be created + /** \param count Number of vertices to set as minimum. */ + virtual void setMinHardwareBufferVertexCount(u32 count); + + //! Get the global Material, which might override local materials. + /** Depending on the enable flags, values from this Material + are used to override those of local materials of some + meshbuffer being rendered. */ + virtual SOverrideMaterial& getOverrideMaterial(); + + //! Get the 2d override material for altering its values + virtual SMaterial& getMaterial2D(); + + //! Enable the 2d override material + virtual void enableMaterial2D(bool enable=true); + //! Only used by the engine internally. virtual void setAllowZWriteOnTransparent(bool flag) { AllowZWriteOnTransparent=flag; } + //! Returns the maximum texture size supported. + virtual core::dimension2du getMaxTextureSize() const; + //! deprecated method - virtual ITexture* createRenderTargetTexture(const core::dimension2d& size, + virtual ITexture* createRenderTargetTexture(const core::dimension2d& size, const c8* name=0); virtual bool checkDriverReset() {return false;} @@ -522,17 +604,17 @@ namespace video void deleteAllTextures(); //! opens the file and loads it into the surface - video::ITexture* loadTextureFromFile(io::IReadFile* file, const c8* hashName = 0); + video::ITexture* loadTextureFromFile(io::IReadFile* file, const io::path& hashName = ""); //! adds a surface, not loaded or created by the Irrlicht Engine void addTexture(video::ITexture* surface); //! Creates a texture from a loaded IImage. - virtual ITexture* addTexture(const c8* name, IImage* image); + virtual ITexture* addTexture(const io::path& name, IImage* image, void* mipmapData=0); //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); //! checks triangle count and print warning if wrong bool checkPrimitiveCount(u32 prmcnt) const; @@ -581,21 +663,19 @@ namespace video struct SDummyTexture : public ITexture { - SDummyTexture(const char* name) : ITexture(name), size(0,0) {}; + SDummyTexture(const io::path& name) : ITexture(name), size(0,0) {}; - virtual void* lock(bool readOnly = false) { return 0; }; + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0) { return 0; }; virtual void unlock(){} - virtual const core::dimension2d& getOriginalSize() const { return size; } - virtual const core::dimension2d& getSize() const { return size; } + virtual const core::dimension2d& getOriginalSize() const { return size; } + virtual const core::dimension2d& getSize() const { return size; } virtual E_DRIVER_TYPE getDriverType() const { return video::EDT_NULL; } virtual ECOLOR_FORMAT getColorFormat() const { return video::ECF_A1R5G5B5; }; virtual u32 getPitch() const { return 0; } - virtual void regenerateMipMapLevels() {}; - core::dimension2d size; + virtual void regenerateMipMapLevels(void* mipmapData=0) {}; + core::dimension2d size; }; - - core::array Textures; core::array SurfaceLoader; core::array SurfaceWriter; @@ -611,12 +691,13 @@ namespace video scene::IMeshManipulator* MeshManipulator; core::rect ViewPort; - core::dimension2d ScreenSize; + core::dimension2d ScreenSize; core::matrix4 TransformationMatrix; CFPSCounter FPSCounter; u32 PrimitivesDrawn; + u32 MinVertexCountForVBO; u32 TextureCreationFlags; @@ -624,14 +705,18 @@ namespace video f32 FogEnd; f32 FogDensity; SColor FogColor; - bool LinearFog; + SExposedVideoData ExposedData; + + SOverrideMaterial OverrideMaterial; + SMaterial OverrideMaterial2D; + SMaterial InitMaterial2D; + bool OverrideMaterial2DEnabled; + + E_FOG_TYPE FogType; bool PixelFog; bool RangeFog; - bool AllowZWriteOnTransparent; - SExposedVideoData ExposedData; - bool FeatureEnabled[video::EVDF_COUNT]; }; @@ -640,6 +725,3 @@ namespace video #endif - - - diff --git a/src/dep/src/irrlicht/COBJMeshFileLoader.cpp b/src/dep/src/irrlicht/COBJMeshFileLoader.cpp index 14bee80..da9f48e 100644 --- a/src/dep/src/irrlicht/COBJMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/COBJMeshFileLoader.cpp @@ -1,8 +1,8 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "IrrCompileConfig.h" +#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ #include "COBJMeshFileLoader.h" @@ -32,6 +32,10 @@ static const u32 WORD_BUFFER_LENGTH = 512; COBJMeshFileLoader::COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs) { + #ifdef _DEBUG + setDebugName("COBJMeshFileLoader"); + #endif + if (FileSystem) FileSystem->grab(); } @@ -47,9 +51,9 @@ COBJMeshFileLoader::~COBJMeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool COBJMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool COBJMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".obj")!=0; + return core::hasFileExtension ( filename, "obj" ); } @@ -73,8 +77,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) Materials.push_back(currMtl); u32 smoothingGroup=0; - const core::stringc fullName = file->getFileName(); - const core::stringc relPath = FileSystem->getFileDir(fullName)+"/"; + const io::path fullName = file->getFileName(); + const io::path relPath = FileSystem->getFileDir(fullName)+"/"; c8* buf = new c8[filesize]; memset(buf, 0, filesize); @@ -83,20 +87,25 @@ 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); + bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES); while(bufPtr != bufEnd) { switch(bufPtr[0]) { case 'm': // mtllib (material) { - c8 name[WORD_BUFFER_LENGTH]; - bufPtr = goAndCopyNextWord(name, bufPtr, WORD_BUFFER_LENGTH, bufEnd); + if (useMaterials) + { + c8 name[WORD_BUFFER_LENGTH]; + bufPtr = goAndCopyNextWord(name, bufPtr, WORD_BUFFER_LENGTH, bufEnd); #ifdef _IRR_DEBUG_OBJ_LOADER_ - os::Printer::log("Reading material file",name); + os::Printer::log("Reading material file",name); #endif - readMTL(name, relPath); + readMTL(name, relPath); + } } break; @@ -143,6 +152,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) else grpName = "default"; } + mtlChanged=true; } break; @@ -168,11 +178,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; @@ -181,6 +188,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; @@ -231,7 +247,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) vertLocation = currMtl->Meshbuffer->Vertices.size() -1; currMtl->VertMap.insert(v, vertLocation); } - + faceCorners.push_back(vertLocation); // go to next vertex @@ -251,7 +267,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) } break; - case '#': // comment + case '#': // comment default: break; } // end switch(bufPtr[0]) @@ -303,15 +319,16 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) } -const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const core::stringc& relPath) +const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const io::path& relPath) { u8 type=0; // map_Kd - diffuse color texture map // map_Ks - specular color texture map // map_Ka - ambient color texture map + // map_Ns - shininess texture map if ((!strncmp(bufPtr,"map_bump",8)) || (!strncmp(bufPtr,"bump",4))) type=1; // normal map - else if (!strncmp(bufPtr,"map_d",5)) - type=2; // opactity map + else if ((!strncmp(bufPtr,"map_d",5)) || (!strncmp(bufPtr,"map_opacity",11))) + type=2; // opacity map else if (!strncmp(bufPtr,"map_refl",8)) type=3; // reflection map // extract new material's name @@ -402,22 +419,41 @@ const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const buf if (clamp) currMaterial->Meshbuffer->Material.setFlag(video::EMF_TEXTURE_WRAP, video::ETC_CLAMP); - core::stringc texname(textureNameBuf); + io::path texname(textureNameBuf); texname.replace('\\', '/'); video::ITexture * texture = 0; - if (FileSystem->existFile(texname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(texname.c_str()); - else - // try to read in the relative path, the .obj is loaded from - texture = SceneManager->getVideoDriver()->getTexture( (relPath + texname).c_str() ); + bool newTexture=false; + if (texname.size()) + { + io::path texnameWithUserPath( SceneManager->getParameters()->getAttributeAsString(OBJ_TEXTURE_PATH) ); + if ( texnameWithUserPath.size() ) + { + texnameWithUserPath += '/'; + texnameWithUserPath += texname; + } + if (FileSystem->existFile(texnameWithUserPath)) + texture = SceneManager->getVideoDriver()->getTexture(texnameWithUserPath); + else if (FileSystem->existFile(texname)) + { + newTexture = SceneManager->getVideoDriver()->findTexture(texname) == 0; + texture = SceneManager->getVideoDriver()->getTexture(texname); + } + else + { + newTexture = SceneManager->getVideoDriver()->findTexture(relPath + texname) == 0; + // try to read in the relative path, the .obj is loaded from + texture = SceneManager->getVideoDriver()->getTexture( relPath + texname ); + } + } if ( texture ) { if (type==0) currMaterial->Meshbuffer->Material.setTexture(0, texture); else if (type==1) { - SceneManager->getVideoDriver()->makeNormalMapTexture(texture, bumpiness); + if (newTexture) + SceneManager->getVideoDriver()->makeNormalMapTexture(texture, bumpiness); currMaterial->Meshbuffer->Material.setTexture(1, texture); currMaterial->Meshbuffer->Material.MaterialType=video::EMT_PARALLAX_MAP_SOLID; currMaterial->Meshbuffer->Material.MaterialTypeParam=0.035f; @@ -442,20 +478,32 @@ const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const buf } -void COBJMeshFileLoader::readMTL(const c8* fileName, const core::stringc& relPath) +void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath) { + const io::path realFile(fileName); io::IReadFile * mtlReader; - if (FileSystem->existFile(fileName)) - mtlReader = FileSystem->createAndOpenFile(fileName); + + if (FileSystem->existFile(realFile)) + mtlReader = FileSystem->createAndOpenFile(realFile); + else if (FileSystem->existFile(relPath + realFile)) + mtlReader = FileSystem->createAndOpenFile(relPath + realFile); + else if (FileSystem->existFile(FileSystem->getFileBasename(realFile))) + mtlReader = FileSystem->createAndOpenFile(FileSystem->getFileBasename(realFile)); else - // try to read in the relative path, the .obj is loaded from - mtlReader = FileSystem->createAndOpenFile((relPath + fileName).c_str()); + mtlReader = FileSystem->createAndOpenFile(relPath + FileSystem->getFileBasename(realFile)); if (!mtlReader) // fail to open and read file + { + os::Printer::log("Could not open material file", realFile, ELL_WARNING); return; + } const long filesize = mtlReader->getSize(); if (!filesize) + { + os::Printer::log("Skipping empty material file", realFile, ELL_WARNING); + mtlReader->drop(); return; + } c8* buf = new c8[filesize]; mtlReader->read((void*)buf, filesize); @@ -672,6 +720,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 ) @@ -679,16 +729,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; } @@ -756,7 +813,7 @@ u32 COBJMeshFileLoader::copyWord(c8* outBuf, const c8* const inBuf, u32 outBufLe for (u32 j=0; jgetFileBasename(SceneManager->getMeshCache()->getMeshFilename(mesh), false)+".mtl"); + const core::stringc name(FileSystem->getFileBasename(SceneManager->getMeshCache()->getMeshName(mesh), false)+".mtl"); file->write("# exported by Irrlicht\n",23); file->write("mtllib ",7); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers - + core::array mat; u32 allVertexCount=1; // count vertices over the whole file @@ -164,7 +164,7 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla if (mat.size() == 0) return true; - file = FileSystem->createAndWriteFile((name).c_str()); + file = FileSystem->createAndWriteFile( name ); if (file) { os::Printer::log("Writing material", file->getFileName()); @@ -186,11 +186,13 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla getColorAsStringLine(mat[i]->EmissiveColor, "Ke", num); file->write(num.c_str(),num.size()); num = core::stringc(mat[i]->Shininess/0.128f); + file->write("Ns ", 3); file->write(num.c_str(),num.size()); + file->write("\n", 1); if (mat[i]->getTexture(0)) { file->write("map_Kd ", 7); - file->write(mat[i]->getTexture(0)->getName().c_str(), mat[i]->getTexture(0)->getName().size()); + file->write(mat[i]->getTexture(0)->getName().getPath().c_str(), mat[i]->getTexture(0)->getName().getPath().size()); file->write("\n",1); } file->write("\n",1); diff --git a/src/dep/src/irrlicht/COBJMeshWriter.h b/src/dep/src/irrlicht/COBJMeshWriter.h index cc04fa5..1e31bb4 100644 --- a/src/dep/src/irrlicht/COBJMeshWriter.h +++ b/src/dep/src/irrlicht/COBJMeshWriter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2008 Christian Stehno +// Copyright (C) 2008-2010 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/COCTLoader.cpp b/src/dep/src/irrlicht/COCTLoader.cpp index 0fc9b61..804e304 100644 --- a/src/dep/src/irrlicht/COCTLoader.cpp +++ b/src/dep/src/irrlicht/COCTLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // @@ -209,7 +209,7 @@ IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file) tex.push_back(SceneManager->getVideoDriver()->getTexture(path)); else // try to read in the relative path of the OCT file - tex.push_back(SceneManager->getVideoDriver()->getTexture( (relpath + path).c_str() )); + tex.push_back(SceneManager->getVideoDriver()->getTexture( (relpath + path) )); } // prepare lightmaps @@ -219,7 +219,7 @@ IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file) const u32 lightmapWidth = 128; const u32 lightmapHeight = 128; - const core::dimension2d lmapsize(lightmapWidth, lightmapHeight); + const core::dimension2d lmapsize(lightmapWidth, lightmapHeight); bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); @@ -323,9 +323,9 @@ IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file) //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool COCTLoader::isALoadableFileExtension(const c8* filename) const +bool COCTLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".oct")!=0; + return core::hasFileExtension ( filename, "oct" ); } diff --git a/src/dep/src/irrlicht/COCTLoader.h b/src/dep/src/irrlicht/COCTLoader.h index ba13074..3c54cd8 100644 --- a/src/dep/src/irrlicht/COCTLoader.h +++ b/src/dep/src/irrlicht/COCTLoader.h @@ -1,8 +1,8 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // -// Because I (Nikolaus Gebhardt) did some changes to Murphy McCauley's loader, +// Because I (Nikolaus Gebhardt) did some changes to Murphy McCauley's loader, // I'm writing this down here: // - Replaced all dependencies to STL and stdio with irr:: methods/constructs // - Disabled logging define @@ -70,7 +70,7 @@ namespace scene //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/src/dep/src/irrlicht/COSOperator.cpp b/src/dep/src/irrlicht/COSOperator.cpp index 6ad2139..a254b21 100644 --- a/src/dep/src/irrlicht/COSOperator.cpp +++ b/src/dep/src/irrlicht/COSOperator.cpp @@ -1,27 +1,39 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "COSOperator.h" -#include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_API_ +#ifndef _IRR_XBOX_PLATFORM_ #include +#endif #else #include #include -#ifdef _IRR_USE_OSX_DEVICE_ -#include "MacOSX/OSXClipboard.h" -#endif -#ifdef _IRR_OSX_PLATFORM_ +#ifndef _IRR_SOLARIS_PLATFORM_ #include #include #endif #endif +#if defined(_IRR_COMPILE_WITH_X11_DEVICE_) +#include "CIrrDeviceLinux.h" +#endif +#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ +#include "MacOSX/OSXClipboard.h" +#endif + namespace irr { +#if defined(_IRR_COMPILE_WITH_X11_DEVICE_) +// constructor linux +COSOperator::COSOperator(const c8* osversion, CIrrDeviceLinux* device) +: IrrDeviceLinux(device) +{ +} +#endif // constructor COSOperator::COSOperator(const c8* osVersion) : OperatingSystem(osVersion) @@ -46,7 +58,8 @@ void COSOperator::copyToClipboard(const c8* text) const return; // Windows version -#if defined(_IRR_WINDOWS_API_) +#if defined(_IRR_XBOX_PLATFORM_) +#elif defined(_IRR_WINDOWS_API_) if (!OpenClipboard(NULL) || text == 0) return; @@ -65,24 +78,29 @@ void COSOperator::copyToClipboard(const c8* text) const CloseClipboard(); // MacOSX version -#elif defined(_IRR_USE_OSX_DEVICE_) +#elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_) OSXCopyToClipboard(text); + +#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_) + if ( IrrDeviceLinux ) + IrrDeviceLinux->copyToClipboard(text); #else -// todo: Linux version #endif } //! gets text from the clipboard //! \return Returns 0 if no string is in there. -c8* COSOperator::getTextFromClipboard() const +const c8* COSOperator::getTextFromClipboard() const { -#if defined(_IRR_WINDOWS_API_) +#if defined(_IRR_XBOX_PLATFORM_) + return 0; +#elif defined(_IRR_WINDOWS_API_) if (!OpenClipboard(NULL)) return 0; - + char * buffer = 0; HANDLE hData = GetClipboardData( CF_TEXT ); @@ -91,11 +109,15 @@ c8* COSOperator::getTextFromClipboard() const CloseClipboard(); return buffer; -#elif defined(_IRR_USE_OSX_DEVICE_) +#elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_) return (OSXCopyFromClipboard()); -#else -// todo: Linux version +#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_) + if ( IrrDeviceLinux ) + return IrrDeviceLinux->getTextFromClipboard(); + return 0; + +#else return 0; #endif @@ -104,12 +126,12 @@ c8* COSOperator::getTextFromClipboard() const bool COSOperator::getProcessorSpeedMHz(u32* MHz) const { -#if defined(_IRR_WINDOWS_API_) && !defined(_WIN32_WCE ) +#if defined(_IRR_WINDOWS_API_) && !defined(_WIN32_WCE ) && !defined (_IRR_XBOX_PLATFORM_) LONG Error; - + HKEY Key; Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", + __TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0, KEY_READ, &Key); if(Error != ERROR_SUCCESS) @@ -117,7 +139,7 @@ bool COSOperator::getProcessorSpeedMHz(u32* MHz) const DWORD Speed = 0; DWORD Size = sizeof(Speed); - Error = RegQueryValueEx(Key, "~MHz", NULL, NULL, (LPBYTE)&Speed, &Size); + Error = RegQueryValueEx(Key, __TEXT("~MHz"), NULL, NULL, (LPBYTE)&Speed, &Size); RegCloseKey(Key); @@ -146,7 +168,7 @@ bool COSOperator::getProcessorSpeedMHz(u32* MHz) const bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const { -#if defined(_IRR_WINDOWS_API_) +#if defined(_IRR_WINDOWS_API_) && !defined (_IRR_XBOX_PLATFORM_) MEMORYSTATUS MemoryStatus; MemoryStatus.dwLength = sizeof(MEMORYSTATUS); @@ -157,16 +179,16 @@ bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const *Total = (u32)(MemoryStatus.dwTotalPhys>>10); if (Avail) *Avail = (u32)(MemoryStatus.dwAvailPhys>>10); - + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return true; -#elif defined(_IRR_POSIX_API_) +#elif defined(_IRR_POSIX_API_) && !defined(__FreeBSD__) #if defined(_SC_PHYS_PAGES) && defined(_SC_AVPHYS_PAGES) long ps = sysconf(_SC_PAGESIZE); long pp = sysconf(_SC_PHYS_PAGES); long ap = sysconf(_SC_AVPHYS_PAGES); - + if ((ps==-1)||(pp==-1)||(ap==-1)) return false; @@ -180,7 +202,7 @@ bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const return false; #endif #else - // TODO: implement for OSX + // TODO: implement for OSX return false; #endif } diff --git a/src/dep/src/irrlicht/COSOperator.h b/src/dep/src/irrlicht/COSOperator.h index a9f794f..a65bd69 100644 --- a/src/dep/src/irrlicht/COSOperator.h +++ b/src/dep/src/irrlicht/COSOperator.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,17 +7,23 @@ #include "IOSOperator.h" #include "irrString.h" +#include "IrrCompileConfig.h" namespace irr { +class CIrrDeviceLinux; + //! The Operating system operator provides operation system specific methods and informations. class COSOperator : public IOSOperator { public: // constructor - COSOperator(const c8* osversion); +#if defined(_IRR_COMPILE_WITH_X11_DEVICE_) + COSOperator(const c8* osversion, CIrrDeviceLinux* device); +#endif + COSOperator(const c8* osversion); //! returns the current operation system version as string. virtual const wchar_t* getOperationSystemVersion() const; @@ -27,7 +33,7 @@ public: //! gets text from the clipboard //! \return Returns 0 if no string is in there. - virtual c8* getTextFromClipboard() const; + virtual const c8* getTextFromClipboard() const; //! gets the processor speed in megahertz //! \param Mhz: @@ -43,6 +49,11 @@ public: private: core::stringw OperatingSystem; + +#if defined(_IRR_COMPILE_WITH_X11_DEVICE_) + CIrrDeviceLinux * IrrDeviceLinux; +#endif + }; } // end namespace diff --git a/src/dep/src/irrlicht/COctTreeTriangleSelector.cpp b/src/dep/src/irrlicht/COctTreeTriangleSelector.cpp deleted file mode 100644 index 3f95563..0000000 --- a/src/dep/src/irrlicht/COctTreeTriangleSelector.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "COctTreeTriangleSelector.h" -#include "ISceneNode.h" - -#include "os.h" - -namespace irr -{ -namespace scene -{ - -//! constructor -COctTreeTriangleSelector::COctTreeTriangleSelector(const IMesh* mesh, - const ISceneNode* node, s32 minimalPolysPerNode) - : CTriangleSelector(mesh, node), Root(0), NodeCount(0), - MinimalPolysPerNode(minimalPolysPerNode) -{ - #ifdef _DEBUG - setDebugName("COctTreeTriangleSelector"); - #endif - - if (!Triangles.empty()) - { - u32 start = os::Timer::getRealTime(); - - // create the triangle octtree - Root = new SOctTreeNode(); - Root->Triangles = Triangles; - constructOctTree(Root); - - u32 end = os::Timer::getRealTime(); - c8 tmp[255]; - sprintf(tmp, "Needed %ums to create OctTreeTriangleSelector.(%d nodes, %u polys)", - end - start, NodeCount, Triangles.size()); - os::Printer::log(tmp, ELL_INFORMATION); - } -} - - -//! destructor -COctTreeTriangleSelector::~COctTreeTriangleSelector() -{ - delete Root; -} - - -void COctTreeTriangleSelector::constructOctTree(SOctTreeNode* node) -{ - ++NodeCount; - - node->Box.reset(node->Triangles[0].pointA); - - // get bounding box - const u32 cnt = node->Triangles.size(); - for (u32 i=0; iBox.addInternalPoint(node->Triangles[i].pointA); - node->Box.addInternalPoint(node->Triangles[i].pointB); - node->Box.addInternalPoint(node->Triangles[i].pointC); - } - - const core::vector3df& middle = node->Box.getCenter(); - core::vector3df edges[8]; - node->Box.getEdges(edges); - - core::aabbox3d box; - core::array keepTriangles; - - // calculate children - - if (!node->Box.isEmpty() && (s32)node->Triangles.size() > MinimalPolysPerNode) - for (s32 ch=0; ch<8; ++ch) - { - box.reset(middle); - box.addInternalPoint(edges[ch]); - node->Child[ch] = new SOctTreeNode(); - - for (s32 i=0; i<(s32)node->Triangles.size(); ++i) - { - if (node->Triangles[i].isTotalInsideBox(box)) - { - node->Child[ch]->Triangles.push_back(node->Triangles[i]); - //node->Triangles.erase(i); - //--i; - } - else - { - keepTriangles.push_back(node->Triangles[i]); - } - } - memcpy(node->Triangles.pointer(), keepTriangles.pointer(), - sizeof(core::triangle3df)*keepTriangles.size()); - - node->Triangles.set_used(keepTriangles.size()); - keepTriangles.set_used(0); - - if (node->Child[ch]->Triangles.empty()) - { - delete node->Child[ch]; - node->Child[ch] = 0; - } - else - constructOctTree(node->Child[ch]); - } -} - - -//! Gets all triangles which lie within a specific bounding box. -void COctTreeTriangleSelector::getTriangles(core::triangle3df* triangles, - s32 arraySize, s32& outTriangleCount, - const core::aabbox3d& box, - const core::matrix4* transform) const -{ - core::matrix4 mat; - core::aabbox3d invbox = box; - - if (SceneNode) - { - mat = SceneNode->getAbsoluteTransformation(); - mat.makeInverse(); - mat.transformBoxEx(invbox); - } - - mat.makeIdentity(); - - if (transform) - mat = *transform; - - if (SceneNode) - mat *= SceneNode->getAbsoluteTransformation(); - - s32 trianglesWritten = 0; - - if (Root) - getTrianglesFromOctTree(Root, trianglesWritten, - arraySize, invbox, &mat, triangles); - - outTriangleCount = trianglesWritten; -} - - -void COctTreeTriangleSelector::getTrianglesFromOctTree( - SOctTreeNode* node, s32& trianglesWritten, - s32 maximumSize, const core::aabbox3d& box, - const core::matrix4* mat, core::triangle3df* triangles) const -{ - if (!box.intersectsWithBox(node->Box)) - return; - - s32 cnt = node->Triangles.size(); - if (cnt + trianglesWritten > maximumSize) - cnt -= cnt + trianglesWritten - maximumSize; - - s32 i; - - for (i=0; iTriangles[i]; - mat->transformVect(triangles[trianglesWritten].pointA); - mat->transformVect(triangles[trianglesWritten].pointB); - mat->transformVect(triangles[trianglesWritten].pointC); - ++trianglesWritten; - } - - for (i=0; i<8; ++i) - if (node->Child[i]) - getTrianglesFromOctTree(node->Child[i], trianglesWritten, - maximumSize, box, mat, triangles); -} - - -//! Gets all triangles which have or may have contact with a 3d line. -void COctTreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, - s32& outTriangleCount, const core::line3d& line, - const core::matrix4* transform) const -{ - core::aabbox3d box(line.start); - box.addInternalPoint(line.end); - - // TODO: Could be optimized for line a little bit more. - COctTreeTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, - box, transform); -} - - -} // end namespace scene -} // end namespace irr - diff --git a/src/dep/src/irrlicht/COctTreeSceneNode.cpp b/src/dep/src/irrlicht/COctreeSceneNode.cpp similarity index 60% rename from src/dep/src/irrlicht/COctTreeSceneNode.cpp rename to src/dep/src/irrlicht/COctreeSceneNode.cpp index 7200945..10b08b4 100644 --- a/src/dep/src/irrlicht/COctTreeSceneNode.cpp +++ b/src/dep/src/irrlicht/COctreeSceneNode.cpp @@ -1,9 +1,9 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "COctTreeSceneNode.h" -#include "OctTree.h" +#include "COctreeSceneNode.h" +#include "Octree.h" #include "ISceneManager.h" #include "IVideoDriver.h" #include "ICameraSceneNode.h" @@ -20,27 +20,28 @@ namespace scene //! constructor -COctTreeSceneNode::COctTreeSceneNode(ISceneNode* parent, ISceneManager* mgr, +COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, s32 minimalPolysPerNode) -: ISceneNode(parent, mgr, id), StdOctTree(0), LightMapOctTree(0), TangentsOctTree(0), - MinimalPolysPerNode(minimalPolysPerNode) + : IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0), + TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1), + MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), + UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY), + BoxBased(OCTREE_BOX_BASED) { #ifdef _DEBUG - setDebugName("COctTreeSceneNode"); + setDebugName("COctreeSceneNode"); #endif - - vertexType = (video::E_VERTEX_TYPE)-1; } //! destructor -COctTreeSceneNode::~COctTreeSceneNode() +COctreeSceneNode::~COctreeSceneNode() { deleteTree(); } -void COctTreeSceneNode::OnRegisterSceneNode() +void COctreeSceneNode::OnRegisterSceneNode() { if (IsVisible) { @@ -84,11 +85,11 @@ void COctTreeSceneNode::OnRegisterSceneNode() //! renders the node. -void COctTreeSceneNode::render() +void COctreeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); - if (vertexType == -1 || !driver) + if (VertexType == -1 || !driver) return; ICameraSceneNode* camera = SceneManager->getActiveCamera(); @@ -104,22 +105,24 @@ void COctTreeSceneNode::render() SViewFrustum frust = *camera->getViewFrustum(); //transform the frustum to the current absolute transformation - core::matrix4 invTrans(AbsoluteTransformation); - invTrans.makeInverse(); + if ( !AbsoluteTransformation.isIdentity() ) + { + core::matrix4 invTrans(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE); + frust.transform(invTrans); + } - frust.transform(invTrans); - /* - //const core::aabbox3d &box = frust.getBoundingBox(); - */ + const core::aabbox3d &box = frust.getBoundingBox(); - switch(vertexType) + switch (VertexType) { case video::EVT_STANDARD: { - //StdOctTree->calculatePolys(box); - StdOctTree->calculatePolys(frust); + if (BoxBased) + StdOctree->calculatePolys(box); + else + StdOctree->calculatePolys(frust); - const OctTree::SIndexData* d = StdOctTree->getIndexData(); + const Octree::SIndexData* d = StdOctree->getIndexData(); for (u32 i=0; isetMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { - StdOctTree->getBoundingBoxes(box, boxes); + StdOctree->getBoundingBoxes(box, boxes); for (u32 b=0; b!=boxes.size(); ++b) driver->draw3DBox(*boxes[b]); } @@ -162,10 +165,12 @@ void COctTreeSceneNode::render() break; case video::EVT_2TCOORDS: { - //LightMapOctTree->calculatePolys(box); - LightMapOctTree->calculatePolys(frust); + if (BoxBased) + LightMapOctree->calculatePolys(box); + else + LightMapOctree->calculatePolys(frust); - const OctTree::SIndexData* d = LightMapOctTree->getIndexData(); + const Octree::SIndexData* d = LightMapOctree->getIndexData(); for (u32 i=0; isetMaterial(Materials[i]); - driver->drawIndexedTriangleList( - &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(), - d[i].Indices, d[i].CurrentSize / 3); + if (UseVBOs) + { + if (UseVisibilityAndVBOs) + { + u16* oldPointer = LightMapMeshes[i].Indices.pointer(); + const u32 oldSize = LightMapMeshes[i].Indices.size(); + LightMapMeshes[i].Indices.set_free_when_destroyed(false); + LightMapMeshes[i].Indices.set_pointer(d[i].Indices, d[i].CurrentSize, false, false); + LightMapMeshes[i].setDirty(scene::EBT_INDEX); + driver->drawMeshBuffer ( &LightMapMeshes[i] ); + LightMapMeshes[i].Indices.set_pointer(oldPointer, oldSize); + LightMapMeshes[i].setDirty(scene::EBT_INDEX); + } + else + driver->drawMeshBuffer ( &LightMapMeshes[i] ); + } + else + driver->drawIndexedTriangleList( + &LightMapMeshes[i].Vertices[0], + LightMapMeshes[i].Vertices.size(), + d[i].Indices, d[i].CurrentSize / 3); } } @@ -196,7 +219,7 @@ void COctTreeSceneNode::render() driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { - LightMapOctTree->getBoundingBoxes(box, boxes); + LightMapOctree->getBoundingBoxes(box, boxes); for (u32 b=0; bdraw3DBox(*boxes[b]); } @@ -208,10 +231,12 @@ void COctTreeSceneNode::render() break; case video::EVT_TANGENTS: { - //TangentsOctTree->calculatePolys(box); - TangentsOctTree->calculatePolys(frust); + if (BoxBased) + TangentsOctree->calculatePolys(box); + else + TangentsOctree->calculatePolys(frust); - const OctTree::SIndexData* d = TangentsOctTree->getIndexData(); + const Octree::SIndexData* d = TangentsOctree->getIndexData(); for (u32 i=0; isetMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { - TangentsOctTree->getBoundingBoxes(box, boxes); + TangentsOctree->getBoundingBoxes(box, boxes); for (u32 b=0; bdraw3DBox(*boxes[b]); } @@ -257,46 +282,51 @@ void COctTreeSceneNode::render() //! returns the axis aligned bounding box of this node -const core::aabbox3d& COctTreeSceneNode::getBoundingBox() const +const core::aabbox3d& COctreeSceneNode::getBoundingBox() const { return Box; } //! creates the tree -bool COctTreeSceneNode::createTree(IMesh* mesh) +bool COctreeSceneNode::createTree(IMesh* mesh) { if (!mesh) return false; - MeshName = SceneManager->getMeshCache()->getMeshFilename( mesh ); + MeshName = SceneManager->getMeshCache()->getMeshName(mesh); + mesh->grab(); deleteTree(); + Mesh = mesh; + u32 beginTime = os::Timer::getRealTime(); u32 nodeCount = 0; u32 polyCount = 0; + u32 i; Box = mesh->getBoundingBox(); if (mesh->getMeshBufferCount()) { - vertexType = mesh->getMeshBuffer(0)->getVertexType(); + VertexType = mesh->getMeshBuffer(0)->getVertexType(); - switch(vertexType) + switch(VertexType) { case video::EVT_STANDARD: { - for (u32 i=0; igetMeshBufferCount(); ++i) + for (i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); - if (b->getVertexCount() && b->getIndexCount()) + + if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); - StdMeshes.push_back(OctTree::SMeshChunk()); - OctTree::SMeshChunk &nchunk = StdMeshes.getLast(); + StdMeshes.push_back(Octree::SMeshChunk()); + Octree::SMeshChunk &nchunk = StdMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; @@ -312,23 +342,44 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) } } - StdOctTree = new OctTree(StdMeshes, MinimalPolysPerNode); - nodeCount = StdOctTree->getNodeCount(); + StdOctree = new Octree(StdMeshes, MinimalPolysPerNode); + nodeCount = StdOctree->getNodeCount(); } break; case video::EVT_2TCOORDS: { - for (u32 i=0; igetMeshBufferCount(); ++i) + IMeshBuffer* b; + u32 meshReserve = 0; + for ( i=0; i < mesh->getMeshBufferCount(); ++i) { - IMeshBuffer* b = mesh->getMeshBuffer(i); + b = mesh->getMeshBuffer(i); + if (b->getVertexCount() && b->getIndexCount()) + { + meshReserve += 1; + } - if (b->getVertexCount() && b->getIndexCount()) + } + LightMapMeshes.reallocate ( LightMapMeshes.size() + meshReserve ); + + for ( i=0; i < mesh->getMeshBufferCount(); ++i) + { + b = mesh->getMeshBuffer(i); + + if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); - LightMapMeshes.push_back(OctTree::SMeshChunk()); - OctTree::SMeshChunk& nchunk = LightMapMeshes.getLast(); + LightMapMeshes.push_back(Octree::SMeshChunk()); + Octree::SMeshChunk& nchunk = LightMapMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; + if (UseVisibilityAndVBOs) + { + nchunk.setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX); + nchunk.setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX); + } + else + nchunk.setHardwareMappingHint(scene::EHM_STATIC); + u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); for (v=0; vgetVertexCount(); ++v) @@ -341,8 +392,8 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) } } - LightMapOctTree = new OctTree(LightMapMeshes, MinimalPolysPerNode); - nodeCount = LightMapOctTree->getNodeCount(); + LightMapOctree = new Octree(LightMapMeshes, MinimalPolysPerNode); + nodeCount = LightMapOctree->getNodeCount(); } break; case video::EVT_TANGENTS: @@ -351,11 +402,11 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) { IMeshBuffer* b = mesh->getMeshBuffer(i); - if (b->getVertexCount() && b->getIndexCount()) + if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); - TangentsMeshes.push_back(OctTree::SMeshChunk()); - OctTree::SMeshChunk& nchunk = TangentsMeshes.getLast(); + TangentsMeshes.push_back(Octree::SMeshChunk()); + Octree::SMeshChunk& nchunk = TangentsMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; @@ -370,8 +421,8 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) } } - TangentsOctTree = new OctTree(TangentsMeshes, MinimalPolysPerNode); - nodeCount = TangentsOctTree->getNodeCount(); + TangentsOctree = new Octree(TangentsMeshes, MinimalPolysPerNode); + nodeCount = TangentsOctree->getNodeCount(); } break; } @@ -379,7 +430,7 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) u32 endTime = os::Timer::getRealTime(); c8 tmp[255]; - sprintf(tmp, "Needed %ums to create OctTree SceneNode.(%u nodes, %u polys)", + sprintf(tmp, "Needed %ums to create Octree SceneNode.(%u nodes, %u polys)", endTime - beginTime, nodeCount, polyCount/3); os::Printer::log(tmp, ELL_INFORMATION); @@ -392,7 +443,7 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. -video::SMaterial& COctTreeSceneNode::getMaterial(u32 i) +video::SMaterial& COctreeSceneNode::getMaterial(u32 i) { if ( i >= Materials.size() ) return ISceneNode::getMaterial(i); @@ -402,14 +453,14 @@ video::SMaterial& COctTreeSceneNode::getMaterial(u32 i) //! returns amount of materials used by this scene node. -u32 COctTreeSceneNode::getMaterialCount() const +u32 COctreeSceneNode::getMaterialCount() const { return Materials.size(); } //! Writes attributes of the scene node. -void COctTreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +void COctreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ISceneNode::serializeAttributes(out, options); @@ -419,12 +470,12 @@ void COctTreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttribute //! Reads attributes of the scene node. -void COctTreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void COctreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { const s32 oldMinimal = MinimalPolysPerNode; MinimalPolysPerNode = in->getAttributeAsInt("MinimalPolysPerNode"); - core::stringc newMeshStr = in->getAttributeAsString("Mesh"); + io::path newMeshStr = in->getAttributeAsString("Mesh"); IMesh* newMesh = 0; @@ -446,23 +497,47 @@ void COctTreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribut } -void COctTreeSceneNode::deleteTree() +void COctreeSceneNode::deleteTree() { - delete StdOctTree; - StdOctTree = 0; + delete StdOctree; + StdOctree = 0; StdMeshes.clear(); - delete LightMapOctTree; - LightMapOctTree = 0; + delete LightMapOctree; + LightMapOctree = 0; LightMapMeshes.clear(); - delete TangentsOctTree; - TangentsOctTree = 0; + delete TangentsOctree; + TangentsOctree = 0; TangentsMeshes.clear(); Materials.clear(); + + if(Mesh) + Mesh->drop(); } +void COctreeSceneNode::setMesh(IMesh* mesh) +{ + createTree(mesh); +} + +IMesh* COctreeSceneNode::getMesh(void) +{ + return Mesh; +} + +void COctreeSceneNode::setReadOnlyMaterials(bool readonly) +{ + // Do nothing +} + +bool COctreeSceneNode::isReadOnlyMaterials() const +{ + return false; +} + + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/COctTreeSceneNode.h b/src/dep/src/irrlicht/COctreeSceneNode.h similarity index 50% rename from src/dep/src/irrlicht/COctTreeSceneNode.h rename to src/dep/src/irrlicht/COctreeSceneNode.h index 16feeb0..cfbcf87 100644 --- a/src/dep/src/irrlicht/COctTreeSceneNode.h +++ b/src/dep/src/irrlicht/COctreeSceneNode.h @@ -1,29 +1,28 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#ifndef __C_OCT_TREE_SCENE_NODE_H_INCLUDED__ -#define __C_OCT_TREE_SCENE_NODE_H_INCLUDED__ +#ifndef __C_OCTREE_SCENE_NODE_H_INCLUDED__ +#define __C_OCTREE_SCENE_NODE_H_INCLUDED__ -#include "ISceneNode.h" -#include "IMesh.h" -#include "OctTree.h" +#include "IMeshSceneNode.h" +#include "Octree.h" namespace irr { namespace scene { //! implementation of the IBspTreeSceneNode - class COctTreeSceneNode : public ISceneNode + class COctreeSceneNode : public IMeshSceneNode { public: //! constructor - COctTreeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, s32 minimalPolysPerNode=512); //! destructor - virtual ~COctTreeSceneNode(); + virtual ~COctreeSceneNode(); virtual void OnRegisterSceneNode(); @@ -42,7 +41,7 @@ namespace scene //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. virtual video::SMaterial& getMaterial(u32 i); - + //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; @@ -53,7 +52,19 @@ namespace scene virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node - virtual ESCENE_NODE_TYPE getType() const { return ESNT_OCT_TREE; } + virtual ESCENE_NODE_TYPE getType() const { return ESNT_OCTREE; } + + //! Sets a new mesh to display + virtual void setMesh(IMesh* mesh); + + //! Get the currently defined mesh for display. + virtual IMesh* getMesh(void); + + //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. + virtual void setReadOnlyMaterials(bool readonly); + + //! Check if the scene node should not copy the materials of the mesh but use them in a read only style + virtual bool isReadOnlyMaterials() const; private: @@ -61,21 +72,29 @@ namespace scene core::aabbox3d Box; - OctTree* StdOctTree; - core::array< OctTree::SMeshChunk > StdMeshes; + Octree* StdOctree; + core::array< Octree::SMeshChunk > StdMeshes; - OctTree* LightMapOctTree; - core::array< OctTree::SMeshChunk > LightMapMeshes; + Octree* LightMapOctree; + core::array< Octree::SMeshChunk > LightMapMeshes; - OctTree* TangentsOctTree; - core::array< OctTree::SMeshChunk > TangentsMeshes; + Octree* TangentsOctree; + core::array< Octree::SMeshChunk > TangentsMeshes; - video::E_VERTEX_TYPE vertexType; + video::E_VERTEX_TYPE VertexType; core::array< video::SMaterial > Materials; core::stringc MeshName; s32 MinimalPolysPerNode; s32 PassCount; + + IMesh * Mesh; + //! use VBOs for rendering where possible + bool UseVBOs; + //! use visibility information together with VBOs + bool UseVisibilityAndVBOs; + //! use bounding box or frustum for calculate polys + bool BoxBased; }; } // end namespace scene diff --git a/src/dep/src/irrlicht/COctreeTriangleSelector.cpp b/src/dep/src/irrlicht/COctreeTriangleSelector.cpp new file mode 100644 index 0000000..54993f1 --- /dev/null +++ b/src/dep/src/irrlicht/COctreeTriangleSelector.cpp @@ -0,0 +1,263 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "COctreeTriangleSelector.h" +#include "ISceneNode.h" + +#include "os.h" + +namespace irr +{ +namespace scene +{ + +//! constructor +COctreeTriangleSelector::COctreeTriangleSelector(const IMesh* mesh, + const ISceneNode* node, s32 minimalPolysPerNode) + : CTriangleSelector(mesh, node), Root(0), NodeCount(0), + MinimalPolysPerNode(minimalPolysPerNode) +{ + #ifdef _DEBUG + setDebugName("COctreeTriangleSelector"); + #endif + + if (!Triangles.empty()) + { + const u32 start = os::Timer::getRealTime(); + + // create the triangle octree + Root = new SOctreeNode(); + Root->Triangles = Triangles; + constructOctree(Root); + + c8 tmp[256]; + sprintf(tmp, "Needed %ums to create OctreeTriangleSelector.(%d nodes, %u polys)", + os::Timer::getRealTime() - start, NodeCount, Triangles.size()); + os::Printer::log(tmp, ELL_INFORMATION); + } +} + + +//! destructor +COctreeTriangleSelector::~COctreeTriangleSelector() +{ + delete Root; +} + + +void COctreeTriangleSelector::constructOctree(SOctreeNode* node) +{ + ++NodeCount; + + node->Box.reset(node->Triangles[0].pointA); + + // get bounding box + const u32 cnt = node->Triangles.size(); + for (u32 i=0; iBox.addInternalPoint(node->Triangles[i].pointA); + node->Box.addInternalPoint(node->Triangles[i].pointB); + node->Box.addInternalPoint(node->Triangles[i].pointC); + } + + const core::vector3df& middle = node->Box.getCenter(); + core::vector3df edges[8]; + node->Box.getEdges(edges); + + core::aabbox3d box; + core::array keepTriangles; + + // calculate children + + if (!node->Box.isEmpty() && (s32)node->Triangles.size() > MinimalPolysPerNode) + for (s32 ch=0; ch<8; ++ch) + { + box.reset(middle); + box.addInternalPoint(edges[ch]); + node->Child[ch] = new SOctreeNode(); + + for (s32 i=0; i<(s32)node->Triangles.size(); ++i) + { + if (node->Triangles[i].isTotalInsideBox(box)) + { + node->Child[ch]->Triangles.push_back(node->Triangles[i]); + //node->Triangles.erase(i); + //--i; + } + else + { + keepTriangles.push_back(node->Triangles[i]); + } + } + memcpy(node->Triangles.pointer(), keepTriangles.pointer(), + sizeof(core::triangle3df)*keepTriangles.size()); + + node->Triangles.set_used(keepTriangles.size()); + keepTriangles.set_used(0); + + if (node->Child[ch]->Triangles.empty()) + { + delete node->Child[ch]; + node->Child[ch] = 0; + } + else + constructOctree(node->Child[ch]); + } +} + + +//! Gets all triangles which lie within a specific bounding box. +void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, + s32 arraySize, s32& outTriangleCount, + const core::aabbox3d& box, + const core::matrix4* transform) const +{ + core::matrix4 mat ( core::matrix4::EM4CONST_NOTHING ); + core::aabbox3d invbox = box; + + if (SceneNode) + { + SceneNode->getAbsoluteTransformation().getInverse ( mat ); + mat.transformBoxEx(invbox); + } + + if (transform) + { + mat = *transform; + } + else + { + mat.makeIdentity(); + } + + + if (SceneNode) + mat *= SceneNode->getAbsoluteTransformation(); + + s32 trianglesWritten = 0; + + if (Root) + getTrianglesFromOctree(Root, trianglesWritten, + arraySize, invbox, &mat, triangles); + + outTriangleCount = trianglesWritten; +} + + +void COctreeTriangleSelector::getTrianglesFromOctree( + SOctreeNode* node, s32& trianglesWritten, + s32 maximumSize, const core::aabbox3d& box, + const core::matrix4* mat, core::triangle3df* triangles) const +{ + if (!box.intersectsWithBox(node->Box)) + return; + + s32 cnt = node->Triangles.size(); + if (cnt + trianglesWritten > maximumSize) + cnt -= cnt + trianglesWritten - maximumSize; + + s32 i; + + for (i=0; itransformVect(triangles[trianglesWritten].pointA, node->Triangles[i].pointA ); + mat->transformVect(triangles[trianglesWritten].pointB, node->Triangles[i].pointB ); + mat->transformVect(triangles[trianglesWritten].pointC, node->Triangles[i].pointC ); + ++trianglesWritten; + } + + for (i=0; i<8; ++i) + if (node->Child[i]) + getTrianglesFromOctree(node->Child[i], trianglesWritten, + maximumSize, box, mat, triangles); +} + + +//! Gets all triangles which have or may have contact with a 3d line. +// new version: from user Piraaate +void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, + s32& outTriangleCount, const core::line3d& line, + const core::matrix4* transform) const +{ +#if 0 + core::aabbox3d box(line.start); + box.addInternalPoint(line.end); + + // TODO: Could be optimized for line a little bit more. + COctreeTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, + box, transform); +#else + + core::matrix4 mat ( core::matrix4::EM4CONST_NOTHING ); + + core::vector3df vectStartInv ( line.start ), vectEndInv ( line.end ); + if (SceneNode) + { + mat = SceneNode->getAbsoluteTransformation(); + mat.makeInverse(); + mat.transformVect(vectStartInv, line.start); + mat.transformVect(vectEndInv, line.end); + } + core::line3d invline(vectStartInv, vectEndInv); + + mat.makeIdentity(); + + if (transform) + mat = (*transform); + + if (SceneNode) + mat *= SceneNode->getAbsoluteTransformation(); + + s32 trianglesWritten = 0; + + if (Root) + getTrianglesFromOctree(Root, trianglesWritten, arraySize, invline, &mat, triangles); + + outTriangleCount = trianglesWritten; +#endif +} + +void COctreeTriangleSelector::getTrianglesFromOctree(SOctreeNode* node, + s32& trianglesWritten, s32 maximumSize, const core::line3d& line, + const core::matrix4* transform, core::triangle3df* triangles) const +{ + if (!node->Box.intersectsWithLine(line)) + return; + + s32 cnt = node->Triangles.size(); + if (cnt + trianglesWritten > maximumSize) + cnt -= cnt + trianglesWritten - maximumSize; + + s32 i; + + if ( transform->isIdentity() ) + { + for (i=0; iTriangles[i]; + ++trianglesWritten; + } + } + else + { + for (i=0; iTriangles[i]; + transform->transformVect(triangles[trianglesWritten].pointA); + transform->transformVect(triangles[trianglesWritten].pointB); + transform->transformVect(triangles[trianglesWritten].pointC); + ++trianglesWritten; + } + } + + for (i=0; i<8; ++i) + if (node->Child[i]) + getTrianglesFromOctree(node->Child[i], trianglesWritten, + maximumSize, line, transform, triangles); +} + + +} // end namespace scene +} // end namespace irr + diff --git a/src/dep/src/irrlicht/COctTreeTriangleSelector.h b/src/dep/src/irrlicht/COctreeTriangleSelector.h similarity index 54% rename from src/dep/src/irrlicht/COctTreeTriangleSelector.h rename to src/dep/src/irrlicht/COctreeTriangleSelector.h index 1a52e4c..2005f80 100644 --- a/src/dep/src/irrlicht/COctTreeTriangleSelector.h +++ b/src/dep/src/irrlicht/COctreeTriangleSelector.h @@ -1,9 +1,9 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#ifndef __C_OCT_TREE_TRIANGLE_SELECTOR_H_INCLUDED__ -#define __C_OCT_TREE_TRIANGLE_SELECTOR_H_INCLUDED__ +#ifndef __C_OCTREE_TRIANGLE_SELECTOR_H_INCLUDED__ +#define __C_OCTREE_TRIANGLE_SELECTOR_H_INCLUDED__ #include "CTriangleSelector.h" @@ -15,54 +15,59 @@ namespace scene class ISceneNode; //! Stupid triangle selector without optimization -class COctTreeTriangleSelector : public CTriangleSelector +class COctreeTriangleSelector : public CTriangleSelector { public: //! Constructs a selector based on a mesh - COctTreeTriangleSelector(const IMesh* mesh, const ISceneNode* node, s32 minimalPolysPerNode); + COctreeTriangleSelector(const IMesh* mesh, const ISceneNode* node, s32 minimalPolysPerNode); - virtual ~COctTreeTriangleSelector(); + virtual ~COctreeTriangleSelector(); //! Gets all triangles which lie within a specific bounding box. - virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, + virtual 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, - s32& outTriangleCount, const core::line3d& line, + s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const; private: - struct SOctTreeNode + struct SOctreeNode { - SOctTreeNode() + SOctreeNode() { for (u32 i=0; i!=8; ++i) Child[i] = 0; } - ~SOctTreeNode() + ~SOctreeNode() { for (u32 i=0; i!=8; ++i) delete Child[i]; } core::array Triangles; - SOctTreeNode* Child[8]; + SOctreeNode* Child[8]; core::aabbox3d Box; }; - void constructOctTree(SOctTreeNode* node); - void deleteEmptyNodes(SOctTreeNode* node); - void getTrianglesFromOctTree(SOctTreeNode* node, s32& trianglesWritten, + void constructOctree(SOctreeNode* node); + void deleteEmptyNodes(SOctreeNode* node); + void getTrianglesFromOctree(SOctreeNode* node, s32& trianglesWritten, s32 maximumSize, const core::aabbox3d& box, const core::matrix4* transform, core::triangle3df* triangles) const; - SOctTreeNode* Root; + void getTrianglesFromOctree(SOctreeNode* node, s32& trianglesWritten, + s32 maximumSize, const core::line3d& line, + const core::matrix4* transform, + core::triangle3df* triangles) const; + + SOctreeNode* Root; s32 NodeCount; s32 MinimalPolysPerNode; }; diff --git a/src/dep/src/irrlicht/COgreMeshFileLoader.cpp b/src/dep/src/irrlicht/COgreMeshFileLoader.cpp index d7eeea3..54289e4 100644 --- a/src/dep/src/irrlicht/COgreMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/COgreMeshFileLoader.cpp @@ -1,9 +1,9 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // orginally written by Christian Stehno, modified by Nikolaus Gebhardt -#include "IrrCompileConfig.h" +#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_ #include "COgreMeshFileLoader.h" @@ -23,31 +23,44 @@ namespace irr namespace scene { -// Main Chunks -const u16 COGRE_HEADER= 0x1000; -const u16 COGRE_MESH= 0x3000; +namespace +{ + enum OGRE_CHUNKS + { + // Main Chunks + COGRE_HEADER= 0x1000, + COGRE_SKELETON= 0x2000, + COGRE_MESH= 0x3000, -// sub chunks of COGRE_MESH -const u16 COGRE_SUBMESH= 0x4000; -const u16 COGRE_GEOMETRY= 0x5000; -const u16 COGRE_SKELETON_LINK= 0x6000; -const u16 COGRE_BONE_ASSIGNMENT= 0x7000; -const u16 COGRE_MESH_LOD= 0x8000; -const u16 COGRE_MESH_BOUNDS= 0x9000; -const u16 COGRE_MESH_SUBMESH_NAME_TABLE= 0xA000; -const u16 COGRE_MESH_EDGE_LISTS= 0xB000; + // sub chunks of COGRE_MESH + COGRE_SUBMESH= 0x4000, + COGRE_GEOMETRY= 0x5000, + COGRE_SKELETON_LINK= 0x6000, + COGRE_BONE_ASSIGNMENT= 0x7000, + COGRE_MESH_LOD= 0x8000, + COGRE_MESH_BOUNDS= 0x9000, + COGRE_MESH_SUBMESH_NAME_TABLE= 0xA000, + COGRE_MESH_EDGE_LISTS= 0xB000, -// sub chunks of COGRE_GEOMETRY -const u16 COGRE_GEOMETRY_VERTEX_DECLARATION= 0x5100; -const u16 COGRE_GEOMETRY_VERTEX_ELEMENT= 0x5110; -const u16 COGRE_GEOMETRY_VERTEX_BUFFER= 0x5200; -const u16 COGRE_GEOMETRY_VERTEX_BUFFER_DATA= 0x5210; + // sub chunks of COGRE_SKELETON + COGRE_BONE_PARENT= 0x3000, + COGRE_ANIMATION= 0x4000, + COGRE_ANIMATION_TRACK= 0x4100, + COGRE_ANIMATION_KEYFRAME= 0x4110, + COGRE_ANIMATION_LINK= 0x5000, -// sub chunks of COGRE_SUBMESH -const u16 COGRE_SUBMESH_OPERATION= 0x4010; -const u16 COGRE_SUBMESH_BONE_ASSIGNMENT= 0x4100; -const u16 COGRE_SUBMESH_TEXTURE_ALIAS= 0x4200; + // sub chunks of COGRE_SUBMESH + COGRE_SUBMESH_OPERATION= 0x4010, + COGRE_SUBMESH_BONE_ASSIGNMENT= 0x4100, + COGRE_SUBMESH_TEXTURE_ALIAS= 0x4200, + // sub chunks of COGRE_GEOMETRY + COGRE_GEOMETRY_VERTEX_DECLARATION= 0x5100, + COGRE_GEOMETRY_VERTEX_ELEMENT= 0x5110, + COGRE_GEOMETRY_VERTEX_BUFFER= 0x5200, + COGRE_GEOMETRY_VERTEX_BUFFER_DATA= 0x5210 + }; +} //! Constructor COgreMeshFileLoader::COgreMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver) @@ -84,9 +97,9 @@ COgreMeshFileLoader::~COgreMeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool COgreMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool COgreMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".mesh")!=0; + return core::hasFileExtension ( filename, "mesh" ); } @@ -108,33 +121,44 @@ IAnimatedMesh* COgreMeshFileLoader::createMesh(io::IReadFile* file) return 0; ChunkData data; readString(file, data, Version); - if ((Version != "[MeshSerializer_v1.30]") && (Version != "[MeshSerializer_v1.40]")) + if ((Version != "[MeshSerializer_v1.30]") && (Version != "[MeshSerializer_v1.40]") && (Version != "[MeshSerializer_v1.41]")) return 0; clearMeshes(); if (Mesh) Mesh->drop(); - Mesh = new SMesh(); - setCurrentlyLoadingPath(file); + CurrentlyLoadingFromPath = FileSystem->getFileDir(file->getFileName()); loadMaterials(file); if (readChunk(file)) { - // success - SAnimatedMesh* am = new SAnimatedMesh(); - am->Type = EAMT_3DS; + // delete data loaded from file + clearMeshes(); - for (u32 i=0; igetMeshBufferCount(); ++i) - ((SMeshBuffer*)Mesh->getMeshBuffer(i))->recalculateBoundingBox(); + if (Skeleton.Bones.size()) + { + ISkinnedMesh* tmp = static_cast(Mesh); + static_cast(Mesh)->updateBoundingBox(); + Skeleton.Animations.clear(); + Skeleton.Bones.clear(); + Mesh=0; + return tmp; + } + else + { + for (u32 i=0; igetMeshBufferCount(); ++i) + ((SMeshBuffer*)Mesh->getMeshBuffer(i))->recalculateBoundingBox(); - Mesh->recalculateBoundingBox(); - - am->addMesh(Mesh); - am->recalculateBoundingBox(); - Mesh->drop(); - Mesh = 0; + ((SMesh*)Mesh)->recalculateBoundingBox(); + SAnimatedMesh* am = new SAnimatedMesh(); + am->Type = EAMT_3DS; + am->addMesh(Mesh); + am->recalculateBoundingBox(); + Mesh->drop(); + Mesh = 0; return am; + } } Mesh->drop(); @@ -157,6 +181,10 @@ bool COgreMeshFileLoader::readChunk(io::IReadFile* file) { Meshes.push_back(OgreMesh()); readObjectChunk(file, data, Meshes.getLast()); + if (Skeleton.Bones.size()) + Mesh = new CSkinnedMesh(); + else + Mesh = new SMesh(); composeObject(); } break; @@ -175,6 +203,7 @@ bool COgreMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData& parent os::Printer::log("Read Object Chunk"); #endif readBool(file, parent, mesh.SkeletalAnimation); + bool skeleton_loaded=false; while ((parent.read < parent.header.length)&&(file->getPos() < file->getSize())) { ChunkData data; @@ -183,24 +212,42 @@ bool COgreMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData& parent switch(data.header.id) { case COGRE_GEOMETRY: - { readGeometry(file, data, mesh.Geometry); - } break; - case COGRE_SUBMESH: + case COGRE_SUBMESH: mesh.SubMeshes.push_back(OgreSubMesh()); readSubMesh(file, data, mesh.SubMeshes.getLast()); break; - case COGRE_MESH_BOUNDS: + case COGRE_MESH_BOUNDS: { +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Read Mesh Bounds"); +#endif readVector(file, data, mesh.BBoxMinEdge); readVector(file, data, mesh.BBoxMaxEdge); - readFloat(file, data, mesh.BBoxRadius); + readFloat(file, data, &mesh.BBoxRadius); } break; - case COGRE_SKELETON_LINK: - case COGRE_BONE_ASSIGNMENT: - case COGRE_MESH_LOD: + case COGRE_SKELETON_LINK: + { +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Read Skeleton link"); +#endif + core::stringc name; + readString(file, data, name); + loadSkeleton(file, name); + skeleton_loaded=true; + } + break; + case COGRE_BONE_ASSIGNMENT: + { + mesh.BoneAssignments.push_back(OgreBoneAssignment()); + readInt(file, data, &mesh.BoneAssignments.getLast().VertexID); + readShort(file, data, &mesh.BoneAssignments.getLast().BoneID); + readFloat(file, data, &mesh.BoneAssignments.getLast().Weight); + } + break; + case COGRE_MESH_LOD: case COGRE_MESH_SUBMESH_NAME_TABLE: case COGRE_MESH_EDGE_LISTS: // ignore chunk @@ -208,12 +255,18 @@ bool COgreMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData& parent data.read += data.header.length-data.read; break; default: - parent.read=parent.header.length; - file->seek(-(long)sizeof(ChunkHeader), true); - return true; +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Skipping", core::stringc(data.header.id)); +#endif + // ignore chunk + file->seek(data.header.length-data.read, true); + data.read += data.header.length-data.read; + break; } parent.read += data.read; } + if (!skeleton_loaded) + loadSkeleton(file, FileSystem->getFileBasename(file->getFileName(), false)); return true; } @@ -223,7 +276,7 @@ bool COgreMeshFileLoader::readGeometry(io::IReadFile* file, ChunkData& parent, O #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Geometry"); #endif - readInt(file, parent, geometry.NumVertex); + readInt(file, parent, &geometry.NumVertex); while(parent.read < parent.header.length) { ChunkData data; @@ -239,6 +292,9 @@ bool COgreMeshFileLoader::readGeometry(io::IReadFile* file, ChunkData& parent, O break; default: // ignore chunk +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Skipping", core::stringc(data.header.id)); +#endif file->seek(data.header.length-data.read, true); data.read += data.header.length-data.read; } @@ -263,18 +319,18 @@ bool COgreMeshFileLoader::readVertexDeclaration(io::IReadFile* file, ChunkData& { case COGRE_GEOMETRY_VERTEX_ELEMENT: { - OgreVertexElement elem; - readShort(file, data, elem.Source); - readShort(file, data, elem.Type); - readShort(file, data, elem.Semantic); + geometry.Elements.push_back(OgreVertexElement()); + OgreVertexElement& elem = geometry.Elements.getLast(); + readShort(file, data, &elem.Source); + readShort(file, data, &elem.Type); + readShort(file, data, &elem.Semantic); if (elem.Semantic == 7) //Tex coords { ++NumUV; } - readShort(file, data, elem.Offset); + readShort(file, data, &elem.Offset); elem.Offset /= sizeof(f32); - readShort(file, data, elem.Index); - geometry.Elements.push_back(elem); + readShort(file, data, &elem.Index); } break; default: @@ -294,17 +350,16 @@ bool COgreMeshFileLoader::readVertexBuffer(io::IReadFile* file, ChunkData& paren os::Printer::log("Read Vertex Buffer"); #endif OgreVertexBuffer buf; - readShort(file, parent, buf.BindIndex); - readShort(file, parent, buf.VertexSize); + readShort(file, parent, &buf.BindIndex); + readShort(file, parent, &buf.VertexSize); buf.VertexSize /= sizeof(f32); ChunkData data; readChunkData(file, data); if (data.header.id == COGRE_GEOMETRY_VERTEX_BUFFER_DATA) { - buf.Data = new f32[geometry.NumVertex*buf.VertexSize]; - for (s32 i=0; iseek(data.header.length-data.read, true); - data.read += data.header.length-data.read; + { + subMesh.BoneAssignments.push_back(OgreBoneAssignment()); + readInt(file, data, &subMesh.BoneAssignments.getLast().VertexID); + readShort(file, data, &subMesh.BoneAssignments.getLast().BoneID); + readFloat(file, data, &subMesh.BoneAssignments.getLast().Weight); + } break; default: +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Skipping", core::stringc(data.header.id)); +#endif parent.read=parent.header.length; file->seek(-(long)sizeof(ChunkHeader), true); return true; @@ -394,19 +458,10 @@ void COgreMeshFileLoader::composeMeshBufferMaterial(scene::IMeshBuffer* mb, cons material=Materials[k].Techniques[0].Passes[0].Material; if (Materials[k].Techniques[0].Passes[0].Texture.Filename.size()) { - material.setTexture(0, Driver->getTexture(Materials[k].Techniques[0].Passes[0].Texture.Filename.c_str())); - if (!material.getTexture(0)) - { - // retry with relative path - core::stringc relative = Materials[k].Techniques[0].Passes[0].Texture.Filename; - s32 idx = relative.findLast('\\'); - if (idx != -1) - relative = relative.subString(idx+1, relative.size()-idx-1); - idx = relative.findLast('/'); - if (idx != -1) - relative = relative.subString(idx+1, relative.size()-idx-1); - material.setTexture(0, Driver->getTexture((CurrentlyLoadingFromPath+"/"+relative).c_str())); - } + if (FileSystem->existFile(Materials[k].Techniques[0].Passes[0].Texture.Filename)) + material.setTexture(0, Driver->getTexture(Materials[k].Techniques[0].Passes[0].Texture.Filename)); + else + material.setTexture(0, Driver->getTexture((CurrentlyLoadingFromPath+"/"+FileSystem->getFileBasename(Materials[k].Techniques[0].Passes[0].Texture.Filename)))); } break; } @@ -542,7 +597,92 @@ scene::SMeshBufferLightMap* COgreMeshFileLoader::composeMeshBufferLightMap(const { mb->Vertices[k].TCoords.set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); mb->Vertices[k].TCoords2.set(geom.Buffers[j].Data[ePos+2], geom.Buffers[j].Data[ePos+3]); - + + ePos += eSize; + } + } + } + } + } + + return mb; +} + + +scene::IMeshBuffer* COgreMeshFileLoader::composeMeshBufferSkinned(scene::CSkinnedMesh& mesh, const core::array& indices, const OgreGeometry& geom) +{ + scene::SSkinMeshBuffer *mb=mesh.addMeshBuffer(); + if (NumUV>1) + { + mb->convertTo2TCoords(); + mb->Vertices_2TCoords.set_used(geom.NumVertex); + } + else + mb->Vertices_Standard.set_used(geom.NumVertex); + + u32 i; + mb->Indices.set_used(indices.size()); + for (i=0; iIndices[i+0]=indices[i+2]; + mb->Indices[i+1]=indices[i+1]; + mb->Indices[i+2]=indices[i+0]; + } + + for (i=0; i1) + mb->Vertices_2TCoords[k].Color=mb->Material.DiffuseColor; + else + mb->Vertices_Standard[k].Color=mb->Material.DiffuseColor; + mb->getPosition(k).set(-geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); + ePos += eSize; + } + } + } + } + + if (geom.Elements[i].Semantic==4) //Normal + { + for (u32 j=0; jgetNormal(k).set(-geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); + ePos += eSize; + } + } + } + } + + if (geom.Elements[i].Semantic==7) //TexCoord + { + for (u32 j=0; jgetTCoords(k).set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); + if (NumUV>1) + mb->Vertices_2TCoords[k].TCoords2.set(geom.Buffers[j].Data[ePos+2], geom.Buffers[j].Data[ePos+3]); + ePos += eSize; } } @@ -563,7 +703,11 @@ void COgreMeshFileLoader::composeObject(void) IMeshBuffer* mb; if (Meshes[i].SubMeshes[j].SharedVertices) { - if (NumUV < 2) + if (Skeleton.Bones.size()) + { + mb = composeMeshBufferSkinned(*(CSkinnedMesh*)Mesh, Meshes[i].SubMeshes[j].Indices, Meshes[i].Geometry); + } + else if (NumUV < 2) { mb = composeMeshBuffer(Meshes[i].SubMeshes[j].Indices, Meshes[i].Geometry); } @@ -574,7 +718,11 @@ void COgreMeshFileLoader::composeObject(void) } else { - if (NumUV < 2) + if (Skeleton.Bones.size()) + { + mb = composeMeshBufferSkinned(*(CSkinnedMesh*)Mesh, Meshes[i].SubMeshes[j].Indices, Meshes[i].SubMeshes[j].Geometry); + } + else if (NumUV < 2) { mb = composeMeshBuffer(Meshes[i].SubMeshes[j].Indices, Meshes[i].SubMeshes[j].Geometry); } @@ -587,29 +735,81 @@ void COgreMeshFileLoader::composeObject(void) if (mb != 0) { composeMeshBufferMaterial(mb, Meshes[i].SubMeshes[j].Material); - Mesh->addMeshBuffer(mb); - mb->drop(); + if (!Skeleton.Bones.size()) + { + ((SMesh*)Mesh)->addMeshBuffer(mb); + mb->drop(); + } } } } -} + if (Skeleton.Bones.size()) + { + CSkinnedMesh* m = (CSkinnedMesh*)Mesh; + // Create Joints + for (u32 i=0; iaddJoint(); + joint->Name=Skeleton.Bones[i].Name; + joint->LocalMatrix = Skeleton.Bones[i].Orientation.getMatrix(); + if (Skeleton.Bones[i].Scale != core::vector3df(1,1,1)) + { + core::matrix4 scaleMatrix; + scaleMatrix.setScale( Skeleton.Bones[i].Scale ); + joint->LocalMatrix *= scaleMatrix; + } + joint->LocalMatrix.setTranslation( Skeleton.Bones[i].Position ); + } + // Joints hierarchy + for (u32 i=0; igetJointCount()) + { + m->getAllJoints()[Skeleton.Bones[i].Parent]->Children.push_back(m->getAllJoints()[Skeleton.Bones[i].Handle]); + } + } -core::stringc COgreMeshFileLoader::getTextureFileName(const core::stringc& texture, - core::stringc& model) -{ - s32 idx = -1; - idx = model.findLast('/'); + // Weights + u32 bufCount=0; + for (u32 i=0; igetJointCount()) + { + ISkinnedMesh::SWeight* w = m->addWeight(m->getAllJoints()[ba.BoneID]); + w->strength=ba.Weight; + w->vertex_id=ba.VertexID; + w->buffer_id=bufCount; + } + } + ++bufCount; + } + } - if (idx == -1) - idx = model.findLast('\\'); - - if (idx == -1) - return core::stringc(); - - core::stringc p = model.subString(0, idx+1); - p.append(texture); - return p; + for (u32 i=0; igetAllJoints()[frame.BoneID]; + ISkinnedMesh::SPositionKey* poskey = m->addPositionKey(keyjoint); + poskey->frame=frame.Time*25; + poskey->position=keyjoint->LocalMatrix.getTranslation()+frame.Position; + ISkinnedMesh::SRotationKey* rotkey = m->addRotationKey(keyjoint); + rotkey->frame=frame.Time*25; + rotkey->rotation=core::quaternion(keyjoint->LocalMatrix)*frame.Orientation; + ISkinnedMesh::SScaleKey* scalekey = m->addScaleKey(keyjoint); + scalekey->frame=frame.Time*25; + scalekey->scale=frame.Scale; + } + } + m->finalize(); + } } @@ -729,21 +929,24 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique getMaterialToken(file, token); //open brace getMaterialToken(file, token); + if (token == "}") + return; u32 inBlocks=1; + u32 textureUnit=0; while(inBlocks) { if (token=="ambient") pass.AmbientTokenColor=readColor(file, pass.Material.AmbientColor); else if (token=="diffuse") - pass.DiffuseTokenColor=readColor(file, pass.Material.AmbientColor); + pass.DiffuseTokenColor=readColor(file, pass.Material.DiffuseColor); else if (token=="specular") { - pass.SpecularTokenColor=readColor(file, pass.Material.AmbientColor); + pass.SpecularTokenColor=readColor(file, pass.Material.SpecularColor); getMaterialToken(file, token); pass.Material.Shininess=core::fast_atof(token.c_str()); } else if (token=="emissive") - pass.EmissiveTokenColor=readColor(file, pass.Material.AmbientColor); + pass.EmissiveTokenColor=readColor(file, pass.Material.EmissiveColor); else if (token=="scene_blend") { // TODO: Choose correct values getMaterialToken(file, token); @@ -761,7 +964,8 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique else if (token=="depth_check") { getMaterialToken(file, token); - pass.Material.ZBuffer=(token=="on"); + if (token!="on") + pass.Material.ZBuffer=video::ECFN_NEVER; } else if (token=="depth_write") { @@ -771,6 +975,27 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique else if (token=="depth_func") { getMaterialToken(file, token); // Function name + if (token=="always_fail") + pass.Material.ZBuffer=video::ECFN_NEVER; + else if (token=="always_pass") + pass.Material.ZBuffer=video::ECFN_ALWAYS; + else if (token=="equal") + pass.Material.ZBuffer=video::ECFN_EQUAL; + else if (token=="greater") + pass.Material.ZBuffer=video::ECFN_GREATER; + else if (token=="greater_equal") + pass.Material.ZBuffer=video::ECFN_GREATEREQUAL; + else if (token=="less") + pass.Material.ZBuffer=video::ECFN_LESS; + else if (token=="less_equal") + pass.Material.ZBuffer=video::ECFN_LESSEQUAL; + else if (token=="not_equal") + pass.Material.ZBuffer=video::ECFN_NOTEQUAL; + } + else if (token=="normalise_normals") + { + getMaterialToken(file, token); + pass.Material.NormalizeNormals=(token=="on"); } else if (token=="depth_bias") { @@ -780,6 +1005,18 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique { getMaterialToken(file, token); // function name getMaterialToken(file, token); // value + pass.Material.MaterialTypeParam=core::fast_atof(token.c_str()); + } + else if (token=="alpha_to_coverage") + { + getMaterialToken(file, token); + if (token=="on") + pass.Material.AntiAliasing |= video::EAAM_ALPHA_TO_COVERAGE; + } + else if (token=="colour_write") + { + getMaterialToken(file, token); + pass.Material.ColorMask = (token=="on")?video::ECP_ALL:video::ECP_NONE; } else if (token=="cull_hardware") { @@ -803,13 +1040,8 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique else if (token=="polygon_mode") { getMaterialToken(file, token); - // We take points as wireframe - pass.Material.Wireframe=(token!="solid"); - } - else if (token=="colour_write") - { - getMaterialToken(file, token); - pass.ColorWrite=(token=="on"); + pass.Material.Wireframe=(token=="wireframe"); + pass.Material.PointCloud=(token=="points"); } else if (token=="max_lights") { @@ -855,8 +1087,54 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique getMaterialToken(file, pass.Texture.MipMaps, true); getMaterialToken(file, pass.Texture.Alpha, true); } + else if (token=="filtering") + { + getMaterialToken(file, token); + pass.Material.TextureLayer[textureUnit].AnisotropicFilter=0; + if (token=="point") + { + pass.Material.TextureLayer[textureUnit].BilinearFilter=false; + pass.Material.TextureLayer[textureUnit].TrilinearFilter=false; + getMaterialToken(file, token); + getMaterialToken(file, token); + } + else if (token=="linear") + { + getMaterialToken(file, token); + if (token=="point") + { + pass.Material.TextureLayer[textureUnit].BilinearFilter=false; + pass.Material.TextureLayer[textureUnit].TrilinearFilter=false; + getMaterialToken(file, token); + } + else + { + pass.Material.TextureLayer[textureUnit].BilinearFilter=true; + getMaterialToken(file, token); + pass.Material.TextureLayer[textureUnit].TrilinearFilter=(token=="linear"); + } + } + else + { + pass.Material.TextureLayer[textureUnit].BilinearFilter=(token=="bilinear"); + pass.Material.TextureLayer[textureUnit].TrilinearFilter=(token=="trilinear"); + pass.Material.TextureLayer[textureUnit].AnisotropicFilter=(token=="anisotropic")?2:1; + } + } + else if (token=="max_anisotropy") + { + getMaterialToken(file, token); + pass.Material.TextureLayer[textureUnit].AnisotropicFilter=(u8)core::strtol10(token.c_str()); + } else if (token=="texture_alias") + { getMaterialToken(file, pass.Texture.Alias); + } + else if (token=="mipmap_bias") + { + getMaterialToken(file, token); + pass.Material.TextureLayer[textureUnit].LODBias=(s8)core::fast_atof(token.c_str()); + } else if (token=="colour_op") { // TODO: Choose correct values getMaterialToken(file, token); @@ -873,6 +1151,7 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique } getMaterialToken(file, token); } + ++textureUnit; } else if (token=="shadow_caster_program_ref") { @@ -880,7 +1159,13 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique { getMaterialToken(file, token); } while (token != "}"); - getMaterialToken(file, token); + } + else if (token=="shadow_caster_vertex_program_ref") + { + do + { + getMaterialToken(file, token); + } while (token != "}"); } else if (token=="vertex_program_ref") { @@ -888,7 +1173,6 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique { getMaterialToken(file, token); } while (token != "}"); - getMaterialToken(file, token); } //fog_override, iteration, point_size_attenuation //not considered yet! @@ -930,19 +1214,22 @@ void COgreMeshFileLoader::readTechnique(io::IReadFile* file, OgreMaterial& mat) } - void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Load Materials"); #endif - core::stringc token,filename=meshFile->getFileName(); - core::stringc material = filename.subString(0, filename.size()-4) + "material"; - io::IReadFile* file = FileSystem->createAndOpenFile(material.c_str()); + core::stringc token; + io::IReadFile* file = 0; + io::path filename = FileSystem->getFileBasename(meshFile->getFileName(), false) + ".material"; + if (FileSystem->existFile(filename)) + file = FileSystem->createAndOpenFile(filename); + else + file = FileSystem->createAndOpenFile(FileSystem->getFileDir(meshFile->getFileName())+"/"+filename); if (!file) { - os::Printer::log("Could not load OGRE material", material.c_str()); + os::Printer::log("Could not load OGRE material", filename); return; } @@ -1018,6 +1305,143 @@ void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile) } +bool COgreMeshFileLoader::loadSkeleton(io::IReadFile* meshFile, const core::stringc& name) +{ +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Load Skeleton", name); +#endif + io::IReadFile* file = 0; + io::path filename; + if (FileSystem->existFile(name)) + file = FileSystem->createAndOpenFile(name); + else if (FileSystem->existFile(filename = FileSystem->getFileDir(meshFile->getFileName())+"/"+name)) + file = FileSystem->createAndOpenFile(filename); + else if (FileSystem->existFile(filename = FileSystem->getFileBasename(meshFile->getFileName(), false) + ".skeleton")) + file = FileSystem->createAndOpenFile(filename); + else + file = FileSystem->createAndOpenFile(FileSystem->getFileDir(meshFile->getFileName())+"/"+filename); + if (!file) + { + os::Printer::log("Could not load matching skeleton", name); + return false; + } + + s16 id; + file->read(&id, 2); + if (SwapEndian) + id = os::Byteswap::byteswap(id); + if (id != COGRE_HEADER) + { + file->drop(); + return false; + } + + core::stringc skeletonVersion; + ChunkData head; + readString(file, head, skeletonVersion); + if (skeletonVersion != "[Serializer_v1.10]") + { + file->drop(); + return false; + } + + u16 bone=0; + f32 animationTotal=0.f; + while(file->getPos() < file->getSize()) + { + ChunkData data; + readChunkData(file, data); + + switch(data.header.id) + { + case COGRE_SKELETON: + { + Skeleton.Bones.push_back(OgreBone()); + OgreBone& bone = Skeleton.Bones.getLast(); + readString(file, data, bone.Name); + readShort(file, data, &bone.Handle); + readVector(file, data, bone.Position); + readQuaternion(file, data, bone.Orientation); +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Bone", bone.Name+" ("+core::stringc(bone.Handle)+")"); + os::Printer::log("Position", core::stringc(bone.Position.X)+" "+core::stringc(bone.Position.Y)+" "+core::stringc(bone.Position.Z)); + os::Printer::log("Rotation quat", core::stringc(bone.Orientation.W)+" "+core::stringc(bone.Orientation.X)+" "+core::stringc(bone.Orientation.Y)+" "+core::stringc(bone.Orientation.Z)); +// core::vector3df rot; +// bone.Orientation.toEuler(rot); +// rot *= core::RADTODEG; +// os::Printer::log("Rotation", core::stringc(rot.X)+" "+core::stringc(rot.Y)+" "+core::stringc(rot.Z)); +#endif + if (data.read<(data.header.length-bone.Name.size())) + { + readVector(file, data, bone.Scale); + bone.Scale.X *= -1.f; + } + else + bone.Scale=core::vector3df(1,1,1); + bone.Parent=0xffff; + } + break; + case COGRE_BONE_PARENT: + { + u16 parent; + readShort(file, data, &bone); + readShort(file, data, &parent); + if (bonedrop(); + return true; +} + + void COgreMeshFileLoader::readChunkData(io::IReadFile* file, ChunkData& data) { file->read(&data.header, sizeof(ChunkHeader)); @@ -1056,84 +1480,72 @@ void COgreMeshFileLoader::readBool(io::IReadFile* file, ChunkData& data, bool& o } -void COgreMeshFileLoader::readInt(io::IReadFile* file, ChunkData& data, s32& out) +void COgreMeshFileLoader::readInt(io::IReadFile* file, ChunkData& data, s32* out, u32 num) { // normal C type because we read a bit string - int tmp; - file->read(&tmp, sizeof(int)); + file->read(out, sizeof(int)*num); if (SwapEndian) { - tmp = os::Byteswap::byteswap(tmp); + for (u32 i=0; iread(&tmp, sizeof(short)); + file->read(out, sizeof(short)*num); if (SwapEndian) { - tmp = os::Byteswap::byteswap(tmp); + for (u32 i=0; iread(&tmp, sizeof(float)); + file->read(out, sizeof(float)*num); if (SwapEndian) { - tmp = os::Byteswap::byteswap(tmp); + for (u32 i=0; igetFileName(); - int idx = CurrentlyLoadingFromPath.findLast('/'); - - if (idx != -1) - { - CurrentlyLoadingFromPath = CurrentlyLoadingFromPath.subString(0, idx); - } - else - { - idx = CurrentlyLoadingFromPath.findLast('\\'); - - if (idx != -1) - CurrentlyLoadingFromPath = CurrentlyLoadingFromPath.subString(0, idx); - } + readVector(file, data, *((core::vector3df*)&out.X)); + readFloat(file, data, &out.W); } + void COgreMeshFileLoader::clearMeshes() { for (u32 i=0; i Data; }; struct OgreVertexElement @@ -170,6 +170,13 @@ private: core::stringc Alias; }; + struct OgreBoneAssignment + { + s32 VertexID; + u16 BoneID; + f32 Weight; + }; + struct OgreSubMesh { core::stringc Material; @@ -178,6 +185,7 @@ private: OgreGeometry Geometry; u16 Operation; core::array TextureAliases; + core::array BoneAssignments; bool Indices32Bit; }; @@ -186,11 +194,44 @@ private: bool SkeletalAnimation; OgreGeometry Geometry; core::array SubMeshes; + core::array BoneAssignments; core::vector3df BBoxMinEdge; core::vector3df BBoxMaxEdge; f32 BBoxRadius; }; + struct OgreBone + { + core::stringc Name; + core::vector3df Position; + core::quaternion Orientation; + core::vector3df Scale; + u16 Handle; + u16 Parent; + }; + + struct OgreKeyframe + { + u16 BoneID; + f32 Time; + core::vector3df Position; + core::quaternion Orientation; + core::vector3df Scale; + }; + + struct OgreAnimation + { + core::stringc Name; + f32 Length; + core::array Keyframes; + }; + + struct OgreSkeleton + { + core::array Bones; + core::array Animations; + }; + bool readChunk(io::IReadFile* file); bool readObjectChunk(io::IReadFile* file, ChunkData& parent, OgreMesh& mesh); bool readGeometry(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry); @@ -201,22 +242,23 @@ private: void readChunkData(io::IReadFile* file, ChunkData& data); void readString(io::IReadFile* file, ChunkData& data, core::stringc& out); void readBool(io::IReadFile* file, ChunkData& data, bool& out); - void readInt(io::IReadFile* file, ChunkData& data, s32& out); - void readShort(io::IReadFile* file, ChunkData& data, u16& out); - void readFloat(io::IReadFile* file, ChunkData& data, f32& out); + void readInt(io::IReadFile* file, ChunkData& data, s32* out, u32 num=1); + void readShort(io::IReadFile* file, ChunkData& data, u16* out, u32 num=1); + void readFloat(io::IReadFile* file, ChunkData& data, f32* out, u32 num=1); void readVector(io::IReadFile* file, ChunkData& data, core::vector3df& out); + void readQuaternion(io::IReadFile* file, ChunkData& data, core::quaternion& out); void composeMeshBufferMaterial(scene::IMeshBuffer* mb, const core::stringc& materialName); scene::SMeshBuffer* composeMeshBuffer(const core::array& indices, const OgreGeometry& geom); scene::SMeshBufferLightMap* composeMeshBufferLightMap(const core::array& indices, const OgreGeometry& geom); + scene::IMeshBuffer* composeMeshBufferSkinned(scene::CSkinnedMesh& mesh, const core::array& indices, const OgreGeometry& geom); void composeObject(void); bool readColor(io::IReadFile* meshFile, video::SColor& col); void getMaterialToken(io::IReadFile* file, core::stringc& token, bool noNewLine=false); void readTechnique(io::IReadFile* meshFile, OgreMaterial& mat); void readPass(io::IReadFile* file, OgreTechnique& technique); void loadMaterials(io::IReadFile* file); - core::stringc getTextureFileName(const core::stringc& texture, core::stringc& model); - void setCurrentlyLoadingPath(io::IReadFile* file); + bool loadSkeleton(io::IReadFile* meshFile, const core::stringc& name); void clearMeshes(); io::IFileSystem* FileSystem; @@ -225,11 +267,12 @@ private: core::stringc Version; bool SwapEndian; core::array Meshes; - core::stringc CurrentlyLoadingFromPath; + io::path CurrentlyLoadingFromPath; core::array Materials; + OgreSkeleton Skeleton; - SMesh* Mesh; + IMesh* Mesh; u32 NumUV; }; diff --git a/src/dep/src/irrlicht/COpenGLDriver.cpp b/src/dep/src/irrlicht/COpenGLDriver.cpp index ec32d03..fdd40ce 100644 --- a/src/dep/src/irrlicht/COpenGLDriver.cpp +++ b/src/dep/src/irrlicht/COpenGLDriver.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,7 +17,7 @@ #include "CImage.h" #include "os.h" -#ifdef _IRR_USE_SDL_DEVICE_ +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ #include #endif @@ -29,210 +29,296 @@ namespace video // ----------------------------------------------------------------------- // WINDOWS CONSTRUCTOR // ----------------------------------------------------------------------- -#ifdef _IRR_USE_WINDOWS_DEVICE_ +#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ //! Windows constructor and init code COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params, - io::IFileSystem* io) + io::IFileSystem* io, CIrrDeviceWin32* device) : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), - AntiAlias(params.AntiAlias), RenderTargetTexture(0), LastSetLight(-1), - CurrentRendertargetSize(0,0), - HDc(0), Window(static_cast(params.WindowId)), HRc(0) + AntiAlias(params.AntiAlias), RenderTargetTexture(0), + CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), + CurrentTarget(ERT_FRAME_BUFFER), + Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), + HDc(0), Window(static_cast(params.WindowId)), Device(device), + DeviceType(EIDT_WIN32) { #ifdef _DEBUG setDebugName("COpenGLDriver"); #endif } -//! inits the open gl driver -bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params) + +bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceWin32* device) { - // Set up ixel format descriptor with desired parameters + if (videoData.OpenGLWin32.HWnd && videoData.OpenGLWin32.HDc && videoData.OpenGLWin32.HRc) + { + if (!wglMakeCurrent((HDC)videoData.OpenGLWin32.HDc, (HGLRC)videoData.OpenGLWin32.HRc)) + { + os::Printer::log("Render Context switch failed."); + return false; + } + else + { + HDc = (HDC)videoData.OpenGLWin32.HDc; + } + } + // set back to main context + else if (HDc != ExposedData.OpenGLWin32.HDc) + { + if (!wglMakeCurrent((HDC)ExposedData.OpenGLWin32.HDc, (HGLRC)ExposedData.OpenGLWin32.HRc)) + { + os::Printer::log("Render Context switch failed."); + return false; + } + else + { + HDc = (HDC)ExposedData.OpenGLWin32.HDc; + } + } + return true; +} + + +//! inits the open gl driver +bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDeviceWin32* device) +{ + // Create a window to test antialiasing support + const fschar_t* ClassName = __TEXT("GLCIrrDeviceWin32"); + HINSTANCE lhInstance = GetModuleHandle(0); + + // Register Class + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)DefWindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = lhInstance; + wcex.hIcon = NULL; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = 0; + wcex.lpszClassName = ClassName; + wcex.hIconSm = 0; + wcex.hIcon = 0; + RegisterClassEx(&wcex); + + RECT clientSize; + clientSize.top = 0; + clientSize.left = 0; + clientSize.right = params.WindowSize.Width; + clientSize.bottom = params.WindowSize.Height; + + DWORD style = WS_POPUP; + if (!params.Fullscreen) + style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + + AdjustWindowRect(&clientSize, style, FALSE); + + const s32 realWidth = clientSize.right - clientSize.left; + const s32 realHeight = clientSize.bottom - clientSize.top; + + const s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; + const s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; + + HWND temporary_wnd=CreateWindow(ClassName, __TEXT(""), style, windowLeft, + windowTop, realWidth, realHeight, NULL, NULL, lhInstance, NULL); + + if (!temporary_wnd) + { + os::Printer::log("Cannot create a temporary window.", ELL_ERROR); + return false; + } + + HDc = GetDC(temporary_wnd); + + // Set up pixel format descriptor with desired parameters PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor - 1, // Version Number - PFD_DRAW_TO_WINDOW | // Format Must Support Window - PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - PFD_DOUBLEBUFFER, // Must Support Double Buffering - PFD_TYPE_RGBA, // Request An RGBA Format - params.Bits, // Select Our Color Depth - 0, 0, 0, 0, 0, 0, // Color Bits Ignored - 0, // No Alpha Buffer - 0, // Shift Bit Ignored - 0, // No Accumulation Buffer - 0, 0, 0, 0, // Accumulation Bits Ignored - 24, // Z-Buffer (Depth Buffer) - params.Stencilbuffer ? 1 : 0, // Stencil Buffer Depth - 0, // No Auxiliary Buffer - PFD_MAIN_PLANE, // Main Drawing Layer - 0, // Reserved - 0, 0, 0 // Layer Masks Ignored + sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + 1, // Version Number + PFD_DRAW_TO_WINDOW | // Format Must Support Window + PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + (params.Doublebuffer?PFD_DOUBLEBUFFER:0) | // Must Support Double Buffering + (params.Stereobuffer?PFD_STEREO:0), // Must Support Stereo Buffer + PFD_TYPE_RGBA, // Request An RGBA Format + params.Bits, // Select Our Color Depth + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0, // No Alpha Buffer + 0, // Shift Bit Ignored + 0, // No Accumulation Buffer + 0, 0, 0, 0, // Accumulation Bits Ignored + params.ZBufferBits, // Z-Buffer (Depth Buffer) + params.Stencilbuffer ? 1 : 0, // Stencil Buffer Depth + 0, // No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0, // Reserved + 0, 0, 0 // Layer Masks Ignored }; GLuint PixelFormat; - if (AntiAlias) + for (u32 i=0; i<5; ++i) { - // Create a window to test antialiasing support - const c8* ClassName = "GLCIrrDeviceWin32"; - HINSTANCE lhInstance = GetModuleHandle(0); - - // Register Class - WNDCLASSEX wcex; - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = (WNDPROC)DefWindowProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = lhInstance; - wcex.hIcon = NULL; - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszMenuName = 0; - wcex.lpszClassName = ClassName; - wcex.hIconSm = 0; - wcex.hIcon = 0; - - RegisterClassEx(&wcex); - RECT clientSize; - clientSize.top = 0; - clientSize.left = 0; - clientSize.right = params.WindowSize.Width; - clientSize.bottom = params.WindowSize.Height; - - DWORD style = WS_POPUP; - - if (!params.Fullscreen) - style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; - - AdjustWindowRect(&clientSize, style, FALSE); - - const s32 realWidth = clientSize.right - clientSize.left; - const s32 realHeight = clientSize.bottom - clientSize.top; - - const s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; - const s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; - - HWND temporary_wnd=CreateWindow(ClassName, "", style, windowLeft, windowTop, - realWidth, realHeight, NULL, NULL, lhInstance, NULL); - - if(!temporary_wnd) + if (i == 1) { - os::Printer::log("Cannot create a temporary window.", ELL_ERROR); - return false; - } - - HDc = GetDC(temporary_wnd); - for (u32 i=0; i<5; ++i) - { - if (i == 1) + if (params.Stencilbuffer) { - if (params.Stencilbuffer) - { - os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); - params.Stencilbuffer = false; - pfd.cStencilBits = 0; - } - else - continue; + os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); + params.Stencilbuffer = false; + pfd.cStencilBits = 0; } else - if (i == 2) - { - pfd.cDepthBits = 24; - } - if (i == 3) - { - if (params.Bits!=16) - pfd.cDepthBits = 16; - else - continue; - } - else - if (i == 4) - { - os::Printer::log("Cannot create a GL device context", "No suitable format for temporary window.", ELL_ERROR); - ReleaseDC(temporary_wnd, HDc); - DestroyWindow(temporary_wnd); - return false; - } - - // choose pixelformat - PixelFormat = ChoosePixelFormat(HDc, &pfd); - if (PixelFormat) - break; + continue; } - - SetPixelFormat(HDc, PixelFormat, &pfd); - HRc=wglCreateContext(HDc); - if(!HRc) + else + if (i == 2) { - os::Printer::log("Cannot create a temporary GL rendering context.", ELL_ERROR); + pfd.cDepthBits = 24; + } + if (i == 3) + { + if (params.Bits!=16) + pfd.cDepthBits = 16; + else + continue; + } + else + if (i == 4) + { + // try single buffer + if (params.Doublebuffer) + pfd.dwFlags &= ~PFD_DOUBLEBUFFER; + else + continue; + } + else + if (i == 5) + { + os::Printer::log("Cannot create a GL device context", "No suitable format for temporary window.", ELL_ERROR); ReleaseDC(temporary_wnd, HDc); DestroyWindow(temporary_wnd); return false; } - if(!wglMakeCurrent(HDc, HRc)) - { - os::Printer::log("Cannot activate a temporary GL rendering context.", ELL_ERROR); - wglDeleteContext(HRc); - ReleaseDC(temporary_wnd, HDc); - DestroyWindow(temporary_wnd); - return false; - } + // choose pixelformat + PixelFormat = ChoosePixelFormat(HDc, &pfd); + if (PixelFormat) + break; + } - PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat_ARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); - if(wglChoosePixelFormat_ARB) - { - // This value determines the number of samples used for antialiasing - // valid numbers are 2, 4, 8. My experience is that 8 does not - // show a big improvement over 4, but 4 shows a big improvement over - // 2. - const s32 numSamples = 4; - f32 fAttributes[] = - { - 0.0, 0.0 - }; - - s32 iAttributes[] = - { - WGL_DRAW_TO_WINDOW_ARB,GL_TRUE, - WGL_SUPPORT_OPENGL_ARB,GL_TRUE, - WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, - WGL_COLOR_BITS_ARB,(params.Bits==32) ? 24 : 15, - WGL_ALPHA_BITS_ARB,(params.Bits==32) ? 8 : 1, - WGL_DEPTH_BITS_ARB,params.ZBufferBits, - WGL_STENCIL_BITS_ARB,(params.Stencilbuffer) ? 1 : 0, - WGL_DOUBLE_BUFFER_ARB,GL_TRUE, - WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, - WGL_SAMPLES_ARB,numSamples, - 0,0 - }; - s32 rv=0; - - // Try to get an acceptable pixel format - while(rv==0 && iAttributes[19]>1) - { - s32 pixelFormat=0; - u32 numFormats=0; - const s32 valid = wglChoosePixelFormat_ARB(HDc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); - - if(valid && numFormats>0) - rv = pixelFormat; - else - iAttributes[19] >>= 1; - } - if(rv) - PixelFormat=rv; - } - - wglMakeCurrent(HDc, NULL); - wglDeleteContext(HRc); + SetPixelFormat(HDc, PixelFormat, &pfd); + HGLRC hrc=wglCreateContext(HDc); + if (!hrc) + { + os::Printer::log("Cannot create a temporary GL rendering context.", ELL_ERROR); ReleaseDC(temporary_wnd, HDc); DestroyWindow(temporary_wnd); + return false; } + SExposedVideoData data; + data.OpenGLWin32.HDc = HDc; + data.OpenGLWin32.HRc = hrc; + data.OpenGLWin32.HWnd = temporary_wnd; + + + if (!changeRenderContext(data, device)) + { + os::Printer::log("Cannot activate a temporary GL rendering context.", ELL_ERROR); + wglDeleteContext(hrc); + ReleaseDC(temporary_wnd, HDc); + DestroyWindow(temporary_wnd); + return false; + } + +#ifdef _DEBUG + core::stringc wglExtensions; +#ifdef WGL_ARB_extensions_string + PFNWGLGETEXTENSIONSSTRINGARBPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); + if (irrGetExtensionsString) + wglExtensions = irrGetExtensionsString(HDc); +#elif defined(WGL_EXT_extensions_string) + PFNWGLGETEXTENSIONSSTRINGEXTPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT"); + if (irrGetExtensionsString) + wglExtensions = irrGetExtensionsString(HDc); +#endif + os::Printer::log("WGL_extensions", wglExtensions); +#endif + +#ifdef WGL_ARB_pixel_format + PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat_ARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); + if (wglChoosePixelFormat_ARB) + { + // This value determines the number of samples used for antialiasing + // My experience is that 8 does not show a big + // improvement over 4, but 4 shows a big improvement + // over 2. + + if(AntiAlias > 32) + AntiAlias = 32; + + f32 fAttributes[] = {0.0, 0.0}; + s32 iAttributes[] = + { + WGL_DRAW_TO_WINDOW_ARB,GL_TRUE, + WGL_SUPPORT_OPENGL_ARB,GL_TRUE, + WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, + WGL_COLOR_BITS_ARB,(params.Bits==32) ? 24 : 15, + WGL_ALPHA_BITS_ARB,(params.Bits==32) ? 8 : 1, + WGL_DEPTH_BITS_ARB,params.ZBufferBits, // 10,11 + WGL_STENCIL_BITS_ARB,(params.Stencilbuffer) ? 1 : 0, + WGL_DOUBLE_BUFFER_ARB,(params.Doublebuffer) ? GL_TRUE : GL_FALSE, + WGL_STEREO_ARB,(params.Stereobuffer) ? GL_TRUE : GL_FALSE, +#ifdef WGL_ARB_multisample + WGL_SAMPLE_BUFFERS_ARB, 1, + WGL_SAMPLES_ARB,AntiAlias, // 20,21 +#elif defined(WGL_EXT_multisample) + WGL_SAMPLE_BUFFERS_EXT, 1, + WGL_SAMPLES_EXT,AntiAlias, // 20,21 +#elif defined(WGL_3DFX_multisample) + WGL_SAMPLE_BUFFERS_3DFX, 1, + WGL_SAMPLES_3DFX,AntiAlias, // 20,21 +#endif + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + // other possible values: + // WGL_ARB_pixel_format_float: WGL_TYPE_RGBA_FLOAT_ARB + // WGL_EXT_pixel_format_packed_float: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT +#if 0 +#ifdef WGL_EXT_framebuffer_sRGB + WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, GL_FALSE, +#endif +#endif + 0,0 + }; + + s32 rv=0; + // Try to get an acceptable pixel format + while(rv==0 && iAttributes[21]>1) + { + s32 pixelFormat=0; + u32 numFormats=0; + const s32 valid = wglChoosePixelFormat_ARB(HDc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); + + if (valid && numFormats>0) + rv = pixelFormat; + else + iAttributes[21] -= 1; + } + if (rv) + { + PixelFormat=rv; + AntiAlias=iAttributes[21]; + } + } + else +#endif + AntiAlias=0; + + wglMakeCurrent(HDc, NULL); + wglDeleteContext(hrc); + ReleaseDC(temporary_wnd, HDc); + DestroyWindow(temporary_wnd); + // get hdc HDc=GetDC(Window); if (!HDc) @@ -242,7 +328,7 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params) } // search for pixel format the simple way - if (!AntiAlias) + if (AntiAlias < 2) { for (u32 i=0; i<5; ++i) { @@ -284,25 +370,46 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params) } // set pixel format - if(!SetPixelFormat(HDc, PixelFormat, &pfd)) + if (!SetPixelFormat(HDc, PixelFormat, &pfd)) { os::Printer::log("Cannot set the pixel format.", ELL_ERROR); return false; } // create rendering context - HRc=wglCreateContext(HDc); - if (!HRc) +#ifdef WGL_ARB_create_context + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs_ARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); + if (wglCreateContextAttribs_ARB) + { + int iAttribs[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, 3, + WGL_CONTEXT_MINOR_VERSION_ARB, 1, + 0 + }; + hrc=wglCreateContextAttribs_ARB(HDc, 0, iAttribs); + } + else +#endif + hrc=wglCreateContext(HDc); + + if (!hrc) { os::Printer::log("Cannot create a GL rendering context.", ELL_ERROR); return false; } + // set exposed data + ExposedData.OpenGLWin32.HDc = HDc; + ExposedData.OpenGLWin32.HRc = hrc; + ExposedData.OpenGLWin32.HWnd = Window; + // activate rendering context - if(!wglMakeCurrent(HDc, HRc)) + + if (!changeRenderContext(ExposedData, device)) { os::Printer::log("Cannot activate GL rendering context", ELL_ERROR); - wglDeleteContext(HRc); + wglDeleteContext(hrc); return false; } @@ -325,31 +432,33 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params) genericDriverInit(params.WindowSize, params.Stencilbuffer); +#ifdef WGL_EXT_swap_control + PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; + // vsync extension + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); // set vsync if (wglSwapIntervalEXT) wglSwapIntervalEXT(params.Vsync ? 1 : 0); - - // set exposed data - ExposedData.OpenGLWin32.HDc = HDc; - ExposedData.OpenGLWin32.HRc = HRc; - ExposedData.OpenGLWin32.HWnd = Window; - +#endif return true; } -#endif //IRR_USE_WINDOWS_DEVICE_ +#endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ // ----------------------------------------------------------------------- // MacOSX CONSTRUCTOR // ----------------------------------------------------------------------- -#ifdef _IRR_USE_OSX_DEVICE_ +#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ //! Windows constructor and init code COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceMacOSX *device) : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), - AntiAlias(params.AntiAlias), RenderTargetTexture(0), LastSetLight(-1), - CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), _device(device) + AntiAlias(params.AntiAlias), RenderTargetTexture(0), + CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), + CurrentTarget(ERT_FRAME_BUFFER), + Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), + Device(device), DeviceType(EIDT_OSX) { #ifdef _DEBUG setDebugName("COpenGLDriver"); @@ -362,26 +471,70 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, // ----------------------------------------------------------------------- // LINUX CONSTRUCTOR // ----------------------------------------------------------------------- -#ifdef _IRR_USE_LINUX_DEVICE_ +#ifdef _IRR_COMPILE_WITH_X11_DEVICE_ //! Linux constructor and init code COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, - io::IFileSystem* io) + io::IFileSystem* io, CIrrDeviceLinux* device) : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), - RenderTargetTexture(0), LastSetLight(-1), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8) + RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), + CurrentTarget(ERT_FRAME_BUFFER), + Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), + Device(device), DeviceType(EIDT_X11) { #ifdef _DEBUG setDebugName("COpenGLDriver"); #endif +} + + +bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceLinux* device) +{ + if (videoData.OpenGLLinux.X11Display && videoData.OpenGLLinux.X11Window && videoData.OpenGLLinux.X11Context) + { + if (!glXMakeCurrent((Display*)videoData.OpenGLLinux.X11Display, videoData.OpenGLLinux.X11Window, (GLXContext)videoData.OpenGLLinux.X11Context)) + { + os::Printer::log("Render Context switch failed."); + return false; + } + else + { + Drawable = videoData.OpenGLLinux.X11Window; + X11Display = (Display*)videoData.OpenGLLinux.X11Display; + } + } + // set back to main context + else if (X11Display != ExposedData.OpenGLLinux.X11Display) + { + if (!glXMakeCurrent((Display*)ExposedData.OpenGLLinux.X11Display, ExposedData.OpenGLLinux.X11Window, (GLXContext)ExposedData.OpenGLLinux.X11Context)) + { + os::Printer::log("Render Context switch failed."); + return false; + } + else + { + Drawable = ExposedData.OpenGLLinux.X11Window; + X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; + } + } + return true; +} + + +//! inits the open gl driver +bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDeviceLinux* device) +{ ExposedData.OpenGLLinux.X11Context = glXGetCurrentContext(); ExposedData.OpenGLLinux.X11Display = glXGetCurrentDisplay(); ExposedData.OpenGLLinux.X11Window = (unsigned long)params.WindowId; Drawable = glXGetCurrentDrawable(); + X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; genericDriverInit(params.WindowSize, params.Stencilbuffer); // set vsync + //TODO: Check GLX_EXT_swap_control and GLX_MESA_swap_control #ifdef GLX_SGI_swap_control #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (params.Vsync && glxSwapIntervalSGI) @@ -391,22 +544,26 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, glXSwapIntervalSGI(1); #endif #endif + return true; } -#endif // _IRR_USE_LINUX_DEVICE_ +#endif // _IRR_COMPILE_WITH_X11_DEVICE_ // ----------------------------------------------------------------------- // SDL CONSTRUCTOR // ----------------------------------------------------------------------- -#ifdef _IRR_USE_SDL_DEVICE_ +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ //! SDL constructor and init code COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, - io::IFileSystem* io) + io::IFileSystem* io, CIrrDeviceSDL* device) : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), - RenderTargetTexture(0), LastSetLight(-1), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8) + RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), + CurrentTarget(ERT_FRAME_BUFFER), + Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), + Device(device), DeviceType(EIDT_SDL) { #ifdef _DEBUG setDebugName("COpenGLDriver"); @@ -415,12 +572,14 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, genericDriverInit(params.WindowSize, params.Stencilbuffer); } -#endif // _IRR_USE_SDL_DEVICE_ +#endif // _IRR_COMPILE_WITH_SDL_DEVICE_ //! destructor COpenGLDriver::~COpenGLDriver() { + RequestedLights.clear(); + deleteMaterialRenders(); // I get a blue screen on my laptop, when I do not delete the @@ -428,18 +587,22 @@ COpenGLDriver::~COpenGLDriver() deleteAllTextures(); -#ifdef _IRR_USE_WINDOWS_DEVICE_ - if (HRc) +#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + if (DeviceType == EIDT_WIN32) { - if (!wglMakeCurrent(0, 0)) - os::Printer::log("Release of dc and rc failed.", ELL_WARNING); - if (!wglDeleteContext(HRc)) - os::Printer::log("Release of rendering context failed.", ELL_WARNING); + if (ExposedData.OpenGLWin32.HRc) + { + if (!wglMakeCurrent(0, 0)) + os::Printer::log("Release of dc and rc failed.", ELL_WARNING); + + if (!wglDeleteContext((HGLRC)ExposedData.OpenGLWin32.HRc)) + os::Printer::log("Release of rendering context failed.", ELL_WARNING); + } + + if (HDc) + ReleaseDC(Window, HDc); } - - if (HDc) - ReleaseDC(Window, HDc); #endif } @@ -447,7 +610,7 @@ COpenGLDriver::~COpenGLDriver() // METHODS // ----------------------------------------------------------------------- -bool COpenGLDriver::genericDriverInit(const core::dimension2d& screenSize, bool stencilBuffer) +bool COpenGLDriver::genericDriverInit(const core::dimension2d& screenSize, bool stencilBuffer) { Name=L"OpenGL "; Name.append(glGetString(GL_VERSION)); @@ -462,7 +625,7 @@ bool COpenGLDriver::genericDriverInit(const core::dimension2d& screenSize, if (renderer && vendor) { os::Printer::log(reinterpret_cast(renderer), reinterpret_cast(vendor), ELL_INFORMATION); - vendorName = reinterpret_cast(vendor); + VendorName = reinterpret_cast(vendor); } u32 i; @@ -485,9 +648,12 @@ bool COpenGLDriver::genericDriverInit(const core::dimension2d& screenSize, // Reset The Current Viewport glViewport(0, 0, screenSize.Width, screenSize.Height); -// This needs an SMaterial flag to enable/disable later on, but should become default sometimes -// glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); -// glEnable(GL_COLOR_MATERIAL); + UserClipPlanes.reallocate(MaxUserClipPlanes); + for (i=0; i(i), core::IdentityMatrix); setAmbientLight(SColorf(0.0f,0.0f,0.0f,0.0f)); #ifdef GL_EXT_separate_specular_color @@ -502,28 +668,14 @@ bool COpenGLDriver::genericDriverInit(const core::dimension2d& screenSize, glClearDepth(1.0); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); glDepthFunc(GL_LEQUAL); - glFrontFace( GL_CW ); - - if (AntiAlias) - { - if (MultiSamplingExtension) - glEnable(GL_MULTISAMPLE_ARB); - - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glEnable(GL_LINE_SMOOTH); - } -// currently disabled, because often in software, and thus very slow -// glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); -// glEnable(GL_POINT_SMOOTH); - - UserClipPlane.reallocate(MaxUserClipPlanes); - UserClipPlaneEnabled.reallocate(MaxUserClipPlanes); - for (i=0; i& screenSize, glAlphaFunc(GL_GREATER, 0.f); // set fog mode - setFog(FogColor, LinearFog, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); + setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); // create matrix for flipping textures TextureFlipMatrix.buildTextureTransform(0.0f, core::vector2df(0,0), core::vector2df(0,1.0f), core::vector2df(1.0f,-1.0f)); + // We need to reset once more at the beginning of the first rendering. + // This fixes problems with intermediate changes to the material during texture load. + ResetRenderStates = true; + return true; } @@ -601,31 +757,45 @@ bool COpenGLDriver::endScene() glFlush(); -#ifdef _IRR_USE_WINDOWS_DEVICE_ - return SwapBuffers(HDc) == TRUE; -#elif defined(_IRR_USE_LINUX_DEVICE_) - glXSwapBuffers((Display*)ExposedData.OpenGLLinux.X11Display, Drawable); - return true; -#elif defined(_IRR_USE_OSX_DEVICE_) - _device->flush(); - return true; -#elif defined(_IRR_USE_SDL_DEVICE_) - SDL_GL_SwapBuffers(); - return true; -#else - return false; +#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + if (DeviceType == EIDT_WIN32) + return SwapBuffers(HDc) == TRUE; #endif + +#ifdef _IRR_COMPILE_WITH_X11_DEVICE_ + if (DeviceType == EIDT_X11) + { + glXSwapBuffers(X11Display, Drawable); + return true; + } +#endif + +#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ + if (DeviceType == EIDT_OSX) + { + Device->flush(); + return true; + } +#endif + +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ + if (DeviceType == EIDT_SDL) + { + SDL_GL_SwapBuffers(); + return true; + } +#endif + + // todo: console device present + + return false; } -//! clears the zbuffer -bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, - void* windowId, core::rect* sourceRect) +//! clears the zbuffer and color buffer +void COpenGLDriver::clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); - GLbitfield mask = 0; - if (backBuffer) { const f32 inv = 1.0f / 255.0f; @@ -642,7 +812,31 @@ bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, mask |= GL_DEPTH_BUFFER_BIT; } + if (stencilBuffer) + mask |= GL_STENCIL_BUFFER_BIT; + glClear(mask); +} + + +//! init call for rendering start +bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, + const SExposedVideoData& videoData, core::rect* sourceRect) +{ + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + + changeRenderContext(videoData, Device); + +#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_) + if (DeviceType == EIDT_SDL) + { + // todo: SDL sets glFrontFace(GL_CCW) after driver creation, + // it would be better if this was fixed elsewhere. + glFrontFace(GL_CW); + } +#endif + + clearBuffers(backBuffer, zBuffer, false, color); return true; } @@ -660,7 +854,7 @@ void COpenGLDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matri Matrices[state] = mat; Transformation3DChanged = true; - switch(state) + switch (state) { case ETS_VIEW: case ETS_WORLD: @@ -670,7 +864,7 @@ void COpenGLDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matri glLoadMatrixf((Matrices[ETS_VIEW] * Matrices[ETS_WORLD]).pointer()); // we have to update the clip planes to the latest view matrix for (u32 i=0; i= MATERIAL_MAX_TEXTURES) + break; + const bool isRTT = Material.getTexture(i) && Material.getTexture(i)->isRenderTarget(); if (MultiTextureExtension) extGlActiveTexture(GL_TEXTURE0_ARB + i); glMatrixMode(GL_TEXTURE); - if (mat.isIdentity() && !isRTT) + if (!isRTT && mat.isIdentity() ) glLoadIdentity(); else { @@ -710,11 +906,10 @@ void COpenGLDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matri } break; } - default: - break; } } + bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) { if (!HWBuffer) @@ -743,7 +938,7 @@ bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) const S3DVertex* po = static_cast(vertices); for (u32 i=0; i(vertices); for (u32 i=0; i(vertices); for (u32 i=0; ivbo_verticesID) { extGlGenBuffers(1, &HWBuffer->vbo_verticesID); - if (!HWBuffer->vbo_verticesID) return false; + if (!HWBuffer->vbo_verticesID) + return false; newBuffer=true; } else if (HWBuffer->vbo_verticesSize < vertexCount*vertexSize) @@ -786,7 +982,7 @@ bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) newBuffer=true; } - extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID ); + extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); //copy data to graphics card glGetError(); // clear error storage @@ -818,7 +1014,7 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) if (!HWBuffer) return false; - if(!FeatureAvailable[IRR_ARB_vertex_buffer_object]) + if (!FeatureAvailable[IRR_ARB_vertex_buffer_object]) return false; #if defined(GL_ARB_vertex_buffer_object) @@ -830,12 +1026,12 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) GLenum indexSize; switch (mb->getIndexType()) { - case (EIT_16BIT): + case EIT_16BIT: { indexSize=sizeof(u16); break; } - case (EIT_32BIT): + case EIT_32BIT: { indexSize=sizeof(u32); break; @@ -852,7 +1048,8 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) if (!HWBuffer->vbo_indicesID) { extGlGenBuffers(1, &HWBuffer->vbo_indicesID); - if (!HWBuffer->vbo_indicesID) return false; + if (!HWBuffer->vbo_indicesID) + return false; newBuffer=true; } else if (HWBuffer->vbo_indicesSize < indexCount*indexSize) @@ -960,8 +1157,8 @@ COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::I void COpenGLDriver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer) { - if (!_HWBuffer) return; - + if (!_HWBuffer) + return; #if defined(GL_ARB_vertex_buffer_object) SHWBufferLink_opengl *HWBuffer=(SHWBufferLink_opengl*)_HWBuffer; @@ -978,7 +1175,6 @@ void COpenGLDriver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer) #endif CNullDriver::deleteHardwareBuffer(_HWBuffer); - } @@ -988,16 +1184,13 @@ void COpenGLDriver::drawHardwareBuffer(SHWBufferLink *_HWBuffer) if (!_HWBuffer) return; - SHWBufferLink_opengl *HWBuffer=(SHWBufferLink_opengl*)_HWBuffer; - - updateHardwareBuffer(HWBuffer); //check if update is needed - - HWBuffer->LastUsed=0;//reset count + updateHardwareBuffer(_HWBuffer); //check if update is needed + _HWBuffer->LastUsed=0; //reset count #if defined(GL_ARB_vertex_buffer_object) + SHWBufferLink_opengl *HWBuffer=(SHWBufferLink_opengl*)_HWBuffer; + const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; - - const void *vertices=mb->getVertices(); const void *indexList=mb->getIndices(); @@ -1013,17 +1206,12 @@ void COpenGLDriver::drawHardwareBuffer(SHWBufferLink *_HWBuffer) indexList=0; } - drawVertexPrimitiveList(vertices, mb->getVertexCount(), indexList, mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType()); if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) extGlBindBuffer(GL_ARRAY_BUFFER, 0); - if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - - #endif } @@ -1049,46 +1237,7 @@ void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCoun CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); if (vertices) - { - // convert colors to gl color format. - vertexCount *= 4; //reused as color component count - ColorBuffer.set_used(vertexCount); - u32 i; - - switch (vType) - { - case EVT_STANDARD: - { - const S3DVertex* p = static_cast(vertices); - for ( i=0; iColor.toOpenGLColor(&ColorBuffer[i]); - ++p; - } - } - break; - case EVT_2TCOORDS: - { - const S3DVertex2TCoords* p = static_cast(vertices); - for ( i=0; iColor.toOpenGLColor(&ColorBuffer[i]); - ++p; - } - } - break; - case EVT_TANGENTS: - { - const S3DVertexTangents* p = static_cast(vertices); - for ( i=0; iColor.toOpenGLColor(&ColorBuffer[i]); - ++p; - } - } - break; - } - } + createColorBuffer(vertices, vertexCount, vType); // draw everything setRenderStates3DMode(); @@ -1184,7 +1333,7 @@ void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCoun glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(36)); extGlClientActiveTexture(GL_TEXTURE2_ARB); - glEnableClientState ( GL_TEXTURE_COORD_ARRAY ); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (vertices) glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].Binormal); else @@ -1193,16 +1342,85 @@ void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCoun break; } + renderArray(indexList, primitiveCount, pType, iType); + + if (MultiTextureExtension) + { + if (vType==EVT_TANGENTS) + { + extGlClientActiveTexture(GL_TEXTURE2_ARB); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + if ((vType!=EVT_STANDARD) || CurrentTexture[1]) + { + extGlClientActiveTexture(GL_TEXTURE1_ARB); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + extGlClientActiveTexture(GL_TEXTURE0_ARB); + } + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + + +void COpenGLDriver::createColorBuffer(const void* vertices, u32 vertexCount, E_VERTEX_TYPE vType) +{ + // convert colors to gl color format. + vertexCount *= 4; //reused as color component count + ColorBuffer.set_used(vertexCount); + u32 i; + + switch (vType) + { + case EVT_STANDARD: + { + const S3DVertex* p = static_cast(vertices); + for (i=0; iColor.toOpenGLColor(&ColorBuffer[i]); + ++p; + } + } + break; + case EVT_2TCOORDS: + { + const S3DVertex2TCoords* p = static_cast(vertices); + for (i=0; iColor.toOpenGLColor(&ColorBuffer[i]); + ++p; + } + } + break; + case EVT_TANGENTS: + { + const S3DVertexTangents* p = static_cast(vertices); + for (i=0; iColor.toOpenGLColor(&ColorBuffer[i]); + ++p; + } + } + break; + } +} + + +void COpenGLDriver::renderArray(const void* indexList, u32 primitiveCount, + scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) +{ GLenum indexSize=0; switch (iType) { - case (EIT_16BIT): + case EIT_16BIT: { indexSize=GL_UNSIGNED_SHORT; break; } - case (EIT_32BIT): + case EIT_32BIT: { indexSize=GL_UNSIGNED_INT; break; @@ -1218,15 +1436,39 @@ void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCoun if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) glEnable(GL_POINT_SPRITE_ARB); #endif - float quadratic[] = {0.0f, 0.0f, 10.01f}; - extGlPointParameterfv(GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic); - float maxParticleSize=1.0f; - glGetFloatv(GL_POINT_SIZE_MAX_ARB, &maxParticleSize); -// maxParticleSize=maxParticleSizesetActiveTexture(0, Material.getTexture(0)); + if (Material.MaterialType==EMT_ONETEXTURE_BLEND) + { + E_BLEND_FACTOR srcFact; + E_BLEND_FACTOR dstFact; + E_MODULATE_FUNC modulo; + u32 alphaSource; + unpack_texureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam); + setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0); + } + else + setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL); + + if (MultiTextureExtension) + extGlClientActiveTexture(GL_TEXTURE0_ARB); + + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + if (vertices) + glColorPointer(4, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]); + + switch (vType) + { + case EVT_STANDARD: + if (vertices) + { + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].TCoords); + glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].Pos); + } + else + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(S3DVertex), buffer_offset(24)); + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); + glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), 0); + } + + if (MultiTextureExtension && CurrentTexture[1]) + { + extGlClientActiveTexture(GL_TEXTURE1_ARB); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + if (vertices) + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].TCoords); + else + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); + } + break; + case EVT_2TCOORDS: + if (vertices) + { + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].TCoords); + glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].Pos); + } + else + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), buffer_offset(24)); + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(28)); + glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(0)); + } + + if (MultiTextureExtension) + { + extGlClientActiveTexture(GL_TEXTURE1_ARB); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + if (vertices) + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].TCoords2); + else + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(36)); + } + break; + case EVT_TANGENTS: + if (vertices) + { + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].TCoords); + glVertexPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].Pos); + } + else + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), buffer_offset(24)); + glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(28)); + glVertexPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(0)); + } + + break; + } + + renderArray(indexList, primitiveCount, pType, iType); if (MultiTextureExtension) { - if (vType==EVT_TANGENTS) - { - extGlClientActiveTexture(GL_TEXTURE2_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } if ((vType!=EVT_STANDARD) || CurrentTexture[1]) { extGlClientActiveTexture(GL_TEXTURE1_ARB); @@ -1286,11 +1632,148 @@ void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCoun } glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } +//! draws a set of 2d images, using a color and the alpha channel of the +//! texture if desired. +void COpenGLDriver::draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect, + SColor color, + bool useAlphaChannelOfTexture) +{ + if (!texture) + return; + + const u32 drawCount = core::min_(positions.size(), sourceRects.size()); + + // texcoords need to be flipped horizontally for RTTs + const bool isRTT = texture->isRenderTarget(); + const core::dimension2d& ss = texture->getOriginalSize(); + const f32 invW = 1.f / static_cast(ss.Width); + const f32 invH = 1.f / static_cast(ss.Height); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + + disableTextures(1); + if (!setActiveTexture(0, texture)) + return; + setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); + + glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + glBegin(GL_QUADS); + + for (u32 i=0; i targetPos(positions[i]); + core::position2d sourcePos(sourceRects[i].UpperLeftCorner); + // This needs to be signed as it may go negative. + core::dimension2d sourceSize(sourceRects[i].getSize()); + if (clipRect) + { + if (targetPos.X < clipRect->UpperLeftCorner.X) + { + sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; + if (sourceSize.Width <= 0) + continue; + + sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; + targetPos.X = clipRect->UpperLeftCorner.X; + } + + if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) + { + sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; + if (sourceSize.Width <= 0) + continue; + } + + if (targetPos.Y < clipRect->UpperLeftCorner.Y) + { + sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; + if (sourceSize.Height <= 0) + continue; + + sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; + targetPos.Y = clipRect->UpperLeftCorner.Y; + } + + if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) + { + sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; + if (sourceSize.Height <= 0) + continue; + } + } + + // clip these coordinates + + if (targetPos.X<0) + { + sourceSize.Width += targetPos.X; + if (sourceSize.Width <= 0) + continue; + + sourcePos.X -= targetPos.X; + targetPos.X = 0; + } + + if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) + { + sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; + if (sourceSize.Width <= 0) + continue; + } + + if (targetPos.Y<0) + { + sourceSize.Height += targetPos.Y; + if (sourceSize.Height <= 0) + continue; + + sourcePos.Y -= targetPos.Y; + targetPos.Y = 0; + } + + if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) + { + sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; + if (sourceSize.Height <= 0) + continue; + } + + // ok, we've clipped everything. + // now draw it. + + const core::rect tcoords( + sourcePos.X * invW, + (isRTT?(sourcePos.Y + sourceSize.Height):sourcePos.Y) * invH, + (sourcePos.X + sourceSize.Width) * invW, + (isRTT?sourcePos.Y:(sourcePos.Y + sourceSize.Height)) * invH); + + const core::rect poss(targetPos, sourceSize); + + glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); + glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); + + glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); + glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); + + glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); + glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); + + glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); + glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); + } + glEnd(); +} + + //! draws a 2d image, using a color and the alpha channel of the texture if //! desired. The image is drawn at pos, clipped against clipRect (if != 0). //! Only the subtexture defined by sourceRect is used. @@ -1308,6 +1791,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, core::position2d targetPos(pos); core::position2d sourcePos(sourceRect.UpperLeftCorner); + // This needs to be signed as it may go negative. core::dimension2d sourceSize(sourceRect.getSize()); if (clipRect) { @@ -1358,9 +1842,9 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, targetPos.X = 0; } - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - if (targetPos.X + sourceSize.Width > renderTargetSize.Width) + if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; if (sourceSize.Width <= 0) @@ -1377,7 +1861,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, targetPos.Y = 0; } - if (targetPos.Y + sourceSize.Height > renderTargetSize.Height) + if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; if (sourceSize.Height <= 0) @@ -1389,7 +1873,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, // texcoords need to be flipped horizontally for RTTs const bool isRTT = texture->isRenderTarget(); - const core::dimension2d& ss = texture->getOriginalSize(); + const core::dimension2d& ss = texture->getOriginalSize(); const f32 invW = 1.f / static_cast(ss.Width); const f32 invH = 1.f / static_cast(ss.Height); const core::rect tcoords( @@ -1401,7 +1885,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect poss(targetPos, sourceSize); disableTextures(1); - if (!setTexture(0, texture)) + if (!setActiveTexture(0, texture)) return; setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); @@ -1434,7 +1918,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect // texcoords need to be flipped horizontally for RTTs const bool isRTT = texture->isRenderTarget(); - const core::dimension2d& ss = texture->getOriginalSize(); + const core::dimension2d& ss = texture->getOriginalSize(); const f32 invW = 1.f / static_cast(ss.Width); const f32 invH = 1.f / static_cast(ss.Height); const core::rect tcoords( @@ -1454,7 +1938,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect const video::SColor* const useColor = colors ? colors : temp; disableTextures(1); - setTexture(0, texture); + setActiveTexture(0, texture); setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 || useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255, true, useAlphaChannelOfTexture); @@ -1465,7 +1949,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect return; glEnable(GL_SCISSOR_TEST); - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height-clipRect->LowerRightCorner.Y, clipRect->getWidth(), clipRect->getHeight()); } @@ -1511,7 +1995,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, return; disableTextures(1); - if (!setTexture(0, texture)) + if (!setActiveTexture(0, texture)) return; setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); @@ -1522,12 +2006,12 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, return; glEnable(GL_SCISSOR_TEST); - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height-clipRect->LowerRightCorner.Y, clipRect->getWidth(),clipRect->getHeight()); } - const core::dimension2d& ss = texture->getOriginalSize(); + const core::dimension2d& ss = texture->getOriginalSize(); core::position2d targetPos(pos); // texcoords need to be flipped horizontally for RTTs const bool isRTT = texture->isRenderTarget(); @@ -1650,8 +2134,8 @@ void COpenGLDriver::draw2DLine(const core::position2d& start, //! Draws a pixel void COpenGLDriver::drawPixel(u32 x, u32 y, const SColor &color) { - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - if(x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) return; disableTextures(); @@ -1661,9 +2145,9 @@ void COpenGLDriver::drawPixel(u32 x, u32 y, const SColor &color) glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); glVertex2i(x, y); glEnd(); -} +} -bool COpenGLDriver::setTexture(u32 stage, const video::ITexture* texture) +bool COpenGLDriver::setActiveTexture(u32 stage, const video::ITexture* texture) { if (stage >= MaxTextureUnits) return false; @@ -1704,7 +2188,7 @@ bool COpenGLDriver::disableTextures(u32 fromStage) { bool result=true; for (u32 i=fromStage; i= 0; --i) { - setTransform ((E_TRANSFORMATION_STATE) ( ETS_TEXTURE_0 + i ), - material.getTextureMatrix(i)); + setActiveTexture(i, material.getTexture(i)); + setTransform ((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), + Material.getTextureMatrix(i)); } } @@ -1768,7 +2252,7 @@ bool COpenGLDriver::testGLError() { #ifdef _DEBUG GLenum g = glGetError(); - switch(g) + switch (g) { case GL_NO_ERROR: return false; @@ -1821,7 +2305,7 @@ void COpenGLDriver::setRenderStates3DMode() ResetRenderStates = true; } - if ( ResetRenderStates || LastMaterial != Material) + if (ResetRenderStates || LastMaterial != Material) { // unset old material @@ -1845,6 +2329,108 @@ void COpenGLDriver::setRenderStates3DMode() } +//! Get native wrap mode value +GLint COpenGLDriver::getTextureWrapMode(const u8 clamp) +{ + GLint mode=GL_REPEAT; + switch (clamp) + { + case ETC_REPEAT: + mode=GL_REPEAT; + break; + case ETC_CLAMP: + mode=GL_CLAMP; + break; + case ETC_CLAMP_TO_EDGE: +#ifdef GL_VERSION_1_2 + if (Version>101) + mode=GL_CLAMP_TO_EDGE; + else +#endif +#ifdef GL_SGIS_texture_edge_clamp + if (FeatureAvailable[IRR_SGIS_texture_edge_clamp]) + mode=GL_CLAMP_TO_EDGE_SGIS; + else +#endif + // fallback + mode=GL_CLAMP; + break; + case ETC_CLAMP_TO_BORDER: +#ifdef GL_VERSION_1_3 + if (Version>102) + mode=GL_CLAMP_TO_BORDER; + else +#endif +#ifdef GL_ARB_texture_border_clamp + if (FeatureAvailable[IRR_ARB_texture_border_clamp]) + mode=GL_CLAMP_TO_BORDER_ARB; + else +#endif +#ifdef GL_SGIS_texture_border_clamp + if (FeatureAvailable[IRR_SGIS_texture_border_clamp]) + mode=GL_CLAMP_TO_BORDER_SGIS; + else +#endif + // fallback + mode=GL_CLAMP; + break; + case ETC_MIRROR: +#ifdef GL_VERSION_1_4 + if (Version>103) + mode=GL_MIRRORED_REPEAT; + else +#endif +#ifdef GL_ARB_texture_border_clamp + if (FeatureAvailable[IRR_ARB_texture_mirrored_repeat]) + mode=GL_MIRRORED_REPEAT_ARB; + else +#endif +#ifdef GL_IBM_texture_mirrored_repeat + if (FeatureAvailable[IRR_IBM_texture_mirrored_repeat]) + mode=GL_MIRRORED_REPEAT_IBM; + else +#endif + mode=GL_REPEAT; + break; + case ETC_MIRROR_CLAMP: +#ifdef GL_EXT_texture_mirror_clamp + if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) + mode=GL_MIRROR_CLAMP_EXT; + else +#endif +#if defined(GL_ATI_texture_mirror_once) + if (FeatureAvailable[IRR_ATI_texture_mirror_once]) + mode=GL_MIRROR_CLAMP_ATI; + else +#endif + mode=GL_CLAMP; + break; + case ETC_MIRROR_CLAMP_TO_EDGE: +#ifdef GL_EXT_texture_mirror_clamp + if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) + mode=GL_MIRROR_CLAMP_TO_EDGE_EXT; + else +#endif +#if defined(GL_ATI_texture_mirror_once) + if (FeatureAvailable[IRR_ATI_texture_mirror_once]) + mode=GL_MIRROR_CLAMP_TO_EDGE_ATI; + else +#endif + mode=GL_CLAMP; + break; + case ETC_MIRROR_CLAMP_TO_BORDER: +#ifdef GL_EXT_texture_mirror_clamp + if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) + mode=GL_MIRROR_CLAMP_TO_BORDER_EXT; + else +#endif + mode=GL_CLAMP; + break; + } + return mode; +} + + void COpenGLDriver::setWrapMode(const SMaterial& material) { // texture address mode @@ -1856,70 +2442,8 @@ void COpenGLDriver::setWrapMode(const SMaterial& material) else if (u>0) break; // stop loop - GLint mode=GL_REPEAT; - switch (material.TextureLayer[u].TextureWrap) - { - case ETC_REPEAT: - mode=GL_REPEAT; - break; - case ETC_CLAMP: - mode=GL_CLAMP; - break; - case ETC_CLAMP_TO_EDGE: -#ifdef GL_VERSION_1_2 - if (Version>101) - mode=GL_CLAMP_TO_EDGE; - else -#endif -#ifdef GL_SGIS_texture_edge_clamp - if (FeatureAvailable[IRR_SGIS_texture_edge_clamp]) - mode=GL_CLAMP_TO_EDGE_SGIS; - else -#endif - // fallback - mode=GL_CLAMP; - break; - case ETC_CLAMP_TO_BORDER: -#ifdef GL_VERSION_1_3 - if (Version>102) - mode=GL_CLAMP_TO_BORDER; - else -#endif -#ifdef GL_ARB_texture_border_clamp - if (FeatureAvailable[IRR_ARB_texture_border_clamp]) - mode=GL_CLAMP_TO_BORDER_ARB; - else -#endif -#ifdef GL_SGIS_texture_border_clamp - if (FeatureAvailable[IRR_SGIS_texture_border_clamp]) - mode=GL_CLAMP_TO_BORDER_SGIS; - else -#endif - // fallback - mode=GL_CLAMP; - break; - case ETC_MIRROR: -#ifdef GL_VERSION_1_4 - if (Version>103) - mode=GL_MIRRORED_REPEAT; - else -#endif -#ifdef GL_ARB_texture_border_clamp - if (FeatureAvailable[IRR_ARB_texture_mirrored_repeat]) - mode=GL_MIRRORED_REPEAT_ARB; - else -#endif -#ifdef GL_IBM_texture_mirrored_repeat - if (FeatureAvailable[IRR_IBM_texture_mirrored_repeat]) - mode=GL_MIRRORED_REPEAT_IBM; - else -#endif - mode=GL_REPEAT; - break; - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[u].TextureWrapU)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[u].TextureWrapV)); } } @@ -1928,54 +2452,101 @@ void COpenGLDriver::setWrapMode(const SMaterial& material) void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderStates) { + if (resetAllRenderStates || + lastmaterial.ColorMaterial != material.ColorMaterial) + { + switch (material.ColorMaterial) + { + case ECM_NONE: + glDisable(GL_COLOR_MATERIAL); + break; + case ECM_DIFFUSE: + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + break; + case ECM_AMBIENT: + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT); + break; + case ECM_EMISSIVE: + glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION); + break; + case ECM_SPECULAR: + glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); + break; + case ECM_DIFFUSE_AND_AMBIENT: + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + break; + } + if (material.ColorMaterial != ECM_NONE) + glEnable(GL_COLOR_MATERIAL); + } + if (resetAllRenderStates || lastmaterial.AmbientColor != material.AmbientColor || lastmaterial.DiffuseColor != material.DiffuseColor || - lastmaterial.SpecularColor != material.SpecularColor || lastmaterial.EmissiveColor != material.EmissiveColor || - lastmaterial.Shininess != material.Shininess) + lastmaterial.ColorMaterial != material.ColorMaterial) { GLfloat color[4]; const f32 inv = 1.0f / 255.0f; - color[0] = material.AmbientColor.getRed() * inv; - color[1] = material.AmbientColor.getGreen() * inv; - color[2] = material.AmbientColor.getBlue() * inv; - color[3] = material.AmbientColor.getAlpha() * inv; - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color); + if ((material.ColorMaterial != video::ECM_AMBIENT) && + (material.ColorMaterial != video::ECM_DIFFUSE_AND_AMBIENT)) + { + color[0] = material.AmbientColor.getRed() * inv; + color[1] = material.AmbientColor.getGreen() * inv; + color[2] = material.AmbientColor.getBlue() * inv; + color[3] = material.AmbientColor.getAlpha() * inv; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color); + } - color[0] = material.DiffuseColor.getRed() * inv; - color[1] = material.DiffuseColor.getGreen() * inv; - color[2] = material.DiffuseColor.getBlue() * inv; - color[3] = material.DiffuseColor.getAlpha() * inv; - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); + if ((material.ColorMaterial != video::ECM_DIFFUSE) && + (material.ColorMaterial != video::ECM_DIFFUSE_AND_AMBIENT)) + { + color[0] = material.DiffuseColor.getRed() * inv; + color[1] = material.DiffuseColor.getGreen() * inv; + color[2] = material.DiffuseColor.getBlue() * inv; + color[3] = material.DiffuseColor.getAlpha() * inv; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); + } + if (material.ColorMaterial != video::ECM_EMISSIVE) + { + 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 || + lastmaterial.ColorMaterial != material.ColorMaterial) + { + 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) + if ((material.Shininess != 0.0f) && + (material.ColorMaterial != video::ECM_SPECULAR)) { #ifdef GL_EXT_separate_specular_color 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 @@ -1988,22 +2559,35 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater else if (i>0) break; - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, +#ifdef GL_EXT_texture_lod_bias + if (FeatureAvailable[IRR_EXT_texture_lod_bias]) + { + if (material.TextureLayer[i].LODBias) + { + const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias); + glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmp); + } + else + glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.f); + } +#endif + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); if (material.getTexture(i) && material.getTexture(i)->hasMipMaps()) - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR : material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST : - GL_NEAREST_MIPMAP_NEAREST ); + GL_NEAREST_MIPMAP_NEAREST); else - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); #ifdef GL_EXT_texture_filter_anisotropic - if (AnisotropyExtension) - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - material.TextureLayer[i].AnisotropicFilter ? MaxAnisotropy : 1.0f ); + if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic]) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1); #endif } @@ -2034,16 +2618,36 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater { switch (material.ZBuffer) { - case 0: + case ECFN_NEVER: glDisable(GL_DEPTH_TEST); break; - case 1: + case ECFN_LESSEQUAL: glEnable(GL_DEPTH_TEST); - glDepthFunc ( GL_LEQUAL ); + glDepthFunc(GL_LEQUAL); break; - case 2: + case ECFN_EQUAL: glEnable(GL_DEPTH_TEST); - glDepthFunc ( GL_EQUAL ); + glDepthFunc(GL_EQUAL); + break; + case ECFN_LESS: + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + break; + case ECFN_NOTEQUAL: + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_NOTEQUAL); + break; + case ECFN_GREATEREQUAL: + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_GEQUAL); + break; + case ECFN_GREATER: + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_GREATER); + break; + case ECFN_ALWAYS: + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); break; } } @@ -2101,11 +2705,74 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater glDisable(GL_NORMALIZE); } + // Color Mask + if (resetAllRenderStates || lastmaterial.ColorMask != material.ColorMask) + { + glColorMask( + (material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, + (material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, + (material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, + (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); + } + // thickness if (resetAllRenderStates || lastmaterial.Thickness != material.Thickness) { - glPointSize(material.Thickness); - glLineWidth(material.Thickness); + if (AntiAlias) + { +// glPointSize(core::clamp(static_cast(material.Thickness), DimSmoothedPoint[0], DimSmoothedPoint[1])); + // we don't use point smoothing + glPointSize(core::clamp(static_cast(material.Thickness), DimAliasedPoint[0], DimAliasedPoint[1])); + glLineWidth(core::clamp(static_cast(material.Thickness), DimSmoothedLine[0], DimSmoothedLine[1])); + } + else + { + glPointSize(core::clamp(static_cast(material.Thickness), DimAliasedPoint[0], DimAliasedPoint[1])); + glLineWidth(core::clamp(static_cast(material.Thickness), DimAliasedLine[0], DimAliasedLine[1])); + } + } + + // Anti aliasing + if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing) + { + if (FeatureAvailable[IRR_ARB_multisample]) + { + if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) + glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); + else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); + + if ((AntiAlias >= 2) && (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))) + { + glEnable(GL_MULTISAMPLE_ARB); +#ifdef GL_NV_multisample_filter_hint + if (FeatureAvailable[IRR_NV_multisample_filter_hint]) + { + if ((material.AntiAliasing & EAAM_QUALITY) == EAAM_QUALITY) + glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); + else + glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); + } +#endif + } + else + glDisable(GL_MULTISAMPLE_ARB); + } + if ((material.AntiAliasing & EAAM_LINE_SMOOTH) != (lastmaterial.AntiAliasing & EAAM_LINE_SMOOTH)) + { + if (material.AntiAliasing & EAAM_LINE_SMOOTH) + glEnable(GL_LINE_SMOOTH); + else if (lastmaterial.AntiAliasing & EAAM_LINE_SMOOTH) + glDisable(GL_LINE_SMOOTH); + } + if ((material.AntiAliasing & EAAM_POINT_SMOOTH) != (lastmaterial.AntiAliasing & EAAM_POINT_SMOOTH)) + { + if (material.AntiAliasing & EAAM_POINT_SMOOTH) + // often in software, and thus very slow + glEnable(GL_POINT_SMOOTH); + else if (lastmaterial.AntiAliasing & EAAM_POINT_SMOOTH) + glDisable(GL_POINT_SMOOTH); + } } setWrapMode(material); @@ -2116,6 +2783,15 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater } +//! Enable the 2d override material +void COpenGLDriver::enableMaterial2D(bool enable) +{ + if (!enable) + CurrentRenderMode = ERM_NONE; + CNullDriver::enableMaterial2D(enable); +} + + //! sets the needed renderstates void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) { @@ -2126,31 +2802,41 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh { if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); - SMaterial mat; - mat.ZBuffer=0; - mat.Lighting=false; - mat.TextureLayer[0].BilinearFilter=false; - setBasicRenderStates(mat, mat, true); - LastMaterial = mat; - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } + if (Transformation3DChanged) + { + glMatrixMode(GL_PROJECTION); - glMatrixMode(GL_PROJECTION); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + core::matrix4 m; + m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0); + m.setTranslation(core::vector3df(-1,1,0)); + glLoadMatrixf(m.pointer()); - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - core::matrix4 m; - m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-renderTargetSize.Height), -1.0, 1.0); - m.setTranslation(core::vector3df(-1,1,0)); - glLoadMatrixf(m.pointer()); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.375, 0.375, 0.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.375, 0.375, 0.0); + // Make sure we set first texture matrix + if (MultiTextureExtension) + extGlActiveTexture(GL_TEXTURE0_ARB); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - - Transformation3DChanged = false; + Transformation3DChanged = false; + } + if (!OverrideMaterial2DEnabled) + { + setBasicRenderStates(InitMaterial2D, LastMaterial, true); + LastMaterial = InitMaterial2D; + } + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + if (OverrideMaterial2DEnabled) + { + OverrideMaterial2D.Lighting=false; + OverrideMaterial2D.ZBuffer=ECFN_NEVER; + OverrideMaterial2D.ZWriteEnable=false; + setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); + LastMaterial = OverrideMaterial2D; } if (alphaChannel || alpha) @@ -2167,11 +2853,14 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh if (texture) { - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (!OverrideMaterial2DEnabled) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + setTransform(ETS_TEXTURE_0, core::IdentityMatrix); if (alphaChannel) { @@ -2182,26 +2871,60 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh } else { - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); - // rgb always modulates - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); +#if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) + if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) + { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); + // rgb always modulates + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); + // rgb always modulates + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); +#endif + } + else +#endif + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } else { if (alpha) { - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); - // rgb always modulates - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); +#if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) + if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) + { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); + // rgb always modulates + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); + // rgb always modulates + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); +#endif + } + else +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else { @@ -2224,28 +2947,50 @@ const wchar_t* COpenGLDriver::getName() const //! deletes all dynamic lights there are void COpenGLDriver::deleteAllDynamicLights() { - for (s32 i=0; i= (s32)RequestedLights.size()) + return; + + RequestedLight & requestedLight = RequestedLights[lightIndex]; + + requestedLight.DesireToBeOn = turnOn; + + if(turnOn) + { + if(-1 == requestedLight.HardwareLightIndex) + assignHardwareLight(lightIndex); + } + else + { + if(-1 != requestedLight.HardwareLightIndex) + { + // It's currently assigned, so free up the hardware light + glDisable(requestedLight.HardwareLightIndex); + requestedLight.HardwareLightIndex = -1; + + // Now let the first light that's waiting on a free hardware light grab it + for(u32 requested = 0; requested < RequestedLights.size(); ++requested) + if(RequestedLights[requested].DesireToBeOn + && + -1 == RequestedLights[requested].HardwareLightIndex) + { + assignHardwareLight(requested); + break; + } + } + } +} + + //! returns the maximal amount of dynamic lights the device can handle u32 COpenGLDriver::getMaximalDynamicLightAmount() const { @@ -2380,7 +3164,7 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3 glDisable(GL_FOG); glDepthFunc(GL_LEQUAL); glDepthMask(GL_FALSE); // no depth buffer writing - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); // no color buffer drawing + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no color buffer drawing glEnable(GL_STENCIL_TEST); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0.0f, 1.0f); @@ -2390,6 +3174,16 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3 glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); + GLenum incr = GL_INCR; + GLenum decr = GL_DECR; +#ifdef GL_EXT_stencil_wrap + if (FeatureAvailable[IRR_EXT_stencil_wrap]) + { + incr = GL_INCR_WRAP_EXT; + decr = GL_DECR_WRAP_EXT; + } +#endif + // The first parts are not correctly working, yet. #if 0 #ifdef GL_EXT_stencil_two_side @@ -2406,18 +3200,12 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3 // ZPASS Method extGlActiveStencilFace(GL_BACK); - if (FeatureAvailable[IRR_EXT_stencil_wrap]) - glStencilOp(GL_KEEP, GL_KEEP, GL_DECR_WRAP_EXT); - else - glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); + glStencilOp(GL_KEEP, GL_KEEP, decr); glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); extGlActiveStencilFace(GL_FRONT); - if (FeatureAvailable[IRR_EXT_stencil_wrap]) - glStencilOp(GL_KEEP, GL_KEEP, GL_INCR_WRAP_EXT); - else - glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); + glStencilOp(GL_KEEP, GL_KEEP, incr); glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); @@ -2428,18 +3216,12 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3 // ZFAIL Method extGlActiveStencilFace(GL_BACK); - if (FeatureAvailable[IRR_EXT_stencil_wrap]) - glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP); - else - glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); + glStencilOp(GL_KEEP, incr, GL_KEEP); glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); extGlActiveStencilFace(GL_FRONT); - if (FeatureAvailable[IRR_EXT_stencil_wrap]) - glStencilOp(GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP); - else - glStencilOp(GL_KEEP, GL_DECR, GL_KEEP); + glStencilOp(GL_KEEP, decr, GL_KEEP); glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); @@ -2455,8 +3237,8 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3 { // ZPASS Method - extGlStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR); - extGlStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR); + extGlStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, decr); + extGlStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, incr); extGlStencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, 0, ~0); glStencilMask(~0); @@ -2466,8 +3248,8 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3 { // ZFAIL Method - extGlStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR, GL_KEEP); - extGlStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR, GL_KEEP); + extGlStencilOpSeparate(GL_BACK, GL_KEEP, incr, GL_KEEP); + extGlStencilOpSeparate(GL_FRONT, GL_KEEP, decr, GL_KEEP); extGlStencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, 0, ~0); glDrawArrays(GL_TRIANGLES,0,count); @@ -2482,22 +3264,22 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3 // ZPASS Method glCullFace(GL_BACK); - glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); + glStencilOp(GL_KEEP, GL_KEEP, incr); glDrawArrays(GL_TRIANGLES,0,count); glCullFace(GL_FRONT); - glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); + glStencilOp(GL_KEEP, GL_KEEP, decr); glDrawArrays(GL_TRIANGLES,0,count); } else { // ZFAIL Method - glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); + glStencilOp(GL_KEEP, incr, GL_KEEP); glCullFace(GL_FRONT); glDrawArrays(GL_TRIANGLES,0,count); - glStencilOp(GL_KEEP, GL_DECR, GL_KEEP); + glStencilOp(GL_KEEP, decr, GL_KEEP); glCullFace(GL_BACK); glDrawArrays(GL_TRIANGLES,0,count); } @@ -2508,7 +3290,6 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3 } - void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge, video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge) { @@ -2518,19 +3299,19 @@ void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor lef disableTextures(); // store attributes - glPushAttrib( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT ); + glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT); - glDisable( GL_LIGHTING ); + glDisable(GL_LIGHTING); glDisable(GL_FOG); glDepthMask(GL_FALSE); - glShadeModel( GL_FLAT ); - glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); + glShadeModel(GL_FLAT); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable( GL_STENCIL_TEST ); + glEnable(GL_STENCIL_TEST); glStencilFunc(GL_NOTEQUAL, 0, ~0); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -2538,45 +3319,59 @@ void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor lef glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); glBegin(GL_QUADS); - glColor4ub (leftDownEdge.getRed(), leftDownEdge.getGreen(), leftDownEdge.getBlue(), leftDownEdge.getAlpha() ); - glVertex3f(-1.1f,-1.1f,0.9f); + glColor4ub(leftDownEdge.getRed(), leftDownEdge.getGreen(), leftDownEdge.getBlue(), leftDownEdge.getAlpha()); + glVertex3f(-1.f,-1.f,-0.9f); - glColor4ub (leftUpEdge.getRed(), leftUpEdge.getGreen(), leftUpEdge.getBlue(), leftUpEdge.getAlpha() ); - glVertex3f(-1.1f, 1.1f,0.9f); + glColor4ub(leftUpEdge.getRed(), leftUpEdge.getGreen(), leftUpEdge.getBlue(), leftUpEdge.getAlpha()); + glVertex3f(-1.f, 1.f,-0.9f); - glColor4ub (rightUpEdge.getRed(), rightUpEdge.getGreen(), rightUpEdge.getBlue(), rightUpEdge.getAlpha() ); - glVertex3f( 1.1f, 1.1f,0.9f); + glColor4ub(rightUpEdge.getRed(), rightUpEdge.getGreen(), rightUpEdge.getBlue(), rightUpEdge.getAlpha()); + glVertex3f(1.f, 1.f,-0.9f); - glColor4ub (rightDownEdge.getRed(), rightDownEdge.getGreen(), rightDownEdge.getBlue(), rightDownEdge.getAlpha() ); - glVertex3f( 1.1f,-1.1f,0.9f); + glColor4ub(rightDownEdge.getRed(), rightDownEdge.getGreen(), rightDownEdge.getBlue(), rightDownEdge.getAlpha()); + glVertex3f(1.f,-1.f,-0.9f); glEnd(); - if (clearStencilBuffer) - glClear(GL_STENCIL_BUFFER_BIT); + clearBuffers(false, false, clearStencilBuffer, 0x0); // restore settings glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); glPopAttrib(); } //! Sets the fog mode. -void COpenGLDriver::setFog(SColor c, bool linearFog, f32 start, +void COpenGLDriver::setFog(SColor c, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { - CNullDriver::setFog(c, linearFog, start, end, density, pixelFog, rangeFog); + CNullDriver::setFog(c, fogType, start, end, density, pixelFog, rangeFog); + + glFogf(GL_FOG_MODE, GLfloat((fogType==EFT_FOG_LINEAR)? GL_LINEAR : (fogType==EFT_FOG_EXP)?GL_EXP:GL_EXP2)); - glFogf(GL_FOG_MODE, GLfloat(linearFog ? GL_LINEAR : GL_EXP)); #ifdef GL_EXT_fog_coord if (FeatureAvailable[IRR_EXT_fog_coord]) glFogi(GL_FOG_COORDINATE_SOURCE, GL_FRAGMENT_DEPTH); #endif +#ifdef GL_NV_fog_distance + if (FeatureAvailable[IRR_NV_fog_distance]) + { + if (rangeFog) + glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV); + else + glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV); + } +#endif - if(linearFog) + if (fogType==EFT_FOG_LINEAR) { glFogf(GL_FOG_START, start); glFogf(GL_FOG_END, end); @@ -2595,7 +3390,6 @@ void COpenGLDriver::setFog(SColor c, bool linearFog, f32 start, } - //! Draws a 3d line. void COpenGLDriver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) @@ -2614,7 +3408,7 @@ void COpenGLDriver::draw3DLine(const core::vector3df& start, //! Only used by the internal engine. Used to notify the driver that //! the window was resized. -void COpenGLDriver::OnResize(const core::dimension2d& size) +void COpenGLDriver::OnResize(const core::dimension2d& size) { CNullDriver::OnResize(size); glViewport(0, 0, size.Width, size.Height); @@ -2694,6 +3488,12 @@ s32 COpenGLDriver::addHighLevelShaderMaterial( const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, + scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) @@ -2701,14 +3501,17 @@ s32 COpenGLDriver::addHighLevelShaderMaterial( s32 nr = -1; COpenGLSLMaterialRenderer* r = new COpenGLSLMaterialRenderer( - this, nr, vertexShaderProgram, vertexShaderEntryPointName, - vsCompileTarget, pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, + this, nr, + vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, + pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, + geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, + inType, outType, verticesOut, callback,getMaterialRenderer(baseMaterial), userData); - r->drop(); return nr; } + //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) IVideoDriver* COpenGLDriver::getVideoDriver() @@ -2717,37 +3520,40 @@ IVideoDriver* COpenGLDriver::getVideoDriver() } -//! Returns pointer to the IGPUProgrammingServices interface. -IGPUProgrammingServices* COpenGLDriver::getGPUProgrammingServices() -{ - return this; -} - - -ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d& size, const c8* name) +ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, + const ECOLOR_FORMAT format) { //disable mip-mapping bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); video::ITexture* rtt = 0; - if (name==0) - name="rt"; #if defined(GL_EXT_framebuffer_object) // if driver supports FrameBufferObjects, use them if (queryFeature(EVDF_FRAMEBUFFER_OBJECT)) { - rtt = new COpenGLFBOTexture(size, name, this); + rtt = new COpenGLFBOTexture(size, name, this, format); if (rtt) { + bool success = false; addTexture(rtt); ITexture* tex = createDepthTexture(rtt); if (tex) { - static_cast(tex)->attach(rtt); + success = static_cast(tex)->attach(rtt); + if ( !success ) + { + removeDepthTexture(tex); + } tex->drop(); } rtt->drop(); + if (!success) + { + removeTexture(rtt); + rtt=0; + } } } else @@ -2755,7 +3561,7 @@ ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d& si { // the simple texture is only possible for size <= screensize // we try to find an optimal size with the original constraints - core::dimension2di destSize(core::min_(size.Width,ScreenSize.Width), core::min_(size.Height,ScreenSize.Height)); + core::dimension2du destSize(core::min_(size.Width,ScreenSize.Width), core::min_(size.Height,ScreenSize.Height)); destSize = destSize.getOptimalSize((size==size.getOptimalSize()), false, false); rtt = addTexture(destSize, name, ECF_A8R8G8B8); if (rtt) @@ -2780,6 +3586,53 @@ u32 COpenGLDriver::getMaximalPrimitiveCount() const } +//! set or reset render target +bool COpenGLDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, + bool clearZBuffer, SColor color) +{ + if (target != CurrentTarget) + setRenderTarget(0, false, false, 0x0); + + if (ERT_RENDER_TEXTURE == target) + { + os::Printer::log("Fatal Error: For render textures call setRenderTarget with the actual texture as first parameter.", ELL_ERROR); + return false; + } + + if (Stereo && (ERT_STEREO_RIGHT_BUFFER == target)) + { + if (Doublebuffer) + glDrawBuffer(GL_BACK_RIGHT); + else + glDrawBuffer(GL_FRONT_RIGHT); + } + else if (Stereo && ERT_STEREO_BOTH_BUFFERS == target) + { + if (Doublebuffer) + glDrawBuffer(GL_BACK); + else + glDrawBuffer(GL_FRONT); + } + else if ((target >= ERT_AUX_BUFFER0) && (target-ERT_AUX_BUFFER0 < MaxAuxBuffers)) + { + glDrawBuffer(GL_AUX0+target-ERT_AUX_BUFFER0); + } + else + { + if (Doublebuffer) + glDrawBuffer(GL_BACK_LEFT); + else + glDrawBuffer(GL_FRONT_LEFT); + // exit with false, but also with working color buffer + if (target != ERT_FRAME_BUFFER) + return false; + } + CurrentTarget=target; + clearBuffers(clearTarget, clearZBuffer, false, color); + return true; +} + + //! set or reset render target bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color) @@ -2794,7 +3647,7 @@ bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuff // check if we should set the previous RT back - setTexture(0, 0); + setActiveTexture(0, 0); ResetRenderStates=true; if (RenderTargetTexture!=0) { @@ -2808,40 +3661,166 @@ bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuff RenderTargetTexture = static_cast(texture); RenderTargetTexture->bindRTT(); CurrentRendertargetSize = texture->getSize(); + CurrentTarget=ERT_RENDER_TEXTURE; } else { glViewport(0,0,ScreenSize.Width,ScreenSize.Height); RenderTargetTexture = 0; - CurrentRendertargetSize = core::dimension2d(0,0); + CurrentRendertargetSize = core::dimension2d(0,0); + CurrentTarget=ERT_FRAME_BUFFER; + glDrawBuffer(Doublebuffer?GL_BACK_LEFT:GL_FRONT_LEFT); } - GLbitfield mask = 0; - if (clearBackBuffer) + clearBuffers(clearBackBuffer, clearZBuffer, false, color); + return true; +} + + +//! Sets multiple render targets +bool COpenGLDriver::setRenderTarget(const core::array& targets, + bool clearBackBuffer, bool clearZBuffer, SColor color) +{ + if (targets.size()==0) + return setRenderTarget(0, clearBackBuffer, clearZBuffer, color); + + u32 maxMultipleRTTs = core::min_(static_cast(MaxMultipleRenderTargets), targets.size()); + + // determine common size + core::dimension2du rttSize = CurrentRendertargetSize; + if (targets[0].TargetType==ERT_RENDER_TEXTURE) { - const f32 inv = 1.0f / 255.0f; - glClearColor(color.getRed() * inv, color.getGreen() * inv, - color.getBlue() * inv, color.getAlpha() * inv); - - mask |= GL_COLOR_BUFFER_BIT; + if (!targets[0].RenderTexture) + { + os::Printer::log("Missing render texture for MRT.", ELL_ERROR); + return false; + } + rttSize=targets[0].RenderTexture->getSize(); } - if (clearZBuffer) + + for (u32 i = 0; i < maxMultipleRTTs; ++i) { - glDepthMask(GL_TRUE); - LastMaterial.ZWriteEnable=true; - mask |= GL_DEPTH_BUFFER_BIT; + // check for right driver type + if (targets[i].TargetType==ERT_RENDER_TEXTURE) + { + if (!targets[i].RenderTexture) + { + maxMultipleRTTs=i; + os::Printer::log("Missing render texture for MRT.", ELL_WARNING); + break; + } + if (targets[i].RenderTexture->getDriverType() != EDT_OPENGL) + { + maxMultipleRTTs=i; + os::Printer::log("Tried to set a texture not owned by this driver.", ELL_WARNING); + break; + } + + // check for valid render target + if (!targets[i].RenderTexture->isRenderTarget() || !static_cast(targets[i].RenderTexture)->isFrameBufferObject()) + { + maxMultipleRTTs=i; + os::Printer::log("Tried to set a non FBO-RTT as render target.", ELL_WARNING); + break; + } + + // check for valid size + if (rttSize != targets[i].RenderTexture->getSize()) + { + maxMultipleRTTs=i; + os::Printer::log("Render target texture has wrong size.", ELL_WARNING); + break; + } + } + } + if (maxMultipleRTTs==0) + { + os::Printer::log("No valid MRTs.", ELL_ERROR); + return false; } - glClear(mask); + // init FBO, if any + for (u32 i=0; i 1) + { + CurrentTarget=ERT_MULTI_RENDER_TEXTURES; + core::array MRTs; + MRTs.set_used(maxMultipleRTTs); + for(u32 i = 0; i < maxMultipleRTTs; i++) + { + if (FeatureAvailable[IRR_EXT_draw_buffers2]) + { + extGlColorMaskIndexed(i, + (targets[i].ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, + (targets[i].ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, + (targets[i].ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, + (targets[i].ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); + if (targets[i].BlendEnable) + extGlEnableIndexed(GL_BLEND, i); + else + extGlDisableIndexed(GL_BLEND, i); + } + if (FeatureAvailable[IRR_AMD_draw_buffers_blend] || FeatureAvailable[IRR_ARB_draw_buffers_blend]) + { + extGlBlendFuncIndexed(i, targets[i].BlendFuncSrc, targets[i].BlendFuncDst); + } + if (targets[i].TargetType==ERT_RENDER_TEXTURE) + { + GLenum attachment = GL_NONE; +#ifdef GL_EXT_framebuffer_object + // attach texture to FrameBuffer Object on Color [i] + attachment = GL_COLOR_ATTACHMENT0_EXT+i; + extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, static_cast(targets[i].RenderTexture)->getOpenGLTextureName(), 0); +#endif + MRTs[i]=attachment; + } + else + { + switch(targets[i].TargetType) + { + case ERT_FRAME_BUFFER: + MRTs[i]=GL_BACK_LEFT; + break; + case ERT_STEREO_BOTH_BUFFERS: + MRTs[i]=GL_BACK; + break; + case ERT_STEREO_RIGHT_BUFFER: + MRTs[i]=GL_BACK_RIGHT; + break; + case ERT_STEREO_LEFT_BUFFER: + MRTs[i]=GL_BACK_LEFT; + break; + default: + MRTs[i]=GL_AUX0+(targets[i].TargetType-ERT_AUX_BUFFER0); + break; + } + } + } + + extGlDrawBuffers(maxMultipleRTTs, MRTs.const_pointer()); + } + + clearBuffers(clearBackBuffer, clearZBuffer, false, color); return true; } // returns the current size of the screen or rendertarget -const core::dimension2d& COpenGLDriver::getCurrentRenderTargetSize() const +const core::dimension2d& COpenGLDriver::getCurrentRenderTargetSize() const { - if ( CurrentRendertargetSize.Width == 0 ) + if (CurrentRendertargetSize.Width == 0) return ScreenSize; else return CurrentRendertargetSize; @@ -2851,13 +3830,7 @@ const core::dimension2d& COpenGLDriver::getCurrentRenderTargetSize() const //! Clears the ZBuffer. void COpenGLDriver::clearZBuffer() { - GLboolean enabled = GL_TRUE; - glGetBooleanv(GL_DEPTH_WRITEMASK, &enabled); - - glDepthMask(GL_TRUE); - glClear(GL_DEPTH_BUFFER_BIT); - - glDepthMask(enabled); + clearBuffers(false, true, false, 0x0); } @@ -2894,7 +3867,7 @@ IImage* COpenGLDriver::createScreenShot() const s32 pitch=newImage->getPitch(); u8* p2 = pixels + (ScreenSize.Height - 1) * pitch; u8* tmpBuffer = new u8[pitch]; - for (s32 i=0; i < ScreenSize.Height; i += 2) + for (u32 i=0; i < ScreenSize.Height; i += 2) { memcpy(tmpBuffer, pixels, pitch); memcpy(pixels, p2, pitch); @@ -2963,7 +3936,7 @@ bool COpenGLDriver::setClipPlane(u32 index, const core::plane3df& plane, bool en if (index >= MaxUserClipPlanes) return false; - UserClipPlane[index]=plane; + UserClipPlanes[index].Plane=plane; enableClipPlane(index, enable); return true; } @@ -2973,10 +3946,10 @@ void COpenGLDriver::uploadClipPlane(u32 index) { // opengl needs an array of doubles for the plane equation double clip_plane[4]; - clip_plane[0] = UserClipPlane[index].Normal.X; - clip_plane[1] = UserClipPlane[index].Normal.Y; - clip_plane[2] = UserClipPlane[index].Normal.Z; - clip_plane[3] = UserClipPlane[index].D; + clip_plane[0] = UserClipPlanes[index].Plane.Normal.X; + clip_plane[1] = UserClipPlanes[index].Plane.Normal.Y; + clip_plane[2] = UserClipPlanes[index].Plane.Normal.Z; + clip_plane[3] = UserClipPlanes[index].Plane.D; glClipPlane(GL_CLIP_PLANE0 + index, clip_plane); } @@ -2988,7 +3961,7 @@ void COpenGLDriver::enableClipPlane(u32 index, bool enable) return; if (enable) { - if (!UserClipPlaneEnabled[index]) + if (!UserClipPlanes[index].Enabled) { uploadClipPlane(index); glEnable(GL_CLIP_PLANE0 + index); @@ -2997,10 +3970,50 @@ void COpenGLDriver::enableClipPlane(u32 index, bool enable) else glDisable(GL_CLIP_PLANE0 + index); - UserClipPlaneEnabled[index]=enable; + UserClipPlanes[index].Enabled=enable; } +core::dimension2du COpenGLDriver::getMaxTextureSize() const +{ + return core::dimension2du(MaxTextureSize, MaxTextureSize); +} + +//! Convert E_PRIMITIVE_TYPE to OpenGL equivalent +GLenum COpenGLDriver::primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const +{ + switch (type) + { + case scene::EPT_POINTS: + return GL_POINTS; + case scene::EPT_LINE_STRIP: + return GL_LINE_STRIP; + case scene::EPT_LINE_LOOP: + return GL_LINE_LOOP; + case scene::EPT_LINES: + return GL_LINES; + case scene::EPT_TRIANGLE_STRIP: + return GL_TRIANGLE_STRIP; + case scene::EPT_TRIANGLE_FAN: + return GL_TRIANGLE_FAN; + case scene::EPT_TRIANGLES: + return GL_TRIANGLES; + case scene::EPT_QUAD_STRIP: + return GL_QUAD_STRIP; + case scene::EPT_QUADS: + return GL_QUADS; + case scene::EPT_POLYGON: + return GL_POLYGON; + case scene::EPT_POINT_SPRITES: +#ifdef GL_ARB_point_sprite + return GL_POINT_SPRITE_ARB; +#else + return GL_POINTS; +#endif + } + return GL_TRIANGLES; +} + } // end namespace } // end namespace @@ -3015,13 +4028,13 @@ namespace video // ----------------------------------- // WINDOWS VERSION // ----------------------------------- -#ifdef _IRR_USE_WINDOWS_DEVICE_ -IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, - io::IFileSystem* io) +#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ +IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, + io::IFileSystem* io, CIrrDeviceWin32* device) { #ifdef _IRR_COMPILE_WITH_OPENGL_ - COpenGLDriver* ogl = new COpenGLDriver(params, io); - if (!ogl->initDriver(params)) + COpenGLDriver* ogl = new COpenGLDriver(params, io, device); + if (!ogl->initDriver(params, device)) { ogl->drop(); ogl = 0; @@ -3031,12 +4044,12 @@ IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, return 0; #endif // _IRR_COMPILE_WITH_OPENGL_ } -#endif // _IRR_USE_WINDOWS_DEVICE_ +#endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ // ----------------------------------- // MACOSX VERSION // ----------------------------------- -#if defined(_IRR_USE_OSX_DEVICE_) +#if defined(_IRR_COMPILE_WITH_OSX_DEVICE_) IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceMacOSX *device) { @@ -3046,22 +4059,44 @@ IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, return 0; #endif // _IRR_COMPILE_WITH_OPENGL_ } -#endif // _IRR_USE_OSX_DEVICE_ +#endif // _IRR_COMPILE_WITH_OSX_DEVICE_ // ----------------------------------- -// X11/SDL VERSION +// X11 VERSION // ----------------------------------- -#if defined(_IRR_USE_LINUX_DEVICE_) || defined(_IRR_USE_SDL_DEVICE_) +#ifdef _IRR_COMPILE_WITH_X11_DEVICE_ IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, - io::IFileSystem* io) + io::IFileSystem* io, CIrrDeviceLinux* device) { #ifdef _IRR_COMPILE_WITH_OPENGL_ - return new COpenGLDriver(params, io); + COpenGLDriver* ogl = new COpenGLDriver(params, io, device); + if (!ogl->initDriver(params, device)) + { + ogl->drop(); + ogl = 0; + } + return ogl; #else return 0; #endif // _IRR_COMPILE_WITH_OPENGL_ } -#endif // _IRR_USE_LINUX_DEVICE_ +#endif // _IRR_COMPILE_WITH_X11_DEVICE_ + + +// ----------------------------------- +// SDL VERSION +// ----------------------------------- +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ +IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, + io::IFileSystem* io, CIrrDeviceSDL* device) +{ +#ifdef _IRR_COMPILE_WITH_OPENGL_ + return new COpenGLDriver(params, io, device); +#else + return 0; +#endif // _IRR_COMPILE_WITH_OPENGL_ +} +#endif // _IRR_COMPILE_WITH_SDL_DEVICE_ } // end namespace } // end namespace diff --git a/src/dep/src/irrlicht/COpenGLDriver.h b/src/dep/src/irrlicht/COpenGLDriver.h index 3682a30..157ea91 100644 --- a/src/dep/src/irrlicht/COpenGLDriver.h +++ b/src/dep/src/irrlicht/COpenGLDriver.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h @@ -7,68 +7,26 @@ #include "IrrCompileConfig.h" -#if defined(_IRR_WINDOWS_API_) - // include windows headers for HWND - #define WIN32_LEAN_AND_MEAN - #include -#elif defined(_IRR_USE_OSX_DEVICE_) - #include "CIrrDeviceMacOSX.h" -#endif - #include "SIrrCreationParameters.h" +namespace irr +{ + class CIrrDeviceWin32; + class CIrrDeviceLinux; + class CIrrDeviceSDL; + class CIrrDeviceMacOSX; +} + #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "CNullDriver.h" #include "IMaterialRendererServices.h" +// also includes the OpenGL stuff #include "COpenGLExtensionHandler.h" -#if defined(_IRR_WINDOWS_API_) - #include - #include "glext.h" - #include "wglext.h" -#ifdef _MSC_VER - #pragma comment(lib, "OpenGL32.lib") - #pragma comment(lib, "GLu32.lib") -#endif -#elif defined(_IRR_USE_OSX_DEVICE_) - #if defined(_IRR_OPENGL_USE_EXTPOINTER_) - #define GL_GLEXT_LEGACY 1 - #endif - #include - #if defined(_IRR_OPENGL_USE_EXTPOINTER_) - #include "glext.h" - #endif -#elif defined(_IRR_USE_SDL_DEVICE_) - #if defined(_IRR_OPENGL_USE_EXTPOINTER_) - #define GL_GLEXT_LEGACY 1 - #define GLX_GLXEXT_LEGACY 1 - #else - #define GL_GLEXT_PROTOTYPES 1 - #define GLX_GLXEXT_PROTOTYPES 1 - #endif - #define NO_SDL_GLEXT - #include - #include "glext.h" -#else - #if defined(_IRR_OPENGL_USE_EXTPOINTER_) - #define GL_GLEXT_LEGACY 1 - #define GLX_GLXEXT_LEGACY 1 - #else - #define GL_GLEXT_PROTOTYPES 1 - #define GLX_GLXEXT_PROTOTYPES 1 - #endif - #include - #include - #if defined(_IRR_OPENGL_USE_EXTPOINTER_) - #include "glext.h" - #undef GLX_ARB_get_proc_address // avoid problems with local glxext.h - #include "glxext.h" - #endif -#endif - namespace irr { + namespace video { class COpenGLTexture; @@ -77,27 +35,38 @@ namespace video { public: - #if defined(_IRR_WINDOWS_API_) || defined(_IRR_USE_LINUX_DEVICE_) || defined(_IRR_USE_SDL_DEVICE_) - COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io); - #endif - - #ifdef _IRR_USE_OSX_DEVICE_ - COpenGLDriver(const SIrrlichtCreationParameters& params, - io::IFileSystem* io, CIrrDeviceMacOSX *device); - #endif - - #ifdef _IRR_WINDOWS_API_ + #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceWin32* device); //! inits the windows specific parts of the open gl driver - bool initDriver(SIrrlichtCreationParameters params); + bool initDriver(SIrrlichtCreationParameters params, CIrrDeviceWin32* device); + bool changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceWin32* device); #endif + #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ + COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceLinux* device); + //! inits the GLX specific parts of the open gl driver + bool initDriver(SIrrlichtCreationParameters params, CIrrDeviceLinux* device); + bool changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceLinux* device); + #endif + + #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ + COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceSDL* device); + #endif + + #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ + COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceMacOSX *device); + #endif + + //! generic version which overloads the unimplemented versions + bool changeRenderContext(const SExposedVideoData& videoData, void* device) {return false;} + //! destructor virtual ~COpenGLDriver(); //! clears the zbuffer virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! presents the rendered scene on the screen, returns false if failed @@ -116,12 +85,8 @@ namespace video GLuint vbo_verticesSize; //tmp GLuint vbo_indicesSize; //tmp - }; - bool updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer); - bool updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer); - //! updates hardware buffer if needed virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer); @@ -139,6 +104,11 @@ namespace video const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); + //! draws a vertex primitive list in 2d + virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); + //! queries the features of the driver, returns true if feature is available virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { @@ -150,6 +120,15 @@ namespace video //! \param material: Material to be used from now on. virtual void setMaterial(const SMaterial& material); + //! draws a set of 2d images, using a color and the alpha channel of the + //! texture if desired. + void draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect, + SColor color, + bool useAlphaChannelOfTexture); + //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, @@ -213,8 +192,15 @@ namespace video //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); - //! adds a dynamic light - virtual void addDynamicLight(const SLight& light); + //! adds a dynamic light, returning an index to the light + //! \param light: the light data to use to create the light + //! \return An index to the light, or -1 if an error occurs + virtual s32 addDynamicLight(const SLight& light); + + //! Turns a dynamic light on or off + //! \param lightIndex: the index returned by addDynamicLight + //! \param turnOn: true to turn the light on, false to turn it off + virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; @@ -242,12 +228,12 @@ namespace video virtual void setViewPort(const core::rect& area); //! Sets the fog mode. - virtual void setFog(SColor color, bool linearFog, f32 start, + virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog); //! Only used by the internal engine. Used to notify the driver that //! the window was resized. - virtual void OnResize(const core::dimension2d& size); + virtual void OnResize(const core::dimension2d& size); //! Returns type of video driver virtual E_DRIVER_TYPE getDriverType() const; @@ -276,7 +262,7 @@ namespace video //! sets the current Texture //! Returns whether setting was a success or not. - bool setTexture(u32 stage, const video::ITexture* texture); + bool setActiveTexture(u32 stage, const video::ITexture* texture); //! disables all textures beginning with the optional fromStage parameter. Otherwise all texture stages are disabled. //! Returns whether disabling was successful or not. @@ -289,13 +275,22 @@ namespace video IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData); //! Adds a new material renderer to the VideoDriver, using GLSL to render geometry. - virtual s32 addHighLevelShaderMaterial(const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, - E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, - E_PIXEL_SHADER_TYPE psCompileTarget, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, - s32 userData); - - //! Returns pointer to the IGPUProgrammingServices interface. - virtual IGPUProgrammingServices* getGPUProgrammingServices(); + virtual s32 addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const c8* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0); //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) @@ -306,12 +301,21 @@ namespace video //! call. virtual u32 getMaximalPrimitiveCount() const; - virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); + //! set or reset render target + virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, + bool clearZBuffer, SColor color); + + //! set or reset render target texture virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color); + //! Sets multiple render targets + virtual bool setRenderTarget(const core::array& texture, + bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=SColor(0,0,0,0)); + //! Clears the ZBuffer. virtual void clearZBuffer(); @@ -335,20 +339,35 @@ namespace video //! \param enable: If true, enable the clipping plane else disable it. virtual void enableClipPlane(u32 index, bool enable); + //! Enable the 2d override material + virtual void enableMaterial2D(bool enable=true); + //! Returns the graphics card vendor name. - virtual core::stringc getVendorInfo() {return vendorName;} + virtual core::stringc getVendorInfo() {return VendorName;} + + //! Returns the maximum texture size supported. + virtual core::dimension2du getMaxTextureSize() const; ITexture* createDepthTexture(ITexture* texture, bool shared=true); void removeDepthTexture(ITexture* texture); + //! Convert E_PRIMITIVE_TYPE to OpenGL equivalent + GLenum primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const; + private: + //! clears the zbuffer and color buffer + void clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color); + + bool updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer); + bool updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer); + void uploadClipPlane(u32 index); //! inits the parts of the open gl driver used on all platforms - bool genericDriverInit(const core::dimension2d& screenSize, bool stencilBuffer); + bool genericDriverInit(const core::dimension2d& screenSize, bool stencilBuffer); //! returns a device dependent texture from a software surface (IImage) - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData); //! creates a transposed matrix in supplied GLfloat array to pass to OpenGL inline void createGLMatrix(GLfloat gl_matrix[16], const core::matrix4& m); @@ -357,6 +376,9 @@ namespace video //! Set GL pipeline to desired texture wrap modes of the material void setWrapMode(const SMaterial& material); + //! get native wrap mode value + GLint getTextureWrapMode(const u8 clamp); + //! sets the needed renderstates void setRenderStates3DMode(); @@ -364,10 +386,21 @@ namespace video void setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel); // returns the current size of the screen or rendertarget - virtual const core::dimension2d& getCurrentRenderTargetSize() const; + virtual const core::dimension2d& getCurrentRenderTargetSize() const; void createMaterialRenderers(); + //! Assign a hardware light to the specified requested light, if any + //! free hardware lights exist. + //! \param[in] lightIndex: the index of the requesting light + void assignHardwareLight(u32 lightIndex); + + //! helper function for render setup. + void createColorBuffer(const void* vertices, u32 vertexCount, E_VERTEX_TYPE vType); + + //! helper function doing the actual rendering. + void renderArray(const void* indexList, u32 primitiveCount, + scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); core::stringw Name; core::matrix4 Matrices[ETS_COUNT]; @@ -385,34 +418,68 @@ namespace video //! bool to make all renderstates reset if set to true. bool ResetRenderStates; bool Transformation3DChanged; - bool AntiAlias; + u8 AntiAlias; SMaterial Material, LastMaterial; COpenGLTexture* RenderTargetTexture; const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES]; core::array DepthTextures; - s32 LastSetLight; - core::array UserClipPlane; - core::array UserClipPlaneEnabled; + struct SUserClipPlane + { + SUserClipPlane() : Enabled(false) {} + core::plane3df Plane; + bool Enabled; + }; + core::array UserClipPlanes; - core::dimension2d CurrentRendertargetSize; + core::dimension2d CurrentRendertargetSize; - core::stringc vendorName; + core::stringc VendorName; core::matrix4 TextureFlipMatrix; //! Color buffer format ECOLOR_FORMAT ColorFormat; + //! Render target type for render operations + E_RENDER_TARGET CurrentTarget; + + bool Doublebuffer; + bool Stereo; + + //! All the lights that have been requested; a hardware limited + //! number of them will be used at once. + struct RequestedLight + { + RequestedLight(SLight const & lightData) + : LightData(lightData), HardwareLightIndex(-1), DesireToBeOn(true) { } + + SLight LightData; + s32 HardwareLightIndex; // GL_LIGHT0 - GL_LIGHT7 + bool DesireToBeOn; + }; + core::array RequestedLights; + #ifdef _IRR_WINDOWS_API_ HDC HDc; // Private GDI Device Context HWND Window; - HGLRC HRc; // Permanent Rendering Context - #elif defined(_IRR_USE_LINUX_DEVICE_) - GLXDrawable Drawable; - #elif defined(_IRR_USE_OSX_DEVICE_) - CIrrDeviceMacOSX *_device; + #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + CIrrDeviceWin32 *Device; #endif + #endif + #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ + GLXDrawable Drawable; + Display* X11Display; + CIrrDeviceLinux *Device; + #endif + #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ + CIrrDeviceMacOSX *Device; + #endif + #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ + CIrrDeviceSDL *Device; + #endif + + E_DEVICE_TYPE DeviceType; }; } // end namespace video diff --git a/src/dep/src/irrlicht/COpenGLExtensionHandler.cpp b/src/dep/src/irrlicht/COpenGLExtensionHandler.cpp index 82afe25..97a2d36 100644 --- a/src/dep/src/irrlicht/COpenGLExtensionHandler.cpp +++ b/src/dep/src/irrlicht/COpenGLExtensionHandler.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,43 +17,59 @@ namespace video { COpenGLExtensionHandler::COpenGLExtensionHandler() : - StencilBuffer(false), - MultiTextureExtension(false), MultiSamplingExtension(false), AnisotropyExtension(false), + StencilBuffer(false), MultiTextureExtension(false), TextureCompressionExtension(false), - MaxTextureUnits(1), MaxLights(1), MaxIndices(65535), - MaxAnisotropy(1.0f), MaxUserClipPlanes(0), - Version(0), ShaderLanguageVersion(0) + MaxTextureUnits(1), MaxLights(1), MaxAnisotropy(1), + MaxUserClipPlanes(0), MaxAuxBuffers(0), + MaxMultipleRenderTargets(1), MaxIndices(65535), + MaxTextureSize(1), MaxGeometryVerticesOut(0), + MaxTextureLODBias(0.f), Version(0), ShaderLanguageVersion(0) #ifdef _IRR_OPENGL_USE_EXTPOINTER_ ,pGlActiveTextureARB(0), pGlClientActiveTextureARB(0), - pGlGenProgramsARB(0), pGlBindProgramARB(0), pGlProgramStringARB(0), - pGlDeleteProgramsARB(0), pGlProgramLocalParameter4fvARB(0), + pGlGenProgramsARB(0), pGlGenProgramsNV(0), + pGlBindProgramARB(0), pGlBindProgramNV(0), + pGlDeleteProgramsARB(0), pGlDeleteProgramsNV(0), + pGlProgramStringARB(0), pGlLoadProgramNV(0), + pGlProgramLocalParameter4fvARB(0), pGlCreateShaderObjectARB(0), pGlShaderSourceARB(0), pGlCompileShaderARB(0), pGlCreateProgramObjectARB(0), pGlAttachObjectARB(0), pGlLinkProgramARB(0), pGlUseProgramObjectARB(0), pGlDeleteObjectARB(0), + pGlGetAttachedObjectsARB(0), pGlGetInfoLogARB(0), pGlGetObjectParameterivARB(0), pGlGetUniformLocationARB(0), pGlUniform1ivARB(0), pGlUniform1fvARB(0), pGlUniform2fvARB(0), pGlUniform3fvARB(0), pGlUniform4fvARB(0), pGlUniformMatrix2fvARB(0), - pGlUniformMatrix3fvARB(0), pGlUniformMatrix4fvARB(0), pGlGetActiveUniformARB(0), pGlPointParameterfARB(0), pGlPointParameterfvARB(0), + pGlUniformMatrix3fvARB(0), pGlUniformMatrix4fvARB(0), + pGlGetActiveUniformARB(0), + pGlPointParameterfARB(0), pGlPointParameterfvARB(0), pGlStencilFuncSeparate(0), pGlStencilOpSeparate(0), pGlStencilFuncSeparateATI(0), pGlStencilOpSeparateATI(0), pGlCompressedTexImage2D(0), -#ifdef _IRR_USE_WINDOWS_DEVICE_ - wglSwapIntervalEXT(0), -#elif defined(GLX_SGI_swap_control) +#if defined(GLX_SGI_swap_control) glxSwapIntervalSGI(0), #endif pGlBindFramebufferEXT(0), pGlDeleteFramebuffersEXT(0), pGlGenFramebuffersEXT(0), pGlCheckFramebufferStatusEXT(0), pGlFramebufferTexture2DEXT(0), pGlBindRenderbufferEXT(0), pGlDeleteRenderbuffersEXT(0), pGlGenRenderbuffersEXT(0), pGlRenderbufferStorageEXT(0), pGlFramebufferRenderbufferEXT(0), + pGlDrawBuffersARB(0), pGlDrawBuffersATI(0), pGlGenBuffersARB(0), pGlBindBufferARB(0), pGlBufferDataARB(0), pGlDeleteBuffersARB(0), pGlBufferSubDataARB(0), pGlGetBufferSubDataARB(0), pGlMapBufferARB(0), pGlUnmapBufferARB(0), - pGlIsBufferARB(0), pGlGetBufferParameterivARB(0), pGlGetBufferPointervARB(0) - - + pGlIsBufferARB(0), pGlGetBufferParameterivARB(0), pGlGetBufferPointervARB(0), + pGlProvokingVertexARB(0), pGlProvokingVertexEXT(0), + pGlColorMaskIndexedEXT(0), pGlEnableIndexedEXT(0), pGlDisableIndexedEXT(0), + pGlBlendFuncIndexedAMD(0), pGlBlendFunciARB(0), + pGlProgramParameteriARB(0), pGlProgramParameteriEXT(0) #endif // _IRR_OPENGL_USE_EXTPOINTER_ { for (u32 i=0; i(glGetString(GL_VERSION))); - Version = core::floor32(ogl_ver)*100+core::ceil32(core::fract(ogl_ver)*10.0f); + Version = static_cast(core::floor32(ogl_ver)*100+core::round32(core::fract(ogl_ver)*10.0f)); if ( Version >= 102) os::Printer::log("OpenGL driver version is 1.2 or better.", ELL_INFORMATION); else @@ -74,8 +90,13 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) { const char* t = reinterpret_cast(glGetString(GL_EXTENSIONS)); - const size_t len = strlen(t); - c8 *str = new c8[len+1]; + size_t len = 0; + c8 *str = 0; + if (t) + { + len = strlen(t); + str = new c8[len+1]; + } c8* p = str; for (size_t i=0; i(x)) #else // Accessing the correct function is quite complex @@ -199,8 +231,9 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) #ifndef _IRR_GETPROCADDRESS_WORKAROUND_ __GLXextFuncPtr (*IRR_OGL_LOAD_EXTENSION)(const GLubyte*)=0; #ifdef GLX_VERSION_1_4 - int major,minor; - glXQueryVersion(glXGetCurrentDisplay(), &major, &minor); + int major=0,minor=0; + if (glXGetCurrentDisplay()) + glXQueryVersion(glXGetCurrentDisplay(), &major, &minor); if ((major>1) || (minor>3)) IRR_OGL_LOAD_EXTENSION=glXGetProcAddress; else @@ -221,14 +254,26 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) pGlGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glGenProgramsARB")); + pGlGenProgramsNV = (PFNGLGENPROGRAMSNVPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glGenProgramsNV")); + pGlBindProgramARB = (PFNGLBINDPROGRAMARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glBindProgramARB")); + pGlBindProgramNV = (PFNGLBINDPROGRAMNVPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glBindProgramNV")); + + pGlDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDeleteProgramsARB")); + + pGlDeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDeleteProgramsNV")); + pGlProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProgramStringARB")); - pGlDeleteProgramsARB = (PFNGLDELETEPROGRAMSNVPROC) - IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDeleteProgramsARB")); + pGlLoadProgramNV = (PFNGLLOADPROGRAMNVPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glLoadProgramNV")); pGlProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProgramLocalParameter4fvARB")); @@ -257,6 +302,9 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) pGlDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDeleteObjectARB")); + pGlGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glGetAttachedObjectsARB")); + pGlGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glGetInfoLogARB")); @@ -316,7 +364,7 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) pGlCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glCompressedTexImage2D")); - #if defined(GLX_SGI_swap_control) && !defined(_IRR_USE_SDL_DEVICE_) + #if defined(GLX_SGI_swap_control) && !defined(_IRR_COMPILE_WITH_SDL_DEVICE_) // get vsync extension glxSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glXSwapIntervalSGI")); #endif @@ -352,6 +400,12 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) pGlFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glFramebufferRenderbufferEXT")); + pGlDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDrawBuffersARB")); + + pGlDrawBuffersATI = (PFNGLDRAWBUFFERSATIPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDrawBuffersATI")); + pGlGenBuffersARB = (PFNGLGENBUFFERSARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glGenBuffersARB")); @@ -384,30 +438,90 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) pGlGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glGetBufferPointervARB")); - + pGlProvokingVertexARB= (PFNGLPROVOKINGVERTEXPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProvokingVertex")); + pGlProvokingVertexEXT= (PFNGLPROVOKINGVERTEXEXTPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProvokingVertexEXT")); + pGlColorMaskIndexedEXT= (PFNGLCOLORMASKINDEXEDEXTPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glColorMaskIndexedEXT")); + pGlEnableIndexedEXT= (PFNGLENABLEINDEXEDEXTPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glEnableIndexedEXT")); + pGlDisableIndexedEXT= (PFNGLDISABLEINDEXEDEXTPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDisableIndexedEXT")); + pGlBlendFuncIndexedAMD= (PFNGLBLENDFUNCINDEXEDAMDPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glBlendFuncIndexedAMD")); + pGlBlendFunciARB= (PFNGLBLENDFUNCIPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glBlendFunciARB")); + pGlProgramParameteriARB = (PFNGLPROGRAMPARAMETERIARBPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProgramParameteriARB")); + pGlProgramParameteriEXT = (PFNGLPROGRAMPARAMETERIEXTPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProgramParameteriEXT")); #endif // _IRR_OPENGL_USE_EXTPOINTER_ #endif // _IRR_WINDOWS_API_ + GLint num; // set some properties #if defined(GL_ARB_multitexture) || defined(GL_VERSION_1_3) if (Version>102 || FeatureAvailable[IRR_ARB_multitexture]) { - GLint num; glGetIntegerv(GL_MAX_TEXTURE_UNITS, &num); - MaxTextureUnits=num; + MaxTextureUnits=static_cast(num); } #endif - glGetIntegerv(GL_MAX_LIGHTS, &MaxLights); + glGetIntegerv(GL_MAX_LIGHTS, &num); + MaxLights=static_cast(num); #ifdef GL_EXT_texture_filter_anisotropic if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic]) - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &MaxAnisotropy); + { + glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &num); + MaxAnisotropy=static_cast(num); + } #endif #ifdef GL_VERSION_1_2 if (Version>101) - glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &MaxIndices); + { + glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &num); + MaxIndices=num; + } #endif - glGetIntegerv(GL_MAX_CLIP_PLANES, reinterpret_cast(&MaxUserClipPlanes)); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &num); + MaxTextureSize=static_cast(num); + if (queryFeature(EVDF_GEOMETRY_SHADER)) + { +#if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_shader4) + glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &num); + MaxGeometryVerticesOut=static_cast(num); +#elif defined(GL_NV_geometry_program4) + extGlGetProgramiv(GEOMETRY_PROGRAM_NV, GL_MAX_PROGRAM_OUTPUT_VERTICES_NV, &num); + MaxGeometryVerticesOut=static_cast(num); +#endif + } +#ifdef GL_EXT_texture_lod_bias + if (FeatureAvailable[IRR_EXT_texture_lod_bias]) + glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &MaxTextureLODBias); +#endif + glGetIntegerv(GL_MAX_CLIP_PLANES, &num); + MaxUserClipPlanes=static_cast(num); + glGetIntegerv(GL_AUX_BUFFERS, &num); + MaxAuxBuffers=static_cast(num); +#ifdef GL_ARB_draw_buffers + if (FeatureAvailable[IRR_ARB_draw_buffers]) + { + glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &num); + MaxMultipleRenderTargets = static_cast(num); + } +#elif defined(GL_ATI_draw_buffers) + if (FeatureAvailable[IRR_ATI_draw_buffers]) + { + glGetIntegerv(GL_MAX_DRAW_BUFFERS_ATI, &num); + MaxMultipleRenderTargets = static_cast(num); + } +#endif + glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, DimAliasedLine); + glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, DimAliasedPoint); + glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, DimSmoothedLine); + glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE, DimSmoothedPoint); #if defined(GL_ARB_shading_language_100) || defined (GL_VERSION_2_0) if (FeatureAvailable[IRR_ARB_shading_language_100] || Version>=200) { @@ -422,7 +536,7 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) else { const f32 sl_ver = core::fast_atof(reinterpret_cast(shaderVersion)); - ShaderLanguageVersion = core::floor32(sl_ver)*100+core::ceil32(core::fract(sl_ver)*10.0f); + ShaderLanguageVersion = static_cast(core::floor32(sl_ver)*100+core::round32(core::fract(sl_ver)*10.0f)); } } #endif @@ -440,7 +554,7 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) MultiTextureExtension = false; os::Printer::log("Warning: OpenGL device only has one texture unit. Disabling multitexturing.", ELL_WARNING); } - MaxTextureUnits = core::min_(MaxTextureUnits,MATERIAL_MAX_TEXTURES); + MaxTextureUnits = core::min_(MaxTextureUnits,static_cast(MATERIAL_MAX_TEXTURES)); } @@ -450,6 +564,8 @@ bool COpenGLExtensionHandler::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { case EVDF_RENDER_TO_TARGET: return true; + case EVDF_HARDWARE_TL: + return true; // we cannot tell other things case EVDF_MULTITEXTURE: return MultiTextureExtension; case EVDF_BILINEAR_FILTER: @@ -460,10 +576,15 @@ bool COpenGLExtensionHandler::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const return FeatureAvailable[IRR_SGIS_generate_mipmap]; case EVDF_STENCIL_BUFFER: return StencilBuffer; + case EVDF_VERTEX_SHADER_1_1: case EVDF_ARB_VERTEX_PROGRAM_1: - return FeatureAvailable[IRR_ARB_vertex_program]; + return FeatureAvailable[IRR_ARB_vertex_program] || FeatureAvailable[IRR_NV_vertex_program1_1]; + case EVDF_PIXEL_SHADER_1_1: + case EVDF_PIXEL_SHADER_1_2: case EVDF_ARB_FRAGMENT_PROGRAM_1: - return FeatureAvailable[IRR_ARB_fragment_program]; + return FeatureAvailable[IRR_ARB_fragment_program] || FeatureAvailable[IRR_NV_fragment_program]; + case EVDF_PIXEL_SHADER_2_0: + case EVDF_VERTEX_SHADER_2_0: case EVDF_ARB_GLSL: return (FeatureAvailable[IRR_ARB_shading_language_100]||Version>=200); case EVDF_TEXTURE_NSQUARE: @@ -478,6 +599,19 @@ bool COpenGLExtensionHandler::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const return FeatureAvailable[IRR_EXT_framebuffer_object]; case EVDF_VERTEX_BUFFER_OBJECT: return FeatureAvailable[IRR_ARB_vertex_buffer_object]; + case EVDF_COLOR_MASK: + return true; + case EVDF_ALPHA_TO_COVERAGE: + return FeatureAvailable[IRR_ARB_multisample]; + case EVDF_GEOMETRY_SHADER: + return FeatureAvailable[IRR_ARB_geometry_shader4] || FeatureAvailable[IRR_EXT_geometry_shader4] || FeatureAvailable[IRR_NV_geometry_program4] || FeatureAvailable[IRR_NV_geometry_shader4]; + case EVDF_MULTIPLE_RENDER_TARGETS: + return FeatureAvailable[IRR_ARB_draw_buffers] || FeatureAvailable[IRR_ATI_draw_buffers]; + case EVDF_MRT_BLEND: + case EVDF_MRT_COLOR_MASK: + return FeatureAvailable[IRR_EXT_draw_buffers2]; + case EVDF_MRT_BLEND_FUNC: + return FeatureAvailable[IRR_ARB_draw_buffers_blend] || FeatureAvailable[IRR_AMD_draw_buffers_blend]; default: return false; }; @@ -488,5 +622,3 @@ bool COpenGLExtensionHandler::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const } #endif - - diff --git a/src/dep/src/irrlicht/COpenGLExtensionHandler.h b/src/dep/src/irrlicht/COpenGLExtensionHandler.h index ade7b3a..abcc536 100644 --- a/src/dep/src/irrlicht/COpenGLExtensionHandler.h +++ b/src/dep/src/irrlicht/COpenGLExtensionHandler.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h @@ -16,12 +16,20 @@ // include windows headers for HWND #define WIN32_LEAN_AND_MEAN #include + #if defined(_IRR_OPENGL_USE_EXTPOINTER_) + #define GL_GLEXT_LEGACY 1 + #endif #include - #include "glext.h" -#ifdef _MSC_VER - #pragma comment(lib, "OpenGL32.lib") -#endif -#elif defined(_IRR_USE_OSX_DEVICE_) + #if defined(_IRR_OPENGL_USE_EXTPOINTER_) + #include "glext.h" + #endif + #include "wglext.h" + + #ifdef _MSC_VER + #pragma comment(lib, "OpenGL32.lib") + #endif + +#elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_) #include "CIrrDeviceMacOSX.h" #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 @@ -30,7 +38,7 @@ #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #include "glext.h" #endif -#elif defined(_IRR_USE_SDL_DEVICE_) +#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) && !defined(_IRR_COMPILE_WITH_X11_DEVICE_) #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 #define GLX_GLXEXT_LEGACY 1 @@ -65,24 +73,42 @@ namespace irr namespace video { + static const char* const OpenGLFeatureStrings[] = { "GL_3DFX_multisample", "GL_3DFX_tbuffer", "GL_3DFX_texture_compression_FXT1", + "GL_AMD_draw_buffers_blend", + "GL_AMD_performance_monitor", + "GL_AMD_texture_texture4", + "GL_AMD_vertex_shader_tesselator", + "GL_APPLE_aux_depth_stencil", "GL_APPLE_client_storage", "GL_APPLE_element_array", "GL_APPLE_fence", + "GL_APPLE_float_pixels", "GL_APPLE_flush_buffer_range", + "GL_APPLE_object_purgeable", + "GL_APPLE_rgb_422", + "GL_APPLE_row_bytes", "GL_APPLE_specular_vector", + "GL_APPLE_texture_range", "GL_APPLE_transform_hint", "GL_APPLE_vertex_array_object", "GL_APPLE_vertex_array_range", + "GL_APPLE_vertex_program_evaluators", "GL_APPLE_ycbcr_422", "GL_ARB_color_buffer_float", + "GL_ARB_compatibility", + "GL_ARB_copy_buffer", "GL_ARB_depth_buffer_float", + "GL_ARB_depth_clamp", "GL_ARB_depth_texture", "GL_ARB_draw_buffers", + "GL_ARB_draw_buffers_blend", + "GL_ARB_draw_elements_base_vertex", "GL_ARB_draw_instanced", + "GL_ARB_fragment_coord_conventions", "GL_ARB_fragment_program", "GL_ARB_fragment_program_shadow", "GL_ARB_fragment_shader", @@ -101,25 +127,36 @@ static const char* const OpenGLFeatureStrings[] = { "GL_ARB_pixel_buffer_object", "GL_ARB_point_parameters", "GL_ARB_point_sprite", + "GL_ARB_provoking_vertex", + "GL_ARB_sample_shading", + "GL_ARB_seamless_cube_map", "GL_ARB_shader_objects", + "GL_ARB_shader_texture_lod", "GL_ARB_shading_language_100", "GL_ARB_shadow", "GL_ARB_shadow_ambient", + "GL_ARB_sync", "GL_ARB_texture_border_clamp", "GL_ARB_texture_buffer_object", "GL_ARB_texture_compression", "GL_ARB_texture_compression_rgtc", "GL_ARB_texture_cube_map", + "GL_ARB_texture_cube_map_array", "GL_ARB_texture_env_add", "GL_ARB_texture_env_combine", "GL_ARB_texture_env_crossbar", "GL_ARB_texture_env_dot3", "GL_ARB_texture_float", + "GL_ARB_texture_gather", "GL_ARB_texture_mirrored_repeat", + "GL_ARB_texture_multisample", "GL_ARB_texture_non_power_of_two", + "GL_ARB_texture_query_lod", "GL_ARB_texture_rectangle", "GL_ARB_texture_rg", "GL_ARB_transpose_matrix", + "GL_ARB_uniform_buffer_object", + "GL_ARB_vertex_array_bgra", "GL_ARB_vertex_array_object", "GL_ARB_vertex_blend", "GL_ARB_vertex_buffer_object", @@ -131,6 +168,7 @@ static const char* const OpenGLFeatureStrings[] = { "GL_ATI_envmap_bumpmap", "GL_ATI_fragment_shader", "GL_ATI_map_object_buffer", + "GL_ATI_meminfo", "GL_ATI_pixel_format_float", "GL_ATI_pn_triangles", "GL_ATI_separate_stencil", @@ -190,8 +228,10 @@ static const char* const OpenGLFeatureStrings[] = { "GL_EXT_pixel_transform_color_table", "GL_EXT_point_parameters", "GL_EXT_polygon_offset", + "GL_EXT_provoking_vertex", "GL_EXT_rescale_normal", "GL_EXT_secondary_color", + "GL_EXT_separate_shader_objects", "GL_EXT_separate_specular_color", "GL_EXT_shadow_funcs", "GL_EXT_shared_texture_palette", @@ -217,7 +257,9 @@ static const char* const OpenGLFeatureStrings[] = { "GL_EXT_texture_object", "GL_EXT_texture_perturb_normal", "GL_EXT_texture_shared_exponent", + "GL_EXT_texture_snorm", "GL_EXT_texture_sRGB", + "GL_EXT_texture_swizzle", "GL_EXT_timer_query", "GL_EXT_transform_feedback", "GL_EXT_vertex_array", @@ -250,9 +292,11 @@ static const char* const OpenGLFeatureStrings[] = { "GL_NV_blend_square", "GL_NV_conditional_render", "GL_NV_copy_depth_to_color", + "GL_NV_copy_image", "GL_NV_depth_buffer_float", "GL_NV_depth_clamp", "GL_NV_evaluators", + "GL_NV_explicit_multisample", "GL_NV_fence", "GL_NV_float_buffer", "GL_NV_fog_distance", @@ -270,14 +314,17 @@ static const char* const OpenGLFeatureStrings[] = { "GL_NV_occlusion_query", "GL_NV_packed_depth_stencil", "GL_NV_parameter_buffer_object", + "GL_NV_parameter_buffer_object2", "GL_NV_pixel_data_range", "GL_NV_point_sprite", "GL_NV_present_video", "GL_NV_primitive_restart", "GL_NV_register_combiners", "GL_NV_register_combiners2", + "GL_NV_shader_buffer_load", "GL_NV_texgen_emboss", "GL_NV_texgen_reflection", + "GL_NV_texture_barrier", "GL_NV_texture_compression_vtc", "GL_NV_texture_env_combine4", "GL_NV_texture_expand_normal", @@ -286,14 +333,17 @@ static const char* const OpenGLFeatureStrings[] = { "GL_NV_texture_shader2", "GL_NV_texture_shader3", "GL_NV_transform_feedback", + "GL_NV_transform_feedback2", "GL_NV_vertex_array_range", "GL_NV_vertex_array_range2", + "GL_NV_vertex_buffer_unified_memory", "GL_NV_vertex_program", "GL_NV_vertex_program1_1", "GL_NV_vertex_program2", "GL_NV_vertex_program2_option", "GL_NV_vertex_program3", "GL_NV_vertex_program4", + "GL_NV_video_capture", "GL_OES_read_format", "GL_OML_interlace", "GL_OML_resample", @@ -381,20 +431,37 @@ class COpenGLExtensionHandler IRR_3DFX_multisample = 0, IRR_3DFX_tbuffer, IRR_3DFX_texture_compression_FXT1, + IRR_AMD_draw_buffers_blend, + IRR_AMD_performance_monitor, + IRR_AMD_texture_texture4, + IRR_AMD_vertex_shader_tesselator, + IRR_APPLE_aux_depth_stencil, IRR_APPLE_client_storage, IRR_APPLE_element_array, IRR_APPLE_fence, + IRR_APPLE_float_pixels, IRR_APPLE_flush_buffer_range, + IRR_APPLE_object_purgeable, + IRR_APPLE_rgb_422, + IRR_APPLE_row_bytes, IRR_APPLE_specular_vector, + IRR_APPLE_texture_range, IRR_APPLE_transform_hint, IRR_APPLE_vertex_array_object, IRR_APPLE_vertex_array_range, + IRR_APPLE_vertex_program_evaluators, IRR_APPLE_ycbcr_422, IRR_ARB_color_buffer_float, + IRR_ARB_compatibility, + IRR_ARB_copy_buffer, IRR_ARB_depth_buffer_float, + IRR_ARB_depth_clamp, IRR_ARB_depth_texture, IRR_ARB_draw_buffers, + IRR_ARB_draw_buffers_blend, + IRR_ARB_draw_elements_base_vertex, IRR_ARB_draw_instanced, + IRR_ARB_fragment_coord_conventions, IRR_ARB_fragment_program, IRR_ARB_fragment_program_shadow, IRR_ARB_fragment_shader, @@ -413,25 +480,36 @@ class COpenGLExtensionHandler IRR_ARB_pixel_buffer_object, IRR_ARB_point_parameters, IRR_ARB_point_sprite, + IRR_ARB_provoking_vertex, + IRR_ARB_sample_shading, + IRR_ARB_seamless_cube_map, IRR_ARB_shader_objects, + IRR_ARB_shader_texture_lod, IRR_ARB_shading_language_100, IRR_ARB_shadow, IRR_ARB_shadow_ambient, + IRR_ARB_sync, IRR_ARB_texture_border_clamp, IRR_ARB_texture_buffer_object, IRR_ARB_texture_compression, IRR_ARB_texture_compression_rgtc, IRR_ARB_texture_cube_map, + IRR_ARB_texture_cube_map_array, IRR_ARB_texture_env_add, IRR_ARB_texture_env_combine, IRR_ARB_texture_env_crossbar, IRR_ARB_texture_env_dot3, IRR_ARB_texture_float, + IRR_ARB_texture_gather, IRR_ARB_texture_mirrored_repeat, + IRR_ARB_texture_multisample, IRR_ARB_texture_non_power_of_two, + IRR_ARB_texture_query_lod, IRR_ARB_texture_rectangle, IRR_ARB_texture_rg, IRR_ARB_transpose_matrix, + IRR_ARB_uniform_buffer_object, + IRR_ARB_vertex_array_bgra, IRR_ARB_vertex_array_object, IRR_ARB_vertex_blend, IRR_ARB_vertex_buffer_object, @@ -443,6 +521,7 @@ class COpenGLExtensionHandler IRR_ATI_envmap_bumpmap, IRR_ATI_fragment_shader, IRR_ATI_map_object_buffer, + IRR_ATI_meminfo, IRR_ATI_pixel_format_float, IRR_ATI_pn_triangles, IRR_ATI_separate_stencil, @@ -502,8 +581,10 @@ class COpenGLExtensionHandler IRR_EXT_pixel_transform_color_table, IRR_EXT_point_parameters, IRR_EXT_polygon_offset, + IRR_EXT_provoking_vertex, IRR_EXT_rescale_normal, IRR_EXT_secondary_color, + IRR_EXT_separate_shader_objects, IRR_EXT_separate_specular_color, IRR_EXT_shadow_funcs, IRR_EXT_shared_texture_palette, @@ -529,7 +610,9 @@ class COpenGLExtensionHandler IRR_EXT_texture_object, IRR_EXT_texture_perturb_normal, IRR_EXT_texture_shared_exponent, + IRR_EXT_texture_snorm, IRR_EXT_texture_sRGB, + IRR_EXT_texture_swizzle, IRR_EXT_timer_query, IRR_EXT_transform_feedback, IRR_EXT_vertex_array, @@ -562,9 +645,11 @@ class COpenGLExtensionHandler IRR_NV_blend_square, IRR_NV_conditional_render, IRR_NV_copy_depth_to_color, + IRR_NV_copy_image, IRR_NV_depth_buffer_float, IRR_NV_depth_clamp, IRR_NV_evaluators, + IRR_NV_explicit_multisample, IRR_NV_fence, IRR_NV_float_buffer, IRR_NV_fog_distance, @@ -582,14 +667,17 @@ class COpenGLExtensionHandler IRR_NV_occlusion_query, IRR_NV_packed_depth_stencil, IRR_NV_parameter_buffer_object, + IRR_NV_parameter_buffer_object2, IRR_NV_pixel_data_range, IRR_NV_point_sprite, IRR_NV_present_video, IRR_NV_primitive_restart, IRR_NV_register_combiners, IRR_NV_register_combiners2, + IRR_NV_shader_buffer_load, IRR_NV_texgen_emboss, IRR_NV_texgen_reflection, + IRR_NV_texture_barrier, IRR_NV_texture_compression_vtc, IRR_NV_texture_env_combine4, IRR_NV_texture_expand_normal, @@ -598,14 +686,17 @@ class COpenGLExtensionHandler IRR_NV_texture_shader2, IRR_NV_texture_shader3, IRR_NV_transform_feedback, + IRR_NV_transform_feedback2, IRR_NV_vertex_array_range, IRR_NV_vertex_array_range2, + IRR_NV_vertex_buffer_unified_memory, IRR_NV_vertex_program, IRR_NV_vertex_program1_1, IRR_NV_vertex_program2, IRR_NV_vertex_program2_option, IRR_NV_vertex_program3, IRR_NV_vertex_program4, + IRR_NV_video_capture, IRR_OES_read_format, IRR_OML_interlace, IRR_OML_resample, @@ -708,26 +799,42 @@ class COpenGLExtensionHandler // Some variables for properties bool StencilBuffer; bool MultiTextureExtension; - bool MultiSamplingExtension; - bool AnisotropyExtension; bool TextureCompressionExtension; // Some non-boolean properties //! Maxmimum texture layers supported by the fixed pipeline - u32 MaxTextureUnits; + u8 MaxTextureUnits; //! Maximum hardware lights supported - GLint MaxLights; - //! Optimal number of indices per meshbuffer - GLint MaxIndices; + u8 MaxLights; //! Maximal Anisotropy - f32 MaxAnisotropy; + u8 MaxAnisotropy; //! Number of user clipplanes - u32 MaxUserClipPlanes; + u8 MaxUserClipPlanes; + //! Number of auxiliary buffers + u8 MaxAuxBuffers; + //! Number of rendertargets available as MRTs + u8 MaxMultipleRenderTargets; + //! Optimal number of indices per meshbuffer + u32 MaxIndices; + //! Maximal texture dimension + u32 MaxTextureSize; + //! Maximal vertices handled by geometry shaders + u32 MaxGeometryVerticesOut; + //! Maximal LOD Bias + f32 MaxTextureLODBias; + //! Minimal and maximal supported thickness for lines without smoothing + GLfloat DimAliasedLine[2]; + //! Minimal and maximal supported thickness for points without smoothing + GLfloat DimAliasedPoint[2]; + //! Minimal and maximal supported thickness for lines with smoothing + GLfloat DimSmoothedLine[2]; + //! Minimal and maximal supported thickness for points with smoothing + GLfloat DimSmoothedPoint[2]; //! OpenGL version as Integer: 100*Major+Minor, i.e. 2.1 becomes 201 - u32 Version; + u16 Version; //! GLSL version as Integer: 100*Major+Minor - u32 ShaderLanguageVersion; + u16 ShaderLanguageVersion; // public access to the (loaded) extensions. // general functions @@ -745,19 +852,24 @@ class COpenGLExtensionHandler void extGlGenPrograms(GLsizei n, GLuint *programs); void extGlBindProgram(GLenum target, GLuint program); void extGlProgramString(GLenum target, GLenum format, GLsizei len, const GLvoid *string); + void extGlLoadProgram(GLenum target, GLuint id, GLsizei len, const GLubyte *string); void extGlDeletePrograms(GLsizei n, const GLuint *programs); void extGlProgramLocalParameter4fv(GLenum, GLuint, const GLfloat *); GLhandleARB extGlCreateShaderObject(GLenum shaderType); - void extGlShaderSource(GLhandleARB shader, int numOfStrings, const char **strings, int *lenOfStrings); - void extGlCompileShader(GLhandleARB shader); + // note: Due to the type confusion between shader_objects and OpenGL 2.0 + // we have to add the ARB extension for proper method definitions in case + // that handleARB and uint are the same type + void extGlShaderSourceARB(GLhandleARB shader, int numOfStrings, const char **strings, int *lenOfStrings); + void extGlCompileShaderARB(GLhandleARB shader); GLhandleARB extGlCreateProgramObject(void); void extGlAttachObject(GLhandleARB program, GLhandleARB shader); - void extGlLinkProgram(GLhandleARB program); + void extGlLinkProgramARB(GLhandleARB program); void extGlUseProgramObject(GLhandleARB prog); void extGlDeleteObject(GLhandleARB object); + void extGlGetAttachedObjects(GLhandleARB program, GLsizei maxcount, GLsizei* count, GLhandleARB* shaders); void extGlGetInfoLog(GLhandleARB object, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); - void extGlGetObjectParameteriv(GLhandleARB object, GLenum type, int *param); - GLint extGlGetUniformLocation(GLhandleARB program, const char *name); + void extGlGetObjectParameteriv(GLhandleARB object, GLenum type, GLint *param); + GLint extGlGetUniformLocationARB(GLhandleARB program, const char *name); void extGlUniform4fv(GLint location, GLsizei count, const GLfloat *v); void extGlUniform1iv(GLint loc, GLsizei count, const GLint *v); void extGlUniform1fv(GLint loc, GLsizei count, const GLfloat *v); @@ -766,7 +878,7 @@ class COpenGLExtensionHandler void extGlUniformMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat *v); void extGlUniformMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat *v); void extGlUniformMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat *v); - void extGlGetActiveUniform(GLhandleARB program, GLuint index, GLsizei maxlength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); + void extGlGetActiveUniformARB(GLhandleARB program, GLuint index, GLsizei maxlength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); // framebuffer objects void extGlBindFramebuffer(GLenum target, GLuint framebuffer); @@ -780,6 +892,7 @@ class COpenGLExtensionHandler void extGlRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); void extGlFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); void extGlActiveStencilFace(GLenum face); + void extGlDrawBuffers(GLsizei n, const GLenum *bufs); // vertex buffer object void extGlGenBuffers(GLsizei n, GLuint *buffers); @@ -793,6 +906,12 @@ class COpenGLExtensionHandler GLboolean extGlIsBuffer (GLuint buffer); void extGlGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); void extGlGetBufferPointerv (GLenum target, GLenum pname, GLvoid **params); + void extGlProvokingVertex(GLenum mode); + void extGlColorMaskIndexed(GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a); + void extGlEnableIndexed(GLenum target, GLuint index); + void extGlDisableIndexed(GLenum target, GLuint index); + void extGlBlendFuncIndexed(GLuint buf, GLenum src, GLenum dst); + void extGlProgramParameteri(GLuint program, GLenum pname, GLint value); protected: @@ -803,9 +922,13 @@ class COpenGLExtensionHandler PFNGLACTIVETEXTUREARBPROC pGlActiveTextureARB; PFNGLCLIENTACTIVETEXTUREARBPROC pGlClientActiveTextureARB; PFNGLGENPROGRAMSARBPROC pGlGenProgramsARB; + PFNGLGENPROGRAMSNVPROC pGlGenProgramsNV; PFNGLBINDPROGRAMARBPROC pGlBindProgramARB; + PFNGLBINDPROGRAMNVPROC pGlBindProgramNV; + PFNGLDELETEPROGRAMSARBPROC pGlDeleteProgramsARB; + PFNGLDELETEPROGRAMSNVPROC pGlDeleteProgramsNV; PFNGLPROGRAMSTRINGARBPROC pGlProgramStringARB; - PFNGLDELETEPROGRAMSNVPROC pGlDeleteProgramsARB; + PFNGLLOADPROGRAMNVPROC pGlLoadProgramNV; PFNGLPROGRAMLOCALPARAMETER4FVARBPROC pGlProgramLocalParameter4fvARB; PFNGLCREATESHADEROBJECTARBPROC pGlCreateShaderObjectARB; PFNGLSHADERSOURCEARBPROC pGlShaderSourceARB; @@ -815,6 +938,7 @@ class COpenGLExtensionHandler PFNGLLINKPROGRAMARBPROC pGlLinkProgramARB; PFNGLUSEPROGRAMOBJECTARBPROC pGlUseProgramObjectARB; PFNGLDELETEOBJECTARBPROC pGlDeleteObjectARB; + PFNGLGETATTACHEDOBJECTSARBPROC pGlGetAttachedObjectsARB; PFNGLGETINFOLOGARBPROC pGlGetInfoLogARB; PFNGLGETOBJECTPARAMETERIVARBPROC pGlGetObjectParameterivARB; PFNGLGETUNIFORMLOCATIONARBPROC pGlGetUniformLocationARB; @@ -834,10 +958,7 @@ class COpenGLExtensionHandler PFNGLSTENCILFUNCSEPARATEATIPROC pGlStencilFuncSeparateATI; PFNGLSTENCILOPSEPARATEATIPROC pGlStencilOpSeparateATI; PFNGLCOMPRESSEDTEXIMAGE2DPROC pGlCompressedTexImage2D; - #ifdef _IRR_WINDOWS_API_ - typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)(int); - PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT; - #elif defined(_IRR_LINUX_PLATFORM_) && defined(GLX_SGI_swap_control) + #if defined(_IRR_LINUX_PLATFORM_) && defined(GLX_SGI_swap_control) PFNGLXSWAPINTERVALSGIPROC glxSwapIntervalSGI; #endif PFNGLBINDFRAMEBUFFEREXTPROC pGlBindFramebufferEXT; @@ -851,6 +972,8 @@ class COpenGLExtensionHandler PFNGLRENDERBUFFERSTORAGEEXTPROC pGlRenderbufferStorageEXT; PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC pGlFramebufferRenderbufferEXT; PFNGLACTIVESTENCILFACEEXTPROC pGlActiveStencilFaceEXT; + PFNGLDRAWBUFFERSARBPROC pGlDrawBuffersARB; + PFNGLDRAWBUFFERSATIPROC pGlDrawBuffersATI; PFNGLGENBUFFERSARBPROC pGlGenBuffersARB; PFNGLBINDBUFFERARBPROC pGlBindBufferARB; PFNGLBUFFERDATAARBPROC pGlBufferDataARB; @@ -862,6 +985,15 @@ class COpenGLExtensionHandler PFNGLISBUFFERARBPROC pGlIsBufferARB; PFNGLGETBUFFERPARAMETERIVARBPROC pGlGetBufferParameterivARB; PFNGLGETBUFFERPOINTERVARBPROC pGlGetBufferPointervARB; + PFNGLPROVOKINGVERTEXPROC pGlProvokingVertexARB; + PFNGLPROVOKINGVERTEXEXTPROC pGlProvokingVertexEXT; + PFNGLCOLORMASKINDEXEDEXTPROC pGlColorMaskIndexedEXT; + PFNGLENABLEINDEXEDEXTPROC pGlEnableIndexedEXT; + PFNGLDISABLEINDEXEDEXTPROC pGlDisableIndexedEXT; + PFNGLBLENDFUNCINDEXEDAMDPROC pGlBlendFuncIndexedAMD; + PFNGLBLENDFUNCIPROC pGlBlendFunciARB; + PFNGLPROGRAMPARAMETERIARBPROC pGlProgramParameteriARB; + PFNGLPROGRAMPARAMETERIEXTPROC pGlProgramParameteriEXT; #endif }; @@ -871,7 +1003,12 @@ inline void COpenGLExtensionHandler::extGlActiveTexture(GLenum texture) if (MultiTextureExtension && pGlActiveTextureARB) pGlActiveTextureARB(texture); #else - if (MultiTextureExtension) glActiveTextureARB(texture); + if (MultiTextureExtension) +#ifdef GL_ARB_multitexture + glActiveTextureARB(texture); +#else + glActiveTexture(texture); +#endif #endif } @@ -881,7 +1018,8 @@ inline void COpenGLExtensionHandler::extGlClientActiveTexture(GLenum texture) if (MultiTextureExtension && pGlClientActiveTextureARB) pGlClientActiveTextureARB(texture); #else - if (MultiTextureExtension) glClientActiveTextureARB(texture); + if (MultiTextureExtension) + glClientActiveTextureARB(texture); #endif } @@ -890,8 +1028,12 @@ inline void COpenGLExtensionHandler::extGlGenPrograms(GLsizei n, GLuint *program #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGenProgramsARB) pGlGenProgramsARB(n, programs); -#elif defined(GL_ARB_vertex_program) + else if (pGlGenProgramsNV) + pGlGenProgramsNV(n, programs); +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glGenProgramsARB(n,programs); +#elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) + glGenProgramsNV(n,programs); #else os::Printer::log("glGenPrograms not supported", ELL_ERROR); #endif @@ -902,8 +1044,12 @@ inline void COpenGLExtensionHandler::extGlBindProgram(GLenum target, GLuint prog #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBindProgramARB) pGlBindProgramARB(target, program); -#elif defined(GL_ARB_vertex_program) + else if (pGlBindProgramNV) + pGlBindProgramNV(target, program); +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glBindProgramARB(target, program); +#elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) + glBindProgramNV(target, program); #else os::Printer::log("glBindProgram not supported", ELL_ERROR); #endif @@ -914,20 +1060,36 @@ inline void COpenGLExtensionHandler::extGlProgramString(GLenum target, GLenum fo #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlProgramStringARB) pGlProgramStringARB(target, format, len, string); -#elif defined(GL_ARB_vertex_program) +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glProgramStringARB(target,format,len,string); #else os::Printer::log("glProgramString not supported", ELL_ERROR); #endif } +inline void COpenGLExtensionHandler::extGlLoadProgram(GLenum target, GLuint id, GLsizei len, const GLubyte *string) +{ +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + if (pGlLoadProgramNV) + pGlLoadProgramNV(target, id, len, string); +#elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) + glLoadProgramNV(target,id,len,string); +#else + os::Printer::log("glLoadProgram not supported", ELL_ERROR); +#endif +} + inline void COpenGLExtensionHandler::extGlDeletePrograms(GLsizei n, const GLuint *programs) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteProgramsARB) pGlDeleteProgramsARB(n, programs); -#elif defined(GL_ARB_vertex_program) + else if (pGlDeleteProgramsNV) + pGlDeleteProgramsNV(n, programs); +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glDeleteProgramsARB(n,programs); +#elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) + glDeleteProgramsNV(n,programs); #else os::Printer::log("glDeletePrograms not supported", ELL_ERROR); #endif @@ -938,7 +1100,7 @@ inline void COpenGLExtensionHandler::extGlProgramLocalParameter4fv(GLenum n, GLu #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlProgramLocalParameter4fvARB) pGlProgramLocalParameter4fvARB(n,i,f); -#elif defined(GL_ARB_vertex_program) +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glProgramLocalParameter4fvARB(n,i,f); #else os::Printer::log("glProgramLocalParameter4fv not supported", ELL_ERROR); @@ -958,7 +1120,7 @@ inline GLhandleARB COpenGLExtensionHandler::extGlCreateShaderObject(GLenum shade return 0; } -inline void COpenGLExtensionHandler::extGlShaderSource(GLhandleARB shader, int numOfStrings, const char **strings, int *lenOfStrings) +inline void COpenGLExtensionHandler::extGlShaderSourceARB(GLhandleARB shader, int numOfStrings, const char **strings, int *lenOfStrings) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlShaderSourceARB) @@ -970,7 +1132,7 @@ inline void COpenGLExtensionHandler::extGlShaderSource(GLhandleARB shader, int n #endif } -inline void COpenGLExtensionHandler::extGlCompileShader(GLhandleARB shader) +inline void COpenGLExtensionHandler::extGlCompileShaderARB(GLhandleARB shader) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlCompileShaderARB) @@ -1007,7 +1169,7 @@ inline void COpenGLExtensionHandler::extGlAttachObject(GLhandleARB program, GLha #endif } -inline void COpenGLExtensionHandler::extGlLinkProgram(GLhandleARB program) +inline void COpenGLExtensionHandler::extGlLinkProgramARB(GLhandleARB program) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlLinkProgramARB) @@ -1039,7 +1201,19 @@ inline void COpenGLExtensionHandler::extGlDeleteObject(GLhandleARB object) #elif defined(GL_ARB_shader_objects) glDeleteObjectARB(object); #else - os::Printer::log("gldeleteObject not supported", ELL_ERROR); + os::Printer::log("glDeleteObject not supported", ELL_ERROR); +#endif +} + +inline void COpenGLExtensionHandler::extGlGetAttachedObjects(GLhandleARB program, GLsizei maxcount, GLsizei* count, GLhandleARB* shaders) +{ +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + if (pGlGetAttachedObjectsARB) + pGlGetAttachedObjectsARB(program, maxcount, count, shaders); +#elif defined(GL_ARB_shader_objects) + glGetAttachedObjectsARB(program, maxcount, count, shaders); +#else + os::Printer::log("glGetAttachedObjects not supported", ELL_ERROR); #endif } @@ -1055,19 +1229,19 @@ inline void COpenGLExtensionHandler::extGlGetInfoLog(GLhandleARB object, GLsizei #endif } -inline void COpenGLExtensionHandler::extGlGetObjectParameteriv(GLhandleARB object, GLenum type, int *param) +inline void COpenGLExtensionHandler::extGlGetObjectParameteriv(GLhandleARB object, GLenum type, GLint *param) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetObjectParameterivARB) pGlGetObjectParameterivARB(object, type, param); #elif defined(GL_ARB_shader_objects) - glGetObjectParameterivARB(object, type, (GLint *)param); + glGetObjectParameterivARB(object, type, param); #else os::Printer::log("glGetObjectParameteriv not supported", ELL_ERROR); #endif } -inline GLint COpenGLExtensionHandler::extGlGetUniformLocation(GLhandleARB program, const char *name) +inline GLint COpenGLExtensionHandler::extGlGetUniformLocationARB(GLhandleARB program, const char *name) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetUniformLocationARB) @@ -1176,7 +1350,7 @@ inline void COpenGLExtensionHandler::extGlUniformMatrix4fv(GLint loc, GLsizei co #endif } -inline void COpenGLExtensionHandler::extGlGetActiveUniform(GLhandleARB program, +inline void COpenGLExtensionHandler::extGlGetActiveUniformARB(GLhandleARB program, GLuint index, GLsizei maxlength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name) { @@ -1394,6 +1568,22 @@ inline void COpenGLExtensionHandler::extGlActiveStencilFace(GLenum face) #endif } +inline void COpenGLExtensionHandler::extGlDrawBuffers(GLsizei n, const GLenum *bufs) +{ +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + if (pGlDrawBuffersARB) + pGlDrawBuffersARB(n, bufs); + else if (pGlDrawBuffersATI) + pGlDrawBuffersATI(n, bufs); +#elif defined(GL_ARB_draw_buffers) + glDrawBuffersARB(n, bufs); +#elif defined(GL_ATI_draw_buffers) + glDrawBuffersATI(n, bufs); +#else + os::Printer::log("glDrawBuffers not supported", ELL_ERROR); +#endif +} + inline void COpenGLExtensionHandler::extGlGenBuffers(GLsizei n, GLuint *buffers) { @@ -1534,6 +1724,101 @@ inline void COpenGLExtensionHandler::extGlGetBufferPointerv (GLenum target, GLen } +inline void COpenGLExtensionHandler::extGlProvokingVertex(GLenum mode) +{ +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + if (FeatureAvailable[IRR_ARB_provoking_vertex] && pGlProvokingVertexARB) + pGlProvokingVertexARB(mode); + else if (FeatureAvailable[IRR_EXT_provoking_vertex] && pGlProvokingVertexEXT) + pGlProvokingVertexEXT(mode); +#elif defined(GL_ARB_provoking_vertex) + glProvokingVertex(mode); +#elif defined(GL_EXT_provoking_vertex) + glProvokingVertexEXT(mode); +#else + os::Printer::log("glProvokingVertex not supported", ELL_ERROR); +#endif +} + + +inline void COpenGLExtensionHandler::extGlColorMaskIndexed(GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a) +{ +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + if (FeatureAvailable[IRR_EXT_draw_buffers2] && pGlColorMaskIndexedEXT) + pGlColorMaskIndexedEXT(buf, r, g, b, a); +#elif defined(GL_EXT_draw_buffers2) + glColorMaskIndexedEXT(buf, r, g, b, a); +#else + os::Printer::log("glColorMaskIndexed not supported", ELL_ERROR); +#endif +} + + +inline void COpenGLExtensionHandler::extGlEnableIndexed(GLenum target, GLuint index) +{ +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + if (FeatureAvailable[IRR_EXT_draw_buffers2] && pGlEnableIndexedEXT) + pGlEnableIndexedEXT(target, index); +#elif defined(GL_EXT_draw_buffers2) + glEnableIndexedEXT(target, index); +#else + os::Printer::log("glEnableIndexed not supported", ELL_ERROR); +#endif +} + + +inline void COpenGLExtensionHandler::extGlDisableIndexed(GLenum target, GLuint index) +{ +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + if (FeatureAvailable[IRR_EXT_draw_buffers2] && pGlDisableIndexedEXT) + pGlDisableIndexedEXT(target, index); +#elif defined(GL_EXT_draw_buffers2) + glDisableIndexedEXT(target, index); +#else + os::Printer::log("glDisableIndexed not supported", ELL_ERROR); +#endif +} + + +inline void COpenGLExtensionHandler::extGlBlendFuncIndexed(GLuint buf, GLenum src, GLenum dst) +{ +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + if (FeatureAvailable[IRR_ARB_draw_buffers_blend] && pGlBlendFunciARB) + pGlBlendFunciARB(buf, src, dst); + if (FeatureAvailable[IRR_AMD_draw_buffers_blend] && pGlBlendFuncIndexedAMD) + pGlBlendFuncIndexedAMD(buf, src, dst); +#elif defined(GL_ARB_draw_buffers_blend) + glBlendFunciARB(buf, src, dst); +#elif defined(GL_AMD_draw_buffers_blend) + glBlendFuncIndexedAMD(buf, src, dst); +#else + os::Printer::log("glBlendFuncIndexed not supported", ELL_ERROR); +#endif +} + + +inline void COpenGLExtensionHandler::extGlProgramParameteri(GLuint program, GLenum pname, GLint value) +{ +#if defined(_IRR_OPENGL_USE_EXTPOINTER_) + if (queryFeature(EVDF_GEOMETRY_SHADER)) + { + if (pGlProgramParameteriARB) + pGlProgramParameteriARB(program, pname, value); + else if (pGlProgramParameteriEXT) + pGlProgramParameteriEXT(program, pname, value); + } +#elif defined(GL_ARB_geometry_shader4) + glProgramParameteriARB(program, pname, value); +#elif defined(GL_EXT_geometry_shader4) + glProgramParameteriEXT(program, pname, value); +#elif defined(GL_NV_geometry_program4) || defined(GL_NV_geometry_shader4) + glProgramParameteriNV(program, pname, value); +#else + os::Printer::log("glProgramParameteri not supported", ELL_ERROR); +#endif +} + + } } diff --git a/src/dep/src/irrlicht/COpenGLMaterialRenderer.h b/src/dep/src/irrlicht/COpenGLMaterialRenderer.h index 83dde8a..31491f6 100644 --- a/src/dep/src/irrlicht/COpenGLMaterialRenderer.h +++ b/src/dep/src/irrlicht/COpenGLMaterialRenderer.h @@ -1,688 +1,766 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __C_OPENGL_MATERIAL_RENDERER_H_INCLUDED__ -#define __C_OPENGL_MATERIAL_RENDERER_H_INCLUDED__ - -#include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_OPENGL_ - -#include "COpenGLDriver.h" -#include "IMaterialRenderer.h" -#if defined(_IRR_USE_OSX_DEVICE_) - #define GL_COMBINE_EXT 0x8570 - #define GL_COMBINE_RGB_EXT 0x8571 - #define GL_COMBINE_ALPHA_EXT 0x8572 - #define GL_RGB_SCALE_EXT 0x8573 - #define GL_ADD_SIGNED_EXT 0x8574 - #define GL_INTERPOLATE_EXT 0x8575 - #define GL_CONSTANT_EXT 0x8576 - #define GL_PRIMARY_COLOR_EXT 0x8577 - #define GL_PREVIOUS_EXT 0x8578 - #define GL_SOURCE0_RGB_EXT 0x8580 - #define GL_SOURCE1_RGB_EXT 0x8581 - #define GL_SOURCE2_RGB_EXT 0x8582 - #define GL_SOURCE3_RGB_EXT 0x8583 - #define GL_SOURCE4_RGB_EXT 0x8584 - #define GL_SOURCE5_RGB_EXT 0x8585 - #define GL_SOURCE6_RGB_EXT 0x8586 - #define GL_SOURCE7_RGB_EXT 0x8587 - #define GL_SOURCE0_ALPHA_EXT 0x8588 - #define GL_SOURCE1_ALPHA_EXT 0x8589 - #define GL_SOURCE2_ALPHA_EXT 0x858A - #define GL_SOURCE3_ALPHA_EXT 0x858B - #define GL_SOURCE4_ALPHA_EXT 0x858C - #define GL_SOURCE5_ALPHA_EXT 0x858D - #define GL_SOURCE6_ALPHA_EXT 0x858E - #define GL_SOURCE7_ALPHA_EXT 0x858F - #define GL_OPERAND0_RGB_EXT 0x8590 - #define GL_OPERAND1_RGB_EXT 0x8591 - #define GL_OPERAND2_RGB_EXT 0x8592 - #define GL_OPERAND3_RGB_EXT 0x8593 - #define GL_OPERAND4_RGB_EXT 0x8594 - #define GL_OPERAND5_RGB_EXT 0x8595 - #define GL_OPERAND6_RGB_EXT 0x8596 - #define GL_OPERAND7_RGB_EXT 0x8597 - #define GL_OPERAND0_ALPHA_EXT 0x8598 - #define GL_OPERAND1_ALPHA_EXT 0x8599 - #define GL_OPERAND2_ALPHA_EXT 0x859A - #define GL_OPERAND3_ALPHA_EXT 0x859B - #define GL_OPERAND4_ALPHA_EXT 0x859C - #define GL_OPERAND5_ALPHA_EXT 0x859D - #define GL_OPERAND6_ALPHA_EXT 0x859E - #define GL_OPERAND7_ALPHA_EXT 0x859F -#endif - -namespace irr -{ -namespace video -{ - -//! Base class for all internal OpenGL material renderers -class COpenGLMaterialRenderer : public IMaterialRenderer -{ -public: - - //! Constructor - COpenGLMaterialRenderer(video::COpenGLDriver* driver) : Driver(driver) - { - } - -protected: - - video::COpenGLDriver* Driver; -}; - - -//! Solid material renderer -class COpenGLMaterialRenderer_SOLID : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_SOLID(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(1); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (resetAllRenderstates || (material.MaterialType != lastMaterial.MaterialType)) - { - // thanks to Murphy, the following line removed some - // bugs with several OpenGL implementations. - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - } -}; - - -//! Generic Texture Blend -class COpenGLMaterialRenderer_ONETEXTURE_BLEND : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_ONETEXTURE_BLEND(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(1); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - -// if (material.MaterialType != lastMaterial.MaterialType || -// material.MaterialTypeParam != lastMaterial.MaterialTypeParam || -// resetAllRenderstates) - { - E_BLEND_FACTOR srcFact,dstFact; - E_MODULATE_FUNC modulate; - unpack_texureBlendFunc ( srcFact, dstFact, modulate, material.MaterialTypeParam ); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); - - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, (f32) modulate ); - - glBlendFunc( getGLBlend(srcFact), getGLBlend(dstFact) ); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.f); - glEnable(GL_BLEND); - - if ( getTexelAlpha(srcFact) || getTexelAlpha(dstFact) ) - { - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); - - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); - } - } - } - - virtual void OnUnsetMaterial() - { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); - - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - } - - private: - - u32 getGLBlend ( E_BLEND_FACTOR factor ) const - { - u32 r = 0; - switch ( factor ) - { - case EBF_ZERO: r = GL_ZERO; break; - case EBF_ONE: r = GL_ONE; break; - case EBF_DST_COLOR: r = GL_DST_COLOR; break; - case EBF_ONE_MINUS_DST_COLOR: r = GL_ONE_MINUS_DST_COLOR; break; - case EBF_SRC_COLOR: r = GL_SRC_COLOR; break; - case EBF_ONE_MINUS_SRC_COLOR: r = GL_ONE_MINUS_SRC_COLOR; break; - case EBF_SRC_ALPHA: r = GL_SRC_ALPHA; break; - case EBF_ONE_MINUS_SRC_ALPHA: r = GL_ONE_MINUS_SRC_ALPHA; break; - case EBF_DST_ALPHA: r = GL_DST_ALPHA; break; - case EBF_ONE_MINUS_DST_ALPHA: r = GL_ONE_MINUS_DST_ALPHA; break; - case EBF_SRC_ALPHA_SATURATE: r = GL_SRC_ALPHA_SATURATE; break; - } - return r; - } - - u32 getTexelAlpha ( E_BLEND_FACTOR factor ) const - { - u32 r; - switch ( factor ) - { - case EBF_SRC_ALPHA: r = 1; break; - case EBF_ONE_MINUS_SRC_ALPHA: r = 1; break; - case EBF_DST_ALPHA: r = 1; break; - case EBF_ONE_MINUS_DST_ALPHA: r = 1; break; - case EBF_SRC_ALPHA_SATURATE: r = 1; break; - default: r = 0; break; - } - return r; - } -}; - - -//! Solid 2 layer material renderer -class COpenGLMaterialRenderer_SOLID_2_LAYER : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_SOLID_2_LAYER(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(2); - Driver->setTexture(1, material.getTexture(1)); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) - { - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR); - glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); - } - } - } - - virtual void OnUnsetMaterial() - { - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR); - Driver->extGlActiveTexture(GL_TEXTURE0_ARB); - } - } -}; - - -//! Transparent add color material renderer -class COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(1); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if ((material.MaterialType != lastMaterial.MaterialType) || resetAllRenderstates) - { - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glEnable(GL_BLEND); - } - } - - virtual void OnUnsetMaterial() - { - glDisable(GL_BLEND); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return true; - } -}; - - -//! Transparent vertex alpha material renderer -class COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(1); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) - { - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT ); - - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PRIMARY_COLOR_EXT ); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); - - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - } - } - - virtual void OnUnsetMaterial() - { - // default values - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE ); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT ); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE ); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); - - glDisable(GL_BLEND); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return true; - } -}; - - -//! Transparent alpha channel material renderer -class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(1); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates - || material.MaterialTypeParam != lastMaterial.MaterialTypeParam ) - { - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); - - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_ALPHA_TEST); - - glAlphaFunc(GL_GREATER, material.MaterialTypeParam); - } - } - - virtual void OnUnsetMaterial() - { - glDisable(GL_ALPHA_TEST); - glDisable(GL_BLEND); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return true; - } -}; - - - -//! Transparent alpha channel material renderer -class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(1); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) - { - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.5f); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - } - } - - virtual void OnUnsetMaterial() - { - glDisable(GL_ALPHA_TEST); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return false; // this material is not really transparent because it does no blending. - } -}; - - -//! material renderer for all kinds of lightmaps -class COpenGLMaterialRenderer_LIGHTMAP : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_LIGHTMAP(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(2); - Driver->setTexture(1, material.getTexture(1)); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) - { - // diffuse map - - switch (material.MaterialType) - { - case EMT_LIGHTMAP_LIGHTING: - case EMT_LIGHTMAP_LIGHTING_M2: - case EMT_LIGHTMAP_LIGHTING_M4: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - break; - case EMT_LIGHTMAP_ADD: - case EMT_LIGHTMAP: - case EMT_LIGHTMAP_M2: - case EMT_LIGHTMAP_M4: - default: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - break; - } - - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - // lightmap - - Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - - if (material.MaterialType == EMT_LIGHTMAP_ADD) - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD_SIGNED_ARB); - else - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); - - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_ARB); - - switch (material.MaterialType) - { - case EMT_LIGHTMAP_M4: - case EMT_LIGHTMAP_LIGHTING_M4: - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 4.0f); - break; - case EMT_LIGHTMAP_M2: - case EMT_LIGHTMAP_LIGHTING_M2: - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); - break; - default: - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f); - } - } - } - } - - virtual void OnUnsetMaterial() - { - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - Driver->extGlActiveTexture(GL_TEXTURE0_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - } -}; - - - -//! detail map material renderer -class COpenGLMaterialRenderer_DETAIL_MAP : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_DETAIL_MAP(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(2); - Driver->setTexture(1, material.getTexture(1)); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) - { - // diffuse map - - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - // detail map - Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD_SIGNED_EXT); - glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_EXT,GL_PREVIOUS_EXT); - glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_EXT, GL_TEXTURE); - Driver->extGlActiveTexture(GL_TEXTURE0_ARB); - } - } - } -}; - - -//! sphere map material renderer -class COpenGLMaterialRenderer_SPHERE_MAP : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_SPHERE_MAP(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(1); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) - { - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - } - } - - virtual void OnUnsetMaterial() - { - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - } -}; - - -//! reflection 2 layer material renderer -class COpenGLMaterialRenderer_REFLECTION_2_LAYER : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_REFLECTION_2_LAYER(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(2); - Driver->setTexture(1, material.getTexture(1)); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) - { - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); - - } - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - } - } - - virtual void OnUnsetMaterial() - { - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - Driver->extGlActiveTexture(GL_TEXTURE0_ARB); - } - } -}; - - -//! reflection 2 layer material renderer -class COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public COpenGLMaterialRenderer -{ -public: - - COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(video::COpenGLDriver* d) - : COpenGLMaterialRenderer(d) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - Driver->disableTextures(2); - Driver->setTexture(1, material.getTexture(1)); - Driver->setTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - - if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) - { - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); - } - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); - glEnable(GL_BLEND); - } - } - - virtual void OnUnsetMaterial() - { - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - if (Driver->queryFeature(EVDF_MULTITEXTURE)) - { - Driver->extGlActiveTexture(GL_TEXTURE0_ARB); - } - glDisable(GL_BLEND); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return true; - } -}; - -} // end namespace video -} // end namespace irr - -#endif -#endif - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_OPENGL_MATERIAL_RENDERER_H_INCLUDED__ +#define __C_OPENGL_MATERIAL_RENDERER_H_INCLUDED__ + +#include "IrrCompileConfig.h" +#ifdef _IRR_COMPILE_WITH_OPENGL_ + +#include "COpenGLDriver.h" +#include "IMaterialRenderer.h" + +namespace irr +{ +namespace video +{ + +//! Base class for all internal OpenGL material renderers +class COpenGLMaterialRenderer : public IMaterialRenderer +{ +public: + + //! Constructor + COpenGLMaterialRenderer(video::COpenGLDriver* driver) : Driver(driver) + { + } + +protected: + + video::COpenGLDriver* Driver; +}; + + +//! Solid material renderer +class COpenGLMaterialRenderer_SOLID : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_SOLID(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(1); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (resetAllRenderstates || (material.MaterialType != lastMaterial.MaterialType)) + { + // thanks to Murphy, the following line removed some + // bugs with several OpenGL implementations. + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + } +}; + + +//! Generic Texture Blend +class COpenGLMaterialRenderer_ONETEXTURE_BLEND : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_ONETEXTURE_BLEND(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(1); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + +// if (material.MaterialType != lastMaterial.MaterialType || +// material.MaterialTypeParam != lastMaterial.MaterialTypeParam || +// resetAllRenderstates) + { + E_BLEND_FACTOR srcFact,dstFact; + E_MODULATE_FUNC modulate; + u32 alphaSource; + unpack_texureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam ); + +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (f32) modulate ); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, (f32) modulate ); +#endif + + glBlendFunc( getGLBlend(srcFact), getGLBlend(dstFact) ); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.f); + glEnable(GL_BLEND); + + if ( textureBlendFunc_hasAlpha(srcFact) || textureBlendFunc_hasAlpha(dstFact) ) + { + if (alphaSource==EAS_VERTEX_COLOR) + { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); +#endif + } + else if (alphaSource==EAS_TEXTURE) + { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); +#endif + } + else + { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); +#endif + } + +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); +#endif + } + } + } + + virtual void OnUnsetMaterial() + { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f ); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); +#endif + + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + } + + //! Returns if the material is transparent. + /** Is not always transparent, but mostly. */ + virtual bool isTransparent() const + { + return true; + } + + private: + + u32 getGLBlend ( E_BLEND_FACTOR factor ) const + { + u32 r = 0; + switch ( factor ) + { + case EBF_ZERO: r = GL_ZERO; break; + case EBF_ONE: r = GL_ONE; break; + case EBF_DST_COLOR: r = GL_DST_COLOR; break; + case EBF_ONE_MINUS_DST_COLOR: r = GL_ONE_MINUS_DST_COLOR; break; + case EBF_SRC_COLOR: r = GL_SRC_COLOR; break; + case EBF_ONE_MINUS_SRC_COLOR: r = GL_ONE_MINUS_SRC_COLOR; break; + case EBF_SRC_ALPHA: r = GL_SRC_ALPHA; break; + case EBF_ONE_MINUS_SRC_ALPHA: r = GL_ONE_MINUS_SRC_ALPHA; break; + case EBF_DST_ALPHA: r = GL_DST_ALPHA; break; + case EBF_ONE_MINUS_DST_ALPHA: r = GL_ONE_MINUS_DST_ALPHA; break; + case EBF_SRC_ALPHA_SATURATE: r = GL_SRC_ALPHA_SATURATE; break; + } + return r; + } + +}; + + +//! Solid 2 layer material renderer +class COpenGLMaterialRenderer_SOLID_2_LAYER : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_SOLID_2_LAYER(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(2); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) + { + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PRIMARY_COLOR); + glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR); + glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); +#endif + } + } + } + + virtual void OnUnsetMaterial() + { + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR); +#endif + Driver->extGlActiveTexture(GL_TEXTURE0_ARB); + } + } +}; + + +//! Transparent add color material renderer +class COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(1); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if ((material.MaterialType != lastMaterial.MaterialType) || resetAllRenderstates) + { + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glEnable(GL_BLEND); + } + } + + virtual void OnUnsetMaterial() + { + glDisable(GL_BLEND); + } + + //! Returns if the material is transparent. + virtual bool isTransparent() const + { + return true; + } +}; + + +//! Transparent vertex alpha material renderer +class COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(1); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) + { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT ); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); +#endif + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + } + } + + virtual void OnUnsetMaterial() + { + // default values + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE ); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE ); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE ); +#endif + glDisable(GL_BLEND); + } + + //! Returns if the material is transparent. + virtual bool isTransparent() const + { + return true; + } +}; + + +//! Transparent alpha channel material renderer +class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(1); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates + || material.MaterialTypeParam != lastMaterial.MaterialTypeParam ) + { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); +#endif + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + + glAlphaFunc(GL_GREATER, material.MaterialTypeParam); + } + } + + virtual void OnUnsetMaterial() + { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE ); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); +#endif + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + } + + //! Returns if the material is transparent. + virtual bool isTransparent() const + { + return true; + } +}; + + +//! Transparent alpha channel material renderer +class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(1); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) + { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.5f); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + } + + virtual void OnUnsetMaterial() + { + glDisable(GL_ALPHA_TEST); + } + + //! Returns if the material is transparent. + virtual bool isTransparent() const + { + return false; // this material is not really transparent because it does no blending. + } +}; + + +//! material renderer for all kinds of lightmaps +class COpenGLMaterialRenderer_LIGHTMAP : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_LIGHTMAP(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(2); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) + { + // diffuse map + + switch (material.MaterialType) + { + case EMT_LIGHTMAP_LIGHTING: + case EMT_LIGHTMAP_LIGHTING_M2: + case EMT_LIGHTMAP_LIGHTING_M4: + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + break; + case EMT_LIGHTMAP_ADD: + case EMT_LIGHTMAP: + case EMT_LIGHTMAP_M2: + case EMT_LIGHTMAP_M4: + default: + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + break; + } + + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + // lightmap + + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + + if (material.MaterialType == EMT_LIGHTMAP_ADD) + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD); + else + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB); +#else + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + + if (material.MaterialType == EMT_LIGHTMAP_ADD) + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD); + else + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT); +#endif + + switch (material.MaterialType) + { + case EMT_LIGHTMAP_M4: + case EMT_LIGHTMAP_LIGHTING_M4: +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 4.0f); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 4.0f); +#endif + break; + case EMT_LIGHTMAP_M2: + case EMT_LIGHTMAP_LIGHTING_M2: +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2.0f); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); +#endif + break; + default: +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f); +#endif + } + Driver->extGlActiveTexture(GL_TEXTURE0_ARB); + } + } + } + + virtual void OnUnsetMaterial() + { + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f ); +#else + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + Driver->extGlActiveTexture(GL_TEXTURE0_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + } +}; + + + +//! detail map material renderer +class COpenGLMaterialRenderer_DETAIL_MAP : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_DETAIL_MAP(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(2); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) + { + // diffuse map is default modulated + + // detail map on second layer + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); +#else + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD_SIGNED_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); +#endif + } + } + } + + virtual void OnUnsetMaterial() + { + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + Driver->extGlActiveTexture(GL_TEXTURE0_ARB); + } + } +}; + + +//! sphere map material renderer +class COpenGLMaterialRenderer_SPHERE_MAP : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_SPHERE_MAP(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(1); + // texture needs to be flipped for OpenGL + core::matrix4 tmp = Driver->getTransform(ETS_TEXTURE_0); + tmp[5]*=-1; + Driver->setTransform(ETS_TEXTURE_0, tmp); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) + { + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + } + } + + virtual void OnUnsetMaterial() + { + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + } +}; + + +//! reflection 2 layer material renderer +class COpenGLMaterialRenderer_REFLECTION_2_LAYER : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_REFLECTION_2_LAYER(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(2); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) + { + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); +#else + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); +#endif + } + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + } + } + + virtual void OnUnsetMaterial() + { + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE0_ARB); + } + } +}; + + +//! reflection 2 layer material renderer +class COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public COpenGLMaterialRenderer +{ +public: + + COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(video::COpenGLDriver* d) + : COpenGLMaterialRenderer(d) {} + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) + { + Driver->disableTextures(2); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) + { + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); +#else + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); +#endif + } + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + glEnable(GL_BLEND); + } + } + + virtual void OnUnsetMaterial() + { + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE1_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + if (Driver->queryFeature(EVDF_MULTITEXTURE)) + { + Driver->extGlActiveTexture(GL_TEXTURE0_ARB); + } + glDisable(GL_BLEND); + } + + //! Returns if the material is transparent. + virtual bool isTransparent() const + { + return true; + } +}; + +} // end namespace video +} // end namespace irr + +#endif +#endif + diff --git a/src/dep/src/irrlicht/COpenGLNormalMapRenderer.cpp b/src/dep/src/irrlicht/COpenGLNormalMapRenderer.cpp index d901712..13967f4 100644 --- a/src/dep/src/irrlicht/COpenGLNormalMapRenderer.cpp +++ b/src/dep/src/irrlicht/COpenGLNormalMapRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -47,9 +47,6 @@ const char OPENGL_NORMAL_MAP_VSH[] = "PARAM MVP[4] = { state.matrix.mvp }; # modelViewProjection matrix.\n"\ "TEMP Temp;\n"\ "TEMP TempColor;\n"\ - "TEMP TempNormal;\n"\ - "TEMP TempTangent;\n"\ - "TEMP TempBinormal;\n"\ "TEMP TempLightVector1;\n"\ "TEMP TempLightVector2;\n"\ "TEMP TempTransLightV1;\n"\ @@ -58,43 +55,24 @@ const char OPENGL_NORMAL_MAP_VSH[] = "# transform position to clip space \n"\ "DP4 OutPos.x, MVP[0], InPos;\n"\ "DP4 OutPos.y, MVP[1], InPos;\n"\ - "DP4 OutPos.z, MVP[2], InPos;\n"\ + "DP4 Temp.z, MVP[2], InPos;\n"\ "DP4 OutPos.w, MVP[3], InPos;\n"\ - "\n"\ - "# transform normal \n"\ - "DP3 TempNormal.x, InNormal.x, program.local[0];\n"\ - "DP3 TempNormal.y, InNormal.y, program.local[1]; \n"\ - "DP3 TempNormal.z, InNormal.z, program.local[2];\n"\ - "\n"\ - "# transform tangent \n"\ - "DP3 TempTangent.x, InTangent.x, program.local[0];\n"\ - "DP3 TempTangent.y, InTangent.y, program.local[1]; \n"\ - "DP3 TempTangent.z, InTangent.z, program.local[2];\n"\ - "\n"\ - "# transform binormal \n"\ - "DP3 TempBinormal.x, InBinormal.x, program.local[0];\n"\ - "DP3 TempBinormal.y, InBinormal.y, program.local[1]; \n"\ - "DP3 TempBinormal.z, InBinormal.z, program.local[2];\n"\ - "\n"\ - "# vertex into world position \n"\ - "DP4 Temp.x, InPos, program.local[0];\n"\ - "DP4 Temp.y, InPos, program.local[1];\n"\ - "DP4 Temp.z, InPos, program.local[2];\n"\ - "DP4 Temp.w, InPos, program.local[3];\n"\ + "MOV OutPos.z, Temp.z;\n"\ + "MOV result.fogcoord.x, Temp.z;\n"\ "\n"\ "# vertex - lightpositions \n"\ - "SUB TempLightVector1, program.local[12], Temp; \n"\ - "SUB TempLightVector2, program.local[14], Temp; \n"\ + "SUB TempLightVector1, program.local[12], InPos; \n"\ + "SUB TempLightVector2, program.local[14], InPos; \n"\ "\n"\ "# transform the light vector 1 with U, V, W \n"\ - "DP3 TempTransLightV1.x, TempTangent, TempLightVector1; \n"\ - "DP3 TempTransLightV1.y, TempBinormal, TempLightVector1; \n"\ - "DP3 TempTransLightV1.z, TempNormal, TempLightVector1; \n"\ + "DP3 TempTransLightV1.x, InTangent, TempLightVector1; \n"\ + "DP3 TempTransLightV1.y, InBinormal, TempLightVector1; \n"\ + "DP3 TempTransLightV1.z, InNormal, TempLightVector1; \n"\ "\n"\ "# transform the light vector 2 with U, V, W \n"\ - "DP3 TempTransLightV2.x, TempTangent, TempLightVector2; \n"\ - "DP3 TempTransLightV2.y, TempBinormal, TempLightVector2; \n"\ - "DP3 TempTransLightV2.z, TempNormal, TempLightVector2; \n"\ + "DP3 TempTransLightV2.x, InTangent, TempLightVector2; \n"\ + "DP3 TempTransLightV2.y, InBinormal, TempLightVector2; \n"\ + "DP3 TempTransLightV2.z, InNormal, TempLightVector2; \n"\ "\n"\ "# normalize light vector 1 \n"\ "DP3 TempTransLightV1.w, TempTransLightV1, TempTransLightV1; \n"\ @@ -136,6 +114,7 @@ const char OPENGL_NORMAL_MAP_VSH[] = // transfered it 1:1 to OpenGL const char OPENGL_NORMAL_MAP_PSH[] = "!!ARBfp1.0\n"\ + "#_IRR_FOG_MODE_\n"\ "\n"\ "#Input\n"\ "ATTRIB inTexCoord = fragment.texcoord[0]; \n"\ @@ -236,7 +215,7 @@ COpenGLNormalMapRenderer::~COpenGLNormalMapRenderer() { // prevent this from deleting shaders we did not create VertexShader = 0; - PixelShader = 0; + PixelShader.clear(); } } @@ -274,6 +253,10 @@ void COpenGLNormalMapRenderer::OnSetConstants(IMaterialRendererServices* service u32 cnt = driver->getDynamicLightCount(); + // Load the inverse world matrix. + core::matrix4 invWorldMat; + driver->getTransform(video::ETS_WORLD).getInverse(invWorldMat); + for (u32 i=0; i<2; ++i) { video::SLight light; @@ -288,6 +271,9 @@ void COpenGLNormalMapRenderer::OnSetConstants(IMaterialRendererServices* service light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation + // Transform the light by the inverse world matrix to get it into object space. + invWorldMat.transformVect(light.Position); + services->setVertexShaderConstant( reinterpret_cast(&light.Position), 12+(i*2), 1); diff --git a/src/dep/src/irrlicht/COpenGLNormalMapRenderer.h b/src/dep/src/irrlicht/COpenGLNormalMapRenderer.h index 9f7d755..84607da 100644 --- a/src/dep/src/irrlicht/COpenGLNormalMapRenderer.h +++ b/src/dep/src/irrlicht/COpenGLNormalMapRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/COpenGLParallaxMapRenderer.cpp b/src/dep/src/irrlicht/COpenGLParallaxMapRenderer.cpp index dde494e..7f587d9 100644 --- a/src/dep/src/irrlicht/COpenGLParallaxMapRenderer.cpp +++ b/src/dep/src/irrlicht/COpenGLParallaxMapRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -49,9 +49,6 @@ const char OPENGL_PARALLAX_MAP_VSH[] = "PARAM MVP[4] = { state.matrix.mvp }; # modelViewProjection matrix.\n"\ "TEMP Temp;\n"\ "TEMP TempColor;\n"\ - "TEMP TempNormal;\n"\ - "TEMP TempTangent;\n"\ - "TEMP TempBinormal;\n"\ "TEMP TempLightVector1;\n"\ "TEMP TempLightVector2;\n"\ "TEMP TempEyeVector;\n"\ @@ -61,51 +58,32 @@ const char OPENGL_PARALLAX_MAP_VSH[] = "# transform position to clip space \n"\ "DP4 OutPos.x, MVP[0], InPos;\n"\ "DP4 OutPos.y, MVP[1], InPos;\n"\ - "DP4 OutPos.z, MVP[2], InPos;\n"\ + "DP4 Temp.z, MVP[2], InPos;\n"\ "DP4 OutPos.w, MVP[3], InPos;\n"\ - "\n"\ - "# transform normal \n"\ - "DP3 TempNormal.x, InNormal.x, program.local[0];\n"\ - "DP3 TempNormal.y, InNormal.y, program.local[1]; \n"\ - "DP3 TempNormal.z, InNormal.z, program.local[2];\n"\ - "\n"\ - "# transform tangent \n"\ - "DP3 TempTangent.x, InTangent.x, program.local[0];\n"\ - "DP3 TempTangent.y, InTangent.y, program.local[1]; \n"\ - "DP3 TempTangent.z, InTangent.z, program.local[2];\n"\ - "\n"\ - "# transform binormal \n"\ - "DP3 TempBinormal.x, InBinormal.x, program.local[0];\n"\ - "DP3 TempBinormal.y, InBinormal.y, program.local[1]; \n"\ - "DP3 TempBinormal.z, InBinormal.z, program.local[2];\n"\ - "\n"\ - "# vertex into world position \n"\ - "DP4 Temp.x, InPos, program.local[0];\n"\ - "DP4 Temp.y, InPos, program.local[1];\n"\ - "DP4 Temp.z, InPos, program.local[2];\n"\ - "DP4 Temp.w, InPos, program.local[3];\n"\ + "MOV OutPos.z, Temp.z;\n"\ + "MOV result.fogcoord.x, Temp.z;\n"\ "\n"\ "# vertex - lightpositions \n"\ - "SUB TempLightVector1, program.local[12], Temp; \n"\ - "SUB TempLightVector2, program.local[14], Temp; \n"\ + "SUB TempLightVector1, program.local[12], InPos; \n"\ + "SUB TempLightVector2, program.local[14], InPos; \n"\ "\n"\ "# eye vector \n"\ - "SUB Temp, program.local[16], Temp; \n"\ + "SUB Temp, program.local[16], InPos; \n"\ "\n"\ "# transform the light vector 1 with U, V, W \n"\ - "DP3 TempTransLightV1.x, TempTangent, TempLightVector1; \n"\ - "DP3 TempTransLightV1.y, TempBinormal, TempLightVector1; \n"\ - "DP3 TempTransLightV1.z, TempNormal, TempLightVector1; \n"\ + "DP3 TempTransLightV1.x, InTangent, TempLightVector1; \n"\ + "DP3 TempTransLightV1.y, InBinormal, TempLightVector1; \n"\ + "DP3 TempTransLightV1.z, InNormal, TempLightVector1; \n"\ "\n"\ "# transform the light vector 2 with U, V, W \n"\ - "DP3 TempTransLightV2.x, TempTangent, TempLightVector2; \n"\ - "DP3 TempTransLightV2.y, TempBinormal, TempLightVector2; \n"\ - "DP3 TempTransLightV2.z, TempNormal, TempLightVector2; \n"\ + "DP3 TempTransLightV2.x, InTangent, TempLightVector2; \n"\ + "DP3 TempTransLightV2.y, InBinormal, TempLightVector2; \n"\ + "DP3 TempTransLightV2.z, InNormal, TempLightVector2; \n"\ "\n"\ "# transform the eye vector with U, V, W \n"\ - "DP3 TempEyeVector.x, TempTangent, Temp; \n"\ - "DP3 TempEyeVector.y, TempBinormal, Temp; \n"\ - "DP3 TempEyeVector.z, TempNormal, Temp; \n"\ + "DP3 TempEyeVector.x, InTangent, Temp; \n"\ + "DP3 TempEyeVector.y, InBinormal, Temp; \n"\ + "DP3 TempEyeVector.z, InNormal, Temp; \n"\ "\n"\ "# normalize light vector 1 \n"\ "DP3 TempTransLightV1.w, TempTransLightV1, TempTransLightV1; \n"\ @@ -154,6 +132,7 @@ const char OPENGL_PARALLAX_MAP_VSH[] = // transfered it 1:1 to OpenGL const char OPENGL_PARALLAX_MAP_PSH[] = "!!ARBfp1.0\n"\ + "#_IRR_FOG_MODE_\n"\ "\n"\ "#Input\n"\ "ATTRIB inTexCoord = fragment.texcoord[0]; \n"\ @@ -270,7 +249,7 @@ COpenGLParallaxMapRenderer::~COpenGLParallaxMapRenderer() { // prevent this from deleting shaders we did not create VertexShader = 0; - PixelShader = 0; + PixelShader.clear(); } } @@ -308,17 +287,6 @@ void COpenGLParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* servi const core::matrix4& tWorld = driver->getTransform(video::ETS_WORLD).getTransposed(); services->setVertexShaderConstant(tWorld.pointer(), 0, 4); - // The viewpoint is at (0., 0., 0.) in eye space. - // Turning this into a vector [0 0 0 1] and multiply it by - // the inverse of the view matrix, the resulting vector is the - // object space location of the camera. - - f32 floats[4] = {0.0f,0.0f,0.0f,1.0f}; - core::matrix4 minv(driver->getTransform(video::ETS_VIEW)); - minv.makeInverse(); - minv.multiplyWith1x4Matrix(floats); - services->setVertexShaderConstant(floats, 16, 1); - // set transposed worldViewProj matrix core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); worldViewProj *= driver->getTransform(video::ETS_VIEW); @@ -331,6 +299,10 @@ void COpenGLParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* servi u32 cnt = driver->getDynamicLightCount(); + // Load the inverse world matrix. + core::matrix4 invWorldMat; + driver->getTransform(video::ETS_WORLD).getInverse(invWorldMat); + for (u32 i=0; i<2; ++i) { video::SLight light; @@ -345,6 +317,9 @@ void COpenGLParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* servi light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation + // Transform the light by the inverse world matrix to get it into object space. + invWorldMat.transformVect(light.Position); + services->setVertexShaderConstant( reinterpret_cast(&light.Position), 12+(i*2), 1); @@ -352,6 +327,15 @@ void COpenGLParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* servi reinterpret_cast(&light.DiffuseColor), 13+(i*2), 1); } + // Obtain the view position by transforming 0,0,0 by the inverse view matrix + // and then multiply this by the inverse world matrix. + core::vector3df viewPos(0.0f, 0.0f, 0.0f); + core::matrix4 inverseView; + driver->getTransform(video::ETS_VIEW).getInverse(inverseView); + inverseView.transformVect(viewPos); + invWorldMat.transformVect(viewPos); + services->setVertexShaderConstant(reinterpret_cast(&viewPos.X), 16, 1); + // set scale factor f32 factor = 0.02f; // default value if (CurrentScale != 0.0f) diff --git a/src/dep/src/irrlicht/COpenGLParallaxMapRenderer.h b/src/dep/src/irrlicht/COpenGLParallaxMapRenderer.h index 0fc0f1d..5c39179 100644 --- a/src/dep/src/irrlicht/COpenGLParallaxMapRenderer.h +++ b/src/dep/src/irrlicht/COpenGLParallaxMapRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -35,6 +35,7 @@ public: //! Returns the render capability of the material. virtual s32 getRenderCapability() const; + virtual void OnSetMaterial(const SMaterial& material) { } virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); diff --git a/src/dep/src/irrlicht/COpenGLSLMaterialRenderer.cpp b/src/dep/src/irrlicht/COpenGLSLMaterialRenderer.cpp index e4b5bad..ecffd9a 100644 --- a/src/dep/src/irrlicht/COpenGLSLMaterialRenderer.cpp +++ b/src/dep/src/irrlicht/COpenGLSLMaterialRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -35,6 +35,11 @@ COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(video::COpenGLDriver* drive const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, IShaderConstantSetCallBack* callback, video::IMaterialRenderer* baseMaterial, s32 userData) @@ -58,7 +63,7 @@ COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(video::COpenGLDriver* drive if (!Driver->queryFeature(EVDF_ARB_GLSL)) return; - init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram); + init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, geometryShaderProgram); } @@ -84,8 +89,13 @@ COpenGLSLMaterialRenderer::~COpenGLSLMaterialRenderer() if (CallBack) CallBack->drop(); - if(Program) + if (Program) { + GLhandleARB shaders[8]; + GLint count; + Driver->extGlGetAttachedObjects(Program, 8, &count, shaders); + for (GLint i=0; iextGlDeleteObject(shaders[i]); Driver->extGlDeleteObject(Program); Program = 0; } @@ -96,9 +106,13 @@ COpenGLSLMaterialRenderer::~COpenGLSLMaterialRenderer() BaseMaterial->drop(); } + void COpenGLSLMaterialRenderer::init(s32& outMaterialTypeNr, - const c8* vertexShaderProgram, - const c8* pixelShaderProgram) + const c8* vertexShaderProgram, + const c8* pixelShaderProgram, + const c8* geometryShaderProgram, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut) { outMaterialTypeNr = -1; @@ -110,12 +124,32 @@ void COpenGLSLMaterialRenderer::init(s32& outMaterialTypeNr, if (!createShader(GL_VERTEX_SHADER_ARB, vertexShaderProgram)) return; - if (pixelShaderProgram) if (!createShader(GL_FRAGMENT_SHADER_ARB, pixelShaderProgram)) return; #endif +#if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_program4) || defined(GL_NV_geometry_shader4) + if (geometryShaderProgram && Driver->queryFeature(EVDF_GEOMETRY_SHADER)) + { + if (!createShader(GL_GEOMETRY_SHADER_EXT, geometryShaderProgram)) + return; +#if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_shader4) + Driver->extGlProgramParameteri((GLuint)Program, GL_GEOMETRY_INPUT_TYPE_EXT, Driver->primitiveTypeToGL(inType)); + Driver->extGlProgramParameteri((GLuint)Program, GL_GEOMETRY_OUTPUT_TYPE_EXT, Driver->primitiveTypeToGL(outType)); + if (verticesOut==0) + Driver->extGlProgramParameteri((GLuint)Program, GL_GEOMETRY_VERTICES_OUT_EXT, Driver->MaxGeometryVerticesOut); + else + Driver->extGlProgramParameteri((GLuint)Program, GL_GEOMETRY_VERTICES_OUT_EXT, core::min_(verticesOut, Driver->MaxGeometryVerticesOut)); +#elif defined(GL_NV_geometry_program4) + if (verticesOut==0) + Driver->extGlProgramVertexLimit(GL_GEOMETRY_PROGRAM_NV, Driver->MaxGeometryVerticesOut); + else + Driver->extGlProgramVertexLimit(GL_GEOMETRY_PROGRAM_NV, core::min_(verticesOut, Driver->MaxGeometryVerticesOut)); +#endif + } +#endif + if (!linkProgram()) return; @@ -128,7 +162,7 @@ bool COpenGLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { // call callback to set shader constants - if (CallBack && (Program)) + if (CallBack && Program) CallBack->OnSetConstants(this, UserData); return true; @@ -154,7 +188,7 @@ void COpenGLSLMaterialRenderer::OnSetMaterial(const video::SMaterial& material, CallBack->OnSetMaterial(material); for (u32 i=0; isetTexture(i, material.getTexture(i)); + Driver->setActiveTexture(i, material.getTexture(i)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } @@ -167,26 +201,29 @@ void COpenGLSLMaterialRenderer::OnUnsetMaterial() BaseMaterial->OnUnsetMaterial(); } + //! Returns if the material is transparent. bool COpenGLSLMaterialRenderer::isTransparent() const { return BaseMaterial ? BaseMaterial->isTransparent() : false; } + bool COpenGLSLMaterialRenderer::createProgram() { Program = Driver->extGlCreateProgramObject(); return true; } + bool COpenGLSLMaterialRenderer::createShader(GLenum shaderType, const char* shader) { GLhandleARB shaderHandle = Driver->extGlCreateShaderObject(shaderType); - Driver->extGlShaderSource(shaderHandle, 1, &shader, NULL); - Driver->extGlCompileShader(shaderHandle); + Driver->extGlShaderSourceARB(shaderHandle, 1, &shader, NULL); + Driver->extGlCompileShaderARB(shaderHandle); - int status = 0; + GLint status = 0; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(shaderHandle, GL_OBJECT_COMPILE_STATUS_ARB, &status); @@ -194,18 +231,18 @@ bool COpenGLSLMaterialRenderer::createShader(GLenum shaderType, const char* shad if (!status) { - os::Printer::log("GLSL shader failed to compile"); + os::Printer::log("GLSL shader failed to compile", ELL_ERROR); // check error message and log it - int maxLength=0; + GLint maxLength=0; GLsizei length; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(shaderHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength); #endif - GLcharARB *pInfoLog = new GLcharARB[maxLength]; - Driver->extGlGetInfoLog(shaderHandle, maxLength, &length, pInfoLog); - os::Printer::log(reinterpret_cast(pInfoLog)); - delete [] pInfoLog; + GLcharARB *infoLog = new GLcharARB[maxLength]; + Driver->extGlGetInfoLog(shaderHandle, maxLength, &length, infoLog); + os::Printer::log(reinterpret_cast(infoLog), ELL_ERROR); + delete [] infoLog; return false; } @@ -218,9 +255,9 @@ bool COpenGLSLMaterialRenderer::createShader(GLenum shaderType, const char* shad bool COpenGLSLMaterialRenderer::linkProgram() { - Driver->extGlLinkProgram(Program); + Driver->extGlLinkProgramARB(Program); - int status = 0; + GLint status = 0; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_LINK_STATUS_ARB, &status); @@ -228,25 +265,25 @@ bool COpenGLSLMaterialRenderer::linkProgram() if (!status) { - os::Printer::log("GLSL shader program failed to link"); + os::Printer::log("GLSL shader program failed to link", ELL_ERROR); // check error message and log it - int maxLength=0; + GLint maxLength=0; GLsizei length; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength); #endif - GLcharARB *pInfoLog = new GLcharARB[maxLength]; - Driver->extGlGetInfoLog(Program, maxLength, &length, pInfoLog); - os::Printer::log(reinterpret_cast(pInfoLog)); - delete [] pInfoLog; + GLcharARB *infoLog = new GLcharARB[maxLength]; + Driver->extGlGetInfoLog(Program, maxLength, &length, infoLog); + os::Printer::log(reinterpret_cast(infoLog), ELL_ERROR); + delete [] infoLog; return false; } // get uniforms information - int num = 0; + GLint num = 0; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &num); #endif @@ -257,17 +294,19 @@ bool COpenGLSLMaterialRenderer::linkProgram() return true; } - int maxlen = 0; + GLint maxlen = 0; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &maxlen); #endif if (maxlen == 0) { - os::Printer::log("GLSL: failed to retrieve uniform information"); + os::Printer::log("GLSL: failed to retrieve uniform information", ELL_ERROR); return false; } + // seems that some implementations use an extra null terminator + ++maxlen; c8 *buf = new c8[maxlen]; UniformInfo.clear(); @@ -279,7 +318,7 @@ bool COpenGLSLMaterialRenderer::linkProgram() memset(buf, 0, maxlen); GLint size; - Driver->extGlGetActiveUniform(Program, i, maxlen, 0, &size, &ui.type, reinterpret_cast(buf)); + Driver->extGlGetActiveUniformARB(Program, i, maxlen, 0, &size, &ui.type, reinterpret_cast(buf)); ui.name = buf; UniformInfo.push_back(ui); @@ -308,12 +347,13 @@ bool COpenGLSLMaterialRenderer::setVertexShaderConstant(const c8* name, const f3 void COpenGLSLMaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { - os::Printer::log("Cannot set constant, please use high level shader call instead."); + os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING); } bool COpenGLSLMaterialRenderer::setPixelShaderConstant(const c8* name, const f32* floats, int count) { - int i, num = static_cast(UniformInfo.size()); + u32 i; + const u32 num = UniformInfo.size(); for (i=0; i < num; ++i) { @@ -325,7 +365,7 @@ bool COpenGLSLMaterialRenderer::setPixelShaderConstant(const c8* name, const f32 return false; #ifdef GL_ARB_shader_objects - GLint Location=Driver->extGlGetUniformLocation(Program,name); + GLint Location=Driver->extGlGetUniformLocationARB(Program,name); switch (UniformInfo[i].type) { @@ -354,14 +394,17 @@ bool COpenGLSLMaterialRenderer::setPixelShaderConstant(const c8* name, const f32 Driver->extGlUniform1iv(Location, count, reinterpret_cast(floats)); break; } + return true; +#else + return false; #endif - return true; } + void COpenGLSLMaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { - os::Printer::log("Cannot set constant, use high level shader call."); + os::Printer::log("Cannot set constant, use high level shader call.", ELL_WARNING); } IVideoDriver* COpenGLSLMaterialRenderer::getVideoDriver() diff --git a/src/dep/src/irrlicht/COpenGLSLMaterialRenderer.h b/src/dep/src/irrlicht/COpenGLSLMaterialRenderer.h index ef7f58a..f807808 100644 --- a/src/dep/src/irrlicht/COpenGLSLMaterialRenderer.h +++ b/src/dep/src/irrlicht/COpenGLSLMaterialRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -16,8 +16,10 @@ #else #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 +#else + #define GL_GLEXT_PROTOTYPES 1 #endif -#if defined(_IRR_USE_OSX_DEVICE_) +#if defined(_IRR_OSX_PLATFORM_) #include #else #include @@ -52,15 +54,21 @@ public: COpenGLSLMaterialRenderer( COpenGLDriver* driver, s32& outMaterialTypeNr, - const c8* vertexShaderProgram, - const c8* vertexShaderEntryPointName, - E_VERTEX_SHADER_TYPE vsCompileTarget, - const c8* pixelShaderProgram, - const c8* pixelShaderEntryPointName, - E_PIXEL_SHADER_TYPE psCompileTarget, - IShaderConstantSetCallBack* callback, - IMaterialRenderer* baseMaterial, - s32 userData); + const c8* vertexShaderProgram = 0, + const c8* vertexShaderEntryPointName = 0, + E_VERTEX_SHADER_TYPE vsCompileTarget = video::EVST_VS_1_1, + const c8* pixelShaderProgram = 0, + const c8* pixelShaderEntryPointName = 0, + E_PIXEL_SHADER_TYPE psCompileTarget = video::EPST_PS_1_1, + const c8* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + IMaterialRenderer* baseMaterial = 0, + s32 userData = 0); //! Destructor virtual ~COpenGLSLMaterialRenderer(); @@ -94,7 +102,11 @@ protected: void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, - const c8* pixelShaderProgram); + const c8* pixelShaderProgram, + const c8* geometryShaderProgram, + scene::E_PRIMITIVE_TYPE inType=scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType=scene::EPT_TRIANGLE_STRIP, + u32 verticesOut=0); bool createProgram(); bool createShader(GLenum shaderType, const char* shader); diff --git a/src/dep/src/irrlicht/COpenGLShaderMaterialRenderer.cpp b/src/dep/src/irrlicht/COpenGLShaderMaterialRenderer.cpp index 4dac60e..11bddb8 100644 --- a/src/dep/src/irrlicht/COpenGLShaderMaterialRenderer.cpp +++ b/src/dep/src/irrlicht/COpenGLShaderMaterialRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,13 +23,18 @@ COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(video::COpenGLDrive s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), - VertexShader(0), PixelShader(0), UserData(userData) + VertexShader(0), UserData(userData) { - #ifdef _DEBUG setDebugName("COpenGLShaderMaterialRenderer"); #endif + PixelShader.set_used(4); + for (u32 i=0; i<4; ++i) + { + PixelShader[i]=0; + } + if (BaseMaterial) BaseMaterial->grab(); @@ -46,8 +51,14 @@ COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(COpenGLDriver* driv IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), - VertexShader(0), PixelShader(0), UserData(userData) + VertexShader(0), UserData(userData) { + PixelShader.set_used(4); + for (u32 i=0; i<4; ++i) + { + PixelShader[i]=0; + } + if (BaseMaterial) BaseMaterial->grab(); @@ -65,16 +76,18 @@ COpenGLShaderMaterialRenderer::~COpenGLShaderMaterialRenderer() if (VertexShader) Driver->extGlDeletePrograms(1, &VertexShader); - if (PixelShader) - Driver->extGlDeletePrograms(1, &PixelShader); + for (u32 i=0; iextGlDeletePrograms(1, &PixelShader[i]); if (BaseMaterial) BaseMaterial->drop(); } -void COpenGLShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, - const c8* pixelShaderProgram, E_VERTEX_TYPE type) +void COpenGLShaderMaterialRenderer::init(s32& outMaterialTypeNr, + const c8* vertexShaderProgram, const c8* pixelShaderProgram, + E_VERTEX_TYPE type) { outMaterialTypeNr = -1; @@ -95,7 +108,7 @@ void COpenGLShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* verte bool COpenGLShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { // call callback to set shader constants - if (CallBack && (VertexShader || PixelShader)) + if (CallBack && (VertexShader || PixelShader[0])) CallBack->OnSetConstants(service, UserData); return true; @@ -107,23 +120,43 @@ void COpenGLShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& materi { if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { -#ifdef GL_ARB_vertex_program if (VertexShader) { // set new vertex shader +#ifdef GL_ARB_vertex_program Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader); glEnable(GL_VERTEX_PROGRAM_ARB); - } +#elif defined(GL_NV_vertex_program) + Driver->extGlBindProgram(GL_VERTEX_PROGRAM_NV, VertexShader); + glEnable(GL_VERTEX_PROGRAM_NV); #endif + } // set new pixel shader -#ifdef GL_ARB_fragment_program - if (PixelShader) + if (PixelShader[0]) { - Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader); + GLuint nextShader=PixelShader[0]; + if (material.FogEnable) + { + GLint curFogMode; + glGetIntegerv(GL_FOG_MODE, &curFogMode); +// if (Driver->LinearFog && PixelShader[1]) + if (curFogMode==GL_LINEAR && PixelShader[1]) + nextShader=PixelShader[1]; +// else if (!Driver->LinearFog && PixelShader[2]) + else if (curFogMode==GL_EXP && PixelShader[2]) + nextShader=PixelShader[2]; + else if (curFogMode==GL_EXP2 && PixelShader[3]) + nextShader=PixelShader[3]; + } +#ifdef GL_ARB_fragment_program + Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, nextShader); glEnable(GL_FRAGMENT_PROGRAM_ARB); - } +#elif defined(GL_NV_fragment_program) + Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_NV, nextShader); + glEnable(GL_FRAGMENT_PROGRAM_NV); #endif + } if (BaseMaterial) BaseMaterial->OnSetMaterial(material, material, true, services); @@ -134,7 +167,7 @@ void COpenGLShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& materi CallBack->OnSetMaterial(material); for (u32 i=0; isetTexture(i, material.getTexture(i)); + Driver->setActiveTexture(i, material.getTexture(i)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } @@ -145,11 +178,17 @@ void COpenGLShaderMaterialRenderer::OnUnsetMaterial() #ifdef GL_ARB_vertex_program if (VertexShader) glDisable(GL_VERTEX_PROGRAM_ARB); +#elif defined(GL_NV_vertex_program) + if (VertexShader) + glDisable(GL_VERTEX_PROGRAM_NV); #endif #ifdef GL_ARB_fragment_program - if (PixelShader) + if (PixelShader[0]) glDisable(GL_FRAGMENT_PROGRAM_ARB); +#elif defined(GL_NV_fragment_program) + if (PixelShader[0]) + glDisable(GL_FRAGMENT_PROGRAM_NV); #endif if (BaseMaterial) @@ -164,46 +203,94 @@ bool COpenGLShaderMaterialRenderer::isTransparent() const } +// This method needs a properly cleaned error state before the checked instruction is called +bool COpenGLShaderMaterialRenderer::checkError(const irr::c8* type) +{ +#if defined(GL_ARB_vertex_program) || defined(GL_NV_vertex_program) || defined(GL_ARB_fragment_program) || defined(GL_NV_fragment_program) + GLenum g = glGetError(); + if (g == GL_NO_ERROR) + return false; + + core::stringc errString = type; + errString += " compilation failed"; + + errString += " at position "; + GLint errPos=-1; +#if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) + glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); +#else + glGetIntegerv( GL_PROGRAM_ERROR_POSITION_NV, &errPos ); +#endif + errString += core::stringc(s32(errPos)); + errString += ":\n"; +#if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) + errString += reinterpret_cast(glGetString(GL_PROGRAM_ERROR_STRING_ARB)); +#else + errString += reinterpret_cast(glGetString(GL_PROGRAM_ERROR_STRING_NV)); +#endif +#else + core::stringc errString("Shaders not supported."); +#endif + os::Printer::log(errString.c_str(), ELL_ERROR); + return true; +} + + bool COpenGLShaderMaterialRenderer::createPixelShader(const c8* pxsh) { if (!pxsh) return true; - Driver->extGlGenPrograms(1, &PixelShader); -#ifdef GL_ARB_fragment_program - Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader); + const core::stringc inshdr(pxsh); + core::stringc shdr; + const s32 pos = inshdr.find("#_IRR_FOG_MODE_"); + const u32 numShaders = (-1 != pos)?4:1; - // clear error buffer - while(glGetError() != GL_NO_ERROR) - {} - - // compile - Driver->extGlProgramString(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(pxsh), pxsh); -#endif - -#ifdef GL_ARB_vertex_program - GLenum g = glGetError(); - if (g != GL_NO_ERROR) + for (u32 i=0; i(glGetString(GL_PROGRAM_ERROR_STRING_ARB)); - - char tmp[2048]; - sprintf(tmp, "Pixel shader compilation failed at position %d:\n%s", errPos, errString); - os::Printer::log(tmp); - - Driver->extGlDeletePrograms(1, &PixelShader); - PixelShader=0; - - return false; - } -#else - return false; + if (i==0) + { + shdr=inshdr; + } + else + { + shdr = inshdr.subString(0, pos); + switch (i) { + case 1: shdr += "OPTION ARB_fog_linear;"; break; + case 2: shdr += "OPTION ARB_fog_exp;"; break; + case 3: shdr += "OPTION ARB_fog_exp2;"; break; + } + shdr += inshdr.subString(pos+16, inshdr.size()-pos-16); + } + Driver->extGlGenPrograms(1, &PixelShader[i]); +#ifdef GL_ARB_fragment_program + Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader[i]); +#elif defined GL_NV_fragment_program + Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_NV, PixelShader[i]); #endif + // clear error buffer + while(glGetError() != GL_NO_ERROR) + {} + +#ifdef GL_ARB_fragment_program + // compile + Driver->extGlProgramString(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + shdr.size(), shdr.c_str()); +#elif defined GL_NV_fragment_program + Driver->extGlLoadProgram(GL_FRAGMENT_PROGRAM_NV, PixelShader[i], + shdr.size(), shdr.c_str()); +#endif + + if (checkError("Pixel shader")) + { + Driver->extGlDeletePrograms(1, &PixelShader[i]); + PixelShader[i]=0; + + return false; + } + } + return true; } @@ -213,38 +300,33 @@ bool COpenGLShaderMaterialRenderer::createVertexShader(const c8* vtxsh) if (!vtxsh) return true; -#ifdef GL_ARB_vertex_program Driver->extGlGenPrograms(1, &VertexShader); +#ifdef GL_ARB_vertex_program Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader); +#elif defined GL_NV_vertex_program + Driver->extGlBindProgram(GL_VERTEX_PROGRAM_NV, VertexShader); +#endif // clear error buffer while(glGetError() != GL_NO_ERROR) {} // compile +#ifdef GL_ARB_vertex_program Driver->extGlProgramString(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(vtxsh), vtxsh); + (GLsizei)strlen(vtxsh), vtxsh); +#elif defined GL_NV_vertex_program + Driver->extGlLoadProgram(GL_VERTEX_PROGRAM_NV, VertexShader, + (GLsizei)strlen(vtxsh), vtxsh); +#endif - GLenum g = glGetError(); - if (g != GL_NO_ERROR) + if (checkError("Vertex shader")) { - GLint errPos; - glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); - - const char* errString = reinterpret_cast(glGetString(GL_PROGRAM_ERROR_STRING_ARB)); - - char tmp[2048]; - sprintf(tmp, "Vertex shader compilation failed at position %d:\n%s", errPos, errString); - os::Printer::log(tmp); - Driver->extGlDeletePrograms(1, &VertexShader); VertexShader=0; return false; } -#else - return false; -#endif return true; } @@ -253,6 +335,5 @@ bool COpenGLShaderMaterialRenderer::createVertexShader(const c8* vtxsh) } // end namespace video } // end namespace irr - #endif diff --git a/src/dep/src/irrlicht/COpenGLShaderMaterialRenderer.h b/src/dep/src/irrlicht/COpenGLShaderMaterialRenderer.h index c433de9..ba86c5c 100644 --- a/src/dep/src/irrlicht/COpenGLShaderMaterialRenderer.h +++ b/src/dep/src/irrlicht/COpenGLShaderMaterialRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -8,23 +8,24 @@ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ +#if defined(_IRR_OPENGL_USE_EXTPOINTER_) + #define GL_GLEXT_LEGACY 1 +#else + #define GL_GLEXT_PROTOTYPES 1 +#endif #ifdef _IRR_WINDOWS_API_ #define WIN32_LEAN_AND_MEAN #include #include -#else -#if defined(_IRR_OPENGL_USE_EXTPOINTER_) - #define GL_GLEXT_LEGACY 1 -#endif -#if defined(_IRR_USE_OSX_DEVICE_) +#elif defined(_IRR_OSX_PLATFORM_) #include +#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) + #define NO_SDL_GLEXT + #include + #include #else #include #endif -#if defined(_IRR_OPENGL_USE_EXTPOINTER_) - #include "glext.h" -#endif -#endif #include "IMaterialRenderer.h" @@ -68,18 +69,22 @@ protected: IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData=0); + // must not be called more than once! void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, E_VERTEX_TYPE type); bool createPixelShader(const c8* pxsh); bool createVertexShader(const c8* vtxsh); + bool checkError(const irr::c8* type); COpenGLDriver* Driver; IShaderConstantSetCallBack* CallBack; IMaterialRenderer* BaseMaterial; GLuint VertexShader; - GLuint PixelShader; + // We have 4 values here, [0] is the non-fog version, the other three are + // ARB_fog_linear, ARB_fog_exp, and ARB_fog_exp2 in that order + core::array PixelShader; s32 UserData; }; diff --git a/src/dep/src/irrlicht/COpenGLTexture.cpp b/src/dep/src/irrlicht/COpenGLTexture.cpp index 6130d8a..46be2ea 100644 --- a/src/dep/src/irrlicht/COpenGLTexture.cpp +++ b/src/dep/src/irrlicht/COpenGLTexture.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -21,8 +21,8 @@ namespace video { //! constructor for usual textures -COpenGLTexture::COpenGLTexture(IImage* origImage, const char* name, COpenGLDriver* driver) - : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), +COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mipmapData, COpenGLDriver* driver) + : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), IsRenderTarget(false), AutomaticMipmapUpdate(false), @@ -33,19 +33,22 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const char* name, COpenGLDrive #endif HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); - getImageData(origImage); + getImageValues(origImage); glGenTextures(1, &TextureName); if (ImageSize==TextureSize) - Image = new CImage(ColorFormat, origImage); + { + Image = new CImage(ColorFormat, ImageSize); + origImage->copyTo(Image); + } else { Image = new CImage(ColorFormat, TextureSize); // scale texture origImage->copyToScaling(Image); } - copyTexture(); + uploadTexture(true, mipmapData); if (!KeepImage) { Image->drop(); @@ -53,9 +56,10 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const char* name, COpenGLDrive } } + //! constructor for basic setup (only for derived classes) -COpenGLTexture::COpenGLTexture(const char* name, COpenGLDriver* driver) - : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), +COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver) + : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), HasMipMaps(true), IsRenderTarget(false), AutomaticMipmapUpdate(false), @@ -77,6 +81,7 @@ COpenGLTexture::~COpenGLTexture() } +//! Choose best matching color format, based on texture creation flags ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format) { ECOLOR_FORMAT destFormat = ECF_A8R8G8B8; @@ -99,6 +104,7 @@ ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format) if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) destFormat = ECF_A1R5G5B5; + default: break; } if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL)) @@ -119,7 +125,120 @@ ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format) } -void COpenGLTexture::getImageData(IImage* image) +//! Get opengl values for the GPU texture storage +GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT format, + GLint& filtering, + GLenum& colorformat, + GLenum& type) +{ + // default + filtering = GL_LINEAR; + colorformat = GL_RGBA; + type = GL_UNSIGNED_BYTE; + + switch(format) + { + case ECF_A1R5G5B5: + colorformat=GL_BGRA_EXT; + type=GL_UNSIGNED_SHORT_1_5_5_5_REV; + return GL_RGBA; + case ECF_R5G6B5: + colorformat=GL_BGR; + type=GL_UNSIGNED_SHORT_5_6_5_REV; + return GL_RGB; + case ECF_R8G8B8: + colorformat=GL_BGR; + type=GL_UNSIGNED_BYTE; + return GL_RGB; + case ECF_A8R8G8B8: + colorformat=GL_BGRA_EXT; + if (Driver->Version > 101) + type=GL_UNSIGNED_INT_8_8_8_8_REV; + return GL_RGBA; + // Floating Point texture formats. Thanks to Patryk "Nadro" Nadrowski. + case ECF_R16F: + { +#ifdef GL_ARB_texture_rg + filtering = GL_NEAREST; + colorformat = GL_RED; + type = GL_FLOAT; + + return GL_R16F; +#else + return GL_RGB8; +#endif + } + case ECF_G16R16F: + { +#ifdef GL_ARB_texture_rg + filtering = GL_NEAREST; + colorformat = GL_RG; + type = GL_FLOAT; + + return GL_RG16F; +#else + return GL_RGB8; +#endif + } + case ECF_A16B16G16R16F: + { +#ifdef GL_ARB_texture_rg + filtering = GL_NEAREST; + colorformat = GL_RGBA; + type = GL_FLOAT; + + return GL_RGBA16F_ARB; +#else + return GL_RGBA8; +#endif + } + case ECF_R32F: + { +#ifdef GL_ARB_texture_rg + filtering = GL_NEAREST; + colorformat = GL_RED; + type = GL_FLOAT; + + return GL_R32F; +#else + return GL_RGB8; +#endif + } + case ECF_G32R32F: + { +#ifdef GL_ARB_texture_rg + filtering = GL_NEAREST; + colorformat = GL_RG; + type = GL_FLOAT; + + return GL_RG32F; +#else + return GL_RGB8; +#endif + } + case ECF_A32B32G32R32F: + { +#ifdef GL_ARB_texture_float + filtering = GL_NEAREST; + colorformat = GL_RGBA; + type = GL_FLOAT; + + return GL_RGBA32F_ARB; +#else + return GL_RGBA8; +#endif + } + default: + { + os::Printer::log("Unsupported texture format", ELL_ERROR); + return GL_RGBA8; + } + } +} + + +// prepare values ImageSize, TextureSize, and ColorFormat based on image +void COpenGLTexture::getImageValues(IImage* image) { if (!image) { @@ -135,6 +254,17 @@ void COpenGLTexture::getImageData(IImage* image) return; } + const f32 ratio = (f32)ImageSize.Width/(f32)ImageSize.Height; + if ((ImageSize.Width>Driver->MaxTextureSize) && (ratio >= 1.0f)) + { + ImageSize.Width = Driver->MaxTextureSize; + ImageSize.Height = (u32)(Driver->MaxTextureSize/ratio); + } + else if (ImageSize.Height>Driver->MaxTextureSize) + { + ImageSize.Height = Driver->MaxTextureSize; + ImageSize.Width = (u32)(Driver->MaxTextureSize*ratio); + } TextureSize=ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT)); ColorFormat = getBestColorFormat(image->getColorFormat()); @@ -142,59 +272,53 @@ void COpenGLTexture::getImageData(IImage* image) //! copies the the texture into an open gl texture. -void COpenGLTexture::copyTexture(bool newTexture) +void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) { - if (!Image) + // check which image needs to be uploaded + IImage* image = level?MipImage:Image; + if (!image) { os::Printer::log("No image for OpenGL texture to upload", ELL_ERROR); return; } - switch (ColorFormat) - { - case ECF_A1R5G5B5: - InternalFormat=GL_RGBA; - PixelFormat=GL_BGRA_EXT; - PixelType=GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - case ECF_R5G6B5: - InternalFormat=GL_RGB; - PixelFormat=GL_BGR; - PixelType=GL_UNSIGNED_SHORT_5_6_5_REV; - break; - case ECF_R8G8B8: - InternalFormat=GL_RGB; - PixelFormat=GL_BGR; - PixelType=GL_UNSIGNED_BYTE; - break; - case ECF_A8R8G8B8: - InternalFormat=GL_RGBA; - PixelFormat=GL_BGRA_EXT; - if (Driver->Version > 101) - PixelType=GL_UNSIGNED_INT_8_8_8_8_REV; - break; - default: - os::Printer::log("Unsupported texture format", ELL_ERROR); - break; - } + // get correct opengl color data values + GLenum oldInternalFormat = InternalFormat; + GLint filtering; + InternalFormat = getOpenGLFormatAndParametersFromColorFormat(ColorFormat, filtering, PixelFormat, PixelType); + // make sure we don't change the internal format of existing images + if (!newTexture) + InternalFormat=oldInternalFormat; - glBindTexture(GL_TEXTURE_2D, TextureName); + Driver->setActiveTexture(0, this); if (Driver->testGLError()) os::Printer::log("Could not bind Texture", ELL_ERROR); - if (newTexture) + // mipmap handling for main texture + if (!level && newTexture) { - #ifndef DISABLE_MIPMAPPING - if (HasMipMaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) +#ifndef DISABLE_MIPMAPPING +#ifdef GL_SGIS_generate_mipmap + // auto generate if possible and no mipmap data is given + if (HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) { + if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) + glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST); + else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) + glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); + else + glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_DONT_CARE); // automatically generate and update mipmaps glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE ); AutomaticMipmapUpdate=true; } else +#endif { + // Either generate manually due to missing capability + // or use predefined mipmap data AutomaticMipmapUpdate=false; - regenerateMipMapLevels(); + regenerateMipMapLevels(mipmapData); } if (HasMipMaps) // might have changed in regenerateMipMapLevels { @@ -203,10 +327,10 @@ void COpenGLTexture::copyTexture(bool newTexture) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else - #else +#else HasMipMaps=false; - os::Printer::log("Did not create OpenGL texture mip maps.", ELL_ERROR); - #endif + os::Printer::log("Did not create OpenGL texture mip maps.", ELL_INFORMATION); +#endif { // enable bilinear filter without mipmaps glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -214,14 +338,15 @@ void COpenGLTexture::copyTexture(bool newTexture) } } - void* source = Image->lock(); + // now get image data and upload to GPU + void* source = image->lock(); if (newTexture) - glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Image->getDimension().Width, - Image->getDimension().Height, 0, PixelFormat, PixelType, source); + glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, + image->getDimension().Height, 0, PixelFormat, PixelType, source); else - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Image->getDimension().Width, - Image->getDimension().Height, PixelFormat, PixelType, source); - Image->unlock(); + glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, + image->getDimension().Height, PixelFormat, PixelType, source); + image->unlock(); if (Driver->testGLError()) os::Printer::log("Could not glTexImage2D", ELL_ERROR); @@ -229,24 +354,47 @@ void COpenGLTexture::copyTexture(bool newTexture) //! lock function -void* COpenGLTexture::lock(bool readOnly) +void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel) { + // store info about which image is locked + IImage* image = (mipmapLevel==0)?Image:MipImage; ReadOnlyLock |= readOnly; + MipLevelStored = mipmapLevel; - if (!Image || IsRenderTarget) + // if data not available or might have changed on GPU download it + if (!image || IsRenderTarget) { // prepare the data storage if necessary - if (!Image) - Image = new CImage(ECF_A8R8G8B8, ImageSize); - if (!Image) + if (!image) + { + if (mipmapLevel) + { + u32 i=0; + u32 width = TextureSize.Width; + u32 height = TextureSize.Height; + do + { + if (width>1) + width>>=1; + if (height>1) + height>>=1; + ++i; + } + while (i != mipmapLevel); + MipImage = image = new CImage(ECF_A8R8G8B8, core::dimension2du(width,height)); + } + else + Image = image = new CImage(ECF_A8R8G8B8, ImageSize); + ColorFormat = ECF_A8R8G8B8; + } + if (!image) return 0; - u8* pPixels = static_cast(Image->lock()); - if (!pPixels) - { + u8* pixels = static_cast(image->lock()); + if (!pixels) return 0; - } - // we need to keep the correct texture bound... + + // we need to keep the correct texture bound later on GLint tmpTexture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture); glBindTexture(GL_TEXTURE_2D, TextureName); @@ -257,7 +405,8 @@ void* COpenGLTexture::lock(bool readOnly) glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); #endif - glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pPixels); + // download GPU data as ARGB8 to pixels; + glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); #ifdef GL_MESA_pack_invert if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) @@ -266,54 +415,69 @@ void* COpenGLTexture::lock(bool readOnly) #endif { // opengl images are horizontally flipped, so we have to fix that here. - const s32 pitch=Image->getPitch(); - u8* p2 = pPixels + (ImageSize.Height - 1) * pitch; + const s32 pitch=image->getPitch(); + u8* p2 = pixels + (image->getDimension().Height - 1) * pitch; u8* tmpBuffer = new u8[pitch]; - for (s32 i=0; i < ImageSize.Height; i += 2) + for (u32 i=0; i < image->getDimension().Height; i += 2) { - memcpy(tmpBuffer, pPixels, pitch); - memcpy(pPixels, p2, pitch); + memcpy(tmpBuffer, pixels, pitch); + memcpy(pixels, p2, pitch); memcpy(p2, tmpBuffer, pitch); - pPixels += pitch; + pixels += pitch; p2 -= pitch; } delete [] tmpBuffer; } - Image->unlock(); + image->unlock(); //reset old bound texture glBindTexture(GL_TEXTURE_2D, tmpTexture); } - return Image->lock(); + return image->lock(); } //! unlock function void COpenGLTexture::unlock() { - if (!Image) + // test if miplevel or main texture was locked + IImage* image = MipImage?MipImage:Image; + if (!image) return; - Image->unlock(); + // unlock image to see changes + image->unlock(); + // copy texture data to GPU if (!ReadOnlyLock) - copyTexture(false); + uploadTexture(false, 0, MipLevelStored); ReadOnlyLock = false; - if (!KeepImage) + // cleanup local image + if (MipImage) + { + MipImage->drop(); + MipImage=0; + } + else if (!KeepImage) { Image->drop(); Image=0; } + // update information + if (Image) + ColorFormat=Image->getColorFormat(); + else + ColorFormat=ECF_A8R8G8B8; } //! Returns size of the original image. -const core::dimension2d& COpenGLTexture::getOriginalSize() const +const core::dimension2d& COpenGLTexture::getOriginalSize() const { return ImageSize; } //! Returns size of the texture. -const core::dimension2d& COpenGLTexture::getSize() const +const core::dimension2d& COpenGLTexture::getSize() const { return TextureSize; } @@ -351,7 +515,6 @@ GLuint COpenGLTexture::getOpenGLTextureName() const //! Returns whether this texture has mipmaps -//! return true if texture has mipmaps bool COpenGLTexture::hasMipMaps() const { return HasMipMaps; @@ -360,18 +523,18 @@ bool COpenGLTexture::hasMipMaps() const //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void COpenGLTexture::regenerateMipMapLevels() +void COpenGLTexture::regenerateMipMapLevels(void* mipmapData) { if (AutomaticMipmapUpdate || !HasMipMaps || !Image) return; if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1)) return; - // Manually create mipmaps + // Manually create mipmaps or use prepared version u32 width=Image->getDimension().Width; u32 height=Image->getDimension().Height; u32 i=0; - u8* target = new u8[Image->getImageDataSizeInBytes()]; + u8* target = static_cast(mipmapData); do { if (width>1) @@ -379,25 +542,36 @@ void COpenGLTexture::regenerateMipMapLevels() if (height>1) height>>=1; ++i; - Image->copyToScaling(target, width, height, Image->getColorFormat()); + if (!target) + target = new u8[width*height*Image->getBytesPerPixel()]; + // create scaled version if no mipdata available + if (!mipmapData) + Image->copyToScaling(target, width, height, Image->getColorFormat()); glTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width, height, 0, PixelFormat, PixelType, target); + // get next prepared mipmap data if available + if (mipmapData) + { + mipmapData = static_cast(mipmapData)+width*height*Image->getBytesPerPixel(); + target = static_cast(mipmapData); + } } while (width!=1 || height!=1); - delete [] target; - Image->unlock(); + // cleanup + if (!mipmapData) + delete [] target; } bool COpenGLTexture::isRenderTarget() const { - return IsRenderTarget; + return IsRenderTarget; } void COpenGLTexture::setIsRenderTarget(bool isTarget) { - IsRenderTarget = isTarget; + IsRenderTarget = isTarget; } @@ -416,7 +590,7 @@ void COpenGLTexture::bindRTT() //! Unbind Render Target Texture void COpenGLTexture::unbindRTT() { - glBindTexture(GL_TEXTURE_2D, getOpenGLTextureName()); + Driver->setActiveTexture(0, this); // Copy Our ViewPort To The Texture glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSize().Width, getSize().Height); @@ -425,16 +599,13 @@ void COpenGLTexture::unbindRTT() /* FBO Textures */ -#ifdef GL_EXT_framebuffer_object // helper function for render to texture static bool checkFBOStatus(COpenGLDriver* Driver); -#endif - //! RTT ColorFrameBuffer constructor -COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d& size, - const char* name, - COpenGLDriver* driver) +COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d& size, + const io::path& name, COpenGLDriver* driver, + const ECOLOR_FORMAT format) : COpenGLTexture(name, driver), DepthTexture(0), ColorFrameBuffer(0) { #ifdef _DEBUG @@ -443,9 +614,10 @@ COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d& size, ImageSize = size; TextureSize = size; - InternalFormat = GL_RGBA; - PixelFormat = GL_RGBA; - PixelType = GL_UNSIGNED_BYTE; + + GLint FilteringType; + InternalFormat = getOpenGLFormatAndParametersFromColorFormat(format, FilteringType, PixelFormat, PixelType); + HasMipMaps = false; IsRenderTarget = true; @@ -456,8 +628,8 @@ COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d& size, // generate color texture glGenTextures(1, &TextureName); - glBindTexture(GL_TEXTURE_2D, TextureName); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + Driver->setActiveTexture(0, this); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FilteringType); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width, @@ -515,8 +687,8 @@ void COpenGLFBOTexture::unbindRTT() //! RTT DepthBuffer constructor COpenGLFBODepthTexture::COpenGLFBODepthTexture( - const core::dimension2d& size, - const char* name, + const core::dimension2d& size, + const io::path& name, COpenGLDriver* driver, bool useStencil) : COpenGLFBOTexture(size, name, driver), DepthRenderBuffer(0), @@ -597,10 +769,10 @@ COpenGLFBODepthTexture::~COpenGLFBODepthTexture() //combine depth texture and rtt -void COpenGLFBODepthTexture::attach(ITexture* renderTex) +bool COpenGLFBODepthTexture::attach(ITexture* renderTex) { if (!renderTex) - return; + return false; video::COpenGLFBOTexture* rtt = static_cast(renderTex); rtt->bindRTT(); #ifdef GL_EXT_framebuffer_object @@ -628,13 +800,17 @@ void COpenGLFBODepthTexture::attach(ITexture* renderTex) GL_RENDERBUFFER_EXT, DepthRenderBuffer); } +#endif // check the status if (!checkFBOStatus(Driver)) + { os::Printer::log("FBO incomplete"); -#endif + return false; + } rtt->DepthTexture=this; grab(); // grab the depth buffer, not the RTT rtt->unbindRTT(); + return true; } @@ -650,9 +826,9 @@ void COpenGLFBODepthTexture::unbindRTT() } -#ifdef GL_EXT_framebuffer_object bool checkFBOStatus(COpenGLDriver* Driver) { +#ifdef GL_EXT_framebuffer_object GLenum status = Driver->extGlCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); switch (status) @@ -692,6 +868,12 @@ bool checkFBOStatus(COpenGLDriver* Driver) os::Printer::log("FBO missing an image attachment", ELL_ERROR); break; +#ifdef GL_EXT_framebuffer_multisample + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: + os::Printer::log("FBO wrong multisample setup", ELL_ERROR); + break; +#endif + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: os::Printer::log("FBO format unsupported", ELL_ERROR); break; @@ -699,13 +881,14 @@ bool checkFBOStatus(COpenGLDriver* Driver) default: break; } +#endif os::Printer::log("FBO error", ELL_ERROR); return false; } -#endif } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_OPENGL_ + diff --git a/src/dep/src/irrlicht/COpenGLTexture.h b/src/dep/src/irrlicht/COpenGLTexture.h index 6989395..ef78783 100644 --- a/src/dep/src/irrlicht/COpenGLTexture.h +++ b/src/dep/src/irrlicht/COpenGLTexture.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,28 +11,31 @@ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ +#if defined(_IRR_OPENGL_USE_EXTPOINTER_) + #define GL_GLEXT_LEGACY 1 +#else + #define GL_GLEXT_PROTOTYPES 1 +#endif #ifdef _IRR_WINDOWS_API_ // include windows headers for HWND #define WIN32_LEAN_AND_MEAN #include #include - #include "glext.h" #ifdef _MSC_VER #pragma comment(lib, "OpenGL32.lib") - #pragma comment(lib, "GLu32.lib") #endif +#elif defined(_IRR_OSX_PLATFORM_) + #include +#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) + #define NO_SDL_GLEXT + #include + #include #else - #if defined(_IRR_OPENGL_USE_EXTPOINTER_) - #define GL_GLEXT_LEGACY 1 - #endif - #if defined(_IRR_USE_OSX_DEVICE_) + #if defined(_IRR_OSX_PLATFORM_) #include #else #include #endif - #if defined(_IRR_OPENGL_USE_EXTPOINTER_) - #include "glext.h" - #endif #endif @@ -48,22 +51,22 @@ class COpenGLTexture : public ITexture public: //! constructor - COpenGLTexture(IImage* surface, const char* name, COpenGLDriver* driver=0); + COpenGLTexture(IImage* surface, const io::path& name, void* mipmapData=0, COpenGLDriver* driver=0); //! destructor virtual ~COpenGLTexture(); //! lock function - virtual void* lock(bool readOnly = false); + virtual void* lock(bool readOnly=false, u32 mipmapLevel=0); //! unlock function virtual void unlock(); //! Returns original size of the texture (image). - virtual const core::dimension2d& getOriginalSize() const; + virtual const core::dimension2d& getOriginalSize() const; //! Returns size of the texture. - virtual const core::dimension2d& getSize() const; + virtual const core::dimension2d& getSize() const; //! returns driver type of texture (=the driver, that created it) virtual E_DRIVER_TYPE getDriverType() const; @@ -80,9 +83,10 @@ public: //! return whether this texture has mipmaps virtual bool hasMipMaps() const; - //! Regenerates the mip map levels of the texture. Useful after - //! locking and modifying the texture - virtual void regenerateMipMapLevels(); + //! Regenerates the mip map levels of the texture. + /** Useful after locking and modifying the texture + \param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image. If not set the mipmaps are derived from the main image. */ + virtual void regenerateMipMapLevels(void* mipmapData=0); //! Is it a render target? virtual bool isRenderTarget() const; @@ -102,30 +106,37 @@ public: protected: //! protected constructor with basic setup, no GL texture name created, for derived classes - COpenGLTexture(const char* name, COpenGLDriver* driver); + COpenGLTexture(const io::path& name, COpenGLDriver* driver); //! get the desired color format based on texture creation flags and the input format. ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format); - //! convert the image into an internal image with better properties for this driver. - void getImageData(IImage* image); + //! Get the OpenGL color format parameters based on the given Irrlicht color format + GLint getOpenGLFormatAndParametersFromColorFormat( + ECOLOR_FORMAT format, GLint& filtering, GLenum& colorformat, GLenum& type); + + //! get important numbers of the image and hw texture + void getImageValues(IImage* image); //! copies the texture into an OpenGL texture. - //! \param: newTexture is true if method is called from a newly created texture for the first time. Otherwise call with false to improve memory handling. - void copyTexture(bool newTexture=true); + /** \param newTexture True if method is called for a newly created texture for the first time. Otherwise call with false to improve memory handling. + \param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image. + \param mipLevel If set to non-zero, only that specific miplevel is updated, using the MipImage member. */ + void uploadTexture(bool newTexture=false, void* mipmapData=0, u32 mipLevel=0); - core::dimension2d ImageSize; - core::dimension2d TextureSize; + core::dimension2d ImageSize; + core::dimension2d TextureSize; ECOLOR_FORMAT ColorFormat; - s32 Pitch; COpenGLDriver* Driver; IImage* Image; + IImage* MipImage; GLuint TextureName; GLint InternalFormat; GLenum PixelFormat; GLenum PixelType; + u8 MipLevelStored; bool HasMipMaps; bool IsRenderTarget; bool AutomaticMipmapUpdate; @@ -139,7 +150,8 @@ class COpenGLFBOTexture : public COpenGLTexture public: //! FrameBufferObject constructor - COpenGLFBOTexture(const core::dimension2d& size, const char* name, COpenGLDriver* driver=0); + COpenGLFBOTexture(const core::dimension2d& size, const io::path& name, + COpenGLDriver* driver = 0, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! destructor virtual ~COpenGLFBOTexture(); @@ -164,7 +176,7 @@ class COpenGLFBODepthTexture : public COpenGLFBOTexture { public: //! FrameBufferObject depth constructor - COpenGLFBODepthTexture(const core::dimension2d& size, const char* name, COpenGLDriver* driver=0, bool useStencil=false); + COpenGLFBODepthTexture(const core::dimension2d& size, const io::path& name, COpenGLDriver* driver=0, bool useStencil=false); //! destructor virtual ~COpenGLFBODepthTexture(); @@ -175,7 +187,7 @@ public: //! Unbind RenderTargetTexture virtual void unbindRTT(); - void attach(ITexture*); + bool attach(ITexture*); protected: GLuint DepthRenderBuffer; diff --git a/src/dep/src/irrlicht/CPLYMeshFileLoader.cpp b/src/dep/src/irrlicht/CPLYMeshFileLoader.cpp new file mode 100644 index 0000000..8f3503b --- /dev/null +++ b/src/dep/src/irrlicht/CPLYMeshFileLoader.cpp @@ -0,0 +1,789 @@ +// Copyright (C) 2009-2010 Gaz Davidson +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "IrrCompileConfig.h" +#ifdef _IRR_COMPILE_WITH_PLY_LOADER_ + +#include "CPLYMeshFileLoader.h" +#include "IMeshManipulator.h" +#include "SMesh.h" +#include "CDynamicMeshBuffer.h" +#include "SAnimatedMesh.h" +#include "IReadFile.h" +#include "fast_atof.h" +#include "os.h" + +namespace irr +{ +namespace scene +{ + +// input buffer must be at least twice as long as the longest line in the file +#define PLY_INPUT_BUFFER_SIZE 51200 // file is loaded in 50k chunks + +// constructor +CPLYMeshFileLoader::CPLYMeshFileLoader() +: File(0), Buffer(0) +{ +} + +CPLYMeshFileLoader::~CPLYMeshFileLoader() +{ + // delete the buffer in case we didn't earlier + // (we do, but this could be disabled to increase the speed of loading hundreds of meshes) + if (Buffer) + { + delete [] Buffer; + Buffer = 0; + } + + // Destroy the element list if it exists + for (u32 i=0; igrab(); + + // attempt to allocate the buffer and fill with data + if (!allocateBuffer()) + { + File->drop(); + File = 0; + return 0; + } + + // start with empty mesh + SAnimatedMesh* animMesh = 0; + u32 vertCount=0; + + // Currently only supports ASCII meshes + if (strcmp(getNextLine(), "ply")) + { + os::Printer::log("Not a valid PLY file", file->getFileName().c_str(), ELL_ERROR); + } + else + { + // cut the next line out + c8 *line = getNextLine(); + // grab the word from this line + c8 *word = getNextWord(); + + // ignore comments + while (strcmp(word, "comment") == 0) + { + line = getNextLine(); + word = getNextWord(); + } + + bool readingHeader = true; + bool continueReading = true; + IsBinaryFile = false; + IsWrongEndian= false; + + do + { + if (strcmp(word, "format") == 0) + { + word = getNextWord(); + + if (strcmp(word, "binary_little_endian") == 0) + { + IsBinaryFile = true; +#ifdef __BIG_ENDIAN__ + IsWrongEndian = true; +#endif + + } + else if (strcmp(word, "binary_big_endian") == 0) + { + IsBinaryFile = true; +#ifndef __BIG_ENDIAN__ + IsWrongEndian = true; +#endif + } + else if (strcmp(word, "ascii")) + { + // abort if this isn't an ascii or a binary mesh + os::Printer::log("Unsupported PLY mesh format", word, ELL_ERROR); + continueReading = false; + } + + if (continueReading) + { + word = getNextWord(); + if (strcmp(word, "1.0")) + { + os::Printer::log("Unsupported PLY mesh version", word, ELL_WARNING); + } + } + } + else if (strcmp(word, "property") == 0) + { + word = getNextWord(); + + if (!ElementList.size()) + { + os::Printer::log("PLY property found before element", word, ELL_WARNING); + } + else + { + // get element + SPLYElement* el = ElementList[ElementList.size()-1]; + + // fill property struct + SPLYProperty prop; + prop.Type = getPropertyType(word); + el->KnownSize += prop.size(); + + if (prop.Type == EPLYPT_LIST) + { + el->IsFixedWidth = false; + + word = getNextWord(); + + prop.Data.List.CountType = getPropertyType(word); + if (IsBinaryFile && prop.Data.List.CountType == EPLYPT_UNKNOWN) + { + os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); + continueReading = false; + } + else + { + word = getNextWord(); + prop.Data.List.ItemType = getPropertyType(word); + if (IsBinaryFile && prop.Data.List.ItemType == EPLYPT_UNKNOWN) + { + os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); + continueReading = false; + } + } + } + else if (IsBinaryFile && prop.Type == EPLYPT_UNKNOWN) + { + os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); + continueReading = false; + } + + prop.Name = getNextWord(); + + // add property to element + el->Properties.push_back(prop); + } + } + else if (strcmp(word, "element") == 0) + { + SPLYElement* el = new SPLYElement; + el->Name = getNextWord(); + el->Count = atoi(getNextWord()); + el->IsFixedWidth = true; + el->KnownSize = 0; + ElementList.push_back(el); + + if (el->Name == "vertex") + vertCount = el->Count; + + } + else if (strcmp(word, "end_header") == 0) + { + readingHeader = false; + if (IsBinaryFile) + { + StartPointer = LineEndPointer + 1; + } + } + else if (strcmp(word, "comment") == 0) + { + // ignore line + } + else + { + os::Printer::log("Unknown item in PLY file", word, ELL_WARNING); + } + + if (readingHeader && continueReading) + { + line = getNextLine(); + word = getNextWord(); + } + } + while (readingHeader && continueReading); + + // now to read the actual data from the file + if (continueReading) + { + // create a mesh buffer + CDynamicMeshBuffer *mb = new CDynamicMeshBuffer(video::EVT_STANDARD, vertCount > 65565 ? video::EIT_32BIT : video::EIT_16BIT); + mb->getVertexBuffer().reallocate(vertCount); + mb->getIndexBuffer().reallocate(vertCount); + mb->setHardwareMappingHint(EHM_STATIC); + + // loop through each of the elements + for (u32 i=0; iName == "vertex") + { + // loop through vertex properties + for (u32 j=0; j < ElementList[i]->Count; ++j) + readVertex(*ElementList[i], mb); + } + else if (ElementList[i]->Name == "face") + { + // read faces + for (u32 j=0; j < ElementList[i]->Count; ++j) + readFace(*ElementList[i], mb); + } + else + { + // skip these elements + for (u32 j=0; j < ElementList[i]->Count; ++j) + skipElement(*ElementList[i]); + } + } + mb->recalculateBoundingBox(); + SMesh* m = new SMesh(); + m->addMeshBuffer(mb); + m->recalculateBoundingBox(); + mb->drop(); + animMesh = new SAnimatedMesh(); + animMesh->addMesh(m); + animMesh->recalculateBoundingBox(); + m->drop(); + } + } + + + // free the buffer + delete [] Buffer; + Buffer = 0; + File->drop(); + File = 0; + + // if we managed to create a mesh, return it + return animMesh; +} + +bool CPLYMeshFileLoader::readVertex(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb) +{ + if (!IsBinaryFile) + getNextLine(); + + video::S3DVertex vert; + vert.Color.set(255,255,255,255); + vert.TCoords.X = 0.0f; + vert.TCoords.Y = 0.0f; + vert.Normal.X = 0.0f; + vert.Normal.Y = 1.0f; + vert.Normal.Z = 0.0f; + + for (u32 i=0; i < Element.Properties.size(); ++i) + { + E_PLY_PROPERTY_TYPE t = Element.Properties[i].Type; + + if (Element.Properties[i].Name == "x") + vert.Pos.X = getFloat(t); + else if (Element.Properties[i].Name == "y") + vert.Pos.Z = getFloat(t); + else if (Element.Properties[i].Name == "z") + vert.Pos.Y = getFloat(t); + else if (Element.Properties[i].Name == "nx") + vert.Normal.X = getFloat(t); + else if (Element.Properties[i].Name == "ny") + vert.Normal.Z = getFloat(t); + else if (Element.Properties[i].Name == "nz") + vert.Normal.Y = getFloat(t); + else if (Element.Properties[i].Name == "u") + vert.TCoords.X = getFloat(t); + else if (Element.Properties[i].Name == "v") + vert.TCoords.Y = getFloat(t); + else if (Element.Properties[i].Name == "red") + { + u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); + vert.Color.setRed(value); + } + else if (Element.Properties[i].Name == "green") + { + u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); + vert.Color.setGreen(value); + } + else if (Element.Properties[i].Name == "blue") + { + u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); + vert.Color.setBlue(value); + } + else if (Element.Properties[i].Name == "alpha") + { + u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); + vert.Color.setAlpha(value); + } + else + skipProperty(Element.Properties[i]); + } + + mb->getVertexBuffer().push_back(vert); + + return true; +} + +bool CPLYMeshFileLoader::readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb) +{ + if (!IsBinaryFile) + getNextLine(); + + for (u32 i=0; i < Element.Properties.size(); ++i) + { + if ( (Element.Properties[i].Name == "vertex_indices" || + Element.Properties[i].Name == "vertex_index") && Element.Properties[i].Type == EPLYPT_LIST) + { + // get count + s32 count = getInt(Element.Properties[i].Data.List.CountType); + u32 a = getInt(Element.Properties[i].Data.List.ItemType), + b = getInt(Element.Properties[i].Data.List.ItemType), + c = getInt(Element.Properties[i].Data.List.ItemType); + s32 j = 3; + + mb->getIndexBuffer().push_back(a); + mb->getIndexBuffer().push_back(c); + mb->getIndexBuffer().push_back(b); + + for (; j < count; ++j) + { + b = c; + c = getInt(Element.Properties[i].Data.List.ItemType); + mb->getIndexBuffer().push_back(a); + mb->getIndexBuffer().push_back(c); + mb->getIndexBuffer().push_back(b); + } + } + else if (Element.Properties[i].Name == "intensity") + { + // todo: face intensity + skipProperty(Element.Properties[i]); + } + else + skipProperty(Element.Properties[i]); + } + return true; +} + +// skips an element and all properties. return false on EOF +void CPLYMeshFileLoader::skipElement(const SPLYElement &Element) +{ + if (IsBinaryFile) + if (Element.IsFixedWidth) + moveForward(Element.KnownSize); + else + for (u32 i=0; i < Element.Properties.size(); ++i) + skipProperty(Element.Properties[i]); + else + getNextLine(); +} + +void CPLYMeshFileLoader::skipProperty(const SPLYProperty &Property) +{ + if (Property.Type == EPLYPT_LIST) + { + s32 count = getInt(Property.Data.List.CountType); + + for (s32 i=0; i < count; ++i) + getInt(Property.Data.List.CountType); + } + else + { + if (IsBinaryFile) + moveForward(Property.size()); + else + getNextWord(); + } +} + + +bool CPLYMeshFileLoader::allocateBuffer() +{ + // Destroy the element list if it exists + for (u32 i=0; igetPos() == File->getSize()) + { + EndOfFile = true; + } + else + { + // read data from the file + u32 count = File->read(EndPointer, PLY_INPUT_BUFFER_SIZE - length); + + // increment the end pointer by the number of bytes read + EndPointer = EndPointer + count; + + // if we didn't completely fill the buffer + if (count != PLY_INPUT_BUFFER_SIZE - length) + { + // blank the rest of the memory + memset(EndPointer, 0, Buffer + PLY_INPUT_BUFFER_SIZE - EndPointer); + + // end of file + EndOfFile = true; + } + } +} + +// skips x bytes in the file, getting more data if required +void CPLYMeshFileLoader::moveForward(u32 bytes) +{ + if (StartPointer + bytes >= EndPointer) + fillBuffer(); + if (StartPointer + bytes < EndPointer) + StartPointer += bytes; + else + StartPointer = EndPointer; +} + +E_PLY_PROPERTY_TYPE CPLYMeshFileLoader::getPropertyType(const c8* typeString) const +{ + if (strcmp(typeString, "char") == 0 || + strcmp(typeString, "uchar") == 0 || + strcmp(typeString, "int8") == 0 || + strcmp(typeString, "uint8") == 0) + { + return EPLYPT_INT8; + } + else if (strcmp(typeString, "uint") == 0 || + strcmp(typeString, "int16") == 0 || + strcmp(typeString, "uint16") == 0 || + strcmp(typeString, "short") == 0 || + strcmp(typeString, "ushort") == 0) + { + return EPLYPT_INT16; + } + else if (strcmp(typeString, "int") == 0 || + strcmp(typeString, "long") == 0 || + strcmp(typeString, "ulong") == 0 || + strcmp(typeString, "int32") == 0 || + strcmp(typeString, "uint32") == 0) + { + return EPLYPT_INT32; + } + else if (strcmp(typeString, "float") == 0 || + strcmp(typeString, "float32") == 0) + { + return EPLYPT_FLOAT32; + } + else if (strcmp(typeString, "float64") == 0 || + strcmp(typeString, "double") == 0) + { + return EPLYPT_FLOAT64; + } + else if ( strcmp(typeString, "list") == 0 ) + { + return EPLYPT_LIST; + } + else + { + // unsupported type. + // cannot be loaded in binary mode + return EPLYPT_UNKNOWN; + } +} + + +// Split the string data into a line in place by terminating it instead of copying. +c8* CPLYMeshFileLoader::getNextLine() +{ + // move the start pointer along + StartPointer = LineEndPointer + 1; + + // crlf split across buffer move + if (*StartPointer == '\n') + { + *StartPointer = '\0'; + ++StartPointer; + } + + // begin at the start of the next line + c8* pos = StartPointer; + while (pos < EndPointer && *pos && *pos != '\r' && *pos != '\n') + ++pos; + + if ( pos < EndPointer && ( *(pos+1) == '\r' || *(pos+1) == '\n') ) + { + *pos = '\0'; + ++pos; + } + + // we have reached the end of the buffer + if (pos >= EndPointer) + { + // get data from the file + if (!EndOfFile) + { + fillBuffer(); + // reset line end pointer + LineEndPointer = StartPointer - 1; + + if (StartPointer != EndPointer) + return getNextLine(); + else + return Buffer; + } + else + { + // EOF + StartPointer = EndPointer-1; + *StartPointer = '\0'; + return StartPointer; + } + } + else + { + // null terminate the string in place + *pos = '\0'; + LineEndPointer = pos; + WordLength = -1; + // return pointer to the start of the line + return StartPointer; + } +} +// null terminate the next word on the previous line and move the next word pointer along +// since we already have a full line in the buffer, we never need to retrieve more data +c8* CPLYMeshFileLoader::getNextWord() +{ + // move the start pointer along + StartPointer += WordLength + 1; + + if (StartPointer == LineEndPointer) + { + WordLength = -1; // + return LineEndPointer; + } + // begin at the start of the next word + c8* pos = StartPointer; + while (*pos && pos < LineEndPointer && pos < EndPointer && *pos != ' ' && *pos != '\t') + ++pos; + + while(*pos && pos < LineEndPointer && pos < EndPointer && (*pos == ' ' || *pos == '\t') ) + { + // null terminate the string in place + *pos = '\0'; + ++pos; + } + --pos; + WordLength = pos-StartPointer; + // return pointer to the start of the word + return StartPointer; +} +// read the next float from the file and move the start pointer along +f32 CPLYMeshFileLoader::getFloat(E_PLY_PROPERTY_TYPE t) +{ + f32 retVal = 0.0f; + + if (IsBinaryFile) + { + if (EndPointer - StartPointer < 8) + fillBuffer(); + + if (EndPointer - StartPointer > 0) + { + switch (t) + { + case EPLYPT_INT8: + retVal = *StartPointer; + StartPointer++; + break; + case EPLYPT_INT16: + if (IsWrongEndian) + retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = *(reinterpret_cast(StartPointer)); + StartPointer += 2; + break; + case EPLYPT_INT32: + if (IsWrongEndian) + retVal = f32(os::Byteswap::byteswap(*(reinterpret_cast(StartPointer)))); + else + retVal = f32(*(reinterpret_cast(StartPointer))); + StartPointer += 4; + break; + case EPLYPT_FLOAT32: + if (IsWrongEndian) + retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = *(reinterpret_cast(StartPointer)); + StartPointer += 4; + break; + case EPLYPT_FLOAT64: + // todo: byteswap 64-bit + retVal = f32(*(reinterpret_cast(StartPointer))); + StartPointer += 8; + break; + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + retVal = 0.0f; + StartPointer++; // ouch! + } + } + else + retVal = 0.0f; + } + else + { + c8* word = getNextWord(); + switch (t) + { + case EPLYPT_INT8: + case EPLYPT_INT16: + case EPLYPT_INT32: + retVal = f32(atoi(word)); + break; + case EPLYPT_FLOAT32: + case EPLYPT_FLOAT64: + retVal = f32(atof(word)); + break; + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + retVal = 0.0f; + } + } + return retVal; +} +// read the next int from the file and move the start pointer along +u32 CPLYMeshFileLoader::getInt(E_PLY_PROPERTY_TYPE t) +{ + u32 retVal = 0; + + if (IsBinaryFile) + { + if (!EndOfFile && EndPointer - StartPointer < 8) + fillBuffer(); + + if (EndPointer - StartPointer) + { + switch (t) + { + case EPLYPT_INT8: + retVal = *StartPointer; + StartPointer++; + break; + case EPLYPT_INT16: + if (IsWrongEndian) + retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = *(reinterpret_cast(StartPointer)); + StartPointer += 2; + break; + case EPLYPT_INT32: + if (IsWrongEndian) + retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = *(reinterpret_cast(StartPointer)); + StartPointer += 4; + break; + case EPLYPT_FLOAT32: + if (IsWrongEndian) + retVal = (u32)os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = (u32)(*(reinterpret_cast(StartPointer))); + StartPointer += 4; + break; + case EPLYPT_FLOAT64: + // todo: byteswap 64-bit + retVal = (u32)(*(reinterpret_cast(StartPointer))); + StartPointer += 8; + break; + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + retVal = 0; + StartPointer++; // ouch! + } + } + else + retVal = 0; + } + else + { + c8* word = getNextWord(); + switch (t) + { + case EPLYPT_INT8: + case EPLYPT_INT16: + case EPLYPT_INT32: + retVal = atoi(word); + break; + case EPLYPT_FLOAT32: + case EPLYPT_FLOAT64: + retVal = u32(atof(word)); + break; + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + retVal = 0; + } + } + return retVal; +} + + + +} // end namespace scene +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_PLY_LOADER_ + diff --git a/src/dep/src/irrlicht/CPLYMeshFileLoader.h b/src/dep/src/irrlicht/CPLYMeshFileLoader.h new file mode 100644 index 0000000..2592c59 --- /dev/null +++ b/src/dep/src/irrlicht/CPLYMeshFileLoader.h @@ -0,0 +1,146 @@ +// Copyright (C) 2009-2010 Gaz Davidson +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_PLY_MESH_FILE_LOADER_H_INCLUDED__ +#define __C_PLY_MESH_FILE_LOADER_H_INCLUDED__ + +#include "IMeshLoader.h" +#include "CDynamicMeshBuffer.h" + +namespace irr +{ +namespace scene +{ + +enum E_PLY_PROPERTY_TYPE +{ + EPLYPT_INT8 = 0, + EPLYPT_INT16, + EPLYPT_INT32, + EPLYPT_FLOAT32, + EPLYPT_FLOAT64, + EPLYPT_LIST, + EPLYPT_UNKNOWN +}; + +//! Meshloader capable of loading obj meshes. +class CPLYMeshFileLoader : public IMeshLoader +{ +public: + + //! Constructor + CPLYMeshFileLoader(); + + //! Destructor + virtual ~CPLYMeshFileLoader(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".ply") + virtual bool isALoadableFileExtension(const io::path& filename) const; + + //! creates/loads an animated mesh from the file. + virtual IAnimatedMesh* createMesh(io::IReadFile* file); + +private: + + struct SPLYProperty + { + core::stringc Name; + E_PLY_PROPERTY_TYPE Type; + union + { + u8 Int8; + u16 Int16; + u32 Int32; + f32 Float32; + f64 Double; + struct SPLYListProperty + { + E_PLY_PROPERTY_TYPE CountType; + E_PLY_PROPERTY_TYPE ItemType; + } List; + + } Data; + + inline u32 size() const + { + switch(Type) + { + case EPLYPT_INT8: + return 1; + case EPLYPT_INT16: + return 2; + case EPLYPT_INT32: + case EPLYPT_FLOAT32: + return 4; + case EPLYPT_FLOAT64: + return 8; + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + return 0; + } + } + + inline bool isFloat() const + { + switch(Type) + { + case EPLYPT_FLOAT32: + case EPLYPT_FLOAT64: + return true; + case EPLYPT_INT8: + case EPLYPT_INT16: + case EPLYPT_INT32: + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + return false; + } + } + }; + + struct SPLYElement + { + // name of the element. We only want "vertex" and "face" elements + // but we have to parse the others anyway. + core::stringc Name; + // The number of elements in the file + u32 Count; + // Properties of this element + core::array Properties; + // in binary files, true if this is a fixed size + bool IsFixedWidth; + // known size in bytes, 0 if unknown + u32 KnownSize; + }; + + bool allocateBuffer(); + c8* getNextLine(); + c8* getNextWord(); + void fillBuffer(); + E_PLY_PROPERTY_TYPE getPropertyType(const c8* typeString) const; + + bool readVertex(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb); + bool readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb); + void skipElement(const SPLYElement &Element); + void skipProperty(const SPLYProperty &Property); + f32 getFloat(E_PLY_PROPERTY_TYPE t); + u32 getInt(E_PLY_PROPERTY_TYPE t); + void moveForward(u32 bytes); + + core::array ElementList; + + io::IReadFile *File; + c8 *Buffer; + bool IsBinaryFile, IsWrongEndian, EndOfFile; + s32 LineLength, WordLength; + c8 *StartPointer, *EndPointer, *LineEndPointer; +}; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/src/dep/src/irrlicht/CPLYMeshWriter.cpp b/src/dep/src/irrlicht/CPLYMeshWriter.cpp new file mode 100644 index 0000000..88dc14d --- /dev/null +++ b/src/dep/src/irrlicht/CPLYMeshWriter.cpp @@ -0,0 +1,183 @@ +// Copyright (C) 2008-2010 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_PLY_WRITER_ + +#include "CPLYMeshWriter.h" +#include "os.h" +#include "IMesh.h" +#include "IMeshBuffer.h" +#include "IWriteFile.h" + +namespace irr +{ +namespace scene +{ + +CPLYMeshWriter::CPLYMeshWriter() +{ + #ifdef _DEBUG + setDebugName("CPLYMeshWriter"); + #endif +} + + +//! Returns the type of the mesh writer +EMESH_WRITER_TYPE CPLYMeshWriter::getType() const +{ + return EMWT_PLY; +} + +//! writes a mesh +bool CPLYMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) +{ + if (!file || !mesh) + return false; + + os::Printer::log("Writing mesh", file->getFileName()); + + // write PLY header + core::stringc header = + "ply\n" + "format ascii 1.0\n" + "comment Irrlicht Engine "; + header += IRRLICHT_SDK_VERSION; + + // get vertex and triangle counts + u32 VertexCount = 0; + u32 TriangleCount = 0; + + for (u32 i=0; i < mesh->getMeshBufferCount(); ++i) + { + VertexCount += mesh->getMeshBuffer(i)->getVertexCount(); + TriangleCount += mesh->getMeshBuffer(i)->getIndexCount() / 3; + } + + // vertex definition + header += "\nelement vertex "; + header += VertexCount; + + header += "\n" + "property float x\n" + "property float y\n" + "property float z\n" + "property float nx\n" + "property float ny\n" + "property float nz\n"; + // todo: writer flags for extended (r,g,b,u,v) and non-standard (alpha,u1,uv,tx,ty,tz) properties + // "property uchar red\n" + // "property uchar green\n" + // "property uchar blue\n" + // "property uchar alpha\n" + // "property float u\n" + // "property float v\n"; + // "property float u1\n + // "property float v1\n" + // "property float tx\n" + // "property float ty\n" + // "property float tz\n" + + // face definition + + header += "element face "; + header += TriangleCount; + header += "\n" + "property list uchar int vertex_indices\n" + "end_header\n"; + + // write header + file->write(header.c_str(), header.size()); + + // write vertices + + c8 outLine[1024]; + + for (u32 i=0; i < mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* mb = mesh->getMeshBuffer(i); + for (u32 j=0; j < mb->getVertexCount(); ++j) + { + const core::vector3df& pos = mb->getPosition(j); + const core::vector3df& n = mb->getNormal(j); +// const core::vector2df& tc = mb->getTCoords(j); + + u8 *buf = (u8*)mb->getVertices(); + switch(mb->getVertexType()) + { + case video::EVT_STANDARD: + buf += sizeof(video::S3DVertex)*j; + break; + case video::EVT_2TCOORDS: + buf += sizeof(video::S3DVertex2TCoords)*j; + break; + case video::EVT_TANGENTS: + buf += sizeof(video::S3DVertexTangents)*j; + break; + } +// video::SColor &col = ( (video::S3DVertex*)buf )->Color; + + // x y z nx ny nz red green blue alpha u v [u1 v1 | tx ty tz]\n + snprintf(outLine, 1024, + "%f %f %f %f %f %f\n",// %u %u %u %u %f %f\n", + pos.X, pos.Z, pos.Y, // Y and Z are flipped + n.X, n.Z, n.Y); + /*col.getRed(), col.getGreen(), col.getBlue(), col.getAlpha(), + tc.X, tc.Y);*/ + + // write the line + file->write(outLine, strlen(outLine)); + } + } + + // index of the first vertex in the current mesh buffer + u32 StartOffset = 0; + + // write triangles + for (u32 i=0; i < mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* mb = mesh->getMeshBuffer(i); + for (u32 j=0; j < mb->getIndexCount(); j+=3) + { + // y and z are flipped so triangles are reversed + u32 a=StartOffset, + b=StartOffset, + c=StartOffset; + + switch(mb->getIndexType()) + { + case video::EIT_16BIT: + a += mb->getIndices()[j+0]; + c += mb->getIndices()[j+1]; + b += mb->getIndices()[j+2]; + break; + case video::EIT_32BIT: + a += ((u32*)mb->getIndices()) [j+0]; + c += ((u32*)mb->getIndices()) [j+0]; + b += ((u32*)mb->getIndices()) [j+0]; + break; + } + + // count a b c\n + snprintf(outLine, 1024, "3 %u %u %u\n", a, b, c); + // write the line + file->write(outLine, strlen(outLine)); + } + + // increment offset + StartOffset += mb->getVertexCount(); + } + + // all done! + + + return true; +} + +} // end namespace +} // end namespace + +#endif // _IRR_COMPILE_WITH_PLY_WRITER_ + diff --git a/src/dep/src/irrlicht/CPLYMeshWriter.h b/src/dep/src/irrlicht/CPLYMeshWriter.h new file mode 100644 index 0000000..24efb06 --- /dev/null +++ b/src/dep/src/irrlicht/CPLYMeshWriter.h @@ -0,0 +1,35 @@ +// Copyright (C) 2009-2010 Gaz Davidson +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_PLY_MESH_WRITER_H_INCLUDED__ +#define __IRR_PLY_MESH_WRITER_H_INCLUDED__ + +#include "IMeshWriter.h" + +namespace irr +{ + +namespace scene +{ + class IMeshBuffer; + + //! class to write PLY mesh files + class CPLYMeshWriter : public IMeshWriter + { + public: + + CPLYMeshWriter(); + + //! Returns the type of the mesh writer + virtual EMESH_WRITER_TYPE getType() const; + + //! writes a mesh + virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); + + }; + +} // end namespace +} // end namespace + +#endif diff --git a/src/dep/src/irrlicht/CPakReader.cpp b/src/dep/src/irrlicht/CPakReader.cpp index 0315f69..f7d87ca 100644 --- a/src/dep/src/irrlicht/CPakReader.cpp +++ b/src/dep/src/irrlicht/CPakReader.cpp @@ -1,38 +1,120 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // Code contributed by skreamz #include "CPakReader.h" -#include "os.h" -#include "IrrCompileConfig.h" +#ifdef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ + +#include "os.h" +#include "coreutil.h" namespace irr { namespace io { - -CPakReader::CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths) -: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths) +namespace { - #ifdef _DEBUG + +inline bool isHeaderValid(const SPAKFileHeader& header) +{ + const c8* tag = header.tag; + return tag[0] == 'P' && + tag[1] == 'A' && + tag[2] == 'C' && + tag[3] == 'K'; +} + +} // end namespace + +//! Constructor +CArchiveLoaderPAK::CArchiveLoaderPAK( io::IFileSystem* fs) +: FileSystem(fs) +{ +#ifdef _DEBUG + setDebugName("CArchiveLoaderPAK"); +#endif +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderPAK::isALoadableFileFormat(const io::path& filename) const +{ + return core::hasFileExtension(filename, "pak"); +} + +//! Check to see if the loader can create archives of this type. +bool CArchiveLoaderPAK::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const +{ + return fileType == EFAT_PAK; +} + +//! Creates an archive from the filename +/** \param file File handle to check. +\return Pointer to newly created archive, or 0 upon error. */ +IFileArchive* CArchiveLoaderPAK::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + io::IReadFile* file = FileSystem->createAndOpenFile(filename); + + if (file) + { + archive = createArchive(file, ignoreCase, ignorePaths); + file->drop (); + } + + return archive; +} + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderPAK::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + if ( file ) + { + file->seek ( 0 ); + archive = new CPakReader(file, ignoreCase, ignorePaths); + } + return archive; +} + + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderPAK::isALoadableFileFormat(io::IReadFile* file) const +{ + SPAKFileHeader header; + + file->read(&header, sizeof(header)); + + return isHeaderValid(header); +} + + +/*! + PAK Reader +*/ +CPakReader::CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths) +: CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file) +{ +#ifdef _DEBUG setDebugName("CPakReader"); - #endif +#endif if (File) { File->grab(); - - // scan local headers scanLocalHeader(); - - // prepare file index for binary search - FileList.sort(); + sort(); } } + CPakReader::~CPakReader() { if (File) @@ -40,185 +122,78 @@ CPakReader::~CPakReader() } - -//! splits filename from zip file into useful filenames and paths -void CPakReader::extractFilename(SPakFileEntry* entry) +const IFileList* CPakReader::getFileList() const { - s32 lorfn = 56; // length of real file name - - if (!lorfn) - return; - - if (IgnoreCase) - entry->pakFileName.make_lower(); - - const c8* p = entry->pakFileName.c_str() + lorfn; - - // suche ein slash oder den anfang. - - while (*p!='/' && p!=entry->pakFileName.c_str()) - { - --p; - --lorfn; - } - - bool thereIsAPath = p != entry->pakFileName.c_str(); - - if (thereIsAPath) - { - // there is a path - ++p; - ++lorfn; - } - - entry->simpleFileName = p; - entry->path = ""; - - // pfad auch kopieren - if (thereIsAPath) - { - lorfn = (s32)(p - entry->pakFileName.c_str()); - entry->path.append(entry->pakFileName, lorfn); - } - - if (!IgnorePaths) - entry->simpleFileName = entry->pakFileName; // thanks to Pr3t3nd3r for this fix + return this; } - - -//! scans for a local header, returns false if there is no more local file header. bool CPakReader::scanLocalHeader() { - c8 tmp[1024]; + SPAKFileHeader header; - SPakFileEntry entry; - entry.pos = 0; - - memset(&header, 0, sizeof(SPAKFileHeader)); - File->read(&header, sizeof(SPAKFileHeader)); - - - if (header.tag[0] != 'P' && header.tag[1] != 'A') - return false; // local file headers end here. + // Read and validate the header + File->read(&header, sizeof(header)); + if (!isHeaderValid(header)) + return false; + // Seek to the table of contents +#ifdef __BIG_ENDIAN__ + header.offset = os::Byteswap::byteswap(header.offset); + header.length = os::Byteswap::byteswap(header.length); +#endif File->seek(header.offset); - const int count = header.length / ((sizeof(u32) * 2) + 56); + const int numberOfFiles = header.length / sizeof(SPAKFileEntry); - for(int i = 0; i < count; i++) + Offsets.reallocate(numberOfFiles); + // Loop through each entry in the table of contents + for(int i = 0; i < numberOfFiles; i++) { - // read filename - entry.pakFileName.reserve(56+2); - File->read(tmp, 56); - tmp[56] = 0x0; - entry.pakFileName = tmp; + // read an entry + SPAKFileEntry entry; + File->read(&entry, sizeof(entry)); - #ifdef _DEBUG - os::Printer::log(entry.pakFileName.c_str()); - #endif +#ifdef _DEBUG + os::Printer::log(entry.name); +#endif - extractFilename(&entry); +#ifdef __BIG_ENDIAN__ + entry.offset = os::Byteswap::byteswap(entry.offset); + entry.length = os::Byteswap::byteswap(entry.length); +#endif - File->read(&entry.pos, sizeof(u32)); - File->read(&entry.length, sizeof(u32)); - FileList.push_back(entry); + addItem(io::path(entry.name), entry.length, false, Offsets.size()); + Offsets.push_back(entry.offset); } - return true; } - //! opens a file by file name -IReadFile* CPakReader::openFile(const c8* filename) +IReadFile* CPakReader::createAndOpenFile(const io::path& filename) { - s32 index = findFile(filename); + s32 index = findFile(filename, false); if (index != -1) - return openFile(index); + return createAndOpenFile(index); return 0; } - //! opens a file by index -IReadFile* CPakReader::openFile(s32 index) +IReadFile* CPakReader::createAndOpenFile(u32 index) { - File->seek(FileList[index].pos); - return createLimitReadFile(FileList[index].simpleFileName.c_str(), File, FileList[index].length); -} - - - -//! returns count of files in archive -s32 CPakReader::getFileCount() -{ - return FileList.size(); -} - - - -//! returns data of file -const SPakFileEntry* CPakReader::getFileInfo(s32 index) const -{ - return &FileList[index]; -} - - - -//! deletes the path from a filename -void CPakReader::deletePathFromFilename(core::stringc& filename) -{ - // delete path from filename - const c8* p = filename.c_str() + filename.size(); - - // search for path separator or beginning - - while (*p!='/' && *p!='\\' && p!=filename.c_str()) - --p; - - if (p != filename.c_str()) + if (index < Files.size()) { - ++p; - filename = p; + return createLimitReadFile(Files[index].FullName, File, Offsets[Files[index].ID], Files[index].Size); } + else + return 0; } - - -//! returns fileindex -s32 CPakReader::findFile(const c8* simpleFilename) -{ - SPakFileEntry entry; - entry.simpleFileName = simpleFilename; - - if (IgnoreCase) - entry.simpleFileName.make_lower(); - - if (IgnorePaths) - deletePathFromFilename(entry.simpleFileName); - - s32 res = FileList.binary_search(entry); - - #ifdef _DEBUG - if (res == -1) - { - for (u32 i=0; igetFileName(); + } + //! opens a file by file name - virtual IReadFile* openFile(const c8* filename); + virtual IReadFile* createAndOpenFile(const io::path& filename); //! opens a file by index - IReadFile* openFile(s32 index); + virtual IReadFile* createAndOpenFile(u32 index); - //! returns count of files in archive - s32 getFileCount(); + //! returns the list of files + virtual const IFileList* getFileList() const; - //! returns data of file - const SPakFileEntry* getFileInfo(s32 index) const; - - //! returns fileindex - s32 findFile(const c8* filename); + //! get the class Type + virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_PAK; } private: - - //! scans for a local header, returns false if there is no more local file header. + + //! scans for a local header, returns false if the header is invalid bool scanLocalHeader(); - //! splits filename from zip file into useful filenames and paths - void extractFilename(SPakFileEntry* entry); - - //! deletes the path from a filename - void deletePathFromFilename(core::stringc& filename); - IReadFile* File; - SPAKFileHeader header; - - core::array FileList; - - bool IgnoreCase; - bool IgnorePaths; + //! Contains offsets of the files from the start of the archive file + core::array Offsets; }; } // end namespace io } // end namespace irr -#endif +#endif // __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ + +#endif // __C_PAK_READER_H_INCLUDED__ diff --git a/src/dep/src/irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp b/src/dep/src/irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp index c8a56f5..4441d57 100644 --- a/src/dep/src/irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp +++ b/src/dep/src/irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -174,10 +174,18 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall, void CParticleAnimatedMeshSceneNodeEmitter::setAnimatedMeshSceneNode( IAnimatedMeshSceneNode* node ) { Node = node; + AnimatedMesh = 0; + BaseMesh = 0; + TotalVertices = 0; + VertexPerMeshBufferList.clear(); + if ( !node ) + { + return; + } + AnimatedMesh = node->getMesh(); BaseMesh = AnimatedMesh->getMesh(0); - TotalVertices = 0; MBCount = BaseMesh->getMeshBufferCount(); VertexPerMeshBufferList.reallocate(MBCount); for( u32 i = 0; i < MBCount; ++i ) diff --git a/src/dep/src/irrlicht/CParticleAnimatedMeshSceneNodeEmitter.h b/src/dep/src/irrlicht/CParticleAnimatedMeshSceneNodeEmitter.h index ccf6049..4470948 100644 --- a/src/dep/src/irrlicht/CParticleAnimatedMeshSceneNodeEmitter.h +++ b/src/dep/src/irrlicht/CParticleAnimatedMeshSceneNodeEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CParticleAttractionAffector.cpp b/src/dep/src/irrlicht/CParticleAttractionAffector.cpp index 15c376e..f845780 100644 --- a/src/dep/src/irrlicht/CParticleAttractionAffector.cpp +++ b/src/dep/src/irrlicht/CParticleAttractionAffector.cpp @@ -1,8 +1,9 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleAttractionAffector.h" +#include "IAttributes.h" namespace irr { @@ -56,6 +57,27 @@ void CParticleAttractionAffector::affect(u32 now, SParticle* particlearray, u32 } } +//! Writes attributes of the object. +void CParticleAttractionAffector::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + out->addVector3d("Point", Point); + out->addFloat("Speed", Speed); + out->addBool("AffectX", AffectX); + out->addBool("AffectY", AffectY); + out->addBool("AffectZ", AffectZ); + out->addBool("Attract", Attract); +} + +//! Reads attributes of the object. +void CParticleAttractionAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + Point = in->getAttributeAsVector3d("Point"); + Speed = in->getAttributeAsFloat("Speed"); + AffectX = in->getAttributeAsBool("AffectX"); + AffectY = in->getAttributeAsBool("AffectY"); + AffectZ = in->getAttributeAsBool("AffectZ"); + Attract = in->getAttributeAsBool("Attract"); +} } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CParticleAttractionAffector.h b/src/dep/src/irrlicht/CParticleAttractionAffector.h index 4cc3e22..7223c6a 100644 --- a/src/dep/src/irrlicht/CParticleAttractionAffector.h +++ b/src/dep/src/irrlicht/CParticleAttractionAffector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -62,6 +62,12 @@ public: //! Get whether or not the particles Z position are affected virtual bool getAffectZ() const { return AffectZ; } + //! Writes attributes of the object. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; + + //! Reads attributes of the object. + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + private: core::vector3df Point; diff --git a/src/dep/src/irrlicht/CParticleBoxEmitter.cpp b/src/dep/src/irrlicht/CParticleBoxEmitter.cpp index fd72b8f..af28bce 100644 --- a/src/dep/src/irrlicht/CParticleBoxEmitter.cpp +++ b/src/dep/src/irrlicht/CParticleBoxEmitter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -109,6 +109,10 @@ void CParticleBoxEmitter::serializeAttributes(io::IAttributes* out, io::SAttribu b *= 0.5f; out->addVector3d("Box", b); out->addVector3d("Direction", Direction); + out->addFloat("MinStartSizeWidth", MinStartSize.Width); + out->addFloat("MinStartSizeHeight", MinStartSize.Height); + out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); + out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); out->addColor("MinStartColor", MinStartColor); @@ -120,7 +124,7 @@ void CParticleBoxEmitter::serializeAttributes(io::IAttributes* out, io::SAttribu //! Reads attributes of the object. -s32 CParticleBoxEmitter::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void CParticleBoxEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { // read data and correct input values here @@ -144,6 +148,11 @@ s32 CParticleBoxEmitter::deserializeAttributes(s32 startIndex, io::IAttributes* if (Direction.getLength() == 0) Direction.set(0,0.01f,0); + MinStartSize.Width = in->getAttributeAsFloat("MinStartSizeWidth"); + MinStartSize.Height = in->getAttributeAsFloat("MinStartSizeHeight"); + MaxStartSize.Width = in->getAttributeAsFloat("MaxStartSizeWidth"); + MaxStartSize.Height = in->getAttributeAsFloat("MaxStartSizeHeight"); + MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); @@ -162,7 +171,6 @@ s32 CParticleBoxEmitter::deserializeAttributes(s32 startIndex, io::IAttributes* MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); - return in->findAttribute("MaxAngleDegrees"); } diff --git a/src/dep/src/irrlicht/CParticleBoxEmitter.h b/src/dep/src/irrlicht/CParticleBoxEmitter.h index 4ea1ee2..c50d9ad 100644 --- a/src/dep/src/irrlicht/CParticleBoxEmitter.h +++ b/src/dep/src/irrlicht/CParticleBoxEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -90,7 +90,7 @@ public: virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: diff --git a/src/dep/src/irrlicht/CParticleCylinderEmitter.cpp b/src/dep/src/irrlicht/CParticleCylinderEmitter.cpp index c0287e6..38f1e52 100644 --- a/src/dep/src/irrlicht/CParticleCylinderEmitter.cpp +++ b/src/dep/src/irrlicht/CParticleCylinderEmitter.cpp @@ -1,9 +1,10 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleCylinderEmitter.h" #include "os.h" +#include "IAttributes.h" namespace irr { @@ -115,6 +116,67 @@ s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& return 0; } +//! Writes attributes of the object. +void CParticleCylinderEmitter::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + out->addVector3d("Center", Center); + out->addVector3d("Normal", Normal); + out->addVector3d("Direction", Direction); + out->addFloat("MinStartSizeWidth", MinStartSize.Width); + out->addFloat("MinStartSizeHeight", MinStartSize.Height); + out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); + out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); + out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); + out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); + out->addColor("MinStartColor", MinStartColor); + out->addColor("MaxStartColor", MaxStartColor); + out->addInt("MinLifeTime", MinLifeTime); + out->addInt("MaxLifeTime", MaxLifeTime); + out->addFloat("Radius", Radius); + out->addFloat("Length", Length); + out->addInt("MaxAngleDegrees", MaxAngleDegrees); + out->addBool("OutlineOnly", OutlineOnly); +} + +//! Reads attributes of the object. +void CParticleCylinderEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + Center = in->getAttributeAsVector3d("Center"); + Normal = in->getAttributeAsVector3d("Normal"); + if (Normal.getLength() == 0) + Normal.set(0,1.f,0); + Direction = in->getAttributeAsVector3d("Direction"); + if (Direction.getLength() == 0) + Direction.set(0,0.01f,0); + + MinStartSize.Width = in->getAttributeAsFloat("MinStartSizeWidth"); + MinStartSize.Height = in->getAttributeAsFloat("MinStartSizeHeight"); + MaxStartSize.Width = in->getAttributeAsFloat("MaxStartSizeWidth"); + MaxStartSize.Height = in->getAttributeAsFloat("MaxStartSizeHeight"); + + MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); + MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); + + MinParticlesPerSecond = core::max_(1u, MinParticlesPerSecond); + MaxParticlesPerSecond = core::max_(MaxParticlesPerSecond, 1u); + MaxParticlesPerSecond = core::min_(MaxParticlesPerSecond, 200u); + MinParticlesPerSecond = core::min_(MinParticlesPerSecond, MaxParticlesPerSecond); + + MinStartColor = in->getAttributeAsColor("MinStartColor"); + MaxStartColor = in->getAttributeAsColor("MaxStartColor"); + MinLifeTime = in->getAttributeAsInt("MinLifeTime"); + MaxLifeTime = in->getAttributeAsInt("MaxLifeTime"); + MinLifeTime = core::max_(0u, MinLifeTime); + MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); + MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); + + Radius = in->getAttributeAsFloat("Radius"); + Length = in->getAttributeAsFloat("Length"); + MaxAngleDegrees = in->getAttributeAsInt("MaxAngleDegrees"); + OutlineOnly = in->getAttributeAsBool("OutlineOnly"); +} + + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CParticleCylinderEmitter.h b/src/dep/src/irrlicht/CParticleCylinderEmitter.h index 1907066..8380944 100644 --- a/src/dep/src/irrlicht/CParticleCylinderEmitter.h +++ b/src/dep/src/irrlicht/CParticleCylinderEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -110,6 +110,12 @@ public: //! Gets the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const { return MinStartSize; }; + //! Writes attributes of the object. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; + + //! Reads attributes of the object. + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + private: core::array Particles; diff --git a/src/dep/src/irrlicht/CParticleFadeOutAffector.cpp b/src/dep/src/irrlicht/CParticleFadeOutAffector.cpp index 0df27ba..9f7a57f 100644 --- a/src/dep/src/irrlicht/CParticleFadeOutAffector.cpp +++ b/src/dep/src/irrlicht/CParticleFadeOutAffector.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -58,24 +58,10 @@ void CParticleFadeOutAffector::serializeAttributes(io::IAttributes* out, io::SAt //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector -s32 CParticleFadeOutAffector::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void CParticleFadeOutAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - const char* name = in->getAttributeName(startIndex); - - if (!name || strcmp(name, "TargetColor")) - return startIndex; // attribute not valid - - TargetColor = in->getAttributeAsColor(startIndex); - ++startIndex; - - name = in->getAttributeName(startIndex); - if (!name || strcmp(name, "FadeOutTime")) - return startIndex; // attribute not valid - - FadeOutTime = in->getAttributeAsFloat(startIndex); - - ++startIndex; - return startIndex; + TargetColor = in->getAttributeAsColor("TargetColor"); + FadeOutTime = in->getAttributeAsFloat("FadeOutTime"); } diff --git a/src/dep/src/irrlicht/CParticleFadeOutAffector.h b/src/dep/src/irrlicht/CParticleFadeOutAffector.h index 71cfc7a..3e5bbbe 100644 --- a/src/dep/src/irrlicht/CParticleFadeOutAffector.h +++ b/src/dep/src/irrlicht/CParticleFadeOutAffector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -47,7 +47,7 @@ public: //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: diff --git a/src/dep/src/irrlicht/CParticleGravityAffector.cpp b/src/dep/src/irrlicht/CParticleGravityAffector.cpp index f6ce52c..f458e60 100644 --- a/src/dep/src/irrlicht/CParticleGravityAffector.cpp +++ b/src/dep/src/irrlicht/CParticleGravityAffector.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -51,24 +51,10 @@ void CParticleGravityAffector::serializeAttributes(io::IAttributes* out, io::SAt //! Reads attributes of the object. -s32 CParticleGravityAffector::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void CParticleGravityAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - const char* name = in->getAttributeName(startIndex); - - if (!name || strcmp(name, "Gravity")) - return startIndex; // attribute not valid - - Gravity = in->getAttributeAsVector3d(startIndex); - ++startIndex; - - name = in->getAttributeName(startIndex); - if (!name || strcmp(name, "TimeForceLost")) - return startIndex; // attribute not valid - - TimeForceLost = in->getAttributeAsFloat(startIndex); - - ++startIndex; - return startIndex; + Gravity = in->getAttributeAsVector3d("Gravity"); + TimeForceLost = in->getAttributeAsFloat("TimeForceLost"); } diff --git a/src/dep/src/irrlicht/CParticleGravityAffector.h b/src/dep/src/irrlicht/CParticleGravityAffector.h index df082b6..5018d11 100644 --- a/src/dep/src/irrlicht/CParticleGravityAffector.h +++ b/src/dep/src/irrlicht/CParticleGravityAffector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -49,10 +49,9 @@ public: //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: - f32 TimeForceLost; core::vector3df Gravity; }; diff --git a/src/dep/src/irrlicht/CParticleMeshEmitter.cpp b/src/dep/src/irrlicht/CParticleMeshEmitter.cpp index d18288c..6e0f150 100644 --- a/src/dep/src/irrlicht/CParticleMeshEmitter.cpp +++ b/src/dep/src/irrlicht/CParticleMeshEmitter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -178,6 +178,12 @@ void CParticleMeshEmitter::setMesh(IMesh* mesh) Mesh = mesh; TotalVertices = 0; + MBCount = 0; + VertexPerMeshBufferList.clear(); + + if ( !Mesh ) + return; + MBCount = Mesh->getMeshBufferCount(); VertexPerMeshBufferList.reallocate(MBCount); for( u32 i = 0; i < MBCount; ++i ) diff --git a/src/dep/src/irrlicht/CParticleMeshEmitter.h b/src/dep/src/irrlicht/CParticleMeshEmitter.h index 9a8d7b8..6ea1389 100644 --- a/src/dep/src/irrlicht/CParticleMeshEmitter.h +++ b/src/dep/src/irrlicht/CParticleMeshEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CParticlePointEmitter.cpp b/src/dep/src/irrlicht/CParticlePointEmitter.cpp index 8ea9236..7419772 100644 --- a/src/dep/src/irrlicht/CParticlePointEmitter.cpp +++ b/src/dep/src/irrlicht/CParticlePointEmitter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -88,6 +88,10 @@ s32 CParticlePointEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& out void CParticlePointEmitter::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addVector3d("Direction", Direction); + out->addFloat("MinStartSizeWidth", MinStartSize.Width); + out->addFloat("MinStartSizeHeight", MinStartSize.Height); + out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); + out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); out->addColor("MinStartColor", MinStartColor); @@ -97,14 +101,18 @@ void CParticlePointEmitter::serializeAttributes(io::IAttributes* out, io::SAttri out->addInt("MaxAngleDegrees", MaxAngleDegrees); } - //! Reads attributes of the object. -s32 CParticlePointEmitter::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void CParticlePointEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Direction = in->getAttributeAsVector3d("Direction"); if (Direction.getLength() == 0) Direction.set(0,0.01f,0); + MinStartSize.Width = in->getAttributeAsFloat("MinStartSizeWidth"); + MinStartSize.Height = in->getAttributeAsFloat("MinStartSizeHeight"); + MaxStartSize.Width = in->getAttributeAsFloat("MaxStartSizeWidth"); + MaxStartSize.Height = in->getAttributeAsFloat("MaxStartSizeHeight"); + MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); @@ -122,8 +130,6 @@ s32 CParticlePointEmitter::deserializeAttributes(s32 startIndex, io::IAttributes MinLifeTime = core::max_(0u, MinLifeTime); MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); - - return in->findAttribute("MaxAngleDegrees"); } diff --git a/src/dep/src/irrlicht/CParticlePointEmitter.h b/src/dep/src/irrlicht/CParticlePointEmitter.h index bc3ebc4..979fa26 100644 --- a/src/dep/src/irrlicht/CParticlePointEmitter.h +++ b/src/dep/src/irrlicht/CParticlePointEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -81,7 +81,7 @@ public: virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: diff --git a/src/dep/src/irrlicht/CParticleRingEmitter.cpp b/src/dep/src/irrlicht/CParticleRingEmitter.cpp index 91ea47b..5e85c00 100644 --- a/src/dep/src/irrlicht/CParticleRingEmitter.cpp +++ b/src/dep/src/irrlicht/CParticleRingEmitter.cpp @@ -1,9 +1,10 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleRingEmitter.h" #include "os.h" +#include "IAttributes.h" namespace irr { @@ -106,6 +107,62 @@ s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA return 0; } +//! Writes attributes of the object. +void CParticleRingEmitter::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + out->addVector3d("Center", Center); + out->addFloat("Radius", Radius); + out->addFloat("RingThickness", RingThickness); + + out->addVector3d("Direction", Direction); + out->addFloat("MinStartSizeWidth", MinStartSize.Width); + out->addFloat("MinStartSizeHeight", MinStartSize.Height); + out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); + out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); + out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); + out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); + out->addColor("MinStartColor", MinStartColor); + out->addColor("MaxStartColor", MaxStartColor); + out->addInt("MinLifeTime", MinLifeTime); + out->addInt("MaxLifeTime", MaxLifeTime); + out->addInt("MaxAngleDegrees", MaxAngleDegrees); +} + +//! Reads attributes of the object. +void CParticleRingEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + Center = in->getAttributeAsVector3d("Center"); + Radius = in->getAttributeAsFloat("Radius"); + RingThickness = in->getAttributeAsFloat("RingThickness"); + + Direction = in->getAttributeAsVector3d("Direction"); + if (Direction.getLength() == 0) + Direction.set(0,0.01f,0); + + MinStartSize.Width = in->getAttributeAsFloat("MinStartSizeWidth"); + MinStartSize.Height = in->getAttributeAsFloat("MinStartSizeHeight"); + MaxStartSize.Width = in->getAttributeAsFloat("MaxStartSizeWidth"); + MaxStartSize.Height = in->getAttributeAsFloat("MaxStartSizeHeight"); + + MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); + MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); + + MinParticlesPerSecond = core::max_(1u, MinParticlesPerSecond); + MaxParticlesPerSecond = core::max_(MaxParticlesPerSecond, 1u); + MaxParticlesPerSecond = core::min_(MaxParticlesPerSecond, 200u); + MinParticlesPerSecond = core::min_(MinParticlesPerSecond, MaxParticlesPerSecond); + + MinStartColor = in->getAttributeAsColor("MinStartColor"); + MaxStartColor = in->getAttributeAsColor("MaxStartColor"); + MinLifeTime = in->getAttributeAsInt("MinLifeTime"); + MaxLifeTime = in->getAttributeAsInt("MaxLifeTime"); + MinLifeTime = core::max_(0u, MinLifeTime); + MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); + MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); + + MaxAngleDegrees = in->getAttributeAsInt("MaxAngleDegrees"); +} + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CParticleRingEmitter.h b/src/dep/src/irrlicht/CParticleRingEmitter.h index 5b40e25..7c159b7 100644 --- a/src/dep/src/irrlicht/CParticleRingEmitter.h +++ b/src/dep/src/irrlicht/CParticleRingEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -97,6 +97,12 @@ public: //! Get the thickness of the ring virtual f32 getRingThickness() const { return RingThickness; } + //! Writes attributes of the object. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; + + //! Reads attributes of the object. + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + private: core::array Particles; diff --git a/src/dep/src/irrlicht/CParticleRotationAffector.cpp b/src/dep/src/irrlicht/CParticleRotationAffector.cpp index 4f9210b..eb6b4d8 100644 --- a/src/dep/src/irrlicht/CParticleRotationAffector.cpp +++ b/src/dep/src/irrlicht/CParticleRotationAffector.cpp @@ -1,8 +1,9 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleRotationAffector.h" +#include "IAttributes.h" namespace irr { @@ -47,6 +48,19 @@ void CParticleRotationAffector::affect(u32 now, SParticle* particlearray, u32 co } } +//! Writes attributes of the object. +void CParticleRotationAffector::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + out->addVector3d("PivotPoint", PivotPoint); + out->addVector3d("Speed", Speed); +} + +//! Reads attributes of the object. +void CParticleRotationAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + PivotPoint = in->getAttributeAsVector3d("PivotPoint"); + Speed = in->getAttributeAsVector3d("Speed"); +} } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CParticleRotationAffector.h b/src/dep/src/irrlicht/CParticleRotationAffector.h index 3ced836..dd1ec23 100644 --- a/src/dep/src/irrlicht/CParticleRotationAffector.h +++ b/src/dep/src/irrlicht/CParticleRotationAffector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -35,6 +35,12 @@ public: //! Get the speed in degrees per second virtual const core::vector3df& getSpeed() const { return Speed; } + //! Writes attributes of the object. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; + + //! Reads attributes of the object. + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + private: core::vector3df PivotPoint; diff --git a/src/dep/src/irrlicht/CParticleScaleAffector.cpp b/src/dep/src/irrlicht/CParticleScaleAffector.cpp index 6bf002c..b3c2715 100644 --- a/src/dep/src/irrlicht/CParticleScaleAffector.cpp +++ b/src/dep/src/irrlicht/CParticleScaleAffector.cpp @@ -8,6 +8,9 @@ namespace irr CParticleScaleAffector::CParticleScaleAffector(const core::dimension2df& scaleTo) : ScaleTo(scaleTo) { + #ifdef _DEBUG + setDebugName("CParticleScaleAffector"); + #endif } @@ -23,18 +26,17 @@ namespace irr } - void CParticleScaleAffector::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) + void CParticleScaleAffector::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addFloat("ScaleToWidth", ScaleTo.Width); out->addFloat("ScaleToHeight", ScaleTo.Height); } - s32 CParticleScaleAffector::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) + void CParticleScaleAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { ScaleTo.Width = in->getAttributeAsFloat("ScaleToWidth"); ScaleTo.Height = in->getAttributeAsFloat("ScaleToHeight"); - return 0; } diff --git a/src/dep/src/irrlicht/CParticleScaleAffector.h b/src/dep/src/irrlicht/CParticleScaleAffector.h index 6079ab7..99f7b0b 100644 --- a/src/dep/src/irrlicht/CParticleScaleAffector.h +++ b/src/dep/src/irrlicht/CParticleScaleAffector.h @@ -17,14 +17,14 @@ namespace irr //! Writes attributes of the object. //! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. - virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options); + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const; diff --git a/src/dep/src/irrlicht/CParticleSphereEmitter.cpp b/src/dep/src/irrlicht/CParticleSphereEmitter.cpp index fc4cee2..f62db2b 100644 --- a/src/dep/src/irrlicht/CParticleSphereEmitter.cpp +++ b/src/dep/src/irrlicht/CParticleSphereEmitter.cpp @@ -1,10 +1,11 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CParticleSphereEmitter.h" #include "os.h" +#include "IAttributes.h" namespace irr { @@ -107,6 +108,60 @@ s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ou return 0; } +//! Writes attributes of the object. +void CParticleSphereEmitter::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + out->addVector3d("Center", Direction); + out->addFloat("Radius", Radius); + + out->addVector3d("Direction", Direction); + out->addFloat("MinStartSizeWidth", MinStartSize.Width); + out->addFloat("MinStartSizeHeight", MinStartSize.Height); + out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); + out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); + out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); + out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); + out->addColor("MinStartColor", MinStartColor); + out->addColor("MaxStartColor", MaxStartColor); + out->addInt("MinLifeTime", MinLifeTime); + out->addInt("MaxLifeTime", MaxLifeTime); + out->addInt("MaxAngleDegrees", MaxAngleDegrees); +} + +//! Reads attributes of the object. +void CParticleSphereEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + Center = in->getAttributeAsVector3d("Center"); + Radius = in->getAttributeAsFloat("Radius"); + + Direction = in->getAttributeAsVector3d("Direction"); + if (Direction.getLength() == 0) + Direction.set(0,0.01f,0); + + MinStartSize.Width = in->getAttributeAsFloat("MinStartSizeWidth"); + MinStartSize.Height = in->getAttributeAsFloat("MinStartSizeHeight"); + MaxStartSize.Width = in->getAttributeAsFloat("MaxStartSizeWidth"); + MaxStartSize.Height = in->getAttributeAsFloat("MaxStartSizeHeight"); + + MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); + MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); + + MinParticlesPerSecond = core::max_(1u, MinParticlesPerSecond); + MaxParticlesPerSecond = core::max_(MaxParticlesPerSecond, 1u); + MaxParticlesPerSecond = core::min_(MaxParticlesPerSecond, 200u); + MinParticlesPerSecond = core::min_(MinParticlesPerSecond, MaxParticlesPerSecond); + + MinStartColor = in->getAttributeAsColor("MinStartColor"); + MaxStartColor = in->getAttributeAsColor("MaxStartColor"); + MinLifeTime = in->getAttributeAsInt("MinLifeTime"); + MaxLifeTime = in->getAttributeAsInt("MaxLifeTime"); + MinLifeTime = core::max_(0u, MinLifeTime); + MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); + MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); + + MaxAngleDegrees = in->getAttributeAsInt("MaxAngleDegrees"); +} + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CParticleSphereEmitter.h b/src/dep/src/irrlicht/CParticleSphereEmitter.h index 3858bcc..3ddefb6 100644 --- a/src/dep/src/irrlicht/CParticleSphereEmitter.h +++ b/src/dep/src/irrlicht/CParticleSphereEmitter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -91,6 +91,12 @@ public: //! Get the radius of the sphere for particle emissions virtual f32 getRadius() const { return Radius; } + //! Writes attributes of the object. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; + + //! Reads attributes of the object. + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + private: core::array Particles; diff --git a/src/dep/src/irrlicht/CParticleSystemSceneNode.cpp b/src/dep/src/irrlicht/CParticleSystemSceneNode.cpp index dc27d21..6a5ad98 100644 --- a/src/dep/src/irrlicht/CParticleSystemSceneNode.cpp +++ b/src/dep/src/irrlicht/CParticleSystemSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -72,6 +72,8 @@ IParticleEmitter* CParticleSystemSceneNode::getEmitter() //! Sets the particle emitter, which creates the particles. void CParticleSystemSceneNode::setEmitter(IParticleEmitter* emitter) { + if (emitter == Emitter) + return; if (Emitter) Emitter->drop(); @@ -161,7 +163,7 @@ IParticleCylinderEmitter* CParticleSystemSceneNode::createCylinderEmitter( bool outlineOnly, const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, - u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, + u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) { @@ -315,7 +317,7 @@ void CParticleSystemSceneNode::render() #else - const core::matrix4 &m = camera->getViewFrustum()->Matrices [ video::ETS_VIEW ]; + const core::matrix4 &m = camera->getViewFrustum()->getTransform( video::ETS_VIEW ); const core::vector3df view ( -m[2], -m[6] , -m[10] ); @@ -448,6 +450,7 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time) for (u32 i=0; i Particles[i].endTime) Particles.erase(i); else @@ -604,19 +607,39 @@ void CParticleSystemSceneNode::deserializeAttributes(io::IAttributes* in, io::SA case EPET_POINT: Emitter = createPointEmitter(); break; + case EPET_ANIMATED_MESH: + Emitter = createAnimatedMeshSceneNodeEmitter(NULL); // we can't set the node - the user will have to do this + break; case EPET_BOX: Emitter = createBoxEmitter(); break; + case EPET_CYLINDER: + Emitter = createCylinderEmitter(core::vector3df(0,0,0), 10.f, core::vector3df(0,1,0), 10.f); // (values here don't matter) + break; + case EPET_MESH: + Emitter = createMeshEmitter(NULL); // we can't set the mesh - the user will have to do this + break; + case EPET_RING: + Emitter = createRingEmitter(core::vector3df(0,0,0), 10.f, 10.f); // (values here don't matter) + break; + case EPET_SPHERE: + Emitter = createSphereEmitter(core::vector3df(0,0,0), 10.f); // (values here don't matter) + break; default: break; } u32 idx = 0; +#if 0 if (Emitter) idx = Emitter->deserializeAttributes(idx, in); ++idx; +#else + if (Emitter) + Emitter->deserializeAttributes(in); +#endif // read affectors @@ -637,12 +660,18 @@ void CParticleSystemSceneNode::deserializeAttributes(io::IAttributes* in, io::SA switch(atype) { + case EPAT_ATTRACT: + aff = createAttractionAffector(core::vector3df(0,0,0)); + break; case EPAT_FADE_OUT: aff = createFadeOutParticleAffector(); break; case EPAT_GRAVITY: aff = createGravityAffector(); break; + case EPAT_ROTATE: + aff = createRotationAffector(); + break; case EPAT_SCALE: aff = createScaleParticleAffector(); break; @@ -655,8 +684,13 @@ void CParticleSystemSceneNode::deserializeAttributes(io::IAttributes* in, io::SA if (aff) { +#if 0 idx = aff->deserializeAttributes(idx, in, options); ++idx; +#else + aff->deserializeAttributes(in, options); +#endif + addAffector(aff); aff->drop(); } diff --git a/src/dep/src/irrlicht/CParticleSystemSceneNode.h b/src/dep/src/irrlicht/CParticleSystemSceneNode.h index 85f8c11..63836c0 100644 --- a/src/dep/src/irrlicht/CParticleSystemSceneNode.h +++ b/src/dep/src/irrlicht/CParticleSystemSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -25,7 +25,7 @@ public: //! constructor CParticleSystemSceneNode(bool createDefaultEmitter, - ISceneNode* parent, ISceneManager* mgr, s32 id, + ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale); @@ -77,7 +77,7 @@ public: //! Creates a box particle emitter. virtual IParticleBoxEmitter* createBoxEmitter( const core::aabbox3df& box = core::aabbox3d(-10,0,-10,5,30,10), - const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), + const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), @@ -117,7 +117,7 @@ public: //! Creates a point particle emitter. virtual IParticlePointEmitter* createPointEmitter( - const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), + const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), diff --git a/src/dep/src/irrlicht/CQ3LevelMesh.cpp b/src/dep/src/irrlicht/CQ3LevelMesh.cpp index cf28c76..9579ba2 100644 --- a/src/dep/src/irrlicht/CQ3LevelMesh.cpp +++ b/src/dep/src/irrlicht/CQ3LevelMesh.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,32 +12,35 @@ #include "irrString.h" #include "ILightSceneNode.h" #include "IQ3Shader.h" +#include "IFileList.h" + +//#define TJUNCTION_SOLVER_ROUND +//#define TJUNCTION_SOLVER_0125 namespace irr { namespace scene { + using namespace quake3; //! constructor -CQ3LevelMesh::CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr) -: Textures(0), LightMaps(0), - Vertices(0), Faces(0), Planes(0), Nodes(0), Leafs(0), LeafFaces(0), +CQ3LevelMesh::CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr, + const Q3LevelLoadParameter &loadParam) + : LoadParam(loadParam), Textures(0), LightMaps(0), + Vertices(0), Faces(0), Planes(0), Nodes(0), Leafs(0), LeafFaces(0), MeshVerts(0), Brushes(0), FileSystem(fs), SceneManager(smgr) { #ifdef _DEBUG IReferenceCounted::setDebugName("CQ3LevelMesh"); #endif - for ( s32 i = 0; i!= quake3::E_Q3_MESH_SIZE; ++i ) + for ( s32 i = 0; i!= E_Q3_MESH_SIZE; ++i ) { Mesh[i] = 0; } - if (smgr) - Driver = smgr->getVideoDriver(); - else - Driver = 0; + Driver = smgr ? smgr->getVideoDriver() : 0; if (Driver) Driver->grab(); @@ -52,16 +55,7 @@ CQ3LevelMesh::CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr) //! destructor CQ3LevelMesh::~CQ3LevelMesh() { - delete [] Textures; - delete [] LightMaps; - delete [] Vertices; - delete [] Faces; - delete [] Planes; - delete [] Nodes; - delete [] Leafs; - delete [] LeafFaces; - delete [] MeshVerts; - delete [] Brushes; + cleanLoader (); if (Driver) Driver->drop(); @@ -69,10 +63,13 @@ CQ3LevelMesh::~CQ3LevelMesh() if (FileSystem) FileSystem->drop(); - for ( s32 i = 0; i!= quake3::E_Q3_MESH_SIZE; ++i ) + for ( s32 i = 0; i!= E_Q3_MESH_SIZE; ++i ) { - if (Mesh[i]) + if ( Mesh[i] ) + { Mesh[i]->drop(); + Mesh[i] = 0; + } } ReleaseShader(); @@ -88,7 +85,6 @@ bool CQ3LevelMesh::loadFile(io::IReadFile* file) LevelName = file->getFileName(); - tBSPHeader header; file->read(&header, sizeof(tBSPHeader)); #ifdef __BIG_ENDIAN__ @@ -96,33 +92,49 @@ bool CQ3LevelMesh::loadFile(io::IReadFile* file) header.version = os::Byteswap::byteswap(header.version); #endif - if (header.strID != 0x50534249 || header.version != 0x2e) + if ( (header.strID != 0x50534249 || // IBSP + ( header.version != 0x2e // quake3 + && header.version != 0x2f // rtcw + ) + ) + && + ( header.strID != 0x50534252 || header.version != 1 ) // RBSP, starwars jedi, sof + ) { os::Printer::log("Could not load .bsp file, unknown header.", file->getFileName(), ELL_ERROR); return false; } - // now read lumps +#if 0 + if ( header.strID == 0x50534252 ) // RBSP Raven + { + LoadParam.swapHeader = 1; + } +#endif + // now read lumps file->read(&Lumps[0], sizeof(tBSPLump)*kMaxLumps); - #ifdef __BIG_ENDIAN__ - for (int i=0;idrop(); - Mesh[index] = 0; - } -} - - //! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level. IMesh* CQ3LevelMesh::getMesh(s32 frameInMs, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { @@ -187,13 +202,14 @@ void CQ3LevelMesh::loadTextures(tBSPLump* l, io::IReadFile* file) file->seek(l->offset); file->read(Textures, l->length); - for (s32 i=0;iread(LightMaps, l->length); } - +/*! +*/ void CQ3LevelMesh::loadVerts(tBSPLump* l, io::IReadFile* file) { NumVertices = l->length / sizeof(tBSPVertex); @@ -216,7 +233,7 @@ void CQ3LevelMesh::loadVerts(tBSPLump* l, io::IReadFile* file) file->seek(l->offset); file->read(Vertices, l->length); - #ifdef __BIG_ENDIAN__ + if ( LoadParam.swapHeader ) for (s32 i=0;ilength / sizeof(tBSPFace); @@ -242,70 +260,83 @@ void CQ3LevelMesh::loadFaces(tBSPLump* l, io::IReadFile* file) file->seek(l->offset); file->read(Faces, l->length); - #ifdef __BIG_ENDIAN__ - for ( s32 i=0;i entity; @@ -319,28 +350,48 @@ void CQ3LevelMesh::loadEntities(tBSPLump* l, io::IReadFile* file) } -// load shaders named in bsp -void CQ3LevelMesh::loadShaders(tBSPLump* l, io::IReadFile* file) +/*! + load fog brushes +*/ +void CQ3LevelMesh::loadFogs(tBSPLump* l, io::IReadFile* file) { - u32 files = l->length / sizeof(tBSPShader); + u32 files = l->length / sizeof(tBSPFog); file->seek( l->offset ); - - tBSPShader def; + tBSPFog fog; + const IShader *shader; + STexShader t; for ( u32 i = 0; i!= files; ++i ) { - file->read( &def, sizeof( def ) ); - getShader(def.strName); + file->read( &fog, sizeof( fog ) ); + + shader = getShader( fog.shader ); + t.Texture = 0; + t.ShaderID = shader ? shader->ID : -1; + + FogMap.push_back ( t ); } } +/*! + load models named in bsp +*/ void CQ3LevelMesh::loadModels(tBSPLump* l, io::IReadFile* file) { - // ignore + u32 files = l->length / sizeof(tBSPModel); + file->seek( l->offset ); + + tBSPModel def; + for ( u32 i = 0; i!= files; ++i ) + { + file->read( &def, sizeof( def ) ); + } + } - +/*! +*/ void CQ3LevelMesh::loadMeshVerts(tBSPLump* l, io::IReadFile* file) { NumMeshVerts = l->length / sizeof(s32); @@ -349,37 +400,53 @@ void CQ3LevelMesh::loadMeshVerts(tBSPLump* l, io::IReadFile* file) file->seek(l->offset); file->read(MeshVerts, l->length); - #ifdef __BIG_ENDIAN__ - for (int i=0;i= 'a' && symbol <= 'z' ) || + (symbol >= 'A' && symbol <= 'Z' ) || + (symbol >= '0' && symbol <= '9' ) || + (symbol == '/' || symbol == '_' || symbol == '.' ); +} +/*! +*/ void CQ3LevelMesh::parser_nextToken() { u8 symbol; @@ -478,7 +545,7 @@ void CQ3LevelMesh::parser_nextToken() Parser.token.append( symbol ); // continue till whitespace - bool notisWhite = true; + bool validName = true; do { if ( Parser.index >= Parser.sourcesize ) @@ -488,15 +555,13 @@ void CQ3LevelMesh::parser_nextToken() } symbol = Parser.source [ Parser.index ]; - notisWhite = ! isQ3WhiteSpace( symbol ); - if ( notisWhite ) + validName = isQ3ValidName( symbol ); + if ( validName ) { Parser.token.append( symbol ); + Parser.index += 1; } - - Parser.index += 1; - - } while ( notisWhite ); + } while ( validName ); Parser.tokenresult = Q3_TOKEN_TOKEN; return; @@ -513,16 +578,16 @@ void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh Parser.sourcesize = size; Parser.index = 0; - quake3::SVarGroupList *groupList; + SVarGroupList *groupList; s32 active; s32 last; - quake3::SVariable entity; + SVariable entity ( "" ); - groupList = new quake3::SVarGroupList(); + groupList = new SVarGroupList(); - groupList->VariableGroup.push_back( quake3::SVarGroup() ); + groupList->VariableGroup.push_back( SVarGroup() ); active = last = 0; do @@ -535,7 +600,7 @@ void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh { //stack = core::min_( stack + 1, 7 ); - groupList->VariableGroup.push_back( quake3::SVarGroup() ); + groupList->VariableGroup.push_back( SVarGroup() ); last = active; active = groupList->VariableGroup.size() - 1; entity.clear(); @@ -580,12 +645,12 @@ void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh // close tag for first if ( active == 1 ) { - (this->*callback)( groupList ); + (this->*callback)( groupList, Q3_TOKEN_END_LIST ); // new group groupList->drop(); - groupList = new quake3::SVarGroupList(); - groupList->VariableGroup.push_back( quake3::SVarGroup() ); + groupList = new SVarGroupList(); + groupList->VariableGroup.push_back( SVarGroup() ); last = 0; } @@ -594,14 +659,46 @@ void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh } break; + default: + break; } } while ( Parser.tokenresult != Q3_TOKEN_EOF ); + (this->*callback)( groupList, Q3_TOKEN_EOF ); + groupList->drop(); } +/* + this loader applies only textures for stage 1 & 2 +*/ +s32 CQ3LevelMesh::setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const +{ + material.MaterialType = video::EMT_SOLID; + material.Wireframe = false; + material.Lighting = false; + material.BackfaceCulling = false; + material.setTexture(0, 0); + material.setTexture(1, 0); + material.setTexture(2, 0); + material.setTexture(3, 0); + material.ZBuffer = video::ECFN_LESSEQUAL; + material.ZWriteEnable = false; + material.MaterialTypeParam = 0.f; + + s32 shaderState = -1; + + if ( (u32) face->fogNum < FogMap.size() ) + { + material.setTexture(0, FogMap [ face->fogNum ].Texture); + shaderState = FogMap [ face->fogNum ].ShaderID; + } + + return shaderState; + +} /* this loader applies only textures for stage 1 & 2 */ @@ -615,7 +712,7 @@ s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace material.setTexture(1, 0); material.setTexture(2, 0); material.setTexture(3, 0); - material.ZBuffer = true; + material.ZBuffer = video::ECFN_LESSEQUAL; material.ZWriteEnable = true; material.MaterialTypeParam = 0.f; @@ -630,25 +727,27 @@ s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace if ( face->lightmapID >= 0 ) { material.setTexture(1, Lightmap [ face->lightmapID ]); - material.MaterialType = quake3::defaultMaterialType; + material.MaterialType = LoadParam.defaultLightMapMaterial; } // store shader ID material.MaterialTypeParam2 = (f32) shaderState; - const quake3::SShader *shader = getShader(shaderState); + const IShader *shader = getShader(shaderState); if ( 0 == shader ) return shaderState; - const quake3::SVarGroup *group; + return shaderState; + +#if 0 + const SVarGroup *group; - s32 index; // generic group = shader->getGroup( 1 ); if ( group ) { - material.BackfaceCulling = quake3::isDisabled( group->get( "cull" ) ); + material.BackfaceCulling = getCullingFunction( group->get( "cull" ) ); if ( group->isDefined( "surfaceparm", "nolightmap" ) ) { @@ -670,18 +769,27 @@ s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace startPos = 0; - index = group->getIndex( "depthwrite" ); - if ( index >= 0 ) + if ( group->isDefined( "depthwrite" ) ) { material.ZWriteEnable = true; } - quake3::SBlendFunc blendfunc; - quake3::getBlendFunc( group->get( "blendfunc" ), blendfunc ); - quake3::getBlendFunc( group->get( "alphafunc" ), blendfunc ); + SBlendFunc blendfunc ( LoadParam.defaultModulate ); + getBlendFunc( group->get( "blendfunc" ), blendfunc ); + getBlendFunc( group->get( "alphafunc" ), blendfunc ); + + if ( 0 == LoadParam.alpharef && + ( blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL || + blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF + ) + ) + { + blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + blendfunc.param0 = 0.f; + } material.MaterialType = blendfunc.type; - material.MaterialTypeParam = blendfunc.param; + material.MaterialTypeParam = blendfunc.param0; // try if we can match better shaderState |= (material.MaterialType == video::EMT_SOLID ) ? 0x00020000 : 0; @@ -696,42 +804,67 @@ s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace material.MaterialTypeParam2 = (f32) shaderState; return shaderState; +#endif } -//! constructs a mesh from the quake 3 level file. -void CQ3LevelMesh::constructMesh2() + +/*! +*/ +void CQ3LevelMesh::solveTJunction() { - s32 i, j, k; +} + +/*! + constructs a mesh from the quake 3 level file. +*/ +void CQ3LevelMesh::constructMesh() +{ + if ( LoadParam.verbose > 0 ) + { + LoadParam.startTime = os::Timer::getRealTime(); + + if ( LoadParam.verbose > 1 ) + { + snprintf( buf, sizeof ( buf ), + "quake3::constructMesh start to create %d faces, %d vertices,%d mesh vertices", + NumFaces, + NumVertices, + NumMeshVerts + ); + os::Printer::log(buf, ELL_INFORMATION); + } + + } + + s32 i, j, k,s; s32 *index; video::S3DVertex2TCoords temp[3]; - video::SMaterial material; + video::SMaterial material2; - SToBuffer item; + SToBuffer item [ E_Q3_MESH_SIZE ]; + u32 itemSize; - core::array < SToBuffer > toBuffer; - - const s32 mesh0size = (NumTextures+1) * (NumLightMaps+1); - for ( i=0; i < mesh0size; ++i) + for ( i=0; i < NumFaces; ++i) { - scene::SMeshBufferLightMap* buffer = new scene::SMeshBufferLightMap(); - - Mesh[quake3::E_Q3_MESH_GEOMETRY]->addMeshBuffer(buffer); - buffer->drop(); - } - - for ( i=0; ifogNum >= 0 ) + { + setShaderFogMaterial ( material2, face ); + item[itemSize].index = E_Q3_MESH_FOG; + item[itemSize].takeVertexColor = 1; + itemSize += 1; + } + + switch( face->type ) { case 1: // normal polygons case 2: // patches @@ -739,117 +872,81 @@ void CQ3LevelMesh::constructMesh2() { if ( 0 == shader ) { - item.takeVertexColor = material.getTexture(0) == 0 || material.getTexture(1) == 0; - item.index = quake3::E_Q3_MESH_GEOMETRY; - toBuffer.push_back( item ); + if ( LoadParam.cleanUnResolvedMeshes || material.getTexture(0) ) + { + item[itemSize].takeVertexColor = 1; + item[itemSize].index = E_Q3_MESH_GEOMETRY; + itemSize += 1; + } + else + { + item[itemSize].takeVertexColor = 1; + item[itemSize].index = E_Q3_MESH_UNRESOLVED; + itemSize += 1; + } } else { - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); + item[itemSize].takeVertexColor = 1; + item[itemSize].index = E_Q3_MESH_ITEMS; + itemSize += 1; } } break; -/* - case 1: // normal polygons - case 2: // patches - if ( material.Textures[0] && 0 == shader ) - { - item.takeVertexColor = material.Textures[1] == 0; - item.index = quake3::E_Q3_MESH_GEOMETRY; - toBuffer.push_back( item ); - } - else - if ( material.Textures[0] ) - { - item.takeVertexColor = material.Textures[1] == 0; - item.index = quake3::E_Q3_MESH_GEOMETRY; - toBuffer.push_back( item ); - if ( 0 == (shaderState & 0xFFFF0000 ) ) - { - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); - } - } - else - { - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); - } + case 4: // billboards + //item[itemSize].takeVertexColor = 1; + //item[itemSize].index = E_Q3_MESH_ITEMS; + //itemSize += 1; break; - case 3: // mesh vertices - if ( material.Textures[0] && ( shaderState & 0xFFFF0000 ) == 0x00030000 ) - { - item.takeVertexColor = material.Textures[1] == 0; - item.index = quake3::E_Q3_MESH_GEOMETRY; - toBuffer.push_back( item ); - } - else - { - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); - } - break; -*/ - case 4: // billboards - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); - break; } - for ( u32 g = 0; g!= toBuffer.size(); ++g ) + for ( u32 g = 0; g != itemSize; ++g ) { - scene::SMeshBufferLightMap* buffer; + scene::SMeshBufferLightMap* buffer = 0; - if ( toBuffer[g].index == quake3::E_Q3_MESH_GEOMETRY ) + if ( item[g].index == E_Q3_MESH_GEOMETRY ) { - if ( 0 == toBuffer[g].takeVertexColor ) + if ( 0 == item[g].takeVertexColor ) { - toBuffer[g].takeVertexColor = material.getTexture(0) == 0 || material.getTexture(1) == 0; + item[g].takeVertexColor = material.getTexture(0) == 0 || material.getTexture(1) == 0; } + if (Faces[i].lightmapID < -1 || Faces[i].lightmapID > NumLightMaps-1) { Faces[i].lightmapID = -1; } +#if 0 // there are lightmapsids and textureid with -1 const s32 tmp_index = ((Faces[i].lightmapID+1) * (NumTextures+1)) + (Faces[i].textureID+1); - buffer = (SMeshBufferLightMap*) Mesh[quake3::E_Q3_MESH_GEOMETRY]->getMeshBuffer(tmp_index); + buffer = (SMeshBufferLightMap*) Mesh[E_Q3_MESH_GEOMETRY]->getMeshBuffer(tmp_index); + buffer->setHardwareMappingHint ( EHM_STATIC ); buffer->getMaterial() = material; - } - else - { - // Construct a unique mesh for each shader or combine meshbuffers for same shader -#if 0 - buffer = 0; - if ( shader ) - { - const quake3::SVarGroup *group = shader->getGroup( 1 ); - if ( group ) - { - if ( group->getIndex( "deformvertexes" ) >= 0 ) - { - buffer = (SMeshBufferLightMap*) Mesh[ toBuffer[g].index ]->getMeshBuffer( material ); - } - } - - } -#else - buffer = (SMeshBufferLightMap*) Mesh[ toBuffer[g].index ]->getMeshBuffer( material ); #endif + } + + // Construct a unique mesh for each shader or combine meshbuffers for same shader + if ( 0 == buffer ) + { + + if ( LoadParam.mergeShaderBuffer == 1 ) + { + // combine + buffer = (SMeshBufferLightMap*) Mesh[ item[g].index ]->getMeshBuffer( + item[g].index != E_Q3_MESH_FOG ? material : material2 ); + } + + // create a seperate mesh buffer if ( 0 == buffer ) { buffer = new scene::SMeshBufferLightMap(); - Mesh[ toBuffer[g].index ]->addMeshBuffer( buffer ); + Mesh[ item[g].index ]->addMeshBuffer( buffer ); buffer->drop(); - buffer->getMaterial() = material; + buffer->getMaterial() = item[g].index != E_Q3_MESH_FOG ? material : material2; + if ( item[g].index == E_Q3_MESH_GEOMETRY ) + buffer->setHardwareMappingHint ( EHM_STATIC ); } } @@ -859,25 +956,49 @@ void CQ3LevelMesh::constructMesh2() case 4: // billboards break; case 2: // patches - createCurvedSurface2(buffer, i, PatchTesselation,toBuffer[g].takeVertexColor); + createCurvedSurface_bezier( buffer, i, + LoadParam.patchTesselation, + item[g].takeVertexColor + ); break; case 1: // normal polygons case 3: // mesh vertices - index = MeshVerts + face->meshVertIndex; k = buffer->getVertexCount(); - buffer->Indices.reallocate(buffer->getIndexCount()+face->numMeshVerts); + // reallocate better if many small meshes are used + s = buffer->getIndexCount()+face->numMeshVerts; + if ( buffer->Indices.allocated_size () < (u32) s ) + { + if ( buffer->Indices.allocated_size () > 0 && + face->numMeshVerts < 20 && NumFaces > 1000 + ) + { + s = buffer->getIndexCount() + (NumFaces >> 3 * face->numMeshVerts ); + } + buffer->Indices.reallocate( s); + } + for ( j = 0; j < face->numMeshVerts; ++j ) { buffer->Indices.push_back( k + index [j] ); } - buffer->Vertices.reallocate(k+face->numOfVerts); + s = k+face->numOfVerts; + if ( buffer->Vertices.allocated_size () < (u32) s ) + { + if ( buffer->Indices.allocated_size () > 0 && + face->numOfVerts < 20 && NumFaces > 1000 + ) + { + s = buffer->getIndexCount() + (NumFaces >> 3 * face->numOfVerts ); + } + buffer->Vertices.reallocate( s); + } for ( j = 0; j != face->numOfVerts; ++j ) { - copy( &temp[0], &Vertices[ j + face->vertexIndex ], toBuffer[g].takeVertexColor ); + copy( &temp[0], &Vertices[ j + face->vertexIndex ], item[g].takeVertexColor ); buffer->Vertices.push_back( temp[0] ); } break; @@ -885,118 +1006,39 @@ void CQ3LevelMesh::constructMesh2() } // end switch } } + + if ( LoadParam.verbose > 0 ) + { + LoadParam.endTime = os::Timer::getRealTime(); + + snprintf( buf, sizeof ( buf ), + "quake3::constructMesh needed %04d ms to create %d faces, %d vertices,%d mesh vertices", + LoadParam.endTime - LoadParam.startTime, + NumFaces, + NumVertices, + NumMeshVerts + ); + os::Printer::log(buf, ELL_INFORMATION); + } + } -//! constructs a mesh from the quake 3 level file. -void CQ3LevelMesh::constructMesh() -{ - // reserve buffer. - s32 i; // new ISO for scoping problem with some compilers - - for (i=0; i<(NumTextures+1) * (NumLightMaps+1); ++i) - { - scene::SMeshBufferLightMap* buffer = new scene::SMeshBufferLightMap(); - - buffer->Material.MaterialType = video::EMT_LIGHTMAP_M4; - buffer->Material.Wireframe = false; - buffer->Material.Lighting = false; - - Mesh[0]->addMeshBuffer(buffer); - - buffer->drop(); - } - - // go through all faces and add them to the buffer. - - video::S3DVertex2TCoords temp[3]; - - for (i=0; i NumLightMaps-1) - Faces[i].lightmapID = -1; - - // there are lightmapsids and textureid with -1 - s32 meshBufferIndex = ((Faces[i].lightmapID+1) * (NumTextures+1)) + (Faces[i].textureID+1); - SMeshBufferLightMap* meshBuffer = ((SMeshBufferLightMap*)Mesh[0]->getMeshBuffer(meshBufferIndex)); - - switch(Faces[i].type) - { - //case 3: // mesh vertices - case 1: // normal polygons - { - meshBuffer->Vertices.reallocate(meshBuffer->getVertexCount()+3*Faces[i].numMeshVerts); - meshBuffer->Indices.reallocate(meshBuffer->getIndexCount()+3*Faces[i].numMeshVerts); - for (s32 tf=0; tfgetVertexCount(); - s32 vidxes[3]; - - vidxes[0] = MeshVerts[Faces[i].meshVertIndex + tf +0] - + Faces[i].vertexIndex; - vidxes[1] = MeshVerts[Faces[i].meshVertIndex + tf +1] - + Faces[i].vertexIndex; - vidxes[2] = MeshVerts[Faces[i].meshVertIndex + tf +2] - + Faces[i].vertexIndex; - - // add all three vertices - copy( &temp[0], &Vertices[ vidxes[0] ], 0 ); - copy( &temp[1], &Vertices[ vidxes[1] ], 0 ); - copy( &temp[2], &Vertices[ vidxes[2] ], 0 ); - - meshBuffer->Vertices.push_back( temp[0] ); - meshBuffer->Vertices.push_back( temp[1] ); - meshBuffer->Vertices.push_back( temp[2] ); - - // add indexes - - meshBuffer->Indices.push_back(idx); - meshBuffer->Indices.push_back(idx+1); - meshBuffer->Indices.push_back(idx+2); - } - } - break; - case 2: // curved surfaces - createCurvedSurface(meshBuffer, i); - break; - - case 4: // billboards - break; - } // end switch - } -} - - -// helper method for creating curved surfaces, sent in by Dean P. Macri. -inline f32 CQ3LevelMesh::Blend( const f64 s[3], const f64 t[3], const tBSPVertex *v[9], int offset) -{ - f64 res = 0.0; - f32 *ptr; - - for( int i=0; i<3; ++i ) - { - for( int j=0; j<3; ++j ) - { - ptr = (f32 *)( (char*)v[i*3+j] + offset ); - res += s[i] * t[j] * (*ptr); - } - } - - return (f32) res; -} - - -void CQ3LevelMesh::S3DVertex2TCoords_64::copyto( video::S3DVertex2TCoords &dest ) const +void CQ3LevelMesh::S3DVertex2TCoords_64::copy( video::S3DVertex2TCoords &dest ) const { +#if defined (TJUNCTION_SOLVER_ROUND) dest.Pos.X = core::round_( (f32) Pos.X ); dest.Pos.Y = core::round_( (f32) Pos.Y ); dest.Pos.Z = core::round_( (f32) Pos.Z ); - //dest.Pos.X = (f32) Pos.X; - //dest.Pos.Y = (f32) Pos.Y; - //dest.Pos.Z = (f32) Pos.Z; +#elif defined (TJUNCTION_SOLVER_0125) + dest.Pos.X = (f32) ( floor ( Pos.X * 8.f + 0.5 ) * 0.125 ); + dest.Pos.Y = (f32) ( floor ( Pos.Y * 8.f + 0.5 ) * 0.125 ); + dest.Pos.Z = (f32) ( floor ( Pos.Z * 8.f + 0.5 ) * 0.125 ); +#else + dest.Pos.X = (f32) Pos.X; + dest.Pos.Y = (f32) Pos.Y; + dest.Pos.Z = (f32) Pos.Z; +#endif dest.Normal.X = (f32) Normal.X; dest.Normal.Y = (f32) Normal.Y; @@ -1015,12 +1057,19 @@ void CQ3LevelMesh::S3DVertex2TCoords_64::copyto( video::S3DVertex2TCoords &dest void CQ3LevelMesh::copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, s32 vertexcolor ) const { - //dest->Pos.X = core::round( source->vPosition[0] ); - //dest->Pos.Y = core::round( source->vPosition[2] ); - //dest->Pos.Z = core::round( source->vPosition[1] ); +#if defined (TJUNCTION_SOLVER_ROUND) + dest->Pos.X = core::round_( source->vPosition[0] ); + dest->Pos.Y = core::round_( source->vPosition[2] ); + dest->Pos.Z = core::round_( source->vPosition[1] ); +#elif defined (TJUNCTION_SOLVER_0125) + dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 ); + dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 ); + dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 ); +#else dest->Pos.X = source->vPosition[0]; dest->Pos.Y = source->vPosition[2]; dest->Pos.Z = source->vPosition[1]; +#endif dest->Normal.X = source->vNormal[0]; dest->Normal.Y = source->vNormal[2]; @@ -1034,10 +1083,11 @@ void CQ3LevelMesh::copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, if ( vertexcolor ) { - u32 a = core::s32_min( source->color[3] * quake3::defaultModulate, 255 ); - u32 r = core::s32_min( source->color[0] * quake3::defaultModulate, 255 ); - u32 g = core::s32_min( source->color[1] * quake3::defaultModulate, 255 ); - u32 b = core::s32_min( source->color[2] * quake3::defaultModulate, 255 ); + //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 ); + u32 a = source->color[3]; + u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 ); + u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 ); + u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 ); dest->Color.set(a * 1.f/255.f, r * 1.f/255.f, g * 1.f/255.f, b * 1.f/255.f); @@ -1051,13 +1101,19 @@ void CQ3LevelMesh::copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, inline void CQ3LevelMesh::copy( video::S3DVertex2TCoords * dest, const tBSPVertex * source, s32 vertexcolor ) const { +#if defined (TJUNCTION_SOLVER_ROUND) dest->Pos.X = core::round_( source->vPosition[0] ); dest->Pos.Y = core::round_( source->vPosition[2] ); dest->Pos.Z = core::round_( source->vPosition[1] ); - - //dest->Pos.X = source->vPosition[0]; - //dest->Pos.Y = source->vPosition[2]; - //dest->Pos.Z = source->vPosition[1]; +#elif defined (TJUNCTION_SOLVER_0125) + dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 ); + dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 ); + dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 ); +#else + dest->Pos.X = source->vPosition[0]; + dest->Pos.Y = source->vPosition[2]; + dest->Pos.Z = source->vPosition[1]; +#endif dest->Normal.X = source->vNormal[0]; dest->Normal.Y = source->vNormal[2]; @@ -1071,16 +1127,17 @@ inline void CQ3LevelMesh::copy( video::S3DVertex2TCoords * dest, const tBSPVerte if ( vertexcolor ) { - u32 a = core::s32_min( source->color[3] * quake3::defaultModulate, 255 ); - u32 r = core::s32_min( source->color[0] * quake3::defaultModulate, 255 ); - u32 g = core::s32_min( source->color[1] * quake3::defaultModulate, 255 ); - u32 b = core::s32_min( source->color[2] * quake3::defaultModulate, 255 ); + //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 ); + u32 a = source->color[3]; + u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 ); + u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 ); + u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 ); - dest->Color.color = a << 24 | r << 16 | g << 8 | b; + dest->Color.set(a << 24 | r << 16 | g << 8 | b); } else { - dest->Color.color = 0xFFFFFFFF; + dest->Color.set(0xFFFFFFFF); } } @@ -1094,7 +1151,7 @@ void CQ3LevelMesh::SBezier::tesselate( s32 level ) column[1].set_used( level + 1 ); column[2].set_used( level + 1 ); - const f64 w = 0.0 + core::reciprocal( (f32) level ); + const f64 w = 0.0 + (1.0 / (f64) level ); //Tesselate along the columns for( j = 0; j <= level; ++j) @@ -1116,7 +1173,7 @@ void CQ3LevelMesh::SBezier::tesselate( s32 level ) for( k = 0; k <= level; ++k) { f = column[0][j].getInterpolated_quadratic(column[1][j], column[2][j], w * (f64) k); - f.copyto( v ); + f.copy( v ); Patch->Vertices.push_back( v ); } } @@ -1144,7 +1201,7 @@ void CQ3LevelMesh::SBezier::tesselate( s32 level ) /*! no subdivision */ -void CQ3LevelMesh::createCurvedSurface3(SMeshBufferLightMap* meshBuffer, +void CQ3LevelMesh::createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor) @@ -1155,6 +1212,8 @@ void CQ3LevelMesh::createCurvedSurface3(SMeshBufferLightMap* meshBuffer, // number of control points across & up const u32 controlWidth = face->size[0]; const u32 controlHeight = face->size[1]; + if ( 0 == controlWidth || 0 == controlHeight ) + return; video::S3DVertex2TCoords v; @@ -1186,11 +1245,12 @@ void CQ3LevelMesh::createCurvedSurface3(SMeshBufferLightMap* meshBuffer, /*! */ -void CQ3LevelMesh::createCurvedSurface2(SMeshBufferLightMap* meshBuffer, +void CQ3LevelMesh::createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor) { + tBSPFace * face = &Faces[faceIndex]; u32 j,k; @@ -1198,10 +1258,18 @@ void CQ3LevelMesh::createCurvedSurface2(SMeshBufferLightMap* meshBuffer, const u32 controlWidth = face->size[0]; const u32 controlHeight = face->size[1]; + if ( 0 == controlWidth || 0 == controlHeight ) + return; + // number of biquadratic patches const u32 biquadWidth = (controlWidth - 1)/2; const u32 biquadHeight = (controlHeight -1)/2; + if ( LoadParam.verbose > 1 ) + { + LoadParam.startTime = os::Timer::getRealTime(); + } + // Create space for a temporary array of the patch's control points core::array controlPoint; controlPoint.set_used( controlWidth * controlHeight ); @@ -1274,159 +1342,58 @@ void CQ3LevelMesh::createCurvedSurface2(SMeshBufferLightMap* meshBuffer, } delete Bezier.Patch; + + if ( LoadParam.verbose > 1 ) + { + LoadParam.endTime = os::Timer::getRealTime(); + + snprintf( buf, sizeof ( buf ), + "quake3::createCurvedSurface_bezier needed %04d ms to create bezier patch.(%dx%d)", + LoadParam.endTime - LoadParam.startTime, + biquadWidth, + biquadHeight + ); + os::Printer::log(buf, ELL_INFORMATION); + } + } -void CQ3LevelMesh::createCurvedSurface(SMeshBufferLightMap* meshBuffer, s32 i) + +/*! + Loads entities from file +*/ +void CQ3LevelMesh::getConfiguration( io::IReadFile* file ) { - // this implementation for loading curved surfaces was - // sent in by Dean P. Macri. It was a little bit modified - // by me afterwards. - s32 idx; - s32 cpidx[9]; + tBSPLump l; + l.offset = file->getPos(); + l.length = file->getSize (); - const tBSPVertex *v[9]; - video::S3DVertex2TCoords currentVertex[4]; + core::array entity; + entity.set_used( l.length + 2 ); + entity[l.length + 1 ] = 0; - for( s32 row=0; rowseek(l.offset); + file->read( entity.pointer(), l.length); - // For some reason if we tesselate more than this (3x3), - // some of the patches don't show up! + parser_parse( entity.pointer(), l.length, &CQ3LevelMesh::scriptcallback_config ); - f64 s; - f64 t; - f64 cs[3], ct[3], nxs[3], nxt[3]; - - s32 srun = 3; - s32 trun = 3; - const f64 sstep = 1.0 / (f64) srun; - const f64 tstep = 1.0 / (f64) trun; - - v[0] = &Vertices[cpidx[0]]; - v[1] = &Vertices[cpidx[1]]; - v[2] = &Vertices[cpidx[2]]; - v[3] = &Vertices[cpidx[3]]; - v[4] = &Vertices[cpidx[4]]; - v[5] = &Vertices[cpidx[5]]; - v[6] = &Vertices[cpidx[6]]; - v[7] = &Vertices[cpidx[7]]; - v[8] = &Vertices[cpidx[8]]; - - - s32 dos; - s32 dot; - for( dos = 0, s = 0; dos != srun; dos +=1, s+= sstep ) - { - cs[0] = (1.0-s)*(1.0-s); - cs[1] = 2.0 * (1.0 - s) * s; - cs[2] = s * s; - nxs[0] = (1.0-s-sstep)*(1.0-s-sstep); - nxs[1] = 2.0 * (1.0 - s -sstep) * (s+sstep); - nxs[2] = (s+sstep) * (s+sstep); - - for( dot = 0, t = 0; dot != trun; dot += 1, t += tstep ) - { - idx = meshBuffer->getVertexCount(); - ct[0] = (1.0-t)*(1.0-t); - ct[1] = 2.0 * (1.0 - t) * t; - ct[2] = t * t; - nxt[0] = (1.0-t-tstep)*(1.0-t-tstep); - nxt[1] = 2.0 * (1.0 - t - tstep) * (t+tstep); - nxt[2] = (t+tstep) * (t+tstep); - - // Vert 1 - currentVertex[0].Color.set(255,255,255,255); - currentVertex[0].Pos.X = floorf( Blend( cs, ct, v, (char*)&v[0]->vPosition[0] - (char*)v[0])+ 0.5f); - currentVertex[0].Pos.Y = floorf( Blend( cs, ct, v, (char*)&v[0]->vPosition[2] - (char*)v[0])+ 0.5f); - currentVertex[0].Pos.Z = floorf( Blend( cs, ct, v, (char*)&v[0]->vPosition[1] - (char*)v[0])+ 0.5f); - currentVertex[0].Normal.X = Blend( cs, ct, v, (char*)&v[0]->vNormal[0] - (char*)v[0]); - currentVertex[0].Normal.Y = Blend( cs, ct, v, (char*)&v[0]->vNormal[2] - (char*)v[0]); - currentVertex[0].Normal.Z = Blend( cs, ct, v, (char*)&v[0]->vNormal[1] - (char*)v[0]); - currentVertex[0].TCoords.X = Blend( cs, ct, v, (char*)&v[0]->vTextureCoord[0] - (char*)v[0]); - currentVertex[0].TCoords.Y = Blend( cs, ct, v, (char*)&v[0]->vTextureCoord[1] - (char*)v[0]); - currentVertex[0].TCoords2.X = Blend( cs, ct, v, (char*)&v[0]->vLightmapCoord[0] - (char*)v[0]); - currentVertex[0].TCoords2.Y = Blend( cs, ct, v, (char*)&v[0]->vLightmapCoord[1] - (char*)v[0]); - // Vert 2 - currentVertex[1].Color.set(255,255,255,255); - currentVertex[1].Pos.X = floorf( Blend( cs, nxt, v, (char*)&v[0]->vPosition[0] - (char*)v[0])+ 0.5f); - currentVertex[1].Pos.Y = floorf( Blend( cs, nxt, v, (char*)&v[0]->vPosition[2] - (char*)v[0])+ 0.5f); - currentVertex[1].Pos.Z = floorf( Blend( cs, nxt, v, (char*)&v[0]->vPosition[1] - (char*)v[0])+ 0.5f); - currentVertex[1].Normal.X = Blend( cs, nxt, v, (char*)&v[0]->vNormal[0] - (char*)v[0]); - currentVertex[1].Normal.Y = Blend( cs, nxt, v, (char*)&v[0]->vNormal[2] - (char*)v[0]); - currentVertex[1].Normal.Z = Blend( cs, nxt, v, (char*)&v[0]->vNormal[1] - (char*)v[0]); - currentVertex[1].TCoords.X = Blend( cs, nxt, v, (char*)&v[0]->vTextureCoord[0] - (char*)v[0]); - currentVertex[1].TCoords.Y = Blend( cs, nxt, v, (char*)&v[0]->vTextureCoord[1] - (char*)v[0]); - currentVertex[1].TCoords2.X = Blend( cs, nxt, v, (char*)&v[0]->vLightmapCoord[0] - (char*)v[0]); - currentVertex[1].TCoords2.Y = Blend( cs, nxt, v, (char*)&v[0]->vLightmapCoord[1] - (char*)v[0]); - // Vert 3 - currentVertex[2].Color.set(255,255,255,255); - currentVertex[2].Pos.X = floorf( Blend( nxs, ct, v, (char*)&v[0]->vPosition[0] - (char*)v[0])+ 0.5f); - currentVertex[2].Pos.Y = floorf( Blend( nxs, ct, v, (char*)&v[0]->vPosition[2] - (char*)v[0])+ 0.5f); - currentVertex[2].Pos.Z = floorf( Blend( nxs, ct, v, (char*)&v[0]->vPosition[1] - (char*)v[0])+ 0.5f); - currentVertex[2].Normal.X = Blend( nxs, ct, v, (char*)&v[0]->vNormal[0] - (char*)v[0]); - currentVertex[2].Normal.Y = Blend( nxs, ct, v, (char*)&v[0]->vNormal[2] - (char*)v[0]); - currentVertex[2].Normal.Z = Blend( nxs, ct, v, (char*)&v[0]->vNormal[1] - (char*)v[0]); - currentVertex[2].TCoords.X = Blend( nxs, ct, v, (char*)&v[0]->vTextureCoord[0] - (char*)v[0]); - currentVertex[2].TCoords.Y = Blend( nxs, ct, v, (char*)&v[0]->vTextureCoord[1] - (char*)v[0]); - currentVertex[2].TCoords2.X = Blend( nxs, ct, v, (char*)&v[0]->vLightmapCoord[0] - (char*)v[0]); - currentVertex[2].TCoords2.Y = Blend( nxs, ct, v, (char*)&v[0]->vLightmapCoord[1] - (char*)v[0]); - // Vert 4 - currentVertex[3].Color.set(255,255,255,255); - currentVertex[3].Pos.X = floorf(Blend( nxs, nxt, v, (char*)&v[0]->vPosition[0] - (char*)v[0])+ 0.5f); - currentVertex[3].Pos.Y = floorf(Blend( nxs, nxt, v, (char*)&v[0]->vPosition[2] - (char*)v[0])+ 0.5f); - currentVertex[3].Pos.Z = floorf(Blend( nxs, nxt, v, (char*)&v[0]->vPosition[1] - (char*)v[0])+ 0.5f); - currentVertex[3].Normal.X = Blend( nxs, nxt, v, (char*)&v[0]->vNormal[0] - (char*)v[0]); - currentVertex[3].Normal.Y = Blend( nxs, nxt, v, (char*)&v[0]->vNormal[2] - (char*)v[0]); - currentVertex[3].Normal.Z = Blend( nxs, nxt, v, (char*)&v[0]->vNormal[1] - (char*)v[0]); - currentVertex[3].TCoords.X = Blend( nxs, nxt, v, (char*)&v[0]->vTextureCoord[0] - (char*)v[0]); - currentVertex[3].TCoords.Y = Blend( nxs, nxt, v, (char*)&v[0]->vTextureCoord[1] - (char*)v[0]); - currentVertex[3].TCoords2.X = Blend( nxs, nxt, v, (char*)&v[0]->vLightmapCoord[0] - (char*)v[0]); - currentVertex[3].TCoords2.Y = Blend( nxs, nxt, v, (char*)&v[0]->vLightmapCoord[1] - (char*)v[0]); - // Put the vertices in the mesh buffer - meshBuffer->Vertices.push_back(currentVertex[0]); - meshBuffer->Vertices.push_back(currentVertex[2]); - meshBuffer->Vertices.push_back(currentVertex[1]); - - meshBuffer->Vertices.push_back(currentVertex[3]); - - // add indexes - meshBuffer->Indices.push_back(idx); - meshBuffer->Indices.push_back(idx+1); - meshBuffer->Indices.push_back(idx+2); - // add indexes - meshBuffer->Indices.push_back(idx+2); - meshBuffer->Indices.push_back(idx+1); - meshBuffer->Indices.push_back(idx+3); - } - } - } - } + if ( Entity.size () ) + Entity.getLast().name = file->getFileName(); } //! get's an interface to the entities -const quake3::tQ3EntityList & CQ3LevelMesh::getEntityList() +tQ3EntityList & CQ3LevelMesh::getEntityList() { - Entity.sort(); +// Entity.sort(); return Entity; } /*! */ -const quake3::SShader * CQ3LevelMesh::getShader(u32 index) const +const IShader * CQ3LevelMesh::getShader(u32 index) const { index &= 0xFFFF; @@ -1439,23 +1406,36 @@ const quake3::SShader * CQ3LevelMesh::getShader(u32 index) const } -//! loads the shader definition -const quake3::SShader * CQ3LevelMesh::getShader( const c8 * filename, bool fileNameIsValid ) +/*! + loads the shader definition +*/ +const IShader* CQ3LevelMesh::getShader( const c8 * filename, bool fileNameIsValid ) { - quake3::SShader search; - search.name = filename; - search.name.replace( '\\', '/' ); + core::stringc searchName ( filename ); + IShader search; + search.name = searchName; + search.name.replace( '\\', '/' ); + search.name.make_lower(); + + + core::stringc message; s32 index; //! is Shader already in cache? index = Shader.linear_search( search ); if ( index >= 0 ) { + if ( LoadParam.verbose > 1 ) + { + message = searchName + " found " + Shader[index].name; + os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION); + } + return &Shader[index]; } - core::stringc loadFile; + io::path loadFile; if ( !fileNameIsValid ) { @@ -1466,7 +1446,7 @@ const quake3::SShader * CQ3LevelMesh::getShader( const c8 * filename, bool fileN s32 end = cut.findLast( '/' ); s32 start = cut.findLast( '/', end - 1 ); - loadFile = "scripts"; + loadFile = LoadParam.scriptDir; loadFile.append( cut.subString( start, end - start ) ); loadFile.append( ".shader" ); } @@ -1484,36 +1464,55 @@ const quake3::SShader * CQ3LevelMesh::getShader( const c8 * filename, bool fileN ShaderFile.push_back( loadFile ); if ( !FileSystem->existFile( loadFile.c_str() ) ) + { + if ( LoadParam.verbose > 1 ) + { + message = loadFile + " for " + searchName + " failed "; + os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION); + } return 0; + } + + if ( LoadParam.verbose ) + { + message = loadFile + " for " + searchName; + os::Printer::log("quake3:getShader Load shader", message.c_str(), ELL_INFORMATION); + } + io::IReadFile *file = FileSystem->createAndOpenFile( loadFile.c_str() ); - if ( 0 == file ) - return 0; + if ( file ) + { + getShader ( file ); + file->drop (); + } - core::stringc message; - message = loadFile + " for " + core::stringc( filename ); - os::Printer::log("Loaded shader", message.c_str(), ELL_INFORMATION); + + // search again + index = Shader.linear_search( search ); + return index >= 0 ? &Shader[index] : 0; +} + +/*! + loads the shader definition +*/ +void CQ3LevelMesh::getShader( io::IReadFile* file ) +{ + if ( 0 == file ) + return; // load script core::array script; const long len = file->getSize(); script.set_used( len + 2 ); - script[ len + 1 ] = 0; file->seek( 0 ); file->read( script.pointer(), len ); - file->drop(); + script[ len + 1 ] = 0; // start a parser instance parser_parse( script.pointer(), len, &CQ3LevelMesh::scriptcallback_shader ); - - // search again - index = Shader.linear_search( search ); - if ( index >= 0 ) - return &Shader[index]; - - return 0; } @@ -1522,21 +1521,52 @@ void CQ3LevelMesh::InitShader() { ReleaseShader(); - quake3::SShader element; + IShader element; - quake3::SVarGroup group; - quake3::SVariable variable; + SVarGroup group; + SVariable variable ( "noshader" ); - variable.name = "noshader"; group.Variable.push_back( variable ); - element.VarGroup = new quake3::SVarGroupList(); + element.VarGroup = new SVarGroupList(); element.VarGroup->VariableGroup.push_back( group ); - element.name = element.VarGroup->VariableGroup[0].Variable[0].name.c_str(); + element.VarGroup->VariableGroup.push_back( SVarGroup() ); + element.name = element.VarGroup->VariableGroup[0].Variable[0].name; + element.ID = Shader.size(); Shader.push_back( element ); - // load common named shader - getShader("scripts/common.shader"); + if ( LoadParam.loadAllShaders ) + { + io::EFileSystemType current = FileSystem->setFileListSystem ( io::FILESYSTEM_VIRTUAL ); + io::path save = FileSystem->getWorkingDirectory(); + + io::path newDir; + newDir = "/"; + newDir += LoadParam.scriptDir; + newDir += "/"; + FileSystem->changeWorkingDirectoryTo ( newDir.c_str() ); + + core::stringc s; + io::IFileList *fileList = FileSystem->createFileList (); + for (u32 i=0; i< fileList->getFileCount(); ++i) + { + s = fileList->getFullFileName(i); + if ( s.find ( ".shader" ) >= 0 ) + { + if ( 0 == LoadParam.loadSkyShader && s.find ( "sky.shader" ) >= 0 ) + { + } + else + { + getShader ( s.c_str () ); + } + } + } + fileList->drop (); + + FileSystem->changeWorkingDirectoryTo ( save ); + FileSystem->setFileListSystem ( current ); + } } @@ -1553,6 +1583,8 @@ void CQ3LevelMesh::ReleaseShader() } +/*! +*/ void CQ3LevelMesh::ReleaseEntity() { for ( u32 i = 0; i!= Entity.size(); ++i ) @@ -1563,219 +1595,252 @@ void CQ3LevelMesh::ReleaseEntity() } -// entity only has only one valid level.. and no assoziative name.. -void CQ3LevelMesh::scriptcallback_entity( quake3::SVarGroupList *& grouplist ) +// config in simple (quake3) and advanced style +void CQ3LevelMesh::scriptcallback_config( SVarGroupList *& grouplist, eToken token ) { - quake3::SEntity element; + IShader element; - if ( grouplist->VariableGroup.size() != 2 ) - return; + if ( token == Q3_TOKEN_END_LIST ) + { + if ( 0 == grouplist->VariableGroup[0].Variable.size() ) + return; - element.name = grouplist->VariableGroup[1].get( "classname" ); + element.name = grouplist->VariableGroup[0].Variable[0].name; + } + else + { + if ( grouplist->VariableGroup.size() != 2 ) + return; + + element.name = "configuration"; + } grouplist->grab(); element.VarGroup = grouplist; - element.id = Shader.size(); + element.ID = Entity.size(); + Entity.push_back( element ); +} + + +// entity only has only one valid level.. and no assoziative name.. +void CQ3LevelMesh::scriptcallback_entity( SVarGroupList *& grouplist, eToken token ) +{ + if ( token != Q3_TOKEN_END_LIST || grouplist->VariableGroup.size() != 2 ) + return; + + grouplist->grab(); + + IEntity element; + element.VarGroup = grouplist; + element.ID = Entity.size(); + element.name = grouplist->VariableGroup[1].get( "classname" ); + Entity.push_back( element ); } //!. script callback for shaders -void CQ3LevelMesh::scriptcallback_shader( quake3::SVarGroupList *& grouplist ) +void CQ3LevelMesh::scriptcallback_shader( SVarGroupList *& grouplist,eToken token ) { - quake3::SShader element; - - // TODO: There might be something wrong with this fix, but it avoids a core dump... - if (grouplist->VariableGroup[0].Variable.size()==0) + if ( token != Q3_TOKEN_END_LIST || grouplist->VariableGroup[0].Variable.size()==0) return; - // end fix + + + IShader element; grouplist->grab(); - element.VarGroup = grouplist; - element.name = element.VarGroup->VariableGroup[0].Variable[0].name.c_str(); - element.id = Shader.size(); - + element.name = element.VarGroup->VariableGroup[0].Variable[0].name; + element.ID = Shader.size(); +/* + core::stringc s; + dumpShader ( s, &element ); + printf ( s.c_str () ); +*/ Shader.push_back( element ); } +/*! + delete all buffers without geometry in it. +*/ +void CQ3LevelMesh::cleanMeshes() +{ + if ( 0 == LoadParam.cleanUnResolvedMeshes ) + return; + + // delete all buffers without geometry in it. + u32 run = 0; + u32 remove = 0; + + irr::scene::SMesh *m; + IMeshBuffer *b; + for ( u32 g = 0; g < E_Q3_MESH_SIZE; ++g ) + { + bool texture0important = ( g == 0 ); + + run = 0; + remove = 0; + m = Mesh[g]; + if ( LoadParam.verbose > 0 ) + { + LoadParam.startTime = os::Timer::getRealTime(); + if ( LoadParam.verbose > 1 ) + { + snprintf( buf, sizeof ( buf ), + "quake3::cleanMeshes%d start for %d meshes", + g, + m->MeshBuffers.size() + ); + os::Printer::log(buf, ELL_INFORMATION); + } + } + + u32 i = 0; + s32 blockstart = -1; + s32 blockcount; + + while( i < m->MeshBuffers.size()) + { + run += 1; + + b = m->MeshBuffers[i]; + + if ( b->getVertexCount() == 0 || b->getIndexCount() == 0 || + ( texture0important && b->getMaterial().getTexture(0) == 0 ) + ) + { + if ( blockstart < 0 ) + { + blockstart = i; + blockcount = 0; + } + blockcount += 1; + i += 1; + + // delete Meshbuffer + i -= 1; + remove += 1; + b->drop(); + m->MeshBuffers.erase(i); + } + else + { + // clean blockwise + if ( blockstart >= 0 ) + { + if ( LoadParam.verbose > 1 ) + { + snprintf( buf, sizeof ( buf ), + "quake3::cleanMeshes%d cleaning mesh %d %d size", + g, + blockstart, + blockcount + ); + os::Printer::log(buf, ELL_INFORMATION); + } + blockstart = -1; + } + i += 1; + } + } + + if ( LoadParam.verbose > 0 ) + { + LoadParam.endTime = os::Timer::getRealTime(); + snprintf( buf, sizeof ( buf ), + "quake3::cleanMeshes%d needed %04d ms to clean %d of %d meshes", + g, + LoadParam.endTime - LoadParam.startTime, + remove, + run + ); + os::Printer::log(buf, ELL_INFORMATION); + } + } +} + + +// recalculate bounding boxes +void CQ3LevelMesh::calcBoundingBoxes() +{ + if ( LoadParam.verbose > 0 ) + { + LoadParam.startTime = os::Timer::getRealTime(); + + if ( LoadParam.verbose > 1 ) + { + snprintf( buf, sizeof ( buf ), + "quake3::calcBoundingBoxes start create %d textures and %d lightmaps", + NumTextures, + NumLightMaps + ); + os::Printer::log(buf, ELL_INFORMATION); + } + } + + // create bounding box + for ( u32 g = 0; g != E_Q3_MESH_SIZE; ++g ) + { + for ( u32 j=0; j < Mesh[g]->MeshBuffers.size(); ++j) + { + ((SMeshBufferLightMap*)Mesh[g]->MeshBuffers[j])->recalculateBoundingBox(); + } + + Mesh[g]->recalculateBoundingBox(); + // Mesh[0] is the main bbox + if (g!=0) + Mesh[0]->BoundingBox.addInternalBox(Mesh[g]->getBoundingBox()); + } + + if ( LoadParam.verbose > 0 ) + { + LoadParam.endTime = os::Timer::getRealTime(); + + snprintf( buf, sizeof ( buf ), + "quake3::calcBoundingBoxes needed %04d ms to create %d textures and %d lightmaps", + LoadParam.endTime - LoadParam.startTime, + NumTextures, + NumLightMaps + ); + os::Printer::log( buf, ELL_INFORMATION); + } +} + + //! loads the textures void CQ3LevelMesh::loadTextures() { if (!Driver) return; - core::stringc s; - core::stringc extensions[2]; - extensions[0] = ".jpg"; - extensions[1] = ".tga"; - - // load textures - - core::array tex; - tex.set_used(NumTextures+1); - - tex[0] = 0; - - s32 t;// new ISO for scoping problem with some compilers - - for (t=1; t<(NumTextures+1); ++t) + if ( LoadParam.verbose > 0 ) { - tex[t] = 0; + LoadParam.startTime = os::Timer::getRealTime(); - if ( !tex[t] ) + if ( LoadParam.verbose > 1 ) { - for (s32 e=0; e<2; ++e) - { - s = Textures[t-1].strName; - s.append(extensions[e]); - if (FileSystem->existFile(s.c_str())) - { - tex[t] = Driver->getTexture(s.c_str()); - break; - } - } - } - if (!tex[t]) - { - os::Printer::log("Q3: no texmap for texturename ", Textures[t-1].strName, ELL_WARNING); + snprintf( buf, sizeof ( buf ), + "quake3::loadTextures start create %d textures and %d lightmaps", + NumTextures, + NumLightMaps + ); + os::Printer::log( buf, ELL_INFORMATION); } } - // load lightmaps. - core::array lig; - lig.set_used(NumLightMaps+1); - - lig[0] = 0; c8 lightmapname[255]; - core::dimension2d lmapsize(128,128); - - //bool oldMipMapState = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); - //Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); - - video::IImage* lmapImg; - for (t=1; t<(NumLightMaps+1); ++t) - { - sprintf(lightmapname, "%s.lightmap.%d", LevelName.c_str(), t); - - // lightmap is a CTexture::R8G8B8 format - lmapImg = Driver->createImageFromData( - video::ECF_R8G8B8, - lmapsize, - LightMaps[t-1].imageBits, true, false ); - - lig[t] = Driver->addTexture( lightmapname, lmapImg ); - lmapImg->drop(); - - } - //Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); - - - // attach textures to materials. - for (s32 l=0; lgetMeshBuffer(l*(NumTextures+1) + t); - b->Material.setTexture(1, lig[l]); - b->Material.setTexture(0, tex[t]); - - if (!b->Material.getTexture(1)) - b->Material.MaterialType = video::EMT_SOLID; - - if (!b->Material.getTexture(0)) - b->Material.MaterialType = video::EMT_SOLID; - } - } -} - - -// delete all buffers without geometry in it. -void CQ3LevelMesh::cleanMeshes() -{ - // delete all buffers without geometry in it. - for ( u32 g = 0; g < quake3::E_Q3_MESH_SIZE; ++g ) - { - u32 i = 0; - bool texture0important = ( g == 0 ); - while(i < Mesh[g]->MeshBuffers.size()) - { - if (Mesh[g]->MeshBuffers[i]->getVertexCount() == 0 || - Mesh[g]->MeshBuffers[i]->getIndexCount() == 0 || - ( texture0important && Mesh[g]->MeshBuffers[i]->getMaterial().getTexture(0) == 0 ) - ) - { - // delete Meshbuffer - Mesh[g]->MeshBuffers[i]->drop(); - Mesh[g]->MeshBuffers.erase(i); - } - else - ++i; - } - } -} - - -// recalculate bounding boxes -void CQ3LevelMesh::calcBoundingBoxes() -{ - // create bounding box - for ( u32 g = 0; g != quake3::E_Q3_MESH_SIZE; ++g ) - { - for ( u32 j=0; j < Mesh[g]->MeshBuffers.size(); ++j) - { - ((SMeshBufferLightMap*)Mesh[g]->MeshBuffers[j])->recalculateBoundingBox(); - } - - Mesh[g]->recalculateBoundingBox(); - } - -} - -/* -//! loads a texture -video::ITexture* CQ3LevelMesh::loadTexture( const tStringList &stringList ) -{ - static const char * extension[2] = - { - ".jpg", - ".tga" - }; - - core::stringc loadFile; - for ( u32 i = 0; i!= stringList.size(); ++i ) - { - for ( u32 g = 0; g != 2 ; ++g ) - { - cutFilenameExtension( loadFile, stringList[i] ).append( extension[g] ); - - if ( FileSystem->existFile( loadFile.c_str() ) ) - { - video::ITexture* t = Driver->getTexture( loadFile.c_str() ); - if ( t ) - return t; - } - } - } - return 0; -} -*/ - -//! loads the textures -void CQ3LevelMesh::loadTextures2() -{ - if (!Driver) - return; - s32 t; // load lightmaps. Lightmap.set_used(NumLightMaps+1); - c8 lightmapname[255]; - core::dimension2d lmapsize(128,128); +/* + bool oldMipMapState = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); +*/ + core::dimension2d lmapsize(128,128); video::IImage* lmapImg; for ( t = 0; t < NumLightMaps ; ++t) @@ -1784,23 +1849,23 @@ void CQ3LevelMesh::loadTextures2() // lightmap is a CTexture::R8G8B8 format lmapImg = Driver->createImageFromData( - video::ECF_R8G8B8, - lmapsize, - LightMaps[t].imageBits, true, false ); + video::ECF_R8G8B8, lmapsize, + LightMaps[t].imageBits, false, true ); Lightmap[t] = Driver->addTexture( lightmapname, lmapImg ); lmapImg->drop(); - } +// Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); + // load textures Tex.set_used( NumTextures+1 ); - const quake3::SShader * shader; + const IShader* shader; core::stringc list; - core::stringc check; - quake3::tTexArray textureArray; + io::path check; + tTexArray textureArray; // pre-load shaders for ( t=0; t< NumTextures; ++t) @@ -1819,10 +1884,10 @@ void CQ3LevelMesh::loadTextures2() shader = getShader( Textures[t].strName, false); if ( shader ) { - Tex[t].ShaderID = shader->id; + Tex[t].ShaderID = shader->ID; // if texture name == stage1 Texture map - const quake3::SVarGroup * group; + const SVarGroup * group; group = shader->getGroup( 2 ); if ( group ) @@ -1848,23 +1913,36 @@ void CQ3LevelMesh::loadTextures2() } u32 pos = 0; - quake3::getTextures( textureArray, list, pos, FileSystem, Driver ); + getTextures( textureArray, list, pos, FileSystem, Driver ); Tex[t].Texture = textureArray[0]; } + + if ( LoadParam.verbose > 0 ) + { + LoadParam.endTime = os::Timer::getRealTime(); + + snprintf( buf, sizeof ( buf ), + "quake3::loadTextures needed %04d ms to create %d textures and %d lightmaps", + LoadParam.endTime - LoadParam.startTime, + NumTextures, + NumLightMaps + ); + os::Printer::log( buf, ELL_INFORMATION); + } } //! Returns an axis aligned bounding box of the mesh. -//! \return A bounding box of this mesh is returned. const core::aabbox3d& CQ3LevelMesh::getBoundingBox() const { return Mesh[0]->getBoundingBox(); } -void CQ3LevelMesh::setBoundingBox( const core::aabbox3df& box) + +void CQ3LevelMesh::setBoundingBox(const core::aabbox3df& box) { - Mesh[0]->setBoundingBox(box); //? + Mesh[0]->setBoundingBox(box); } diff --git a/src/dep/src/irrlicht/CQ3LevelMesh.h b/src/dep/src/irrlicht/CQ3LevelMesh.h index 864ce72..2868cc2 100644 --- a/src/dep/src/irrlicht/CQ3LevelMesh.h +++ b/src/dep/src/irrlicht/CQ3LevelMesh.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,7 +24,8 @@ namespace scene public: //! constructor - CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr); + CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr, + const quake3::Q3LevelLoadParameter &loadParam); //! destructor virtual ~CQ3LevelMesh(); @@ -43,8 +44,6 @@ namespace scene virtual IMesh* getMesh(s32 frameInMs, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1); - virtual void releaseMesh( s32 index ); - //! Returns an axis aligned bounding box of the mesh. //! \return A bounding box of this mesh is returned. virtual const core::aabbox3d& getBoundingBox() const; @@ -56,15 +55,19 @@ namespace scene virtual E_ANIMATED_MESH_TYPE getMeshType() const; //! loads the shader definition - virtual const quake3::SShader * getShader( const c8 * filename, bool fileNameIsValid=true ); + virtual void getShader( io::IReadFile* file ); + + //! loads the shader definition + virtual const quake3::IShader * getShader( const c8 * filename, bool fileNameIsValid=true ); //! returns a already loaded Shader - virtual const quake3::SShader * getShader( u32 index ) const; + virtual const quake3::IShader * getShader( u32 index ) const; + //! loads a configuration file + virtual void getConfiguration( io::IReadFile* file ); //! get's an interface to the entities - virtual const quake3::tQ3EntityList & getEntityList(); - + virtual quake3::tQ3EntityList & getEntityList(); //Link to held meshes? ... @@ -109,16 +112,11 @@ namespace scene private: - //! constructs a mesh from the quake 3 level file. + void constructMesh(); - - //! loads the textures + void solveTJunction(); void loadTextures(); - void constructMesh2(); - - void loadTextures2(); - struct STexShader { video::ITexture* Texture; @@ -130,30 +128,36 @@ namespace scene enum eLumps { - kEntities = 0, // Stores player/object positions, etc... - kTextures, // Stores texture information - kPlanes, // Stores the splitting planes - kNodes, // Stores the BSP nodes - kLeafs, // Stores the leafs of the nodes - kLeafFaces, // Stores the leaf's indices into the faces - kLeafBrushes, // Stores the leaf's indices into the brushes - kModels, // Stores the info of world models - kBrushes, // Stores the brushes info (for collision) - kBrushSides, // Stores the brush surfaces info - kVertices, // Stores the level vertices - kMeshVerts, // Stores the model vertices offsets - kShaders, // Stores the shader files (blending, anims..) - kFaces, // Stores the faces for the level - kLightmaps, // Stores the lightmaps for the level - kLightVolumes, // Stores extra world lighting information - kVisData, // Stores PVS and cluster info (visibility) - kMaxLumps // A constant to store the number of lumps + kEntities = 0, // Stores player/object positions, etc... + kShaders = 1, // Stores texture information + kPlanes = 2, // Stores the splitting planes + kNodes = 3, // Stores the BSP nodes + kLeafs = 4, // Stores the leafs of the nodes + kLeafFaces = 5, // Stores the leaf's indices into the faces + kLeafBrushes = 6, // Stores the leaf's indices into the brushes + kModels = 7, // Stores the info of world models + kBrushes = 8, // Stores the brushes info (for collision) + kBrushSides = 9, // Stores the brush surfaces info + kVertices = 10, // Stores the level vertices + kMeshVerts = 11, // Stores the model vertices offsets + kFogs = 12, // Stores the shader files (blending, anims..) + kFaces = 13, // Stores the faces for the level + kLightmaps = 14, // Stores the lightmaps for the level + kLightGrid = 15, // Stores extra world lighting information + kVisData = 16, // Stores PVS and cluster info (visibility) + kLightArray = 17, // RBSP + kMaxLumps // A constant to store the number of lumps }; - struct tBSPLump + enum eBspSurfaceType { - s32 offset; - s32 length; + BSP_MST_BAD, + BSP_MST_PLANAR, + BSP_MST_PATCH, + BSP_MST_TRIANGLE_SOUP, + BSP_MST_FLARE, + BSP_MST_FOLIAGE + }; struct tBSPHeader @@ -161,6 +165,14 @@ namespace scene s32 strID; // This should always be 'IBSP' s32 version; // This should be 0x2e for Quake 3 files }; + tBSPHeader header; + + struct tBSPLump + { + s32 offset; + s32 length; + }; + struct tBSPVertex { @@ -174,7 +186,7 @@ namespace scene struct tBSPFace { s32 textureID; // The index into the texture array - s32 effect; // The index for the effects (or -1 = n/a) + s32 fogNum; // The index for the effects (or -1 = n/a) s32 type; // 1=polygon, 2=patch, 3=mesh, 4=billboard s32 vertexIndex; // The index into this face's first vertex s32 numOfVerts; // The number of vertices for this face @@ -258,12 +270,13 @@ namespace scene s32 numOfBrushes; // The number brushes for the model }; - struct tBSPShader + struct tBSPFog { - c8 strName[64]; // The name of the shader file - s32 brushIndex; // The brush index for this shader - s32 unknown; // This is 99% of the time 5 + c8 shader[64]; // The name of the shader file + s32 brushIndex; // The brush index for this shader + s32 visibleSide; // the brush side that ray tests need to clip against (-1 == none }; + core::array < STexShader > FogMap; struct tBSPLights { @@ -287,20 +300,15 @@ namespace scene void loadBrushes (tBSPLump* l, io::IReadFile* file); // load the brushes of the BSP void loadBrushSides (tBSPLump* l, io::IReadFile* file); // load the brushsides of the BSP void loadLeafBrushes(tBSPLump* l, io::IReadFile* file); // load the brushes of the leaf - void loadShaders (tBSPLump* l, io::IReadFile* file); // load the shaders - - // second parameter i is the zero based index of the current face. - void createCurvedSurface(SMeshBufferLightMap* meshBuffer, s32 i); + void loadFogs (tBSPLump* l, io::IReadFile* file); // load the shaders //bi-quadratic bezier patches - void createCurvedSurface2(SMeshBufferLightMap* meshBuffer, + void createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor); - void createCurvedSurface3(SMeshBufferLightMap* meshBuffer, + void createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor); - f32 Blend( const f64 s[3], const f64 t[3], const tBSPVertex *v[9], int offset); - struct S3DVertex2TCoords_64 { core::vector3d Pos; @@ -309,7 +317,7 @@ namespace scene core::vector2d TCoords; core::vector2d TCoords2; - void copyto( video::S3DVertex2TCoords &dest ) const; + void copy( video::S3DVertex2TCoords &dest ) const; S3DVertex2TCoords_64() {} S3DVertex2TCoords_64(const core::vector3d& pos, const core::vector3d& normal, const video::SColorf& color, @@ -348,7 +356,7 @@ namespace scene }; SBezier Bezier; - s32 PatchTesselation; + quake3::Q3LevelLoadParameter LoadParam; tBSPLump Lumps[kMaxLumps]; @@ -409,22 +417,25 @@ namespace scene u32 sourcesize; u32 index; core::stringc token; - u32 tokenresult; + eToken tokenresult; }; SQ3Parser Parser; - typedef void( CQ3LevelMesh::*tParserCallback ) ( quake3::SVarGroupList *& groupList ); + typedef void( CQ3LevelMesh::*tParserCallback ) ( quake3::SVarGroupList *& groupList, eToken token ); void parser_parse( const void * data, u32 size, tParserCallback callback ); void parser_nextToken(); void dumpVarGroup( const quake3::SVarGroup * group, s32 stack ) const; - void scriptcallback_entity( quake3::SVarGroupList *& grouplist ); - quake3::tQ3EntityList Entity; + void scriptcallback_entity( quake3::SVarGroupList *& grouplist, eToken token ); + void scriptcallback_shader( quake3::SVarGroupList *& grouplist, eToken token ); + void scriptcallback_config( quake3::SVarGroupList *& grouplist, eToken token ); + + core::array < quake3::IShader > Shader; + core::array < quake3::IShader > Entity; //quake3::tQ3EntityList Entity; + - void scriptcallback_shader( quake3::SVarGroupList *& grouplist ); - core::array < quake3::SShader > Shader; quake3::tStringList ShaderFile; void InitShader(); void ReleaseShader(); @@ -432,6 +443,7 @@ namespace scene s32 setShaderMaterial( video::SMaterial & material, const tBSPFace * face ) const; + s32 setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const; struct SToBuffer { @@ -440,8 +452,9 @@ namespace scene }; void cleanMeshes(); + void cleanLoader (); void calcBoundingBoxes(); - + c8 buf[128]; }; } // end namespace scene diff --git a/src/dep/src/irrlicht/CQuake3ShaderSceneNode.cpp b/src/dep/src/irrlicht/CQuake3ShaderSceneNode.cpp index 4527c85..c5a0085 100644 --- a/src/dep/src/irrlicht/CQuake3ShaderSceneNode.cpp +++ b/src/dep/src/irrlicht/CQuake3ShaderSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Thomas Alten / Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -20,13 +20,20 @@ namespace irr namespace scene { +// who, if not you.. +using namespace quake3; +/*! +*/ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( scene::ISceneNode* parent, scene::ISceneManager* mgr,s32 id, - io::IFileSystem *fileSystem, scene::IMeshBuffer *buffer, - const quake3::SShader * shader) - : scene::ISceneNode(parent, mgr, id), MeshBuffer(0), Original(0), - Shader(shader), TimeAbs(0.f) + io::IFileSystem *fileSystem, const scene::IMeshBuffer *original, + const IShader * shader) +: scene::IMeshSceneNode(parent, mgr, id, + core::vector3df(0.f, 0.f, 0.f), + core::vector3df(0.f, 0.f, 0.f), + core::vector3df(1.f, 1.f, 1.f)), + Shader(shader), Mesh(0), Original(0), MeshBuffer(0), TimeAbs(0.f) { #ifdef _DEBUG core::stringc dName = "CQuake3ShaderSceneNode "; @@ -35,79 +42,86 @@ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( setDebugName( dName.c_str() ); #endif - MeshBuffer = new SMeshBuffer(); - Original = new SMeshBufferLightMap(); - // name the Scene Node this->Name = Shader->name; + // take lightmap vertex type + MeshBuffer = new SMeshBuffer(); + + Mesh = new SMesh (); + Mesh->addMeshBuffer ( MeshBuffer ); + MeshBuffer->drop (); + + //Original = new SMeshBufferLightMap(); + Original = (const scene::SMeshBufferLightMap*) original; + Original->grab(); + // clone meshbuffer to modifiable buffer - cloneBuffer( static_cast< scene::SMeshBufferLightMap *>( buffer ) ); + cloneBuffer(MeshBuffer, Original, + Original->getMaterial().ColorMask != 0); // load all Textures in all stages loadTextures( fileSystem ); - setAutomaticCulling( scene::EAC_BOX ); + setAutomaticCulling( scene::EAC_OFF ); } +/*! +*/ CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode() { - if (MeshBuffer) - MeshBuffer->drop(); + if (Mesh) + Mesh->drop(); + if (Original) Original->drop(); } + /* create single copies */ -void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBufferLightMap * buffer ) +void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBuffer *dest, const scene::SMeshBufferLightMap * buffer, bool translateCenter ) { - Original->Material = buffer->Material; - MeshBuffer->Material = buffer->Material; - - Original->Indices = buffer->Indices; - MeshBuffer->Indices = buffer->Indices; + dest->Material = buffer->Material; + dest->Indices = buffer->Indices; const u32 vsize = buffer->Vertices.size(); - Original->Vertices.reallocate( vsize ); - MeshBuffer->Vertices.reallocate( vsize ); + dest->Vertices.set_used( vsize ); for ( u32 i = 0; i!= vsize; ++i ) { const video::S3DVertex2TCoords& src = buffer->Vertices[i]; + video::S3DVertex &dst = dest->Vertices[i]; - // Original has same Vertex Format - Original->Vertices.push_back(src); + dst.Pos = src.Pos; + dst.Normal = src.Normal; + dst.Color = 0xFFFFFFFF; + dst.TCoords = src.TCoords; - // we have a different vertex format - MeshBuffer->Vertices.push_back(src); - MeshBuffer->Vertices.getLast().Color=0xFFFFFFFF; + if ( i == 0 ) + dest->BoundingBox.reset ( src.Pos ); + else + dest->BoundingBox.addInternalPoint ( src.Pos ); } - MeshBuffer->recalculateBoundingBox(); + // move the (temp) Mesh to a ScenePosititon + // set Scene Node Position -#if 1 - // move the (temp) Mesh + if ( translateCenter ) { - // original bounding box - const core::aabbox3df& b = MeshBuffer->getBoundingBox(); - - // set Scene Node Position - setPosition( b.getCenter() ); + MeshOffset = dest->BoundingBox.getCenter(); + setPosition( MeshOffset ); core::matrix4 m; - m.setTranslation( -b.getCenter() ); - SceneManager->getMeshManipulator()->transform( Original, m ); - SceneManager->getMeshManipulator()->transform( MeshBuffer, m ); - - MeshBuffer->recalculateBoundingBox(); + m.setTranslation( -MeshOffset ); + SceneManager->getMeshManipulator()->transform( dest, m ); } -#endif - // used for sorting - MeshBuffer->Material.setTexture(0, (video::ITexture*) Shader); + + // No Texture!. Use Shader-Pointer for sorting + dest->Material.setTexture(0, (video::ITexture*) Shader); } @@ -116,10 +130,22 @@ void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBufferLightMap * buffer ) */ void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) { - const quake3::SVarGroup *group; + const SVarGroup *group; u32 i; + video::IVideoDriver *driver = SceneManager->getVideoDriver(); + + // generic stage + u32 mipmap = 0; + group = Shader->getGroup( 1 ); + if ( group->isDefined ( "nomipmaps" ) ) + { + mipmap = 2 | (driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS)? 1: 0 ); + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); + } + // clear all stages and prefill empty + Q3Texture.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); Q3Texture.clear(); for ( i = 0; i != Shader->VarGroup->VariableGroup.size(); ++i ) { @@ -145,7 +171,7 @@ void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) else { pos = 0; - quake3::getTextures( Q3Texture [i].Texture, mapname, pos, fileSystem, SceneManager->getVideoDriver() ); + getTextures( Q3Texture [i].Texture, mapname, pos, fileSystem, driver ); } } @@ -163,9 +189,9 @@ void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) // first parameter is frequency pos = 0; - Q3Texture [i].TextureFrequency = core::max_( 0.0001f, quake3::getAsFloat( animmap, pos ) ); + Q3Texture [i].TextureFrequency = core::max_( 0.0001f, getAsFloat( animmap, pos ) ); - quake3::getTextures( Q3Texture [i].Texture, animmap, pos,fileSystem, SceneManager->getVideoDriver() ); + getTextures( Q3Texture [i].Texture, animmap, pos,fileSystem, driver ); } // get clamp map @@ -180,10 +206,13 @@ void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) if ( 0 == clampmap.size() ) continue; - Q3Texture [i].TextureAddressMode = video::ETC_CLAMP; + Q3Texture [i].TextureAddressMode = video::ETC_CLAMP_TO_EDGE; pos = 0; - quake3::getTextures( Q3Texture [i].Texture, clampmap, pos,fileSystem, SceneManager->getVideoDriver() ); + getTextures( Q3Texture [i].Texture, clampmap, pos,fileSystem, driver ); } + + if ( mipmap & 2 ) + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap & 1); } /* @@ -193,7 +222,7 @@ void CQuake3ShaderSceneNode::OnRegisterSceneNode() { if ( isVisible() ) { - SceneManager->registerNodeForRendering(this, isTransparent() ? ESNRP_TRANSPARENT: ESNRP_SOLID ); + SceneManager->registerNodeForRendering(this, getRenderStage() ); } ISceneNode::OnRegisterSceneNode(); } @@ -201,37 +230,59 @@ void CQuake3ShaderSceneNode::OnRegisterSceneNode() /* is this a transparent node ? */ -bool CQuake3ShaderSceneNode::isTransparent() const +E_SCENE_NODE_RENDER_PASS CQuake3ShaderSceneNode::getRenderStage() const { - bool ret = false; + E_SCENE_NODE_RENDER_PASS ret = ESNRP_SOLID; // generic stage - const quake3::SVarGroup *group; - + const SVarGroup *group; + group = Shader->getGroup( 1 ); /* - if ( group->isDefined( "surfaceparm", "nonsolid" ) ) + else + if ( group->getIndex( "portal" ) >= 0 ) { - ret = true; + ret = ESNRP_TRANSPARENT_EFFECT; } -*/ - if ( group->isDefined( "surfaceparm", "trans" ) ) + else +*/ + if ( group->isDefined( "sort", "opaque" ) ) { - ret = true; + ret = ESNRP_SOLID; + } + else + if ( group->isDefined( "sort", "additive" ) ) + { + ret = ESNRP_TRANSPARENT; + } + else + if ( strstr ( Shader->name.c_str(), "flame" ) || + group->isDefined( "surfaceparm", "water" ) || + group->isDefined( "sort", "underwater" ) || + group->isDefined( "sort", "underwater" ) + ) + { + ret = ESNRP_TRANSPARENT_EFFECT; } else { - for ( u32 stage = 0; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) + // Look if first drawing stage needs graphical underlay + for ( u32 stage = 2; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) { - if ( 0 == Q3Texture [ stage].Texture.size() ) + if ( 0 == Q3Texture [ stage ].Texture.size() ) continue; group = Shader->getGroup( stage ); - quake3::SBlendFunc blendfunc; - quake3::getBlendFunc( group->get( "blendfunc" ), blendfunc ); - quake3::getBlendFunc( group->get( "alphafunc" ), blendfunc ); - ret = blendfunc.isTransparent; + SBlendFunc blendfunc ( video::EMFN_MODULATE_1X ); + getBlendFunc( group->get( "blendfunc" ), blendfunc ); + getBlendFunc( group->get( "alphafunc" ), blendfunc ); + + //ret = blendfunc.isTransparent ? ESNRP_TRANSPARENT : ESNRP_SOLID; + if ( blendfunc.isTransparent ) + { + ret = ESNRP_TRANSPARENT; + } break; } } @@ -246,12 +297,10 @@ bool CQuake3ShaderSceneNode::isTransparent() const void CQuake3ShaderSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); - - bool isTransparentPass = - SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; + E_SCENE_NODE_RENDER_PASS pass = SceneManager->getSceneNodeRenderPass(); video::SMaterial material; - const quake3::SVarGroup *group; + const SVarGroup *group; material.Lighting = false; material.setTexture(1, 0); @@ -259,55 +308,174 @@ void CQuake3ShaderSceneNode::render() // generic stage group = Shader->getGroup( 1 ); - material.BackfaceCulling = quake3::isDisabled( group->get( "cull" ) ); + material.BackfaceCulling = getCullingFunction( group->get( "cull" ) ); -// u32 zEnable = group->getIndex( "polygonoffset" ) >= 0; + u32 pushProjection = 0; + core::matrix4 projection ( core::matrix4::EM4CONST_NOTHING ); + + // decal ( solve z-fighting ) + if ( group->isDefined( "polygonoffset" ) ) + { + projection = driver->getTransform( video::ETS_PROJECTION ); + + core::matrix4 decalProjection ( projection ); + +/* + f32 n = SceneManager->getActiveCamera()->getNearValue(); + f32 f = SceneManager->getActiveCamera()->getFarValue (); + + f32 delta = 0.01f; + f32 pz = 0.2f; + f32 epsilon = -2.f * f * n * delta / ( ( f + n ) * pz * ( pz + delta ) ); + decalProjection[10] *= 1.f + epsilon; +*/ + // TODO: involve camera + decalProjection[10] -= 0.0002f; + driver->setTransform( video::ETS_PROJECTION, decalProjection ); + pushProjection |= 1; + } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation ); - u32 drawCount = 0; - for ( u32 stage = 0; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) - //for ( u32 stage = 2; stage < 3; ++stage ) + //! render all stages + u32 drawCount = (pass == ESNRP_TRANSPARENT_EFFECT) ? 1 : 0; + core::matrix4 textureMatrix ( core::matrix4::EM4CONST_NOTHING ); + for ( u32 stage = 1; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) { SQ3Texture &q = Q3Texture[stage]; // advance current stage - core::matrix4 texture; - animate( stage, texture ); + textureMatrix.makeIdentity(); + animate( stage, textureMatrix ); - // stage 1 finished, no drawing stage ( vertex transform only ) - if ( 0 == q.Texture.size() ) + // stage finished, no drawing stage ( vertex transform only ) + video::ITexture * tex = q.Texture.size() ? q.Texture [ q.TextureIndex ] : 0; + if ( 0 == tex ) continue; // current stage group = Shader->getGroup( stage ); - material.setTexture(0, q.Texture[ q.TextureIndex ]); - material.ZBuffer = quake3::getDepthFunction( group->get( "depthfunc" ) ); + material.setTexture(0, tex ); + material.ZBuffer = getDepthFunction( group->get( "depthfunc" ) ); - if ( group->getIndex( "depthwrite" ) >= 0 ) + if ( group->isDefined( "depthwrite" ) ) { material.ZWriteEnable = true; } else { - material.ZWriteEnable = drawCount ? false: !isTransparentPass; + material.ZWriteEnable = drawCount == 0; } //resolve quake3 blendfunction to irrlicht Material Type - quake3::SBlendFunc blendfunc; - quake3::getBlendFunc( group->get( "blendfunc" ), blendfunc ); - quake3::getBlendFunc( group->get( "alphafunc" ), blendfunc ); + SBlendFunc blendfunc ( video::EMFN_MODULATE_1X ); + getBlendFunc( group->get( "blendfunc" ), blendfunc ); + getBlendFunc( group->get( "alphafunc" ), blendfunc ); material.MaterialType = blendfunc.type; - material.MaterialTypeParam = blendfunc.param; + material.MaterialTypeParam = blendfunc.param0; - material.TextureLayer[0].TextureWrap = q.TextureAddressMode; - material.setTextureMatrix( 0, texture ); + material.TextureLayer[0].TextureWrapU = q.TextureAddressMode; + material.TextureLayer[0].TextureWrapV = q.TextureAddressMode; + //material.TextureLayer[0].TrilinearFilter = 1; + //material.TextureLayer[0].AnisotropicFilter = 0xFF; + material.setTextureMatrix( 0, textureMatrix ); driver->setMaterial( material ); driver->drawMeshBuffer( MeshBuffer ); drawCount += 1; + + } + + if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) + { + video::SMaterial deb_m; + deb_m.Wireframe = true; + deb_m.Lighting = false; + deb_m.BackfaceCulling = material.BackfaceCulling; + driver->setMaterial( deb_m ); + + driver->drawMeshBuffer( MeshBuffer ); + } + + // show normals + if ( DebugDataVisible & scene::EDS_NORMALS ) + { + video::SMaterial deb_m; + + IAnimatedMesh * arrow = SceneManager->addArrowMesh ( + "__debugnormalq3", + 0xFFECEC00,0xFF999900, + 4, 8, + 8.f, 6.f, + 0.5f,1.f + ); + if ( 0 == arrow ) + { + arrow = SceneManager->getMesh ( "__debugnormalq3" ); + } + const IMesh *mesh = arrow->getMesh ( 0 ); + + // find a good scaling factor + + core::matrix4 m2; + + // draw normals + const scene::IMeshBuffer* mb = MeshBuffer; + const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); + const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); + + //f32 colCycle = 270.f / (f32) core::s32_max ( mb->getVertexCount() - 1, 1 ); + + for ( u32 i=0; i != mb->getVertexCount(); ++i ) + { + // Align to v->normal + m2.buildRotateFromTo ( core::vector3df ( 0.f, 1.f, 0 ), v->Normal ); + m2.setTranslation ( v->Pos + AbsoluteTransformation.getTranslation () ); +/* + core::quaternion quatRot( v->Normal.Z, 0.f, -v->Normal.X, 1 + v->Normal.Y ); + quatRot.normalize(); + quatRot.getMatrix ( m2, v->Pos ); + + m2 [ 12 ] += AbsoluteTransformation [ 12 ]; + m2 [ 13 ] += AbsoluteTransformation [ 13 ]; + m2 [ 14 ] += AbsoluteTransformation [ 14 ]; +*/ + driver->setTransform(video::ETS_WORLD, m2 ); + + deb_m.Lighting = true; +/* + irr::video::SColorHSL color; + irr::video::SColor rgb(0); + color.Hue = i * colCycle * core::DEGTORAD; + color.Saturation = 1.f; + color.Luminance = 0.5f; + color.toRGB( deb_m.EmissiveColor ); +*/ + switch ( i ) + { + case 0: deb_m.EmissiveColor.set(0xFFFFFFFF); break; + case 1: deb_m.EmissiveColor.set(0xFFFF0000); break; + case 2: deb_m.EmissiveColor.set(0xFF00FF00); break; + case 3: deb_m.EmissiveColor.set(0xFF0000FF); break; + default: + deb_m.EmissiveColor = v->Color; break; + } + driver->setMaterial( deb_m ); + + for ( u32 a = 0; a != mesh->getMeshBufferCount(); ++a ) + driver->drawMeshBuffer ( mesh->getMeshBuffer ( a ) ); + + v = (const video::S3DVertex*) ( (u8*) v + vSize ); + } + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + } + + + if ( pushProjection & 1 ) + { + driver->setTransform( video::ETS_PROJECTION, projection ); } if ( DebugDataVisible & scene::EDS_BBOX ) @@ -315,47 +483,192 @@ void CQuake3ShaderSceneNode::render() video::SMaterial deb_m; deb_m.Lighting = false; driver->setMaterial(deb_m); - driver->draw3DBox( getBoundingBox(), video::SColor(0,255,255,255)); + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + driver->draw3DBox( getBoundingBox(), video::SColor(255,255,0,0)); } + } /*! +3.3.1 deformVertexes wave
+ Designed for water surfaces, modifying the values differently at each point. + It accepts the standard wave functions of the type sin, triangle, square, sawtooth + or inversesawtooth. The "div" parameter is used to control the wave "spread" + - a value equal to the tessSize of the surface is a good default value + (tessSize is subdivision size, in game units, used for the shader when seen in the game world) . */ -void CQuake3ShaderSceneNode::vertextransform_wave( f32 dt, quake3::SModifierFunction &function ) +void CQuake3ShaderSceneNode::deformvertexes_wave( f32 dt, SModifierFunction &function ) { function.wave = core::reciprocal( function.wave ); const f32 phase = function.phase; - const u32 vsize = MeshBuffer->Vertices.size(); + const u32 vsize = Original->Vertices.size(); for ( u32 i = 0; i != vsize; ++i ) { const video::S3DVertex2TCoords &src = Original->Vertices[i]; video::S3DVertex &dst = MeshBuffer->Vertices[i]; - const f32 wavephase = (src.Pos.X + src.Pos.Y + src.Pos.Z) * function.wave; + if ( 0 == function.count ) + dst.Pos = src.Pos - MeshOffset; + + const f32 wavephase = (dst.Pos.X + dst.Pos.Y + dst.Pos.Z) * function.wave; function.phase = phase + wavephase; const f32 f = function.evaluate( dt ); - dst.Pos.X = src.Pos.X + f * src.Normal.X; - dst.Pos.Y = src.Pos.Y + f * src.Normal.Y; - dst.Pos.Z = src.Pos.Z + f * src.Normal.Z; + dst.Pos.X += f * src.Normal.X; + dst.Pos.Y += f * src.Normal.Y; + dst.Pos.Z += f * src.Normal.Z; + + if ( i == 0 ) + MeshBuffer->BoundingBox.reset ( dst.Pos ); + else + MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); } + function.count = 1; } /*! + deformVertexes move x y z func base amplitude phase freq + The move parameter is used to make a brush, curve patch or model + appear to move together as a unit. The x y z values are the distance + and direction in game units the object appears to move relative to + it's point of origin in the map. The func base amplitude phase freq values are + the same as found in other waveform manipulations. + + The product of the function modifies the values x, y, and z. + Therefore, if you have an amplitude of 5 and an x value of 2, + the object will travel 10 units from its point of origin along the x axis. + This results in a total of 20 units of motion along the x axis, since the + amplitude is the variation both above and below the base. + + It must be noted that an object made with this shader does not actually + change position, it only appears to. + + Design Notes: + If an object is made up of surfaces with different shaders, all must have + matching deformVertexes move values or the object will appear to tear itself apart. */ -void CQuake3ShaderSceneNode::vertextransform_bulge( f32 dt, quake3::SModifierFunction &function ) +void CQuake3ShaderSceneNode::deformvertexes_move( f32 dt, SModifierFunction &function ) { - function.func = 0; + function.wave = core::reciprocal( function.wave ); + const f32 f = function.evaluate( dt ); + + const u32 vsize = Original->Vertices.size(); + for ( u32 i = 0; i != vsize; ++i ) + { + const video::S3DVertex2TCoords &src = Original->Vertices[i]; + video::S3DVertex &dst = MeshBuffer->Vertices[i]; + + if ( 0 == function.count ) + dst.Pos = src.Pos - MeshOffset; + + dst.Pos.X += f * function.x; + dst.Pos.Y += f * function.y; + dst.Pos.Z += f * function.z; + + if ( i == 0 ) + MeshBuffer->BoundingBox.reset ( dst.Pos ); + else + MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); + } + function.count = 1; + +} + +/*! + 3.3.2 deformVertexes normal
+ This deformation affects the normals of a vertex without actually moving it, + which will effect later shader options like lighting and especially environment mapping. + If the shader stages don't use normals in any of their calculations, there will + be no visible effect. + + Design Notes: Putting values of 0.1 t o 0.5 in Amplitude and 1.0 to 4.0 in the + Frequency can produce some satisfying results. Some things that have been + done with it: A small fluttering bat, falling leaves, rain, flags. +*/ +void CQuake3ShaderSceneNode::deformvertexes_normal( f32 dt, SModifierFunction &function ) +{ + function.func = SINUS; + const u32 vsize = Original->Vertices.size(); + for ( u32 i = 0; i != vsize; ++i ) + { + const video::S3DVertex2TCoords &src = Original->Vertices[i]; + video::S3DVertex &dst = MeshBuffer->Vertices[i]; + + function.base = atan2f ( src.Pos.X, src.Pos.Y ); + function.phase = src.Pos.X + src.Pos.Z; + + const f32 lat = function.evaluate( dt ); + + function.base = src.Normal.Y; + function.phase = src.Normal.Z + src.Normal.X; + + const f32 lng = function.evaluate( dt ); + + dst.Normal.X = cosf ( lat ) * sinf ( lng ); + dst.Normal.Y = sinf ( lat ) * sinf ( lng ); + dst.Normal.Z = cosf ( lng ); + + } +} + + +/*! + 3.3.3 deformVertexes bulge + This forces a bulge to move along the given s and t directions. Designed for use + on curved pipes. + + Specific parameter definitions for deform keywords: +
This is roughly defined as the size of the waves that occur. + It is measured in game units. Smaller values create a greater + density of smaller wave forms occurring in a given area. + Larger values create a lesser density of waves, or otherwise put, + the appearance of larger waves. To look correct this value should + closely correspond to the value (in pixels) set for tessSize (tessellation size) + of the texture. A value of 100.0 is a good default value + (which means your tessSize should be close to that for things to look "wavelike"). + + This is the type of wave form being created. Sin stands for sine wave, + a regular smoothly flowing wave. Triangle is a wave with a sharp ascent + and a sharp decay. It will make a choppy looking wave forms. + A square wave is simply on or off for the period of the + frequency with no in between. The sawtooth wave has the ascent of a + triangle wave, but has the decay cut off sharply like a square wave. + An inversesawtooth wave reverses this. + + This is the distance, in game units that the apparent surface of the + texture is displaced from the actual surface of the brush as placed + in the editor. A positive value appears above the brush surface. + A negative value appears below the brush surface. + An example of this is the Quad effect, which essentially is a + shell with a positive base value to stand it away from the model + surface and a 0 (zero) value for amplitude. + + The distance that the deformation moves away from the base value. + See Wave Forms in the introduction for a description of amplitude. + + See Wave Forms in the introduction for a description of phase) + + See Wave Forms in the introduction for a description of frequency) + + Design Note: The div and amplitude parameters, when used in conjunction with + liquid volumes like water should take into consideration how much the water + will be moving. A large ocean area would have have massive swells (big div values) + that rose and fell dramatically (big amplitude values). While a small, quiet pool + may move very little. +*/ +void CQuake3ShaderSceneNode::deformvertexes_bulge( f32 dt, SModifierFunction &function ) +{ + function.func = SINUS; function.wave = core::reciprocal( function.bulgewidth ); dt *= function.bulgespeed * 0.1f; const f32 phase = function.phase; - const u32 vsize = MeshBuffer->Vertices.size(); + const u32 vsize = Original->Vertices.size(); for ( u32 i = 0; i != vsize; ++i ) { const video::S3DVertex2TCoords &src = Original->Vertices[i]; @@ -366,83 +679,235 @@ void CQuake3ShaderSceneNode::vertextransform_bulge( f32 dt, quake3::SModifierFun const f32 f = function.evaluate( dt ); - dst.Pos.X = src.Pos.X + f * src.Normal.X; - dst.Pos.Y = src.Pos.Y + f * src.Normal.Y; - dst.Pos.Z = src.Pos.Z + f * src.Normal.Z; + if ( 0 == function.count ) + dst.Pos = src.Pos - MeshOffset; + + dst.Pos.X += f * src.Normal.X; + dst.Pos.Y += f * src.Normal.Y; + dst.Pos.Z += f * src.Normal.Z; + + if ( i == 0 ) + MeshBuffer->BoundingBox.reset ( dst.Pos ); + else + MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); } + + function.count = 1; } + /*! + deformVertexes autosprite + + This function can be used to make any given triangle quad + (pair of triangles that form a square rectangle) automatically behave + like a sprite without having to make it a separate entity. This means + that the "sprite" on which the texture is placed will rotate to always + appear at right angles to the player's view as a sprite would. Any four-sided + brush side, flat patch, or pair of triangles in a model can have the autosprite + effect on it. The brush face containing a texture with this shader keyword must + be square. */ -void CQuake3ShaderSceneNode::vertextransform_autosprite( f32 dt, quake3::SModifierFunction &function ) +void CQuake3ShaderSceneNode::deformvertexes_autosprite( f32 dt, SModifierFunction &function ) { - const core::matrix4 &m = SceneManager->getActiveCamera()->getViewFrustum()->Matrices [ video::ETS_VIEW ]; - const core::vector3df view( -m[2], -m[6] , -m[10] ); - - const u32 vsize = MeshBuffer->Vertices.size(); - - core::aabbox3df box; + u32 vsize = Original->Vertices.size(); u32 g; + u32 i; - for ( u32 i = 0; i < vsize; i += 4 ) + const core::vector3df& camPos = SceneManager->getActiveCamera()->getPosition(); + + video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); + const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer(); + + core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); + core::quaternion q; + for ( i = 0; i < vsize; i += 4 ) { - // in pairs of 4 - box.reset( Original->Vertices[i].Pos ); - for ( g = 1; g != 4; ++g ) + // quad-plane + core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos ); + core::vector3df forward = camPos - center; + + q.rotationFromTo ( vin[i].Normal, forward ); + q.getMatrixCenter ( lookat, center, MeshOffset ); + + for ( g = 0; g < 4; ++g ) { - box.addInternalPoint( Original->Vertices[i + g].Pos ); + lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos ); + lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal ); } - core::vector3df c = box.getCenter(); - f32 sh = 0.5f * ( box.MaxEdge.Z - box.MinEdge.Z ); - f32 sv = 0.5f * ( box.MaxEdge.Y - box.MinEdge.Y ); - - const core::vector3df h( m[0] * sh, m[4] * sh, m[8] * sh ); - const core::vector3df v( m[1] * sv, m[5] * sv, m[9] * sv ); - - MeshBuffer->Vertices[ i + 0 ].Pos = c + h + v; - MeshBuffer->Vertices[ i + 1 ].Pos = c - h - v; - MeshBuffer->Vertices[ i + 2 ].Pos = c + h - v; - MeshBuffer->Vertices[ i + 3 ].Pos = c - h + v; - - MeshBuffer->Vertices[ i + 0 ].Normal = view; - MeshBuffer->Vertices[ i + 1 ].Normal = view; - MeshBuffer->Vertices[ i + 2 ].Normal = view; - MeshBuffer->Vertices[ i + 3 ].Normal = view; } + function.count = 1; +} + + +/*! + deformVertexes autosprite2 + Is a slightly modified "sprite" that only rotates around the middle of its longest axis. + This allows you to make a pillar of fire that you can walk around, or an energy beam + stretched across the room. +*/ + +struct sortaxis +{ + core::vector3df v; + bool operator < ( const sortaxis &other ) const + { + return v.getLengthSQ () < other.v.getLengthSQ (); + } +}; +/*! +*/ +void CQuake3ShaderSceneNode::deformvertexes_autosprite2( f32 dt, SModifierFunction &function ) +{ + u32 vsize = Original->Vertices.size(); + u32 g; + u32 i; + + const core::vector3df camPos = SceneManager->getActiveCamera()->getAbsolutePosition(); + + video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); + const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer(); + + core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); + + core::array < sortaxis > axis; + axis.set_used ( 3 ); + + for ( i = 0; i < vsize; i += 4 ) + { + // quad-plane + core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos ); + + // longes axe + axis[0].v = vin[i+1].Pos - vin[i+0].Pos; + axis[1].v = vin[i+2].Pos - vin[i+0].Pos; + axis[2].v = vin[i+3].Pos - vin[i+0].Pos; + axis.set_sorted ( false ); + axis.sort (); + + lookat.buildAxisAlignedBillboard ( camPos, center, MeshOffset, axis[1].v, vin[i+0].Normal ); + + for ( g = 0; g < 4; ++g ) + { + lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos ); + lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal ); + } + } + function.count = 1; } /* Generate Vertex Color */ -void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, quake3::SModifierFunction &function ) +void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, SModifierFunction &function ) { u32 i; - const u32 vsize = MeshBuffer->Vertices.size(); + const u32 vsize = Original->Vertices.size(); - switch ( function.masterfunc1 ) + switch ( function.rgbgen ) { - case 6: - //identity + case IDENTITY: + //rgbgen identity for ( i = 0; i != vsize; ++i ) - MeshBuffer->Vertices[i].Color = 0xFFFFFFFF; + MeshBuffer->Vertices[i].Color.set(0xFFFFFFFF); break; - case 7: - // vertex + + case IDENTITYLIGHTING: + // rgbgen identitylighting TODO: overbright for ( i = 0; i != vsize; ++i ) - MeshBuffer->Vertices[i].Color = Original->Vertices[i].Color; + MeshBuffer->Vertices[i].Color.set(0xFF7F7F7F); break; - case 5: + + case EXACTVERTEX: + // alphagen exactvertex TODO lighting + case VERTEX: + // rgbgen vertex + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color=Original->Vertices[i].Color; + break; + case WAVE: { - // wave + // rgbGen wave f32 f = function.evaluate( dt ) * 255.f; s32 value = core::clamp( core::floor32(f), 0, 255 ); - value |= value << 8; - value |= value << 16; + value = 0xFF000000 | value << 16 | value << 8 | value; for ( i = 0; i != vsize; ++i ) - MeshBuffer->Vertices[i].Color = value; + MeshBuffer->Vertices[i].Color.set(value); } break; + case CONSTANT: + { + //rgbgen const ( x y z ) + video::SColorf cf( function.x, function.y, function.z ); + video::SColor col = cf.toSColor(); + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color=col; + } break; + default: + break; + } +} + +/* + Generate Vertex Color, Alpha +*/ +void CQuake3ShaderSceneNode::vertextransform_alphagen( f32 dt, SModifierFunction &function ) +{ + u32 i; + const u32 vsize = Original->Vertices.size(); + + switch ( function.alphagen ) + { + case IDENTITY: + //alphagen identity + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.setAlpha ( 0xFF ); + break; + + case EXACTVERTEX: + // alphagen exactvertex TODO lighting + case VERTEX: + // alphagen vertex + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.setAlpha ( Original->Vertices[i].Color.getAlpha() ); + break; + case CONSTANT: + { + // alphagen const + u32 a = (u32) ( function.x * 255.f ); + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.setAlpha ( a ); + } break; + + case LIGHTINGSPECULAR: + { + // alphagen lightingspecular TODO!!! + const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum(); + const core::matrix4 &view = frustum->getTransform ( video::ETS_VIEW ); + + const f32 *m = view.pointer(); + + for ( i = 0; i != vsize; ++i ) + { + const core::vector3df &n = Original->Vertices[i].Normal; + MeshBuffer->Vertices[i].Color.setAlpha ((u32)( 128.f *(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2])))); + } + + } break; + + + case WAVE: + { + // alphagen wave + f32 f = function.evaluate( dt ) * 255.f; + s32 value = core::clamp( core::floor32(f), 0, 255 ); + + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.setAlpha ( value ); + } break; + default: + break; } } @@ -451,17 +916,17 @@ void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, quake3::SModifierFu /* Generate Texture Coordinates */ -void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, quake3::SModifierFunction &function ) +void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, SModifierFunction &function ) { u32 i; - const u32 vsize = MeshBuffer->Vertices.size(); + const u32 vsize = Original->Vertices.size(); switch ( function.tcgen ) { - case 12: + case TURBULENCE: //tcgen turb { - function.wave = core::reciprocal( function.wave ); + function.wave = core::reciprocal( function.phase ); const f32 phase = function.phase; @@ -481,53 +946,46 @@ void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, quake3::SModifierFun } break; - case 8: + case TEXTURE: // tcgen texture for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords; break; - case 9: + case LIGHTMAP: // tcgen lightmap for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords2; break; - case 10: + case ENVIRONMENT: { - // tcgen environment ( D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR ) + // tcgen environment + const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum(); + const core::matrix4 &view = frustum->getTransform ( video::ETS_VIEW ); - // using eye linear, sphere map may be cooler;-) - // modelmatrix is identity - const core::matrix4 &view = SceneManager->getActiveCamera()->getViewFrustum()->Matrices [ video::ETS_VIEW ]; - const core::matrix4 &viewinverse = SceneManager->getActiveCamera()->getViewFrustum()->Matrices [ SViewFrustum::ETS_VIEW_MODEL_INVERSE_3 ]; + const f32 *m = view.pointer(); - // eyePlane - core::vector3df eyePlaneS; - core::vector3df eyePlaneT; - - viewinverse.transformVect( eyePlaneS, core::vector3df(1.f, 0.f, 0.f) ); - viewinverse.transformVect( eyePlaneT, core::vector3df(0.f, 1.f, 0.f) ); - - eyePlaneS.normalize(); - eyePlaneT.normalize(); - - core::vector3df v; + core::vector3df n; for ( i = 0; i != vsize; ++i ) { - // vertex in eye space - view.transformVect( v, Original->Vertices[i].Pos ); - v.normalize(); + //const core::vector3df &n = Original->Vertices[i].Normal; - MeshBuffer->Vertices[i].TCoords.X = (1.f + eyePlaneS.dotProduct(v) ) * 0.5f; - MeshBuffer->Vertices[i].TCoords.Y = 1.f - ( (1.f + eyePlaneT.dotProduct(v) ) * 0.5f ); + n = frustum->cameraPosition - Original->Vertices[i].Pos; + n.normalize(); + n += Original->Vertices[i].Normal; + n.normalize(); + + MeshBuffer->Vertices[i].TCoords.X = 0.5f*(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2])); + MeshBuffer->Vertices[i].TCoords.Y = 0.5f*(1.f+(n.X*m[4]+n.Y*m[5]+n.Z*m[6])); } } break; - + default: + break; } } - +#if 0 /* Transform Texture Coordinates */ @@ -571,7 +1029,7 @@ void CQuake3ShaderSceneNode::transformtex( const core::matrix4 &m, const u32 add } } - +#endif /* @@ -583,44 +1041,46 @@ void CQuake3ShaderSceneNode::transformtex( const core::matrix4 &m, const u32 add */ void CQuake3ShaderSceneNode::animate( u32 stage,core::matrix4 &texture ) { - const quake3::SVarGroup *group = Shader->getGroup( stage ); + const SVarGroup *group = Shader->getGroup( stage ); // select current texture - if ( Q3Texture [ stage ].TextureFrequency != 0.f ) + SQ3Texture &q3Tex = Q3Texture [ stage ]; + if ( q3Tex.TextureFrequency != 0.f ) { - s32 v = core::floor32( TimeAbs * Q3Texture[stage].TextureFrequency ); - Q3Texture [ stage ].TextureIndex = v % Q3Texture[stage].Texture.size(); + s32 v = core::floor32( TimeAbs * q3Tex.TextureFrequency ); + q3Tex.TextureIndex = v % q3Tex.Texture.size(); } core::matrix4 m2; - quake3::SModifierFunction function; + SModifierFunction function; - f32 f0; - f32 f1; + f32 f[16]; // walk group for all modifiers for ( u32 g = 0; g != group->Variable.size(); ++g ) { - const quake3::SVariable &v = group->Variable[g]; + const SVariable &v = group->Variable[g]; // get the modifier static const c8 * modifierList[] = { - "tcmod","deformvertexes","rgbgen","tcgen","map" + "tcmod","deformvertexes","rgbgen","tcgen","map","alphagen" }; u32 pos = 0; - function.masterfunc0 = quake3::isEqual( v.name, pos, modifierList, 5 ); + function.masterfunc0 = (eQ3ModifierFunction) isEqual( v.name, pos, modifierList, 6 ); - if ( -2 == function.masterfunc0 ) + if ( UNKNOWN == function.masterfunc0 ) continue; switch ( function.masterfunc0 ) { //tcmod - case 0: + case TCMOD: m2.makeIdentity(); break; + default: + break; } // get the modifier function @@ -629,135 +1089,216 @@ void CQuake3ShaderSceneNode::animate( u32 stage,core::matrix4 &texture ) "scroll","scale","rotate","stretch","turb", "wave","identity","vertex", "texture","lightmap","environment","$lightmap", - "bulge","autosprite","autosprite2" + "bulge","autosprite","autosprite2","transform", + "exactvertex","const","lightingspecular","move","normal", + "identitylighting" }; + static const c8 * groupToken[] = { "(", ")" }; pos = 0; - function.masterfunc1 = quake3::isEqual( v.content, pos, funclist, 14 ); + function.masterfunc1 = (eQ3ModifierFunction) isEqual( v.content, pos, funclist, 22 ); + if ( function.masterfunc1 != UNKNOWN ) + function.masterfunc1 = (eQ3ModifierFunction) ((u32) function.masterfunc1 + FUNCTION2 + 1); switch ( function.masterfunc1 ) { - case 0: - // scroll - f0 = quake3::getAsFloat( v.content, pos ) * TimeAbs; - f1 = quake3::getAsFloat( v.content, pos ) * TimeAbs; - m2.setTextureTranslate( f0, f1 ); + case SCROLL: + // tcMod scroll + f[0] = getAsFloat( v.content, pos ) * TimeAbs; + f[1] = getAsFloat( v.content, pos ) * TimeAbs; + m2.setTextureTranslate( f[0], f[1] ); break; - case 1: - // scale - f0 = quake3::getAsFloat( v.content, pos ); - f1 = quake3::getAsFloat( v.content, pos ); - m2.setTextureScale( f0, f1 ); + case SCALE: + // tcmod scale + f[0] = getAsFloat( v.content, pos ); + f[1] = getAsFloat( v.content, pos ); + m2.setTextureScale( f[0], f[1] ); break; - case 2: - //rotate - m2.setTextureRotationCenter( quake3::getAsFloat( v.content, pos ) * core::DEGTORAD * TimeAbs ); + case ROTATE: + // tcmod rotate + m2.setTextureRotationCenter( getAsFloat( v.content, pos ) * + core::DEGTORAD * + TimeAbs + ); break; - case 3: - case 4: - case 5: - case 6: - case 7: + case TRANSFORM: + // tcMod + memset(f, 0, sizeof ( f )); + f[10] = f[15] = 1.f; + + f[0] = getAsFloat( v.content, pos ); + f[1] = getAsFloat( v.content, pos ); + f[4] = getAsFloat( v.content, pos ); + f[5] = getAsFloat( v.content, pos ); + f[8] = getAsFloat( v.content, pos ); + f[9] = getAsFloat( v.content, pos ); + m2.setM ( f ); + break; + + case STRETCH: // stretch + case TURBULENCE: // turb + case WAVE: // wave + case IDENTITY: // identity + case IDENTITYLIGHTING: + case VERTEX: // vertex + case MOVE: + case CONSTANT: { // turb == sin, default == sin - function.func = 0; + function.func = SINUS; - if (function.masterfunc1 == 5 && function.masterfunc0 == 1) + if ( function.masterfunc0 == DEFORMVERTEXES ) { - // deformvertexes, wave - function.wave = quake3::getAsFloat( v.content, pos ); - } - - if (function.masterfunc1 == 3 || - function.masterfunc1 == 4 || - function.masterfunc1 == 5) - { - // stretch, wave, tub - quake3::getModifierFunc( function, v.content, pos ); + switch ( function.masterfunc1 ) + { + case WAVE: + // deformvertexes wave + function.wave = getAsFloat( v.content, pos ); + break; + case MOVE: + //deformvertexes move + function.x = getAsFloat( v.content, pos ); + function.z = getAsFloat( v.content, pos ); + function.y = getAsFloat( v.content, pos ); + break; + default: + break; + } } switch ( function.masterfunc1 ) { - case 3: - // stretch - f0 = core::reciprocal( function.evaluate(TimeAbs) ); - m2.setTextureScaleCenter( f0, f0 ); + case STRETCH: + case TURBULENCE: + case WAVE: + case MOVE: + getModifierFunc( function, v.content, pos ); break; - case 4: - { - // turb -/* - quake3::SModifierFunction ampFunction; - ampFunction.func = 0; - ampFunction.freq = function.freq; - ampFunction.base = 1.f; - ampFunction.amp = 0.2f; - f2 = ampFunction.evaluate( TimeAbs ); + default: + break; + } - f0 = function.evaluate( TimeAbs ); - function.func = 1; - f1 = function.evaluate( TimeAbs ); + switch ( function.masterfunc1 ) + { + case STRETCH: + //tcMod stretch + f[0] = core::reciprocal( function.evaluate(TimeAbs) ); + m2.setTextureScaleCenter( f[0], f[0] ); + break; + case TURBULENCE: + //tcMod turb + //function.tcgen = TURBULENCE; + m2.setTextureRotationCenter( function.frequency * + core::DEGTORAD * + TimeAbs + ); + break; + case WAVE: + case IDENTITY: + case IDENTITYLIGHTING: + case VERTEX: + case EXACTVERTEX: + case CONSTANT: + case LIGHTINGSPECULAR: + case MOVE: + switch ( function.masterfunc0 ) + { + case DEFORMVERTEXES: + switch ( function.masterfunc1 ) + { + case WAVE: + deformvertexes_wave( TimeAbs, function ); + break; + case MOVE: + deformvertexes_move( TimeAbs, function ); + break; + default: + break; + } + break; + case RGBGEN: + function.rgbgen = function.masterfunc1; + if ( function.rgbgen == CONSTANT ) + { + isEqual ( v.content, pos, groupToken, 2 ); + function.x = getAsFloat( v.content, pos ); + function.y = getAsFloat( v.content, pos ); + function.z = getAsFloat( v.content, pos ); + } + //vertextransform_rgbgen( TimeAbs, function ); + break; + case ALPHAGEN: + function.alphagen = function.masterfunc1; + if ( function.alphagen == CONSTANT ) + { + function.x = getAsFloat( v.content, pos ); + } - m2.setTextureTranslate( f0, f1 ); - m2.setTextureScaleCenter( f2, f2 ); - //m2.setTextureScale( f2, f2 ); -*/ - }break; - case 5: - if ( function.masterfunc0 == 1 ) - { - vertextransform_wave( TimeAbs, function ); - } - else - { - vertextransform_rgbgen( TimeAbs, function ); + //vertextransform_alphagen( TimeAbs, function ); + break; + default: + break; } break; - case 6: - case 7: - vertextransform_rgbgen( TimeAbs, function ); + default: break; } } break; - case 8: - case 9: - case 10: + case TEXTURE: + case LIGHTMAP: + case ENVIRONMENT: // "texture","lightmap","environment" function.tcgen = function.masterfunc1; break; - case 11: + case DOLLAR_LIGHTMAP: // map == lightmap, tcgen == lightmap - function.tcgen = 9; + function.tcgen = LIGHTMAP; break; - case 12: + case BULGE: // deformvertexes bulge - function.bulgewidth = quake3::getAsFloat( v.content, pos ); - function.bulgeheight = quake3::getAsFloat( v.content, pos ); - function.bulgespeed = quake3::getAsFloat( v.content, pos ); + function.bulgewidth = getAsFloat( v.content, pos ); + function.bulgeheight = getAsFloat( v.content, pos ); + function.bulgespeed = getAsFloat( v.content, pos ); - vertextransform_bulge(TimeAbs, function); + deformvertexes_bulge(TimeAbs, function); break; - case 13: - case 14: + case NORMAL: + // deformvertexes normal + function.amp = getAsFloat( v.content, pos ); + function.frequency = getAsFloat( v.content, pos ); + + deformvertexes_normal(TimeAbs, function); + break; + + case AUTOSPRITE: // deformvertexes autosprite - vertextransform_autosprite(TimeAbs, function); + deformvertexes_autosprite(TimeAbs, function); break; + case AUTOSPRITE2: + // deformvertexes autosprite2 + deformvertexes_autosprite2(TimeAbs, function); + break; + default: + break; } // func switch ( function.masterfunc0 ) { - case 0: + case TCMOD: texture *= m2; break; + default: + break; } } // group - // texture coordinate modifier - vertextransform_tcgen(TimeAbs, function); + vertextransform_rgbgen( TimeAbs, function ); + vertextransform_alphagen( TimeAbs, function ); + vertextransform_tcgen( TimeAbs, function ); } @@ -780,7 +1321,7 @@ u32 CQuake3ShaderSceneNode::getMaterialCount() const video::SMaterial& CQuake3ShaderSceneNode::getMaterial(u32 i) { - video::SMaterial& m = MeshBuffer->getMaterial(); + video::SMaterial& m = MeshBuffer->Material; m.setTexture(0, 0); if ( Q3Texture [ i ].TextureIndex ) m.setTexture(0, Q3Texture [ i ].Texture [ Q3Texture [ i ].TextureIndex ]); diff --git a/src/dep/src/irrlicht/CQuake3ShaderSceneNode.h b/src/dep/src/irrlicht/CQuake3ShaderSceneNode.h index 34082c4..3022161 100644 --- a/src/dep/src/irrlicht/CQuake3ShaderSceneNode.h +++ b/src/dep/src/irrlicht/CQuake3ShaderSceneNode.h @@ -1,15 +1,17 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_QUAKE3_SCENE_NODE_H_INCLUDED__ #define __C_QUAKE3_SCENE_NODE_H_INCLUDED__ -#include "ISceneNode.h" +#include "IMeshSceneNode.h" #include "IQ3Shader.h" #include "IFileSystem.h" #include "SMeshBuffer.h" #include "SMeshBufferLightMap.h" +#include "SMesh.h" +#include "ISceneManager.h" namespace irr { @@ -17,13 +19,15 @@ namespace scene { //! Scene node which is a quake3 shader. -class CQuake3ShaderSceneNode : public scene::ISceneNode +class CQuake3ShaderSceneNode : public scene::IMeshSceneNode { public: - CQuake3ShaderSceneNode( ISceneNode* parent, ISceneManager* mgr,s32 id, - io::IFileSystem *fileSystem,IMeshBuffer *buffer, - const quake3::SShader * shader); + CQuake3ShaderSceneNode( ISceneNode* parent, ISceneManager* mgr, s32 id, + io::IFileSystem* fileSystem, + const IMeshBuffer* original, + const quake3::IShader* shader + ); virtual ~CQuake3ShaderSceneNode(); @@ -35,17 +39,30 @@ public: virtual u32 getMaterialCount() const; virtual video::SMaterial& getMaterial(u32 i); + //! Returns type of the scene node + virtual ESCENE_NODE_TYPE getType() const { return ESNT_Q3SHADER_SCENE_NODE; } + + virtual void setMesh(IMesh* mesh){} + virtual IMesh* getMesh() { return Mesh; } + virtual void setReadOnlyMaterials(bool readonly) {} + virtual bool isReadOnlyMaterials() const { return true; } + private: + const quake3::IShader* Shader; + SMesh *Mesh; + const SMeshBufferLightMap* Original; SMeshBuffer* MeshBuffer; - SMeshBufferLightMap* Original; - const quake3::SShader* Shader; + core::vector3df MeshOffset; struct SQ3Texture { SQ3Texture () : TextureIndex ( 0 ), TextureFrequency(0.f), - TextureAddressMode( video::ETC_REPEAT ) {} + TextureAddressMode( video::ETC_REPEAT ) + { + Texture.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); + } quake3::tTexArray Texture; @@ -57,20 +74,27 @@ private: core::array< SQ3Texture > Q3Texture; void loadTextures ( io::IFileSystem * fileSystem ); - void cloneBuffer ( scene::SMeshBufferLightMap * buffer ); + void addBuffer ( scene::SMeshBufferLightMap * buffer ); + void cloneBuffer ( scene::SMeshBuffer *dest, const scene::SMeshBufferLightMap * buffer, bool translateCenter ); + + void deformvertexes_wave ( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_move ( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_bulge( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_autosprite( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_autosprite2( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_normal ( f32 dt, quake3::SModifierFunction &function ); - void vertextransform_wave ( f32 dt, quake3::SModifierFunction &function ); - void vertextransform_bulge( f32 dt, quake3::SModifierFunction &function ); - void vertextransform_autosprite( f32 dt, quake3::SModifierFunction &function ); void vertextransform_tcgen ( f32 dt, quake3::SModifierFunction &function ); void vertextransform_rgbgen ( f32 dt, quake3::SModifierFunction &function ); + void vertextransform_alphagen ( f32 dt, quake3::SModifierFunction &function ); void transformtex ( const core::matrix4 &m, const u32 clamp ); f32 TimeAbs; + void animate( u32 stage, core::matrix4 &texture ); - bool isTransparent() const; + E_SCENE_NODE_RENDER_PASS getRenderStage() const; }; diff --git a/src/dep/src/irrlicht/CReadFile.cpp b/src/dep/src/irrlicht/CReadFile.cpp index 7fe733f..6242519 100644 --- a/src/dep/src/irrlicht/CReadFile.cpp +++ b/src/dep/src/irrlicht/CReadFile.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -10,7 +10,7 @@ namespace io { -CReadFile::CReadFile(const c8* fileName) +CReadFile::CReadFile(const io::path& fileName) : File(0), FileSize(0), Filename(fileName) { #ifdef _DEBUG @@ -73,7 +73,11 @@ void CReadFile::openFile() return; } +#if defined ( _IRR_WCHAR_FILESYSTEM ) + File = _wfopen(Filename.c_str(), L"rb"); +#else File = fopen(Filename.c_str(), "rb"); +#endif if (File) { @@ -87,14 +91,14 @@ void CReadFile::openFile() //! returns name of file -const c8* CReadFile::getFileName() const +const io::path& CReadFile::getFileName() const { - return Filename.c_str(); + return Filename; } -IReadFile* createReadFile(const c8* fileName) +IReadFile* createReadFile(const io::path& fileName) { CReadFile* file = new CReadFile(fileName); if (file->isOpen()) diff --git a/src/dep/src/irrlicht/CReadFile.h b/src/dep/src/irrlicht/CReadFile.h index b09da7b..d4455a1 100644 --- a/src/dep/src/irrlicht/CReadFile.h +++ b/src/dep/src/irrlicht/CReadFile.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -22,8 +22,7 @@ namespace io { public: - CReadFile(const wchar_t* fileName); - CReadFile(const c8* fileName); + CReadFile(const io::path& fileName); virtual ~CReadFile(); @@ -46,7 +45,7 @@ namespace io virtual long getPos() const; //! returns name of file - virtual const c8* getFileName() const; + virtual const io::path& getFileName() const; private: @@ -55,7 +54,7 @@ namespace io FILE* File; long FileSize; - core::stringc Filename; + io::path Filename; }; } // end namespace io diff --git a/src/dep/src/irrlicht/CSTLMeshFileLoader.cpp b/src/dep/src/irrlicht/CSTLMeshFileLoader.cpp index 3f4a496..e78a91a 100644 --- a/src/dep/src/irrlicht/CSTLMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CSTLMeshFileLoader.cpp @@ -1,8 +1,8 @@ -// Copyright (C) 2007-2008 Christian Stehno +// Copyright (C) 2007-2010 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "IrrCompileConfig.h" +#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_STL_LOADER_ @@ -23,9 +23,9 @@ namespace scene //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CSTLMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CSTLMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strstr(filename, ".stl")!=0; + return core::hasFileExtension ( filename, "stl" ); } @@ -43,7 +43,9 @@ IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file) const u32 WORD_BUFFER_LENGTH = 512; SMesh* mesh = new SMesh(); - mesh->addMeshBuffer( new SMeshBuffer() ); + SMeshBuffer* meshBuffer = new SMeshBuffer(); + mesh->addMeshBuffer(meshBuffer); + meshBuffer->drop(); core::vector3df vertex[3]; core::vector3df normal; @@ -140,13 +142,16 @@ IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file) video::SColor color(0xffffffff); if (attrib & 0x8000) color = video::A1R5G5B5toA8R8G8B8(attrib); - mb->Vertices.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df())); - mb->Vertices.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df())); + if (normal==core::vector3df()) + normal=core::plane3df(vertex[2],vertex[1],vertex[0]).Normal; mb->Vertices.push_back(video::S3DVertex(vertex[2],normal,color, core::vector2df())); + mb->Vertices.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df())); + mb->Vertices.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df())); mb->Indices.push_back(vCount); mb->Indices.push_back(vCount+1); mb->Indices.push_back(vCount+2); } // end while (file->getPos() < filesize) + mesh->getMeshBuffer(0)->recalculateBoundingBox(); // Create the Animated mesh if there's anything in the mesh SAnimatedMesh* pAM = 0; @@ -165,20 +170,6 @@ IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file) } -//! Read RGB color -const c8* CSTLMeshFileLoader::readColor(const c8* bufPtr, video::SColor& color, const c8* const pBufEnd) const -{ - const u32 COLOR_BUFFER_LENGTH = 16; - c8 colStr[COLOR_BUFFER_LENGTH]; - - color.setAlpha(255); - color.setRed((s32)(core::fast_atof(colStr) * 255.0f)); - color.setGreen((s32)(core::fast_atof(colStr) * 255.0f)); - color.setBlue((s32)(core::fast_atof(colStr) * 255.0f)); - return bufPtr; -} - - //! Read 3d vector of floats void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary) const { @@ -205,6 +196,7 @@ void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vector3df& vec getNextToken(file, tmp); core::fast_atof_move(tmp.c_str(), vec.Z); } + vec.X=-vec.X; } diff --git a/src/dep/src/irrlicht/CSTLMeshFileLoader.h b/src/dep/src/irrlicht/CSTLMeshFileLoader.h index 41e86d3..07cf55d 100644 --- a/src/dep/src/irrlicht/CSTLMeshFileLoader.h +++ b/src/dep/src/irrlicht/CSTLMeshFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2008 Christian Stehno +// Copyright (C) 2007-2010 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,7 +7,6 @@ #include "IMeshLoader.h" #include "irrString.h" -#include "SColor.h" #include "vector3d.h" namespace irr @@ -22,7 +21,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (i.e. ".stl") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -39,8 +38,6 @@ private: // skip to next printable character after the first line break void goNextLine(io::IReadFile* file) const; - //! Read RGB color - const c8* readColor(const c8* pBufPtr, video::SColor& color, const c8* const pBufEnd) const; //! Read 3d vector of floats void getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary) const; }; diff --git a/src/dep/src/irrlicht/CSTLMeshWriter.cpp b/src/dep/src/irrlicht/CSTLMeshWriter.cpp index ca87c6a..965f533 100644 --- a/src/dep/src/irrlicht/CSTLMeshWriter.cpp +++ b/src/dep/src/irrlicht/CSTLMeshWriter.cpp @@ -1,8 +1,8 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "IrrCompileConfig.h" +#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_STL_WRITER_ @@ -66,7 +66,7 @@ bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s // write STL MESH header file->write("binary ",7); - const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); + const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh)); const s32 sizeleft = 73-name.size(); // 80 byte header if (sizeleft<0) file->write(name.c_str(),73); @@ -115,12 +115,12 @@ bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s3 // write STL MESH header file->write("solid ",6); - const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); + const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh)); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers - + for (u32 i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); diff --git a/src/dep/src/irrlicht/CSTLMeshWriter.h b/src/dep/src/irrlicht/CSTLMeshWriter.h index 1380245..6f7d7db 100644 --- a/src/dep/src/irrlicht/CSTLMeshWriter.h +++ b/src/dep/src/irrlicht/CSTLMeshWriter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CSceneCollisionManager.cpp b/src/dep/src/irrlicht/CSceneCollisionManager.cpp index 511b918..6e86456 100644 --- a/src/dep/src/irrlicht/CSceneCollisionManager.cpp +++ b/src/dep/src/irrlicht/CSceneCollisionManager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -10,7 +10,6 @@ #include "os.h" #include "irrMath.h" -#include // For FLT_MAX namespace irr { @@ -30,7 +29,6 @@ CSceneCollisionManager::CSceneCollisionManager(ISceneManager* smanager, video::I } - //! destructor CSceneCollisionManager::~CSceneCollisionManager() { @@ -39,33 +37,33 @@ CSceneCollisionManager::~CSceneCollisionManager() } - -//! Returns the scene node, which is currently visible under the overgiven -//! screencoordinates, viewed from the currently active camera. +//! Returns the scene node, which is currently visible at the given +//! screen coordinates, viewed from the currently active camera. ISceneNode* CSceneCollisionManager::getSceneNodeFromScreenCoordinatesBB( - core::position2d pos, s32 idBitMask, bool bNoDebugObjects) + const core::position2d& pos, s32 idBitMask, bool noDebugObjects, scene::ISceneNode* root) { - core::line3d ln = getRayFromScreenCoordinates(pos, 0); + const core::line3d ln = getRayFromScreenCoordinates(pos, 0); if ( ln.start == ln.end ) return 0; - return getSceneNodeFromRayBB(ln, idBitMask, bNoDebugObjects); + return getSceneNodeFromRayBB(ln, idBitMask, noDebugObjects, root); } - //! Returns the nearest scene node which collides with a 3d ray and //! which id matches a bitmask. -ISceneNode* CSceneCollisionManager::getSceneNodeFromRayBB(core::line3d ray, - s32 idBitMask, - bool bNoDebugObjects) +ISceneNode* CSceneCollisionManager::getSceneNodeFromRayBB( + const core::line3d& ray, + s32 idBitMask, bool noDebugObjects, scene::ISceneNode* root) { ISceneNode* best = 0; f32 dist = FLT_MAX; - getPickedNodeBB(SceneManager->getRootSceneNode(), ray, - idBitMask, bNoDebugObjects, dist, best); + core::line3d truncatableRay(ray); + + getPickedNodeBB((root==0)?SceneManager->getRootSceneNode():root, truncatableRay, + idBitMask, noDebugObjects, dist, best); return best; } @@ -73,87 +71,285 @@ ISceneNode* CSceneCollisionManager::getSceneNodeFromRayBB(core::line3d ray, //! recursive method for going through all scene nodes void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, - const core::line3df& ray, - s32 bits, - bool bNoDebugObjects, - f32& outbestdistance, - ISceneNode*& outbestnode) + core::line3df& ray, s32 bits, bool noDebugObjects, + f32& outbestdistance, ISceneNode*& outbestnode) { - core::vector3df edges[8]; + const ISceneNodeList& children = root->getChildren(); + const core::vector3df rayVector = ray.getVector().normalize(); - const core::list& children = root->getChildren(); + ISceneNodeList::ConstIterator it = children.begin(); + for (; it != children.end(); ++it) + { + ISceneNode* current = *it; - core::list::ConstIterator it = children.begin(); - for (; it != children.end(); ++it) - { - ISceneNode* current = *it; + if (current->isVisible()) + { + if((noDebugObjects ? !current->isDebugObject() : true) && + (bits==0 || (bits != 0 && (current->getID() & bits)))) + { + // get world to object space transform + core::matrix4 worldToObject; + if (!current->getAbsoluteTransformation().getInverse(worldToObject)) + continue; - if (current->isVisible() && - (bNoDebugObjects ? !current->isDebugObject() : true) && - (bits==0 || (bits != 0 && (current->getID() & bits)))) - { - // get world to object space transform - core::matrix4 mat; - if (!current->getAbsoluteTransformation().getInverse(mat)) - continue; + // transform vector from world space to object space + core::line3df objectRay(ray); + worldToObject.transformVect(objectRay.start); + worldToObject.transformVect(objectRay.end); - // transform vector from world space to object space - core::line3df line(ray); - mat.transformVect(line.start); - mat.transformVect(line.end); + const core::aabbox3df & objectBox = current->getBoundingBox(); - const core::aabbox3df& box = current->getBoundingBox(); + // Do the initial intersection test in object space, since the + // object space box test is more accurate. + if(objectBox.isPointInside(objectRay.start)) + { + // use fast bbox intersection to find distance to hitpoint + // algorithm from Kay et al., code from gamedev.net + const core::vector3df dir = (objectRay.end-objectRay.start).normalize(); + const core::vector3df minDist = (objectBox.MinEdge - objectRay.start)/dir; + const core::vector3df maxDist = (objectBox.MaxEdge - objectRay.start)/dir; + const core::vector3df realMin(core::min_(minDist.X, maxDist.X),core::min_(minDist.Y, maxDist.Y),core::min_(minDist.Z, maxDist.Z)); + const core::vector3df realMax(core::max_(minDist.X, maxDist.X),core::max_(minDist.Y, maxDist.Y),core::max_(minDist.Z, maxDist.Z)); - // do intersection test in object space - if (box.intersectsWithLine(line)) - { - box.getEdges(edges); - f32 distance = 0.0f; + const f32 minmax = core::min_(realMax.X, realMax.Y, realMax.Z); + // nearest distance to intersection + const f32 maxmin = core::max_(realMin.X, realMin.Y, realMin.Z); - for (s32 e=0; e<8; ++e) - { - f32 t = edges[e].getDistanceFromSQ(line.start); - if (t > distance) - distance = t; - } + const f32 toIntersectionSq = (maxmin>0?maxmin*maxmin:minmax*minmax); + if (toIntersectionSq < outbestdistance) + { + outbestdistance = toIntersectionSq; + outbestnode = current; - if (distance < outbestdistance) - { - outbestnode = current; - outbestdistance = distance; - } - } - } + // And we can truncate the ray to stop us hitting further nodes. + ray.end = ray.start + (rayVector * sqrtf(toIntersectionSq)); + } + } + else + if (objectBox.intersectsWithLine(objectRay)) + { + // Now transform into world space, since we need to use world space + // scales and distances. + core::aabbox3df worldBox(objectBox); + current->getAbsoluteTransformation().transformBox(worldBox); - getPickedNodeBB(current, ray, bits, bNoDebugObjects, outbestdistance, outbestnode); - } -} + core::vector3df edges[8]; + worldBox.getEdges(edges); + /* We need to check against each of 6 faces, composed of these corners: + /3--------/7 + / | / | + / | / | + 1---------5 | + | 2- - -| -6 + | / | / + |/ | / + 0---------4/ + + Note that we define them as opposite pairs of faces. + */ + static const s32 faceEdges[6][3] = + { + { 0, 1, 5 }, // Front + { 6, 7, 3 }, // Back + { 2, 3, 1 }, // Left + { 4, 5, 7 }, // Right + { 1, 3, 7 }, // Top + { 2, 0, 4 } // Bottom + }; + + core::vector3df intersection; + core::plane3df facePlane; + f32 bestDistToBoxBorder = FLT_MAX; + f32 bestToIntersectionSq = FLT_MAX; + + for(s32 face = 0; face < 6; ++face) + { + facePlane.setPlane(edges[faceEdges[face][0]], + edges[faceEdges[face][1]], + edges[faceEdges[face][2]]); + + // Only consider lines that might be entering through this face, since we + // already know that the start point is outside the box. + if(facePlane.classifyPointRelation(ray.start) != core::ISREL3D_FRONT) + continue; + + // Don't bother using a limited ray, since we already know that it should be long + // enough to intersect with the box. + if(facePlane.getIntersectionWithLine(ray.start, rayVector, intersection)) + { + const f32 toIntersectionSq = ray.start.getDistanceFromSQ(intersection); + if(toIntersectionSq < outbestdistance) + { + // We have to check that the intersection with this plane is actually + // on the box, so need to go back to object space again. + worldToObject.transformVect(intersection); + + // find the closest point on the box borders. Have to do this as exact checks will fail due to floating point problems. + f32 distToBorder = core::max_ ( core::min_ (core::abs_(objectBox.MinEdge.X-intersection.X), core::abs_(objectBox.MaxEdge.X-intersection.X)), + core::min_ (core::abs_(objectBox.MinEdge.Y-intersection.Y), core::abs_(objectBox.MaxEdge.Y-intersection.Y)), + core::min_ (core::abs_(objectBox.MinEdge.Z-intersection.Z), core::abs_(objectBox.MaxEdge.Z-intersection.Z)) ); + if ( distToBorder < bestDistToBoxBorder ) + { + bestDistToBoxBorder = distToBorder; + bestToIntersectionSq = toIntersectionSq; + } + } + } + + // If the ray could be entering through the first face of a pair, then it can't + // also be entering through the opposite face, and so we can skip that face. + if (!(face & 0x01)) + ++face; + } + + if ( bestDistToBoxBorder < FLT_MAX ) + { + outbestdistance = bestToIntersectionSq; + outbestnode = current; + + // If we got a hit, we can now truncate the ray to stop us hitting further nodes. + ray.end = ray.start + (rayVector * sqrtf(outbestdistance)); + } + } + } + + // Only check the children if this node is visible. + getPickedNodeBB(current, ray, bits, noDebugObjects, outbestdistance, outbestnode); + } + } +} + + +ISceneNode* CSceneCollisionManager::getSceneNodeAndCollisionPointFromRay( + core::line3df ray, + core::vector3df & outCollisionPoint, + core::triangle3df & outTriangle, + s32 idBitMask, + ISceneNode * collisionRootNode, + bool noDebugObjects) +{ + ISceneNode* bestNode = 0; + f32 bestDistanceSquared = FLT_MAX; + + if(0 == collisionRootNode) + collisionRootNode = SceneManager->getRootSceneNode(); + + // We don't try to do anything too clever, like sorting the candidate + // nodes by distance to bounding-box. In the example below, we could do the + // triangle collision check with node A first, but we'd have to check node B + // anyway, as the actual collision point could be (and is) closer than the + // collision point in node A. + // + // ray end + // | + // AAAAAAAAAA + // A | + // A | B + // A | B + // A BBBBB + // A | + // A | + // | + // | + // ray start + // + // We therefore have to do a full BB and triangle collision on every scene + // node in order to find the nearest collision point, so sorting them by + // bounding box would be pointless. + + getPickedNodeFromBBAndSelector(collisionRootNode, ray, idBitMask, + noDebugObjects, bestDistanceSquared, bestNode, + outCollisionPoint, outTriangle); + return bestNode; +} + + +void CSceneCollisionManager::getPickedNodeFromBBAndSelector( + ISceneNode * root, + core::line3df & ray, + s32 bits, + bool noDebugObjects, + f32 & outBestDistanceSquared, + ISceneNode * & outBestNode, + core::vector3df & outBestCollisionPoint, + core::triangle3df & outBestTriangle) +{ + const ISceneNodeList& children = root->getChildren(); + + ISceneNodeList::ConstIterator it = children.begin(); + for (; it != children.end(); ++it) + { + ISceneNode* current = *it; + ITriangleSelector * selector = current->getTriangleSelector(); + + if (selector && current->isVisible() && + (noDebugObjects ? !current->isDebugObject() : true) && + (bits==0 || (bits != 0 && (current->getID() & bits)))) + { + // get world to object space transform + core::matrix4 mat; + if (!current->getAbsoluteTransformation().getInverse(mat)) + continue; + + // transform vector from world space to object space + core::line3df line(ray); + mat.transformVect(line.start); + mat.transformVect(line.end); + + const core::aabbox3df& box = current->getBoundingBox(); + + core::vector3df candidateCollisionPoint; + core::triangle3df candidateTriangle; + + // do intersection test in object space + const ISceneNode * hitNode = 0; + if (box.intersectsWithLine(line) && + getCollisionPoint(ray, selector, candidateCollisionPoint, candidateTriangle, hitNode)) + { + const f32 distanceSquared = (candidateCollisionPoint - ray.start).getLengthSQ(); + + if(distanceSquared < outBestDistanceSquared) + { + outBestDistanceSquared = distanceSquared; + outBestNode = current; + outBestCollisionPoint = candidateCollisionPoint; + outBestTriangle = candidateTriangle; + const core::vector3df rayVector = ray.getVector().normalize(); + ray.end = ray.start + (rayVector * sqrtf(distanceSquared)); + } + } + } + + getPickedNodeFromBBAndSelector(current, ray, bits, noDebugObjects, + outBestDistanceSquared, outBestNode, + outBestCollisionPoint, outBestTriangle); + } +} //! Returns the scene node, at which the overgiven camera is looking at and //! which id matches the bitmask. ISceneNode* CSceneCollisionManager::getSceneNodeFromCameraBB( - ICameraSceneNode* camera, s32 idBitMask, bool bNoDebugObjects) + ICameraSceneNode* camera, s32 idBitMask, bool noDebugObjects) { if (!camera) return 0; - core::vector3df start = camera->getAbsolutePosition(); + const core::vector3df start = camera->getAbsolutePosition(); core::vector3df end = camera->getTarget(); end = start + ((end - start).normalize() * camera->getFarValue()); - core::line3d line(start, end); - return getSceneNodeFromRayBB(line, idBitMask, bNoDebugObjects); + return getSceneNodeFromRayBB(core::line3d(start, end), idBitMask, noDebugObjects); } - //! Finds the collision point of a line and lots of triangles, if there is one. bool CSceneCollisionManager::getCollisionPoint(const core::line3d& ray, - ITriangleSelector* selector, core::vector3df& outIntersection, - core::triangle3df& outTriangle) + ITriangleSelector* selector, core::vector3df& outIntersection, + core::triangle3df& outTriangle, + const ISceneNode*& outNode) { if (!selector) { @@ -197,11 +393,6 @@ bool CSceneCollisionManager::getCollisionPoint(const core::line3d& ray, if(maxZ < triangle.pointA.Z && maxZ < triangle.pointB.Z && maxZ < triangle.pointC.Z) continue; - if(ray.start.getDistanceFromSQ(triangle.pointA) >= nearest && - ray.start.getDistanceFromSQ(triangle.pointB) >= nearest && - ray.start.getDistanceFromSQ(triangle.pointC) >= nearest) - continue; - if (triangle.getIntersectionWithLine(ray.start, linevect, intersection)) { const f32 tmp = intersection.getDistanceFromSQ(ray.start); @@ -212,6 +403,7 @@ bool CSceneCollisionManager::getCollisionPoint(const core::line3d& ray, nearest = tmp; outTriangle = triangle; outIntersection = intersection; + outNode = selector->getSceneNodeForTriangle(i); found = true; } } @@ -222,34 +414,32 @@ bool CSceneCollisionManager::getCollisionPoint(const core::line3d& ray, } - //! Collides a moving ellipsoid with a 3d world with gravity and returns //! the resulting new position of the ellipsoid. core::vector3df CSceneCollisionManager::getCollisionResultPosition( - ITriangleSelector* selector, - const core::vector3df &position, const core::vector3df& radius, - const core::vector3df& direction, - core::triangle3df& triout, - bool& outFalling, - f32 slidingSpeed, - const core::vector3df& gravity) + ITriangleSelector* selector, + const core::vector3df &position, const core::vector3df& radius, + const core::vector3df& direction, + core::triangle3df& triout, + core::vector3df& hitPosition, + bool& outFalling, + const ISceneNode*& outNode, + f32 slidingSpeed, + const core::vector3df& gravity) { - if (!selector || radius.X == 0.0f || radius.Y == 0.0f || radius.Z == 0.0f) - return position; - return collideEllipsoidWithWorld(selector, position, - radius, direction, slidingSpeed, gravity, triout, outFalling); + radius, direction, slidingSpeed, gravity, triout, hitPosition, outFalling, outNode); } -void CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData, +bool CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData, const core::triangle3df& triangle) { const core::plane3d trianglePlane = triangle.getPlane(); // only check front facing polygons if ( !trianglePlane.isFrontFacing(colData->normalizedVelocity) ) - return; + return false; // get interval of plane intersection @@ -268,7 +458,7 @@ void CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData, // sphere is traveling parallel to plane if (fabs(signedDistToTrianglePlane) >= 1.0f) - return; // no collision possible + return false; // no collision possible else { // sphere is embedded in plane @@ -290,7 +480,7 @@ void CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData, // check if at least one value is within the range if (t0 > 1.0f || t1 < 0.0f) - return; // both t values are outside 1 and 0, no collision possible + return false; // both t values are outside 1 and 0, no collision possible // clamp to 0 and 1 t0 = core::clamp ( t0, 0.f, 1.f ); @@ -314,7 +504,7 @@ void CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData, (colData->basePoint - trianglePlane.Normal) + (colData->velocity * t0); - if (triangle.isPointInsideFast(planeIntersectionPoint)) + if (triangle.isPointInside(planeIntersectionPoint)) { foundCollision = true; t = t0; @@ -483,21 +673,25 @@ void CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData, colData->foundCollision = true; colData->intersectionTriangle = triangle; ++colData->triangleHits; + return true; } - }// end found collision -} + return false; +} //! Collides a moving ellipsoid with a 3d world with gravity and returns //! the resulting new position of the ellipsoid. core::vector3df CSceneCollisionManager::collideEllipsoidWithWorld( - ITriangleSelector* selector, const core::vector3df &position, - const core::vector3df& radius, const core::vector3df& velocity, - f32 slidingSpeed, - const core::vector3df& gravity, - core::triangle3df& triout, bool& outFalling) + ITriangleSelector* selector, const core::vector3df &position, + const core::vector3df& radius, const core::vector3df& velocity, + f32 slidingSpeed, + const core::vector3df& gravity, + core::triangle3df& triout, + core::vector3df& hitPosition, + bool& outFalling, + const ISceneNode*& outNode) { if (!selector || radius.X == 0.0f || radius.Y == 0.0f || radius.Z == 0.0f) return position; @@ -513,6 +707,7 @@ core::vector3df CSceneCollisionManager::collideEllipsoidWithWorld( colData.selector = selector; colData.slidingSpeed = slidingSpeed; colData.triangleHits = 0; + colData.triangleIndex = -1; core::vector3df eSpacePosition = colData.R3Position / colData.eRadius; core::vector3df eSpaceVelocity = colData.R3Velocity / colData.eRadius; @@ -546,12 +741,15 @@ core::vector3df CSceneCollisionManager::collideEllipsoidWithWorld( triout.pointA *= colData.eRadius; triout.pointB *= colData.eRadius; triout.pointC *= colData.eRadius; + outNode = selector->getSceneNodeForTriangle(colData.triangleIndex); } finalPos *= colData.eRadius; + hitPosition = colData.intersectionPoint * colData.eRadius; return finalPos; } + core::vector3df CSceneCollisionManager::collideWithWorld(s32 recursionDepth, SCollisionData &colData, core::vector3df pos, core::vector3df vel) { @@ -580,17 +778,16 @@ core::vector3df CSceneCollisionManager::collideWithWorld(s32 recursionDepth, core::matrix4 scaleMatrix; scaleMatrix.setScale( - core::vector3df(1.0f / colData.eRadius.X, - 1.0f / colData.eRadius.Y, - 1.0f / colData.eRadius.Z) - ); + core::vector3df(1.0f / colData.eRadius.X, + 1.0f / colData.eRadius.Y, + 1.0f / colData.eRadius.Z)); s32 triangleCnt = 0; colData.selector->getTriangles(Triangles.pointer(), totalTriangleCnt, triangleCnt, box, &scaleMatrix); - //colData.selector->getTriangles(Triangles.pointer(), totalTriangleCnt, triangleCnt, &scaleMatrix); for (s32 i=0; i slidingPlane(slidePlaneOrigin, slidePlaneNormal); core::vector3df newDestinationPoint = @@ -627,7 +823,7 @@ core::vector3df CSceneCollisionManager::collideWithWorld(s32 recursionDepth, // generate slide vector - core::vector3df newVelocityVector = newDestinationPoint - + const core::vector3df newVelocityVector = newDestinationPoint - colData.intersectionPoint; if (newVelocityVector.getLength() < veryCloseDistance) @@ -640,7 +836,7 @@ core::vector3df CSceneCollisionManager::collideWithWorld(s32 recursionDepth, //! Returns a 3d ray which would go through the 2d screen coodinates. core::line3d CSceneCollisionManager::getRayFromScreenCoordinates( - core::position2d pos, ICameraSceneNode* camera) + const core::position2d & pos, ICameraSceneNode* camera) { core::line3d ln(0,0,0,0,0,0); @@ -660,7 +856,7 @@ core::line3d CSceneCollisionManager::getRayFromScreenCoordinates( core::vector3df uptodown = f->getFarLeftDown() - farLeftUp; const core::rect& viewPort = Driver->getViewPort(); - core::dimension2d screenSize(viewPort.getWidth(), viewPort.getHeight()); + core::dimension2d screenSize(viewPort.getWidth(), viewPort.getHeight()); f32 dx = pos.X / (f32)screenSize.Width; f32 dy = pos.Y / (f32)screenSize.Height; @@ -678,7 +874,7 @@ core::line3d CSceneCollisionManager::getRayFromScreenCoordinates( //! Calculates 2d screen position from a 3d position. core::position2d CSceneCollisionManager::getScreenCoordinatesFrom3DPosition( - core::vector3df pos3d, ICameraSceneNode* camera) + const core::vector3df & pos3d, ICameraSceneNode* camera) { if (!SceneManager || !Driver) return core::position2d(-1000,-1000); @@ -690,7 +886,7 @@ core::position2d CSceneCollisionManager::getScreenCoordinatesFrom3DPosition return core::position2d(-1000,-1000); const core::rect& viewPort = Driver->getViewPort(); - core::dimension2d dim(viewPort.getWidth(), viewPort.getHeight()); + core::dimension2d dim(viewPort.getWidth(), viewPort.getHeight()); dim.Width /= 2; dim.Height /= 2; @@ -755,4 +951,3 @@ inline bool CSceneCollisionManager::getLowestRoot(f32 a, f32 b, f32 c, f32 maxR, } // end namespace scene } // end namespace irr - diff --git a/src/dep/src/irrlicht/CSceneCollisionManager.h b/src/dep/src/irrlicht/CSceneCollisionManager.h index 95ac9e4..d41970d 100644 --- a/src/dep/src/irrlicht/CSceneCollisionManager.h +++ b/src/dep/src/irrlicht/CSceneCollisionManager.h @@ -1,10 +1,10 @@ -#ifndef __C_SCENE_COLLISION_MANAGER_H_INCLUDED__ -#define __C_SCENE_COLLISION_MANAGER_H_INCLUDED__ - -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h +#ifndef __C_SCENE_COLLISION_MANAGER_H_INCLUDED__ +#define __C_SCENE_COLLISION_MANAGER_H_INCLUDED__ + #include "ISceneCollisionManager.h" #include "ISceneManager.h" #include "IVideoDriver.h" @@ -14,7 +14,7 @@ namespace irr namespace scene { - //! The Scene Collision Manager provides methods for performing collision tests and picking on scene nodes. + //! The Scene Collision Manager provides methods for performing collision tests and picking on scene nodes. class CSceneCollisionManager : public ISceneCollisionManager { public: @@ -25,60 +25,84 @@ namespace scene //! destructor virtual ~CSceneCollisionManager(); - //! Returns the scene node, which is currently visible under the overgiven - //! screencoordinates, viewed from the currently active camera. - virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(core::position2d pos, - s32 idBitMask=0, bool bNoDebugObjects = false); + //! Returns the scene node, which is currently visible at the given + //! screen coordinates, viewed from the currently active camera. + virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(const core::position2d& pos, + s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0); - //! Returns the nearest scene node which collides with a 3d ray and - //! which id matches a bitmask. - virtual ISceneNode* getSceneNodeFromRayBB(core::line3d ray, s32 idBitMask=0, - bool bNoDebugObjects = false); + //! Returns the nearest scene node which collides with a 3d ray and + //! whose id matches a bitmask. + virtual ISceneNode* getSceneNodeFromRayBB(const core::line3d& ray, + s32 idBitMask=0, bool bNoDebugObjects=false, + ISceneNode* root=0); //! Returns the scene node, at which the overgiven camera is looking at and //! which id matches the bitmask. - virtual ISceneNode* getSceneNodeFromCameraBB(ICameraSceneNode* camera, s32 idBitMask=0, - bool bNoDebugObjects = false); + virtual ISceneNode* getSceneNodeFromCameraBB(ICameraSceneNode* camera, + s32 idBitMask=0, bool bNoDebugObjects = false); //! Finds the collision point of a line and lots of triangles, if there is one. virtual bool getCollisionPoint(const core::line3d& ray, ITriangleSelector* selector, core::vector3df& outCollisionPoint, - core::triangle3df& outTriangle); + core::triangle3df& outTriangle, + const ISceneNode* & outNode); //! Collides a moving ellipsoid with a 3d world with gravity and returns - //! the resulting new position of the ellipsoid. + //! the resulting new position of the ellipsoid. virtual core::vector3df getCollisionResultPosition( ITriangleSelector* selector, - const core::vector3df &ellipsoidPosition, const core::vector3df& ellipsoidRadius, + const core::vector3df &ellipsoidPosition, + const core::vector3df& ellipsoidRadius, const core::vector3df& ellipsoidDirectionAndSpeed, core::triangle3df& triout, + core::vector3df& hitPosition, bool& outFalling, + const ISceneNode*& outNode, f32 slidingSpeed, const core::vector3df& gravityDirectionAndSpeed); //! Returns a 3d ray which would go through the 2d screen coodinates. virtual core::line3d getRayFromScreenCoordinates( - core::position2d pos, ICameraSceneNode* camera = 0); + const core::position2d & pos, ICameraSceneNode* camera = 0); //! Calculates 2d screen position from a 3d position. virtual core::position2d getScreenCoordinatesFrom3DPosition( - core::vector3df pos, ICameraSceneNode* camera=0); + const core::vector3df & pos, ICameraSceneNode* camera=0); + + //! Gets the scene node and nearest collision point for a ray based on + //! the nodes' id bitmasks, bounding boxes and triangle selectors. + virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( + core::line3df ray, + core::vector3df & outCollisionPoint, + core::triangle3df & outTriangle, + s32 idBitMask = 0, + ISceneNode * collisionRootNode = 0, + bool noDebugObjects = false); + private: //! recursive method for going through all scene nodes - void getPickedNodeBB(ISceneNode* root, - const core::line3df& ray, - s32 bits, - bool bNoDebugObjects, - f32& outbestdistance, - ISceneNode*& outbestnode); + void getPickedNodeBB(ISceneNode* root, core::line3df& ray, s32 bits, + bool bNoDebugObjects, + f32& outbestdistance, ISceneNode*& outbestnode); + + //! recursive method for going through all scene nodes + void getPickedNodeFromBBAndSelector(ISceneNode * root, + core::line3df & ray, + s32 bits, + bool noDebugObjects, + f32 & outBestDistanceSquared, + ISceneNode * & outBestNode, + core::vector3df & outBestCollisionPoint, + core::triangle3df & outBestTriangle); + struct SCollisionData { core::vector3df eRadius; - core::vector3df R3Velocity; + core::vector3df R3Velocity; core::vector3df R3Position; core::vector3df velocity; @@ -90,6 +114,7 @@ namespace scene core::vector3df intersectionPoint; core::triangle3df intersectionTriangle; + s32 triangleIndex; s32 triangleHits; f32 slidingSpeed; @@ -97,16 +122,23 @@ namespace scene ITriangleSelector* selector; }; - void testTriangleIntersection(SCollisionData* colData, + //! Tests the current collision data against an individual triangle. + /** + \param colData: the collision data. + \param triangle: the triangle to test against. + \return true if the triangle is hit (and is the closest hit), false otherwise */ + bool testTriangleIntersection(SCollisionData* colData, const core::triangle3df& triangle); //! recursive method for doing collision response - core::vector3df collideEllipsoidWithWorld(ITriangleSelector* selector, + core::vector3df collideEllipsoidWithWorld(ITriangleSelector* selector, const core::vector3df &position, const core::vector3df& radius, const core::vector3df& velocity, f32 slidingSpeed, const core::vector3df& gravity, core::triangle3df& triout, - bool& outFalling); + core::vector3df& hitPosition, + bool& outFalling, + const ISceneNode*& outNode); core::vector3df collideWithWorld(s32 recursionDepth, SCollisionData &colData, core::vector3df pos, core::vector3df vel); @@ -115,7 +147,7 @@ namespace scene ISceneManager* SceneManager; video::IVideoDriver* Driver; - core::array Triangles; // triangle buffer + core::array Triangles; // triangle buffer }; diff --git a/src/dep/src/irrlicht/CSceneManager.cpp b/src/dep/src/irrlicht/CSceneManager.cpp index 596ed8c..8cb1fb9 100644 --- a/src/dep/src/irrlicht/CSceneManager.cpp +++ b/src/dep/src/irrlicht/CSceneManager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,8 +17,6 @@ #include "os.h" -#include "CGeometryCreator.h" - #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ #include "CIrrMeshFileLoader.h" #endif @@ -91,6 +89,10 @@ #include "CSTLMeshFileLoader.h" #endif +#ifdef _IRR_COMPILE_WITH_PLY_LOADER_ +#include "CPLYMeshFileLoader.h" +#endif + #ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_ #include "CColladaMeshWriter.h" #endif @@ -107,10 +109,14 @@ #include "COBJMeshWriter.h" #endif +#ifdef _IRR_COMPILE_WITH_PLY_WRITER_ +#include "CPLYMeshWriter.h" +#endif + #include "CCubeSceneNode.h" #include "CSphereSceneNode.h" #include "CAnimatedMeshSceneNode.h" -#include "COctTreeSceneNode.h" +#include "COctreeSceneNode.h" #include "CCameraSceneNode.h" #include "CLightSceneNode.h" @@ -128,7 +134,7 @@ #include "CSceneCollisionManager.h" #include "CTriangleSelector.h" -#include "COctTreeTriangleSelector.h" +#include "COctreeTriangleSelector.h" #include "CTriangleBBSelector.h" #include "CMetaTriangleSelector.h" #include "CTerrainTriangleSelector.h" @@ -146,6 +152,7 @@ #include "CQuake3ShaderSceneNode.h" #include "CVolumeLightSceneNode.h" +#include "CGeometryCreator.h" //! Enable debug features #define SCENEMANAGER_DEBUG @@ -162,7 +169,7 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, : ISceneNode(0, 0), Driver(driver), FileSystem(fs), GUIEnvironment(gui), CursorControl(cursorControl), CollisionManager(0), ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), - MeshCache(cache), CurrentRendertime(ESNRP_COUNT), + MeshCache(cache), CurrentRendertime(ESNRP_NONE), LightManager(0), IRR_XML_FORMAT_SCENE(L"irr_scene"), IRR_XML_FORMAT_NODE(L"node"), IRR_XML_FORMAT_NODE_ATTR_TYPE(L"type") { #ifdef _DEBUG @@ -173,6 +180,10 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, // root node's scene manager SceneManager = this; + // set scene parameters + Parameters.setAttribute( DEBUG_NORMAL_LENGTH, 1.f ); + Parameters.setAttribute( DEBUG_NORMAL_COLOR, video::SColor(255, 34, 221, 221)); + if (Driver) Driver->grab(); @@ -194,6 +205,9 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, // create collision manager CollisionManager = new CSceneCollisionManager(this, Driver); + // create geometry creator + GeometryCreator = new CGeometryCreator(); + // add file format loaders #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ @@ -239,7 +253,7 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, MeshLoaderList.push_back(new COBJMeshFileLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ - MeshLoaderList.push_back(new CMD3MeshFileLoader()); + MeshLoaderList.push_back(new CMD3MeshFileLoader( this)); #endif #ifdef _IRR_COMPILE_WITH_B3D_LOADER_ MeshLoaderList.push_back(new CB3DMeshFileLoader(this)); @@ -250,6 +264,9 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, #ifdef _IRR_COMPILE_WITH_STL_LOADER_ MeshLoaderList.push_back(new CSTLMeshFileLoader()); #endif + #ifdef _IRR_COMPILE_WITH_PLY_LOADER_ + MeshLoaderList.push_back(new CPLYMeshFileLoader()); + #endif // factories ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this); @@ -262,7 +279,6 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, } - //! destructor CSceneManager::~CSceneManager() { @@ -277,6 +293,9 @@ CSceneManager::~CSceneManager() if (CollisionManager) CollisionManager->drop(); + if (GeometryCreator) + GeometryCreator->drop(); + if (GUIEnvironment) GUIEnvironment->drop(); @@ -298,8 +317,18 @@ CSceneManager::~CSceneManager() for (i=0; idrop(); + //! force to remove hardwareTextures from the driver + //! because Scenes may hold internally data bounded to sceneNodes + //! which may be destroyed twice + if (Driver) + Driver->removeAllHardwareBuffers (); + + if(LightManager) + LightManager->drop(); + // remove all nodes and animators before dropping the driver // as render targets may be destroyed twice + removeAll(); removeAnimators(); @@ -309,25 +338,23 @@ CSceneManager::~CSceneManager() //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. -IAnimatedMesh* CSceneManager::getMesh(const c8* filename) +IAnimatedMesh* CSceneManager::getMesh(const io::path& filename) { - IAnimatedMesh* msh = MeshCache->getMeshByFilename(filename); + IAnimatedMesh* msh = MeshCache->getMeshByName(filename); if (msh) return msh; io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (!file) { - os::Printer::log("Could not load mesh, because file could not be opened.", filename, ELL_ERROR); + os::Printer::log("Could not load mesh, because file could not be opened: ", filename, ELL_ERROR); return 0; } - core::stringc name = filename; - name.make_lower(); s32 count = MeshLoaderList.size(); for (s32 i=count-1; i>=0; --i) { - if (MeshLoaderList[i]->isALoadableFileExtension(name.c_str())) + if (MeshLoaderList[i]->isALoadableFileExtension(filename)) { // reset file to avoid side effects of previous calls to createMesh file->seek(0); @@ -358,16 +385,15 @@ IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file) if (!file) return 0; - core::stringc name = file->getFileName(); - IAnimatedMesh* msh = MeshCache->getMeshByFilename(file->getFileName()); + io::path name = file->getFileName(); + IAnimatedMesh* msh = MeshCache->getMeshByName(file->getFileName()); if (msh) return msh; - name.make_lower(); s32 count = MeshLoaderList.size(); for (s32 i=count-1; i>=0; --i) { - if (MeshLoaderList[i]->isALoadableFileExtension(name.c_str())) + if (MeshLoaderList[i]->isALoadableFileExtension(name)) { // reset file to avoid side effects of previous calls to createMesh file->seek(0); @@ -403,6 +429,15 @@ gui::IGUIEnvironment* CSceneManager::getGUIEnvironment() return GUIEnvironment; } +//! Get the active FileSystem +/** \return Pointer to the FileSystem +This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ +io::IFileSystem* CSceneManager::getFileSystem() +{ + return FileSystem; +} + + //! Adds a text scene node, which is able to display //! 2d text at a position in three dimensional space @@ -450,9 +485,9 @@ IBillboardTextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont* //! Adds a scene node, which can render a quake3 shader -ISceneNode* CSceneManager::addQuake3SceneNode(IMeshBuffer* meshBuffer, - const quake3::SShader * shader, - ISceneNode* parent, s32 id) +IMeshSceneNode* CSceneManager::addQuake3SceneNode(const IMeshBuffer* meshBuffer, + const quake3::IShader * shader, + ISceneNode* parent, s32 id ) { #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ if ( 0 == shader ) @@ -461,7 +496,9 @@ ISceneNode* CSceneManager::addQuake3SceneNode(IMeshBuffer* meshBuffer, if (!parent) parent = this; - CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode( parent, this, id, FileSystem, meshBuffer, shader ); + CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode( parent, + this, id, FileSystem, + meshBuffer, shader ); node->drop(); return node; @@ -470,12 +507,14 @@ ISceneNode* CSceneManager::addQuake3SceneNode(IMeshBuffer* meshBuffer, #endif } + //! adds Volume Lighting Scene Node. //! the returned pointer must not be dropped. -IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode(ISceneNode* parent, s32 id, - const u32 subdivU, const u32 subdivV, - const video::SColor foot, const video::SColor tail, - const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) +IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode( + ISceneNode* parent, s32 id, + const u32 subdivU, const u32 subdivV, + const video::SColor foot, const video::SColor tail, + const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) { if (!parent) parent = this; @@ -486,6 +525,7 @@ IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode(ISceneNode* parent return node; } + //! adds a test scene node for test purposes to the scene. It is a simple cube of (1,1,1) size. //! the returned pointer must not be dropped. IMeshSceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent, @@ -575,25 +615,25 @@ IAnimatedMeshSceneNode* CSceneManager::addAnimatedMeshSceneNode(IAnimatedMesh* m } -//! Adds a scene node for rendering using a octtree to the scene graph. This a good method for rendering +//! Adds a scene node for rendering using a octree to the scene graph. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. -ISceneNode* CSceneManager::addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, +IMeshSceneNode* CSceneManager::addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) { if (!alsoAddIfMeshPointerZero && (!mesh || !mesh->getFrameCount())) return 0; - return addOctTreeSceneNode(mesh ? mesh->getMesh(0) : 0, + return addOctreeSceneNode(mesh ? mesh->getMesh(0) : 0, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); } -//! Adss a scene node for rendering using a octtree. This a good method for rendering +//! Adds a scene node for rendering using a octree. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. -ISceneNode* CSceneManager::addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent, +IMeshSceneNode* CSceneManager::addOctreeSceneNode(IMesh* mesh, ISceneNode* parent, s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) { if (!alsoAddIfMeshPointerZero && !mesh) @@ -602,12 +642,13 @@ ISceneNode* CSceneManager::addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent, if (!parent) parent = this; - COctTreeSceneNode* node = new COctTreeSceneNode(parent, this, id, minimalPolysPerNode); + COctreeSceneNode* node = new COctreeSceneNode(parent, this, id, minimalPolysPerNode); - if (mesh) - node->createTree(mesh); - - node->drop(); + if (node) + { + node->setMesh(mesh); + node->drop(); + } return node; } @@ -620,65 +661,64 @@ ISceneNode* CSceneManager::addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent, //! the camera will move too. //! \return Returns pointer to interface to camera ICameraSceneNode* CSceneManager::addCameraSceneNode(ISceneNode* parent, - const core::vector3df& position, const core::vector3df& lookat, s32 id) + const core::vector3df& position, const core::vector3df& lookat, s32 id, + bool makeActive) { if (!parent) parent = this; ICameraSceneNode* node = new CCameraSceneNode(parent, this, id, position, lookat); - node->drop(); - setActiveCamera(node); + if (makeActive) + setActiveCamera(node); + node->drop(); return node; } -//! Adds a camera scene node which is able to be controlld with the mouse similar +//! Adds a camera scene node which is able to be controlled with the mouse similar //! to in the 3D Software Maya by Alias Wavefront. //! The returned pointer must not be dropped. ICameraSceneNode* CSceneManager::addCameraSceneNodeMaya(ISceneNode* parent, - f32 rotateSpeed, f32 zoomSpeed, f32 translationSpeed, s32 id) + f32 rotateSpeed, f32 zoomSpeed, f32 translationSpeed, s32 id, + bool makeActive) { - if (!parent) - parent = this; + ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(), + core::vector3df(0,0,100), id, makeActive); + if (node) + { + ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraMaya(CursorControl, + rotateSpeed, zoomSpeed, translationSpeed); - ICameraSceneNode* node = new CCameraSceneNode(parent, this, id); - ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraMaya(CursorControl, - rotateSpeed, zoomSpeed, translationSpeed); - - node->addAnimator(anm); - setActiveCamera(node); - - anm->drop(); - node->drop(); + node->addAnimator(anm); + anm->drop(); + } return node; } -//! Adds a camera scene node which is able to be controled with the mouse and keys +//! Adds a camera scene node which is able to be controlled with the mouse and keys //! like in most first person shooters (FPS): ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent, - f32 rotateSpeed, f32 moveSpeed, s32 id, - SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement,f32 jumpSpeed) + f32 rotateSpeed, f32 moveSpeed, s32 id, SKeyMap* keyMapArray, + s32 keyMapSize, bool noVerticalMovement, f32 jumpSpeed, + bool invertMouseY, bool makeActive) { - if (!parent) - parent = this; + ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(), + core::vector3df(0,0,100), id, makeActive); + if (node) + { + ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl, + rotateSpeed, moveSpeed, jumpSpeed, + keyMapArray, keyMapSize, noVerticalMovement, invertMouseY); - ICameraSceneNode* node = new CCameraSceneNode(parent, this, id); - 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); - setActiveCamera(node); - - anm->drop(); - node->drop(); + // 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(); + } return node; } @@ -719,7 +759,6 @@ IBillboardSceneNode* CSceneManager::addBillboardSceneNode(ISceneNode* parent, } - //! Adds a skybox scene node. A skybox is a big cube with 6 textures on it and //! is drawn around the camera position. ISceneNode* CSceneManager::addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, @@ -740,14 +779,14 @@ ISceneNode* CSceneManager::addSkyBoxSceneNode(video::ITexture* top, video::IText //! 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. ISceneNode* CSceneManager::addSkyDomeSceneNode(video::ITexture* texture, - u32 horiRes, u32 vertRes, f64 texturePercentage, - f64 spherePercentage, ISceneNode* parent, s32 id) + u32 horiRes, u32 vertRes, f32 texturePercentage,f32 spherePercentage, f32 radius, + ISceneNode* parent, s32 id) { if (!parent) parent = this; ISceneNode* node = new CSkyDomeSceneNode(texture, horiRes, vertRes, - texturePercentage, spherePercentage, parent, this, id); + texturePercentage, spherePercentage, radius, parent, this, id); node->drop(); return node; @@ -773,7 +812,7 @@ IParticleSystemSceneNode* CSceneManager::addParticleSystemSceneNode( //! Adds a terrain scene node to the scene graph. ITerrainSceneNode* CSceneManager::addTerrainSceneNode( - const char* heightMapFileName, + const io::path& heightMapFileName, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, @@ -873,20 +912,17 @@ IDummyTransformationSceneNode* CSceneManager::addDummyTransformationSceneNode( //! specify a name for the mesh, because the mesh is added to the mesh pool, //! and can be retrieved again using ISceneManager::getMesh with the name as //! parameter. -IAnimatedMesh* CSceneManager::addHillPlaneMesh(const c8* name, +IAnimatedMesh* CSceneManager::addHillPlaneMesh(const io::path& name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material, f32 hillHeight, const core::dimension2d& countHills, const core::dimension2d& textureRepeatCount) { - if (!name) - return 0; - if (MeshCache->isMeshLoaded(name)) - return MeshCache->getMeshByFilename(name); + return MeshCache->getMeshByName(name); - IMesh* mesh = CGeometryCreator::createHillPlaneMesh(tileSize, + IMesh* mesh = GeometryCreator->createHillPlaneMesh(tileSize, tileCount, material, hillHeight, countHills, textureRepeatCount); if (!mesh) @@ -911,19 +947,16 @@ IAnimatedMesh* CSceneManager::addHillPlaneMesh(const c8* name, //! Adds a terrain mesh to the mesh pool. -IAnimatedMesh* CSceneManager::addTerrainMesh(const c8* name, +IAnimatedMesh* CSceneManager::addTerrainMesh(const io::path& name, video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, f32 maxHeight, - const core::dimension2d& defaultVertexBlockSize) + const core::dimension2d& defaultVertexBlockSize) { - if (!name) - return 0; - if (MeshCache->isMeshLoaded(name)) - return MeshCache->getMeshByFilename(name); + return MeshCache->getMeshByName(name); - IMesh* mesh = CGeometryCreator::createTerrainMesh(texture, heightmap, + IMesh* mesh = GeometryCreator->createTerrainMesh(texture, heightmap, stretchSize, maxHeight, getVideoDriver(), defaultVertexBlockSize); if (!mesh) @@ -946,19 +979,17 @@ IAnimatedMesh* CSceneManager::addTerrainMesh(const c8* name, return animatedMesh; } + //! Adds an arrow mesh to the mesh pool. -IAnimatedMesh* CSceneManager::addArrowMesh(const c8* name, +IAnimatedMesh* CSceneManager::addArrowMesh(const io::path& name, video::SColor vtxColor0, video::SColor vtxColor1, u32 tesselationCylinder, u32 tesselationCone, f32 height, f32 cylinderHeight, f32 width0,f32 width1) { - if (!name) - return 0; - if (MeshCache->isMeshLoaded(name)) - return MeshCache->getMeshByFilename(name); + return MeshCache->getMeshByName(name); - IMesh* mesh = CGeometryCreator::createArrowMesh( tesselationCylinder, + IMesh* mesh = GeometryCreator->createArrowMesh( tesselationCylinder, tesselationCone, height, cylinderHeight, width0,width1, vtxColor0, vtxColor1); if (!mesh) @@ -982,18 +1013,14 @@ IAnimatedMesh* CSceneManager::addArrowMesh(const c8* name, } - //! Adds a static sphere mesh to the mesh pool. -IAnimatedMesh* CSceneManager::addSphereMesh(const c8* name, +IAnimatedMesh* CSceneManager::addSphereMesh(const io::path& name, f32 radius, u32 polyCountX, u32 polyCountY) { - if (!name) - return 0; - if (MeshCache->isMeshLoaded(name)) - return MeshCache->getMeshByFilename(name); + return MeshCache->getMeshByName(name); - IMesh* mesh = CGeometryCreator::createSphereMesh(radius, polyCountX, polyCountY); + IMesh* mesh = GeometryCreator->createSphereMesh(radius, polyCountX, polyCountY); if (!mesh) return 0; @@ -1016,6 +1043,36 @@ IAnimatedMesh* CSceneManager::addSphereMesh(const c8* name, +//! Adds a static volume light mesh to the mesh pool. +IAnimatedMesh* CSceneManager::addVolumeLightMesh(const io::path& name, + const u32 SubdivideU, const u32 SubdivideV, + const video::SColor FootColor, const video::SColor TailColor) +{ + if (MeshCache->isMeshLoaded(name)) + return MeshCache->getMeshByName(name); + + IMesh* mesh = GeometryCreator->createVolumeLightMesh(SubdivideU, SubdivideV, FootColor, TailColor); + if (!mesh) + return 0; + + SAnimatedMesh* animatedMesh = new SAnimatedMesh(); + if (!animatedMesh) + { + mesh->drop(); + return 0; + } + + animatedMesh->addMesh(mesh); + mesh->drop(); + animatedMesh->recalculateBoundingBox(); + + MeshCache->addMesh(name, animatedMesh); + animatedMesh->drop(); + + return animatedMesh; +} + + //! Returns the root scene node. This is the scene node wich is parent //! of all scene nodes. The root scene node is a special scene node which //! only exists to manage all scene nodes. It is not rendered and cannot @@ -1030,7 +1087,7 @@ ISceneNode* CSceneManager::getRootSceneNode() //! Returns the current active camera. //! \return The active camera is returned. Note that this can be NULL, if there //! was no camera created yet. -ICameraSceneNode* CSceneManager::getActiveCamera() +ICameraSceneNode* CSceneManager::getActiveCamera() const { return ActiveCamera; } @@ -1040,13 +1097,12 @@ ICameraSceneNode* CSceneManager::getActiveCamera() //! \param camera: The new camera which should be active. void CSceneManager::setActiveCamera(ICameraSceneNode* camera) { + if (camera) + camera->grab(); if (ActiveCamera) ActiveCamera->drop(); ActiveCamera = camera; - - if (ActiveCamera) - ActiveCamera->grab(); } @@ -1067,7 +1123,7 @@ const core::aabbox3d& CSceneManager::getBoundingBox() const //! returns if node is culled -bool CSceneManager::isCulled(const ISceneNode* node) +bool CSceneManager::isCulled(const ISceneNode* node) const { const ICameraSceneNode* cam = getActiveCamera(); if (!cam) @@ -1099,8 +1155,8 @@ bool CSceneManager::isCulled(const ISceneNode* node) SViewFrustum frust = *cam->getViewFrustum(); //transform the frustum to the node's current absolute transformation - core::matrix4 invTrans(node->getAbsoluteTransformation()); - invTrans.makeInverse(); + core::matrix4 invTrans(node->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE); + //invTrans.makeInverse(); frust.transform(invTrans); core::vector3df edges[8]; @@ -1134,14 +1190,14 @@ bool CSceneManager::isCulled(const ISceneNode* node) //! registers a node for rendering it at a specific time. -u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS time) +u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass) { u32 taken = 0; - switch(time) + switch(pass) { - // take camera if it doesn't exists - case ESNRP_CAMERA: + // take camera if it is not already registered + case ESNRP_CAMERA: { taken = 1; for ( u32 i = 0; i != CameraList.size(); ++i ) @@ -1156,14 +1212,15 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE { CameraList.push_back(node); } - }break; + } + break; case ESNRP_LIGHT: // TODO: Point Light culling.. - // Lighting modell in irrlicht has to be redone.. + // Lighting model in irrlicht has to be redone.. //if (!isCulled(node)) { - LightList.push_back(DistanceNodeEntry(node, camWorldPos)); + LightList.push_back(static_cast(node)); taken = 1; } break; @@ -1186,10 +1243,17 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE taken = 1; } break; + case ESNRP_TRANSPARENT_EFFECT: + if (!isCulled(node)) + { + TransparentEffectNodeList.push_back(TransparentNodeEntry(node, camWorldPos)); + taken = 1; + } + break; case ESNRP_AUTOMATIC: if (!isCulled(node)) { - u32 count = node->getMaterialCount(); + const u32 count = node->getMaterialCount(); taken = 0; for (u32 i=0; isetMaterial(video::SMaterial()); driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix ); driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix ); driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix ); - driver->setTransform ( video::ETS_TEXTURE_0, core::IdentityMatrix ); - driver->setTransform ( video::ETS_TEXTURE_1, core::IdentityMatrix ); - driver->setTransform ( video::ETS_TEXTURE_2, core::IdentityMatrix ); - driver->setTransform ( video::ETS_TEXTURE_3, core::IdentityMatrix ); + for (i=video::ETS_COUNT-1; i>=video::ETS_TEXTURE_0; --i) + driver->setTransform ( (video::E_TRANSFORMATION_STATE)i, core::IdentityMatrix ); } driver->setAllowZWriteOnTransparent(Parameters.getAttributeAsBool( ALLOW_ZWRITE_ON_TRANSPARENT) ); @@ -1277,92 +1345,246 @@ void CSceneManager::drawAll() camWorldPos.set(0,0,0); if ( ActiveCamera ) { - ActiveCamera->OnRegisterSceneNode(); + ActiveCamera->render(); camWorldPos = ActiveCamera->getAbsolutePosition(); } // let all nodes register themselves OnRegisterSceneNode(); - u32 i; // new ISO for scoping problem in some compilers + if(LightManager) + LightManager->OnPreRender(LightList); //render camera scenes { CurrentRendertime = ESNRP_CAMERA; + Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); + + if(LightManager) + LightManager->OnRenderPassPreRender(CurrentRendertime); + for (i=0; irender(); CameraList.set_used(0); + + if(LightManager) + LightManager->OnRenderPassPostRender(CurrentRendertime); } //render lights scenes { CurrentRendertime = ESNRP_LIGHT; + Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); + + if(LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRendertime); + } + else + { + // Sort the lights by distance from the camera + core::vector3df camWorldPos(0, 0, 0); + if(ActiveCamera) + camWorldPos = ActiveCamera->getAbsolutePosition(); + + core::array SortedLights; + SortedLights.set_used(LightList.size()); + for(s32 light = (s32)LightList.size() - 1; light >= 0; --light) + SortedLights[light].setNodeAndDistanceFromPosition(LightList[light], camWorldPos); + + SortedLights.set_sorted(false); + SortedLights.sort(); + + for(s32 light = (s32)LightList.size() - 1; light >= 0; --light) + LightList[light] = static_cast(SortedLights[light].Node); + } Driver->deleteAllDynamicLights(); Driver->setAmbientLight(AmbientLight); - LightList.sort(); // on distance to camera + u32 maxLights = LightList.size(); + + if(!LightManager) + maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), maxLights); - u32 maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), LightList.size() ); for (i=0; i< maxLights; ++i) - LightList[i].Node->render(); + LightList[i]->render(); - LightList.set_used(0); + if(LightManager) + LightManager->OnRenderPassPostRender(CurrentRendertime); } // render skyboxes { CurrentRendertime = ESNRP_SKY_BOX; + Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); - for (i=0; irender(); + if(LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRendertime); + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } SkyBoxList.set_used(0); + + if(LightManager) + LightManager->OnRenderPassPostRender(CurrentRendertime); } // render default objects { CurrentRendertime = ESNRP_SOLID; + Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); + SolidNodeList.sort(); // sort by textures - for (i=0; irender(); - - Parameters.setAttribute ( "drawn", (s32) SolidNodeList.size() ); + if(LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRendertime); + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } + Parameters.setAttribute ( "drawn_solid", (s32) SolidNodeList.size() ); SolidNodeList.set_used(0); + + if(LightManager) + LightManager->OnRenderPassPostRender(CurrentRendertime); } // render shadows { CurrentRendertime = ESNRP_SHADOW; - for (i=0; irender(); + Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); + + if(LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRendertime); + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } if (!ShadowNodeList.empty()) Driver->drawStencilShadow(true,ShadowColor, ShadowColor, ShadowColor, ShadowColor); ShadowNodeList.set_used(0); + + if(LightManager) + LightManager->OnRenderPassPostRender(CurrentRendertime); } // render transparent objects. { CurrentRendertime = ESNRP_TRANSPARENT; + Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); + TransparentNodeList.sort(); // sort by distance from camera + if(LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRendertime); - for (i=0; irender(); + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } + Parameters.setAttribute ( "drawn_transparent", (s32) TransparentNodeList.size() ); TransparentNodeList.set_used(0); + + if(LightManager) + LightManager->OnRenderPassPostRender(CurrentRendertime); } + // render transparent effect objects. + { + CurrentRendertime = ESNRP_TRANSPARENT_EFFECT; + Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); + + TransparentEffectNodeList.sort(); // sort by distance from camera + + if(LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRendertime); + + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } + + Parameters.setAttribute ( "drawn_transparent_effect", (s32) TransparentEffectNodeList.size() ); + TransparentEffectNodeList.set_used(0); + } + + if(LightManager) + LightManager->OnPostRender(); + + LightList.set_used(0); clearDeletionList(); - CurrentRendertime = ESNRP_COUNT; + CurrentRendertime = ESNRP_NONE; +} + +void CSceneManager::setLightManager(ILightManager* lightManager) +{ + if ( lightManager ) + lightManager->grab(); + if(LightManager) + LightManager->drop(); + + LightManager = lightManager; } @@ -1395,11 +1617,16 @@ ISceneNodeAnimator* CSceneManager::createRotationAnimator(const core::vector3df& //! creates a fly circle animator, which lets the attached scene node fly around a center. ISceneNodeAnimator* CSceneManager::createFlyCircleAnimator( const core::vector3df& center, f32 radius, f32 speed, - const core::vector3df& direction) + const core::vector3df& direction, + f32 startPosition, + f32 radiusEllipsoid) { + const f32 orbitDurationMs = (core::DEGTORAD * 360.f) / speed; + const u32 effectiveTime = os::Timer::getTime() + (u32)(orbitDurationMs * startPosition); + ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyCircle( - os::Timer::getTime(), center, - radius, speed, direction); + effectiveTime, center, + radius, speed, direction,radiusEllipsoid); return anim; } @@ -1407,10 +1634,10 @@ ISceneNodeAnimator* CSceneManager::createFlyCircleAnimator( //! Creates a fly straight animator, which lets the attached scene node //! fly or move along a line between two points. ISceneNodeAnimator* CSceneManager::createFlyStraightAnimator(const core::vector3df& startPoint, - const core::vector3df& endPoint, u32 timeForWay, bool loop) + const core::vector3df& endPoint, u32 timeForWay, bool loop,bool pingpong) { ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyStraight(startPoint, - endPoint, timeForWay, loop, os::Timer::getTime()); + endPoint, timeForWay, loop, os::Timer::getTime(), pingpong); return anim; } @@ -1457,10 +1684,10 @@ ISceneNodeAnimatorCollisionResponse* CSceneManager::createCollisionResponseAnima //! Creates a follow spline animator. ISceneNodeAnimator* CSceneManager::createFollowSplineAnimator(s32 startTime, const core::array< core::vector3df >& points, - f32 speed, f32 tightness) + f32 speed, f32 tightness, bool loop, bool pingpong) { ISceneNodeAnimator* a = new CSceneNodeAnimatorFollowSpline(startTime, points, - speed, tightness); + speed, tightness, loop, pingpong); return a; } @@ -1494,13 +1721,23 @@ IMeshManipulator* CSceneManager::getMeshManipulator() //! Creates a simple ITriangleSelector, based on a mesh. ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node) { - if (!mesh || !node) + if (!mesh) return 0; return new CTriangleSelector(mesh, node); } +//! Creates a simple and updatable ITriangleSelector, based on a the mesh owned by an +//! animated scene node +ITriangleSelector* CSceneManager::createTriangleSelector(IAnimatedMeshSceneNode* node) +{ + if(!node || !node->getMesh()) + return 0; + + return new CTriangleSelector(node); +} + //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. ITriangleSelector* CSceneManager::createTriangleSelectorFromBoundingBox(ISceneNode* node) { @@ -1512,14 +1749,14 @@ ITriangleSelector* CSceneManager::createTriangleSelectorFromBoundingBox(ISceneNo //! Creates a simple ITriangleSelector, based on a mesh. -ITriangleSelector* CSceneManager::createOctTreeTriangleSelector(IMesh* mesh, +ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode) { - if (!mesh || !node) + if (!mesh) return 0; - return new COctTreeTriangleSelector(mesh, node, minimalPolysPerNode); + return new COctreeTriangleSelector(mesh, node, minimalPolysPerNode); } @@ -1579,8 +1816,8 @@ ISceneNode* CSceneManager::getSceneNodeFromName(const char* name, ISceneNode* st ISceneNode* node = 0; - const core::list& list = start->getChildren(); - core::list::ConstIterator it = list.begin(); + const ISceneNodeList& list = start->getChildren(); + ISceneNodeList::ConstIterator it = list.begin(); for (; it!=list.end(); ++it) { node = getSceneNodeFromName(name, *it); @@ -1603,8 +1840,8 @@ ISceneNode* CSceneManager::getSceneNodeFromId(s32 id, ISceneNode* start) ISceneNode* node = 0; - const core::list& list = start->getChildren(); - core::list::ConstIterator it = list.begin(); + const ISceneNodeList& list = start->getChildren(); + ISceneNodeList::ConstIterator it = list.begin(); for (; it!=list.end(); ++it) { node = getSceneNodeFromId(id, *it); @@ -1627,8 +1864,8 @@ ISceneNode* CSceneManager::getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, IS ISceneNode* node = 0; - const core::list& list = start->getChildren(); - core::list::ConstIterator it = list.begin(); + const ISceneNodeList& list = start->getChildren(); + ISceneNodeList::ConstIterator it = list.begin(); for (; it!=list.end(); ++it) { node = getSceneNodeFromType(type, *it); @@ -1648,8 +1885,8 @@ void CSceneManager::getSceneNodesFromType(ESCENE_NODE_TYPE type, core::arraygetType() == type || ESNT_ANY == type) outNodes.push_back(start); - const core::list& list = start->getChildren(); - core::list::ConstIterator it = list.begin(); + const ISceneNodeList& list = start->getChildren(); + ISceneNodeList::ConstIterator it = list.begin(); for (; it!=list.end(); ++it) { @@ -1677,6 +1914,9 @@ void CSceneManager::removeAll() { ISceneNode::removeAll(); setActiveCamera(0); + // Make sure the driver is reset, might need a more complex method at some point + if (Driver) + Driver->setMaterial(video::SMaterial()); } @@ -1792,7 +2032,7 @@ ISceneNodeAnimatorFactory* CSceneManager::getSceneNodeAnimatorFactory(u32 index) //! Saves the current scene into a file. //! \param filename: Name of the file . -bool CSceneManager::saveScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer) +bool CSceneManager::saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer) { bool ret = false; io::IWriteFile* file = FileSystem->createAndWriteFile(filename); @@ -1832,7 +2072,7 @@ bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* us //! Loads a scene. Note that the current scene is not cleared before. //! \param filename: Name of the file . -bool CSceneManager::loadScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer) +bool CSceneManager::loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer) { bool ret = false; io::IReadFile* read = FileSystem->createAndOpenFile(filename); @@ -2155,7 +2395,7 @@ void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISc writer->writeElement(animatorElement); writer->writeLineBreak(); - core::list::ConstIterator it = node->getAnimators().begin(); + ISceneNodeAnimatorList::ConstIterator it = node->getAnimators().begin(); for (; it != node->getAnimators().end(); ++it) { attr->clear(); @@ -2195,7 +2435,7 @@ void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISc // write children - core::list::ConstIterator it = node->getChildren().begin(); + ISceneNodeList::ConstIterator it = node->getChildren().begin(); for (; it != node->getChildren().end(); ++it) writeSceneNode(writer, (*it), userDataSerializer); @@ -2231,7 +2471,7 @@ ISceneNode* CSceneManager::addSceneNode(const char* sceneNodeTypeName, ISceneNod //! Returns a typename from a scene node animator type or null if not found -const c8* CSceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const +const c8* CSceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) { const char* name = 0; @@ -2248,6 +2488,22 @@ void CSceneManager::serializeAttributes(io::IAttributes* out, io::SAttributeRead out->addString ("Name", Name.c_str()); out->addInt ("Id", ID ); out->addColorf ("AmbientLight", AmbientLight); + + // fog attributes from video driver + video::SColor color; + video::E_FOG_TYPE fogType; + f32 start, end, density; + bool pixelFog, rangeFog; + + Driver->getFog(color, fogType, start, end, density, pixelFog, rangeFog); + + out->addEnum("FogType", fogType, video::FogTypeNames); + out->addColorf("FogColor", color); + out->addFloat("FogStart", start); + out->addFloat("FogEnd", end); + out->addFloat("FogDensity", density); + out->addBool("FogPixel", pixelFog); + out->addBool("FogRange", rangeFog); } //! Reads attributes of the scene node. @@ -2257,6 +2513,23 @@ void CSceneManager::deserializeAttributes(io::IAttributes* in, io::SAttributeRea ID = in->getAttributeAsInt("Id"); AmbientLight = in->getAttributeAsColorf("AmbientLight"); + // fog attributes + video::SColor color; + video::E_FOG_TYPE fogType; + f32 start, end, density; + bool pixelFog, rangeFog; + if (in->existsAttribute("FogType")) + { + fogType = (video::E_FOG_TYPE) in->getAttributeAsEnumeration("FogType", video::FogTypeNames); + color = in->getAttributeAsColorf("FogColor").toSColor(); + start = in->getAttributeAsFloat("FogStart"); + end = in->getAttributeAsFloat("FogEnd"); + density = in->getAttributeAsFloat("FogDensity"); + pixelFog = in->getAttributeAsBool("FogPixel"); + rangeFog = in->getAttributeAsBool("FogRange"); + Driver->setFog(color, fogType, start, end, density, pixelFog, rangeFog); + } + RelativeTranslation.set(0,0,0); RelativeRotation.set(0,0,0); RelativeScale.set(1,1,1); @@ -2283,6 +2556,16 @@ const video::SColorf& CSceneManager::getAmbientLight() const } +//! Get a skinned mesh, which is not available as header-only code +ISkinnedMesh* CSceneManager::createSkinnedMesh() +{ +#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ + return new CSkinnedMesh(); +#else + return 0; +#endif +} + //! Returns a mesh writer implementation if available IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type) { @@ -2312,6 +2595,13 @@ IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type) #else return 0; #endif + + case EMWT_PLY: +#ifdef _IRR_COMPILE_WITH_PLY_WRITER_ + return new CPLYMeshWriter(); +#else + return 0; +#endif } return 0; diff --git a/src/dep/src/irrlicht/CSceneManager.h b/src/dep/src/irrlicht/CSceneManager.h index d6b90d3..d20fab9 100644 --- a/src/dep/src/irrlicht/CSceneManager.h +++ b/src/dep/src/irrlicht/CSceneManager.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,6 +12,7 @@ #include "irrArray.h" #include "IMeshLoader.h" #include "CAttributes.h" +#include "ILightManager.h" namespace irr { @@ -23,6 +24,7 @@ namespace io namespace scene { class IMeshCache; + class IGeometryCreator; /*! The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff. @@ -40,7 +42,7 @@ namespace scene virtual ~CSceneManager(); //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. - virtual IAnimatedMesh* getMesh(const c8* filename); + virtual IAnimatedMesh* getMesh(const io::path& filename); //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. virtual IAnimatedMesh* getMesh(io::IReadFile* file); @@ -51,8 +53,12 @@ namespace scene //! returns the video driver virtual video::IVideoDriver* getVideoDriver(); + //! return the gui environment virtual gui::IGUIEnvironment* getGUIEnvironment(); + //! return the filesystem + virtual io::IFileSystem* getFileSystem(); + //! adds Volume Lighting Scene Node. //! the returned pointer must not be dropped. virtual IVolumeLightSceneNode* addVolumeLightSceneNode(ISceneNode* parent=0, s32 id=-1, @@ -102,21 +108,21 @@ namespace scene virtual const core::aabbox3d& getBoundingBox() const; //! registers a node for rendering it at a specific time. - virtual u32 registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS = ESNRP_AUTOMATIC); + virtual u32 registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass = ESNRP_AUTOMATIC); //! draws all scene nodes virtual void drawAll(); - //! Adds a scene node for rendering using a octtree to the scene graph. This a good method for rendering + //! Adds a scene node for rendering using a octree to the scene graph. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. - virtual ISceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + virtual IMeshSceneNode* addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false); - //! Adss a scene node for rendering using a octtree. This a good method for rendering + //! Adss a scene node for rendering using a octree. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. - virtual ISceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + virtual IMeshSceneNode* addOctreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=128, bool alsoAddIfMeshPointerZero=false); //! Adds a camera scene node to the tree and sets it as active camera. @@ -127,20 +133,24 @@ 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,100), s32 id=-1); + const core::vector3df& lookat = core::vector3df(0,0,100), + s32 id=-1, bool makeActive=true); //! 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 = 1500.0f, s32 id=-1); + f32 rotateSpeed = -1500.0f, f32 zoomSpeed = 200.0f, + f32 translationSpeed = 1500.0f, s32 id=-1, + bool makeActive=true); //! 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 = 100.0f, f32 moveSpeed = .5f, s32 id=-1, - SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, - f32 jumpSpeed = 0.f); + SKeyMap* keyMapArray=0, s32 keyMapSize=0, + bool noVerticalMovement=false, f32 jumpSpeed = 0.f, + bool invertMouseY=false, bool makeActive=true); //! Adds a dynamic light scene node. The light will cast dynamic light on all //! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING @@ -168,7 +178,7 @@ namespace scene //! panoramic texture on it and is drawn around the camera position. virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, u32 horiRes=16, u32 vertRes=8, - f64 texturePercentage=0.9, f64 spherePercentage=2.0, + f32 texturePercentage=0.9, f32 spherePercentage=2.0,f32 radius = 1000.f, ISceneNode* parent=0, s32 id=-1); //! Adds a text scene node, which is able to display @@ -186,7 +196,7 @@ namespace scene video::SColor colorTop = 0xFFFFFFFF, video::SColor colorBottom = 0xFFFFFFFF); //! Adds a scene node, which can render a quake3 shader - virtual ISceneNode* addQuake3SceneNode(IMeshBuffer* meshBuffer, const quake3::SShader * shader, + virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent=0, s32 id=-1 ); @@ -198,27 +208,33 @@ namespace scene //! for the mesh because the mesh is added to the mesh pool and //! can be retrieved back using ISceneManager::getMesh with the //! name as parameter. - virtual IAnimatedMesh* addHillPlaneMesh(const c8* name, + virtual IAnimatedMesh* addHillPlaneMesh(const io::path& name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material = 0, f32 hillHeight = 0.0f, const core::dimension2d& countHills = core::dimension2d(1.0f, 1.0f), const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)); //! Adds a terrain mesh to the mesh pool. - virtual IAnimatedMesh* addTerrainMesh(const c8* meshname, video::IImage* texture, video::IImage* heightmap, + virtual IAnimatedMesh* addTerrainMesh(const io::path& meshname, video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, - f32 maxHeight, const core::dimension2d& defaultVertexBlockSize); + f32 maxHeight, const core::dimension2d& defaultVertexBlockSize); //! Add a arrow mesh to the mesh pool - virtual IAnimatedMesh* addArrowMesh(const c8* name, + virtual IAnimatedMesh* addArrowMesh(const io::path& name, video::SColor vtxColor0, video::SColor vtxColor1, u32 tesselationCylinder, u32 tesselationCone, f32 height, f32 cylinderHeight, f32 width0, f32 width1); //! Adds a static sphere mesh to the mesh pool. - IAnimatedMesh* addSphereMesh(const c8* name, - f32 radius, u32 polyCountX, u32 polyCountY); + IAnimatedMesh* addSphereMesh(const io::path& name, + f32 radius=5.f, u32 polyCountX=16, u32 polyCountY=16); + + //! Adds a static volume light mesh to the mesh pool. + IAnimatedMesh* addVolumeLightMesh(const io::path& name, + const u32 SubdivideU = 32, const u32 SubdivideV = 32, + const video::SColor FootColor = video::SColor(51, 0, 230, 180), + const video::SColor TailColor = video::SColor(0, 0, 0, 0)); //! Adds a particle system scene node. virtual IParticleSystemSceneNode* addParticleSystemSceneNode( @@ -229,7 +245,7 @@ namespace scene //! Adds a terrain scene node to the scene graph. virtual ITerrainSceneNode* addTerrainSceneNode( - const c8* heightMapFileName, + const io::path& heightMapFileName, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), @@ -266,7 +282,7 @@ namespace scene //! Returns the current active camera. //! \return The active camera is returned. Note that this can be NULL, if there //! was no camera created yet. - virtual ICameraSceneNode* getActiveCamera(); + virtual ICameraSceneNode* getActiveCamera() const; //! Sets the active camera. The previous active camera will be deactivated. //! \param camera: The new camera which should be active. @@ -281,18 +297,23 @@ namespace scene //! creates a fly circle animator /** Lets the attached scene node fly around a center. \param center Center relative to node origin - \param speed rotation speed - \return Animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. */ + \param speed: The orbital speed, in radians per millisecond. + \param direction: Specifies the upvector used for alignment of the mesh. + \param startPosition: The position on the circle where the animator will + begin. Value is in multiples of a circle, i.e. 0.5 is half way around. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + */ virtual ISceneNodeAnimator* createFlyCircleAnimator( const core::vector3df& center=core::vector3df(0.f, 0.f, 0.f), f32 radius=100.f, f32 speed=0.001f, - const core::vector3df& direction=core::vector3df(0.f, 1.f, 0.f)); + const core::vector3df& direction=core::vector3df(0.f, 1.f, 0.f), + f32 startPosition = 0.f, + f32 radiusEllipsoid = 0.f); //! Creates a fly straight animator, which lets the attached scene node //! fly or move along a line between two points. virtual ISceneNodeAnimator* createFlyStraightAnimator(const core::vector3df& startPoint, - const core::vector3df& endPoint, u32 timeForWay, bool loop=false); + const core::vector3df& endPoint, u32 timeForWay, bool loop=false,bool pingpong = false); //! Creates a texture animator, which switches the textures of the target scene //! node based on a list of textures. @@ -316,14 +337,21 @@ namespace scene //! Creates a follow spline animator. virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, const core::array< core::vector3df >& points, - f32 speed = 1.0f, f32 tightness = 0.5f); + f32 speed, f32 tightness, bool loop, bool pingpong); //! Creates a simple ITriangleSelector, based on a mesh. virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node); + //! Creates a simple ITriangleSelector, based on an animated mesh scene node. + //! Details of the mesh associated with the node will be extracted internally. + //! Call ITriangleSelector::update() to have the triangle selector updated based + //! on the current frame of the animated mesh scene node. + //! \param: The animated mesh scene node from which to build the selector + virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node); + //! Creates a simple ITriangleSelector, based on a mesh. - virtual ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, + virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode); //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. @@ -408,6 +436,9 @@ namespace scene //! Returns a typename from a scene node type or null if not found virtual const c8* getSceneNodeTypeName(ESCENE_NODE_TYPE type); + //! Returns a typename from a scene node animator type or null if not found + virtual const c8* getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type); + //! Adds a scene node to the scene by name virtual ISceneNode* addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent=0); @@ -425,14 +456,14 @@ namespace scene //! Saves the current scene into a file. //! \param filename: Name of the file . - virtual bool saveScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0); + virtual bool saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0); //! Saves the current scene into a file. virtual bool saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer=0); //! Loads a scene. Note that the current scene is not cleared before. //! \param filename: Name of the file . - virtual bool loadScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0); + virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0); //! Loads a scene. Note that the current scene is not cleared before. virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0); @@ -446,19 +477,25 @@ namespace scene //! Returns a mesh writer implementation if available virtual IMeshWriter* createMeshWriter(EMESH_WRITER_TYPE type); + //! Get a skinned mesh, which is not available as header-only code + virtual ISkinnedMesh* createSkinnedMesh(); + //! Sets ambient color of the scene virtual void setAmbientLight(const video::SColorf &ambientColor); //! Returns ambient color of the scene virtual const video::SColorf& getAmbientLight() const; - private: + //! Register a custom callbacks manager which gets callbacks during scene rendering. + virtual void setLightManager(ILightManager* lightManager); - //! Returns a typename from a scene node animator type or null if not found - virtual const c8* getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const; + //! Get an instance of a geometry creator. + virtual const IGeometryCreator* getGeometryCreator(void) const { return GeometryCreator; } //! returns if node is culled - bool isCulled(const ISceneNode* node); + virtual bool isCulled(const ISceneNode* node) const; + + private: //! clears the deletion list void clearDeletionList(); @@ -497,36 +534,32 @@ namespace scene void* TextureValue; }; - + //! sort on distance (center) to camera struct TransparentNodeEntry { TransparentNodeEntry(ISceneNode* n, const core::vector3df& camera) : Node(n) { - Distance = (f32)(Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(camera)); + Distance = Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(camera); } bool operator < (const TransparentNodeEntry& other) const { - return (Distance > other.Distance); + return Distance > other.Distance; } ISceneNode* Node; private: - f32 Distance; + f64 Distance; }; //! sort on distance (sphere) to camera struct DistanceNodeEntry { - DistanceNodeEntry(ISceneNode* n, f64 d) - : Node(n), Distance(d) {} - DistanceNodeEntry(ISceneNode* n, const core::vector3df& cameraPos) : Node(n) { - Distance = Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(cameraPos); - Distance -= Node->getBoundingBox().getExtent().getLengthSQ() * 0.5; + setNodeAndDistanceFromPosition(n, cameraPos); } bool operator < (const DistanceNodeEntry& other) const @@ -534,6 +567,13 @@ namespace scene return Distance < other.Distance; } + void setNodeAndDistanceFromPosition(ISceneNode* n, const core::vector3df & fromPosition) + { + Node = n; + Distance = Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(fromPosition); + Distance -= Node->getBoundingBox().getExtent().getLengthSQ() * 0.5; + } + ISceneNode* Node; private: f64 Distance; @@ -556,11 +596,12 @@ namespace scene //! render pass lists core::array CameraList; - core::array LightList; + core::array LightList; core::array ShadowNodeList; core::array SkyBoxList; core::array SolidNodeList; core::array TransparentNodeList; + core::array TransparentEffectNodeList; core::array MeshLoaderList; core::array DeletionList; @@ -582,11 +623,17 @@ namespace scene E_SCENE_NODE_RENDER_PASS CurrentRendertime; + //! An optional callbacks manager to allow the user app finer control + //! over the scene lighting and rendering. + ILightManager* LightManager; + //! constants for reading and writing XML. //! Not made static due to portability problems. const core::stringw IRR_XML_FORMAT_SCENE; const core::stringw IRR_XML_FORMAT_NODE; const core::stringw IRR_XML_FORMAT_NODE_ATTR_TYPE; + + IGeometryCreator* GeometryCreator; }; } // end namespace video diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorCameraFPS.cpp b/src/dep/src/irrlicht/CSceneNodeAnimatorCameraFPS.cpp index 82befed..1079cec 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorCameraFPS.cpp +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorCameraFPS.cpp @@ -1,322 +1,356 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "CSceneNodeAnimatorCameraFPS.h" -#include "IVideoDriver.h" -#include "ISceneManager.h" -#include "Keycodes.h" -#include "ICursorControl.h" -#include "ICameraSceneNode.h" -#include "ISceneNodeAnimatorCollisionResponse.h" - -namespace irr -{ -namespace scene -{ - -//! constructor -CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cursorControl, - f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed, - SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement) -: CursorControl(cursorControl), MaxVerticalAngle(88.0f), - MoveSpeed(moveSpeed), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed), - LastAnimationTime(0), firstUpdate(true), NoVerticalMovement(noVerticalMovement) -{ - #ifdef _DEBUG - setDebugName("CCameraSceneNodeAnimatorFPS"); - #endif - - if (CursorControl) - CursorControl->grab(); - - allKeysUp(); - - // create key map - if (!keyMapArray || !keyMapSize) - { - // create default key map - KeyMap.push_back(SCamKeyMap(EKA_MOVE_FORWARD, irr::KEY_UP)); - KeyMap.push_back(SCamKeyMap(EKA_MOVE_BACKWARD, irr::KEY_DOWN)); - KeyMap.push_back(SCamKeyMap(EKA_STRAFE_LEFT, irr::KEY_LEFT)); - KeyMap.push_back(SCamKeyMap(EKA_STRAFE_RIGHT, irr::KEY_RIGHT)); - KeyMap.push_back(SCamKeyMap(EKA_JUMP_UP, irr::KEY_KEY_J)); - } - else - { - // create custom key map - setKeyMap(keyMapArray, keyMapSize); - } -} - - -//! destructor -CSceneNodeAnimatorCameraFPS::~CSceneNodeAnimatorCameraFPS() -{ - if (CursorControl) - CursorControl->drop(); -} - - -//! 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 scene::ISceneManager::addMayaCameraSceneNode or -//! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input -//! for changing their position, look at target or whatever. -bool CSceneNodeAnimatorCameraFPS::OnEvent(const SEvent& evt) -{ - switch(evt.EventType) - { - case EET_KEY_INPUT_EVENT: - for (u32 i=0; igetRelativePosition(); - return true; - } - break; - - default: - break; - } - - return false; -} - - -void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) -{ - if (node->getType() != ESNT_CAMERA) - return; - - ICameraSceneNode* camera = static_cast(node); - - if (firstUpdate) - { - camera->updateAbsolutePosition(); - if (CursorControl && camera) - { - CursorControl->setPosition(0.5f, 0.5f); - CursorPos = CenterCursor = CursorControl->getRelativePosition(); - } - - LastAnimationTime = timeMs; - - firstUpdate = false; - } - - // get time - f32 timeDiff = (f32) ( timeMs - LastAnimationTime ); - LastAnimationTime = timeMs; - - // update position - core::vector3df pos = camera->getPosition(); - - // Update rotation - core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition()); - core::vector3df relativeRotation = target.getHorizontalAngle(); - - if (CursorControl) - { - if (CursorPos != CenterCursor) - { - relativeRotation.Y -= (0.5f - CursorPos.X) * RotateSpeed; - relativeRotation.X -= (0.5f - CursorPos.Y) * RotateSpeed; - - // X < MaxVerticalAngle or X > 360-MaxVerticalAngle - - if (relativeRotation.X > MaxVerticalAngle*2 && - relativeRotation.X < 360.0f-MaxVerticalAngle) - { - relativeRotation.X = 360.0f-MaxVerticalAngle; - } - else - if (relativeRotation.X > MaxVerticalAngle && - relativeRotation.X < 360.0f-MaxVerticalAngle) - { - 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; - } - } - - // set target - - target.set(0,0, core::max_(1.f, pos.getLength())); - core::vector3df movedir = target; - - core::matrix4 mat; - mat.setRotationDegrees(core::vector3df(relativeRotation.X, relativeRotation.Y, 0)); - mat.transformVect(target); - - if (NoVerticalMovement) - { - mat.setRotationDegrees(core::vector3df(0, relativeRotation.Y, 0)); - mat.transformVect(movedir); - } - else - { - movedir = target; - } - - movedir.normalize(); - - if (CursorKeys[EKA_MOVE_FORWARD]) - pos += movedir * timeDiff * MoveSpeed; - - if (CursorKeys[EKA_MOVE_BACKWARD]) - pos -= movedir * timeDiff * MoveSpeed; - - // strafing - - core::vector3df strafevect = target; - strafevect = strafevect.crossProduct(camera->getUpVector()); - - if (NoVerticalMovement) - strafevect.Y = 0.0f; - - strafevect.normalize(); - - if (CursorKeys[EKA_STRAFE_LEFT]) - pos += strafevect * timeDiff * MoveSpeed; - - if (CursorKeys[EKA_STRAFE_RIGHT]) - pos -= strafevect * timeDiff * MoveSpeed; - - // For jumping, we find the collision response animator attached to our camera - // and if it's not falling, we tell it to jump. - if (CursorKeys[EKA_JUMP_UP]) - { - const core::list & animators = camera->getAnimators(); - core::list::ConstIterator it = animators.begin(); - while(it != animators.end()) - { - if(ESNAT_COLLISION_RESPONSE == (*it)->getType()) - { - ISceneNodeAnimatorCollisionResponse * collisionResponse = - static_cast(*it); - - if(!collisionResponse->isFalling()) - collisionResponse->jump(JumpSpeed); - } - - it++; - } - } - - // write translation - camera->setPosition(pos); - - // write right target - - TargetVector = target; - target += pos; - camera->setTarget(target); -} - - -void CSceneNodeAnimatorCameraFPS::allKeysUp() -{ - for (u32 i=0; i<6; ++i) - CursorKeys[i] = false; -} - - -//! Sets the rotation speed -void CSceneNodeAnimatorCameraFPS::setRotateSpeed(f32 speed) -{ - RotateSpeed = speed; -} - - -//! Sets the movement speed -void CSceneNodeAnimatorCameraFPS::setMoveSpeed(f32 speed) -{ - MoveSpeed = speed; -} - - -//! Gets the rotation speed -f32 CSceneNodeAnimatorCameraFPS::getRotateSpeed() const -{ - return RotateSpeed; -} - - -// Gets the movement speed -f32 CSceneNodeAnimatorCameraFPS::getMoveSpeed() const -{ - return MoveSpeed; -} - - -//! Sets the keyboard mapping for this animator -void CSceneNodeAnimatorCameraFPS::setKeyMap(SKeyMap *map, u32 count) -{ - // clear the keymap - KeyMap.clear(); - - // add actions - for (u32 i=0; isetKeyMap(KeyMap); - return newAnimator; -} - - -void CSceneNodeAnimatorCameraFPS::setKeyMap(const core::array& keymap) -{ - KeyMap=keymap; -} - - -} // namespace scene -} // namespace irr - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CSceneNodeAnimatorCameraFPS.h" +#include "IVideoDriver.h" +#include "ISceneManager.h" +#include "Keycodes.h" +#include "ICursorControl.h" +#include "ICameraSceneNode.h" +#include "ISceneNodeAnimatorCollisionResponse.h" + +namespace irr +{ +namespace scene +{ + +//! constructor +CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cursorControl, + f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed, + SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement, bool invertY) +: CursorControl(cursorControl), MaxVerticalAngle(88.0f), + MoveSpeed(moveSpeed), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed), + MouseYDirection(invertY ? -1.0f : 1.0f), + LastAnimationTime(0), firstUpdate(true), NoVerticalMovement(noVerticalMovement) +{ + #ifdef _DEBUG + setDebugName("CCameraSceneNodeAnimatorFPS"); + #endif + + if (CursorControl) + CursorControl->grab(); + + allKeysUp(); + + // create key map + if (!keyMapArray || !keyMapSize) + { + // create default key map + KeyMap.push_back(SCamKeyMap(EKA_MOVE_FORWARD, irr::KEY_UP)); + KeyMap.push_back(SCamKeyMap(EKA_MOVE_BACKWARD, irr::KEY_DOWN)); + KeyMap.push_back(SCamKeyMap(EKA_STRAFE_LEFT, irr::KEY_LEFT)); + KeyMap.push_back(SCamKeyMap(EKA_STRAFE_RIGHT, irr::KEY_RIGHT)); + KeyMap.push_back(SCamKeyMap(EKA_JUMP_UP, irr::KEY_KEY_J)); + } + else + { + // create custom key map + setKeyMap(keyMapArray, keyMapSize); + } +} + + +//! destructor +CSceneNodeAnimatorCameraFPS::~CSceneNodeAnimatorCameraFPS() +{ + if (CursorControl) + CursorControl->drop(); +} + + +//! 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 scene::ISceneManager::addMayaCameraSceneNode or +//! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input +//! for changing their position, look at target or whatever. +bool CSceneNodeAnimatorCameraFPS::OnEvent(const SEvent& evt) +{ + switch(evt.EventType) + { + case EET_KEY_INPUT_EVENT: + for (u32 i=0; igetRelativePosition(); + return true; + } + break; + + default: + break; + } + + return false; +} + + +void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) +{ + if (!node || node->getType() != ESNT_CAMERA) + return; + + ICameraSceneNode* camera = static_cast(node); + + if (firstUpdate) + { + camera->updateAbsolutePosition(); + if (CursorControl && camera) + { + CursorControl->setPosition(0.5f, 0.5f); + CursorPos = CenterCursor = CursorControl->getRelativePosition(); + } + + LastAnimationTime = 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; + + // update position + core::vector3df pos = camera->getPosition(); + + // Update rotation + core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition()); + core::vector3df relativeRotation = target.getHorizontalAngle(); + + if (CursorControl) + { + if (CursorPos != CenterCursor) + { + relativeRotation.Y -= (0.5f - CursorPos.X) * RotateSpeed; + relativeRotation.X -= (0.5f - CursorPos.Y) * RotateSpeed * MouseYDirection; + + // X < MaxVerticalAngle or X > 360-MaxVerticalAngle + + if (relativeRotation.X > MaxVerticalAngle*2 && + relativeRotation.X < 360.0f-MaxVerticalAngle) + { + relativeRotation.X = 360.0f-MaxVerticalAngle; + } + else + if (relativeRotation.X > MaxVerticalAngle && + relativeRotation.X < 360.0f-MaxVerticalAngle) + { + relativeRotation.X = MaxVerticalAngle; + } + + // Do the fix as normal, special case below + // reset cursor position to the centre of the window. + CursorControl->setPosition(0.5f, 0.5f); + CenterCursor = CursorControl->getRelativePosition(); + + // needed to avoid problems when the event receiver is disabled + CursorPos = CenterCursor; + } + + // Special case, mouse is whipped outside of window before it can update. + video::IVideoDriver* driver = smgr->getVideoDriver(); + core::vector2d mousepos(u32(CursorControl->getPosition().X), u32(CursorControl->getPosition().Y)); + core::rect screenRect(0, 0, driver->getScreenSize().Width, driver->getScreenSize().Height); + + // Only if we are moving outside quickly. + bool reset = !screenRect.isPointInside(mousepos); + + if(reset) + { + // Force a reset. + CursorControl->setPosition(0.5f, 0.5f); + CenterCursor = CursorControl->getRelativePosition(); + CursorPos = CenterCursor; + } + } + + // set target + + target.set(0,0, core::max_(1.f, pos.getLength())); + core::vector3df movedir = target; + + core::matrix4 mat; + mat.setRotationDegrees(core::vector3df(relativeRotation.X, relativeRotation.Y, 0)); + mat.transformVect(target); + + if (NoVerticalMovement) + { + mat.setRotationDegrees(core::vector3df(0, relativeRotation.Y, 0)); + mat.transformVect(movedir); + } + else + { + movedir = target; + } + + movedir.normalize(); + + if (CursorKeys[EKA_MOVE_FORWARD]) + pos += movedir * timeDiff * MoveSpeed; + + if (CursorKeys[EKA_MOVE_BACKWARD]) + pos -= movedir * timeDiff * MoveSpeed; + + // strafing + + core::vector3df strafevect = target; + strafevect = strafevect.crossProduct(camera->getUpVector()); + + if (NoVerticalMovement) + strafevect.Y = 0.0f; + + strafevect.normalize(); + + if (CursorKeys[EKA_STRAFE_LEFT]) + pos += strafevect * timeDiff * MoveSpeed; + + if (CursorKeys[EKA_STRAFE_RIGHT]) + pos -= strafevect * timeDiff * MoveSpeed; + + // For jumping, we find the collision response animator attached to our camera + // and if it's not falling, we tell it to jump. + if (CursorKeys[EKA_JUMP_UP]) + { + const ISceneNodeAnimatorList& animators = camera->getAnimators(); + ISceneNodeAnimatorList::ConstIterator it = animators.begin(); + while(it != animators.end()) + { + if(ESNAT_COLLISION_RESPONSE == (*it)->getType()) + { + ISceneNodeAnimatorCollisionResponse * collisionResponse = + static_cast(*it); + + if(!collisionResponse->isFalling()) + collisionResponse->jump(JumpSpeed); + } + + it++; + } + } + + // write translation + camera->setPosition(pos); + + // write right target + target += pos; + camera->setTarget(target); +} + + +void CSceneNodeAnimatorCameraFPS::allKeysUp() +{ + for (u32 i=0; i<6; ++i) + CursorKeys[i] = false; +} + + +//! Sets the rotation speed +void CSceneNodeAnimatorCameraFPS::setRotateSpeed(f32 speed) +{ + RotateSpeed = speed; +} + + +//! Sets the movement speed +void CSceneNodeAnimatorCameraFPS::setMoveSpeed(f32 speed) +{ + MoveSpeed = speed; +} + + +//! Gets the rotation speed +f32 CSceneNodeAnimatorCameraFPS::getRotateSpeed() const +{ + return RotateSpeed; +} + + +// Gets the movement speed +f32 CSceneNodeAnimatorCameraFPS::getMoveSpeed() const +{ + return MoveSpeed; +} + + +//! Sets the keyboard mapping for this animator +void CSceneNodeAnimatorCameraFPS::setKeyMap(SKeyMap *map, u32 count) +{ + // clear the keymap + KeyMap.clear(); + + // add actions + for (u32 i=0; isetKeyMap(KeyMap); + return newAnimator; +} + + +void CSceneNodeAnimatorCameraFPS::setKeyMap(const core::array& keymap) +{ + KeyMap=keymap; +} + + +} // namespace scene +} // namespace irr + diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorCameraFPS.h b/src/dep/src/irrlicht/CSceneNodeAnimatorCameraFPS.h index 5ab78ac..74f9804 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorCameraFPS.h +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorCameraFPS.h @@ -1,121 +1,129 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ -#define __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ - -#include "ISceneNodeAnimatorCameraFPS.h" -#include "vector2d.h" -#include "SKeyMap.h" -#include "irrArray.h" - -namespace irr -{ -namespace gui -{ - class ICursorControl; -} - -namespace scene -{ - - //! Special scene node animator for FPS cameras - class CSceneNodeAnimatorCameraFPS : public ISceneNodeAnimatorCameraFPS - { - public: - - //! Constructor - CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cursorControl, - f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, f32 jumpSpeed=0.f, - SKeyMap* keyMapArray=0, u32 keyMapSize=0, bool noVerticalMovement=false); - - //! Destructor - virtual ~CSceneNodeAnimatorCameraFPS(); - - //! Animates the scene node, currently only works on cameras - virtual void animateNode(ISceneNode* node, u32 timeMs); - - //! Event receiver - virtual bool OnEvent(const SEvent& event); - - //! Returns the speed of movement in units per second - virtual f32 getMoveSpeed() const; - - //! Sets the speed of movement in units per second - virtual void setMoveSpeed(f32 moveSpeed); - - //! Returns the rotation speed - virtual f32 getRotateSpeed() const; - - //! Set the rotation speed - virtual void setRotateSpeed(f32 rotateSpeed); - - //! 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 - virtual void setKeyMap(SKeyMap *map, u32 count); - - //! Sets whether vertical movement should be allowed. - virtual void setVerticalMovement(bool allow); - - //! This animator will receive events when attached to the active camera - virtual bool isEventReceiverEnabled() const - { - return true; - } - - //! Returns the type of this animator - virtual ESCENE_NODE_ANIMATOR_TYPE getType() const - { - return ESNAT_CAMERA_FPS; - } - - //! 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); - - struct SCamKeyMap - { - SCamKeyMap() {}; - SCamKeyMap(s32 a, EKEY_CODE k) : action(a), keycode(k) {} - - s32 action; - 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; - - f32 MaxVerticalAngle; - - f32 MoveSpeed; - f32 RotateSpeed; - f32 JumpSpeed; - - s32 LastAnimationTime; - - core::vector3df TargetVector; - core::array KeyMap; - core::position2d CenterCursor, CursorPos; - - bool CursorKeys[6]; - - bool firstUpdate; - bool NoVerticalMovement; - }; - -} // end namespace scene -} // end namespace irr - -#endif // __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ +#define __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ + +#include "ISceneNodeAnimatorCameraFPS.h" +#include "vector2d.h" +#include "position2d.h" +#include "SKeyMap.h" +#include "irrArray.h" + +namespace irr +{ +namespace gui +{ + class ICursorControl; +} + +namespace scene +{ + + //! Special scene node animator for FPS cameras + class CSceneNodeAnimatorCameraFPS : public ISceneNodeAnimatorCameraFPS + { + public: + + //! Constructor + CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cursorControl, + f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, f32 jumpSpeed=0.f, + SKeyMap* keyMapArray=0, u32 keyMapSize=0, bool noVerticalMovement=false, + bool invertY=false); + + //! Destructor + virtual ~CSceneNodeAnimatorCameraFPS(); + + //! Animates the scene node, currently only works on cameras + virtual void animateNode(ISceneNode* node, u32 timeMs); + + //! Event receiver + virtual bool OnEvent(const SEvent& event); + + //! Returns the speed of movement in units per second + virtual f32 getMoveSpeed() const; + + //! Sets the speed of movement in units per second + virtual void setMoveSpeed(f32 moveSpeed); + + //! Returns the rotation speed + virtual f32 getRotateSpeed() const; + + //! Set the rotation speed + virtual void setRotateSpeed(f32 rotateSpeed); + + //! 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 + virtual void setKeyMap(SKeyMap *map, u32 count); + + //! Sets whether vertical movement should be allowed. + virtual void setVerticalMovement(bool allow); + + //! Sets whether the Y axis of the mouse should be inverted. + /** If enabled then moving the mouse down will cause + the camera to look up. It is disabled by default. */ + virtual void setInvertMouse(bool invert); + + //! This animator will receive events when attached to the active camera + virtual bool isEventReceiverEnabled() const + { + return true; + } + + //! Returns the type of this animator + virtual ESCENE_NODE_ANIMATOR_TYPE getType() const + { + return ESNAT_CAMERA_FPS; + } + + //! Creates a clone of this animator. + /** Please note that you will have to drop + (IReferenceCounted::drop()) the returned pointer once you're + done with it. */ + virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); + + struct SCamKeyMap + { + SCamKeyMap() {}; + SCamKeyMap(s32 a, EKEY_CODE k) : action(a), keycode(k) {} + + s32 action; + 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; + + f32 MaxVerticalAngle; + + f32 MoveSpeed; + f32 RotateSpeed; + f32 JumpSpeed; + // -1.0f for inverted mouse, defaults to 1.0f + f32 MouseYDirection; + + s32 LastAnimationTime; + + core::array KeyMap; + core::position2d CenterCursor, CursorPos; + + bool CursorKeys[6]; + + bool firstUpdate; + bool NoVerticalMovement; + }; + +} // end namespace scene +} // end namespace irr + +#endif // __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ + diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorCameraMaya.cpp b/src/dep/src/irrlicht/CSceneNodeAnimatorCameraMaya.cpp index aa469f8..2cec114 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorCameraMaya.cpp +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorCameraMaya.cpp @@ -1,285 +1,306 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "CSceneNodeAnimatorCameraMaya.h" -#include "ICursorControl.h" -#include "ICameraSceneNode.h" -#include "SViewFrustum.h" - -namespace irr -{ -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), - CurrentZoom(70.0f), RotX(0.0f), RotY(0.0f), OldCamera(0), MousePos(0.5f, 0.5f) -{ - #ifdef _DEBUG - setDebugName("CSceneNodeAnimatorCameraMaya"); - #endif - - if (CursorControl) - { - CursorControl->grab(); - MousePos = CursorControl->getRelativePosition(); - } - - allKeysUp(); -} - - -//! destructor -CSceneNodeAnimatorCameraMaya::~CSceneNodeAnimatorCameraMaya() -{ - if (CursorControl) - CursorControl->drop(); -} - - -//! 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 scene::ISceneManager::addMayaCameraSceneNode or -//! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input -//! for changing their position, look at target or whatever. -bool CSceneNodeAnimatorCameraMaya::OnEvent(const SEvent& event) -{ - if (event.EventType != EET_MOUSE_INPUT_EVENT) - return false; - - switch(event.MouseInput.Event) - { - case EMIE_LMOUSE_PRESSED_DOWN: - MouseKeys[0] = true; - break; - case EMIE_RMOUSE_PRESSED_DOWN: - MouseKeys[2] = true; - break; - case EMIE_MMOUSE_PRESSED_DOWN: - MouseKeys[1] = true; - break; - case EMIE_LMOUSE_LEFT_UP: - MouseKeys[0] = false; - break; - case EMIE_RMOUSE_LEFT_UP: - MouseKeys[2] = false; - break; - case EMIE_MMOUSE_LEFT_UP: - MouseKeys[1] = false; - break; - case EMIE_MOUSE_MOVED: - MousePos = CursorControl->getRelativePosition(); - break; - case EMIE_MOUSE_WHEEL: - case EMIE_COUNT: - return false; - } - return true; -} - - -//! OnAnimate() is called just before rendering the whole scene. -//! nodes may calculate or store animations here, and may do other useful things, -//! dependent on what they are. -void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) -{ - //Alt + LM = Rotate around camera pivot - //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) - return; - - ICameraSceneNode* camera = static_cast(node); - - if (OldCamera != camera) - { - OldTarget = camera->getTarget(); - OldCamera = camera; - } - - core::vector3df target = camera->getTarget(); - - f32 nRotX = RotX; - f32 nRotY = RotY; - f32 nZoom = CurrentZoom; - - if ( (isMouseKeyDown(0) && isMouseKeyDown(2)) || isMouseKeyDown(1) ) - { - if (!Zooming) - { - ZoomStart = MousePos; - Zooming = true; - nZoom = CurrentZoom; - } - else - { - const f32 targetMinDistance = 0.1f; - nZoom += (ZoomStart.X - MousePos.X) * ZoomSpeed; - - if (nZoom < targetMinDistance) // jox: fixed bug: bounce back when zooming to close - nZoom = targetMinDistance; - } - } - else if (Zooming) - { - 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 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.normalize(); - - if (isMouseKeyDown(2) && !Zooming) - { - if (!Translating) - { - TranslateStart = MousePos; - Translating = true; - } - else - { - translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + - tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; - } - } - else if (Translating) - { - translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + - tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; - OldTarget = translate; - Translating = false; - } - - // Rotation ------------------------------------ - - if (isMouseKeyDown(0) && !Zooming) - { - if (!Rotating) - { - RotateStart = MousePos; - Rotating = true; - nRotX = RotX; - nRotY = RotY; - } - else - { - nRotX += (RotateStart.X - MousePos.X) * RotateSpeed; - nRotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; - } - } - else if (Rotating) - { - RotX += (RotateStart.X - MousePos.X) * RotateSpeed; - RotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; - nRotX = RotX; - nRotY = RotY; - Rotating = false; - } - - // Set Pos ------------------------------------ - - target = translate; - - Pos.X = nZoom + target.X; - Pos.Y = target.Y; - Pos.Z = target.Z; - - 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); - - camera->setPosition(Pos); - camera->setTarget(target); - camera->setUpVector(upVector); -} - - -bool CSceneNodeAnimatorCameraMaya::isMouseKeyDown(s32 key) -{ - return MouseKeys[key]; -} - - -void CSceneNodeAnimatorCameraMaya::allKeysUp() -{ - for (s32 i=0; i<3; ++i) - MouseKeys[i] = false; -} - - -//! Sets the rotation speed -void CSceneNodeAnimatorCameraMaya::setRotateSpeed(f32 speed) -{ - RotateSpeed = speed; -} - - -//! Sets the movement speed -void CSceneNodeAnimatorCameraMaya::setMoveSpeed(f32 speed) -{ - TranslateSpeed = speed; -} - - -//! Sets the zoom speed -void CSceneNodeAnimatorCameraMaya::setZoomSpeed(f32 speed) -{ - ZoomSpeed = speed; -} - - -//! Gets the rotation speed -f32 CSceneNodeAnimatorCameraMaya::getRotateSpeed() const -{ - return RotateSpeed; -} - - -// Gets the movement speed -f32 CSceneNodeAnimatorCameraMaya::getMoveSpeed() const -{ - return TranslateSpeed; -} - - -//! Gets the zoom speed -f32 CSceneNodeAnimatorCameraMaya::getZoomSpeed() const -{ - return ZoomSpeed; -} - -ISceneNodeAnimator* CSceneNodeAnimatorCameraMaya::createClone(ISceneNode* node, ISceneManager* newManager) -{ - CSceneNodeAnimatorCameraMaya * newAnimator = - new CSceneNodeAnimatorCameraMaya(CursorControl, RotateSpeed, ZoomSpeed, TranslateSpeed); - return newAnimator; -} - -} // end namespace -} // end namespace - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CSceneNodeAnimatorCameraMaya.h" +#include "ICursorControl.h" +#include "ICameraSceneNode.h" +#include "SViewFrustum.h" +#include "ISceneManager.h" + +namespace irr +{ +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), + CurrentZoom(70.0f), RotX(0.0f), RotY(0.0f), OldCamera(0), MousePos(0.5f, 0.5f) +{ + #ifdef _DEBUG + setDebugName("CSceneNodeAnimatorCameraMaya"); + #endif + + if (CursorControl) + { + CursorControl->grab(); + MousePos = CursorControl->getRelativePosition(); + } + + allKeysUp(); +} + + +//! destructor +CSceneNodeAnimatorCameraMaya::~CSceneNodeAnimatorCameraMaya() +{ + if (CursorControl) + CursorControl->drop(); +} + + +//! 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 scene::ISceneManager::addMayaCameraSceneNode or +//! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input +//! for changing their position, look at target or whatever. +bool CSceneNodeAnimatorCameraMaya::OnEvent(const SEvent& event) +{ + if (event.EventType != EET_MOUSE_INPUT_EVENT) + return false; + + switch(event.MouseInput.Event) + { + case EMIE_LMOUSE_PRESSED_DOWN: + MouseKeys[0] = true; + break; + case EMIE_RMOUSE_PRESSED_DOWN: + MouseKeys[2] = true; + break; + case EMIE_MMOUSE_PRESSED_DOWN: + MouseKeys[1] = true; + break; + case EMIE_LMOUSE_LEFT_UP: + MouseKeys[0] = false; + break; + case EMIE_RMOUSE_LEFT_UP: + MouseKeys[2] = false; + break; + case EMIE_MMOUSE_LEFT_UP: + MouseKeys[1] = false; + break; + case EMIE_MOUSE_MOVED: + MousePos = CursorControl->getRelativePosition(); + break; + case EMIE_MOUSE_WHEEL: + case EMIE_LMOUSE_DOUBLE_CLICK: + case EMIE_RMOUSE_DOUBLE_CLICK: + case EMIE_MMOUSE_DOUBLE_CLICK: + case EMIE_LMOUSE_TRIPLE_CLICK: + case EMIE_RMOUSE_TRIPLE_CLICK: + case EMIE_MMOUSE_TRIPLE_CLICK: + case EMIE_COUNT: + return false; + } + return true; +} + + +//! OnAnimate() is called just before rendering the whole scene. +//! nodes may calculate or store animations here, and may do other useful things, +//! dependent on what they are. +void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) +{ + //Alt + LM = Rotate around camera pivot + //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 || 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; + LastCameraTarget = OldTarget; + } + else + { + OldTarget += camera->getTarget() - LastCameraTarget; + } + + core::vector3df target = camera->getTarget(); + + f32 nRotX = RotX; + f32 nRotY = RotY; + f32 nZoom = CurrentZoom; + + if ( (isMouseKeyDown(0) && isMouseKeyDown(2)) || isMouseKeyDown(1) ) + { + if (!Zooming) + { + ZoomStart = MousePos; + Zooming = true; + nZoom = CurrentZoom; + } + else + { + const f32 targetMinDistance = 0.1f; + nZoom += (ZoomStart.X - MousePos.X) * ZoomSpeed; + + if (nZoom < targetMinDistance) // jox: fixed bug: bounce back when zooming to close + nZoom = targetMinDistance; + } + } + else if (Zooming) + { + 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 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.normalize(); + + if (isMouseKeyDown(2) && !Zooming) + { + if (!Translating) + { + TranslateStart = MousePos; + Translating = true; + } + else + { + translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + + tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; + } + } + else if (Translating) + { + translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + + tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; + OldTarget = translate; + Translating = false; + } + + // Rotation ------------------------------------ + + if (isMouseKeyDown(0) && !Zooming) + { + if (!Rotating) + { + RotateStart = MousePos; + Rotating = true; + nRotX = RotX; + nRotY = RotY; + } + else + { + nRotX += (RotateStart.X - MousePos.X) * RotateSpeed; + nRotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; + } + } + else if (Rotating) + { + RotX += (RotateStart.X - MousePos.X) * RotateSpeed; + RotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; + nRotX = RotX; + nRotY = RotY; + Rotating = false; + } + + // Set Pos ------------------------------------ + + target = translate; + + Pos.X = nZoom + target.X; + Pos.Y = target.Y; + Pos.Z = target.Z; + + 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); + + camera->setPosition(Pos); + camera->setTarget(target); + camera->setUpVector(upVector); + LastCameraTarget = camera->getTarget(); +} + + +bool CSceneNodeAnimatorCameraMaya::isMouseKeyDown(s32 key) +{ + return MouseKeys[key]; +} + + +void CSceneNodeAnimatorCameraMaya::allKeysUp() +{ + for (s32 i=0; i<3; ++i) + MouseKeys[i] = false; +} + + +//! Sets the rotation speed +void CSceneNodeAnimatorCameraMaya::setRotateSpeed(f32 speed) +{ + RotateSpeed = speed; +} + + +//! Sets the movement speed +void CSceneNodeAnimatorCameraMaya::setMoveSpeed(f32 speed) +{ + TranslateSpeed = speed; +} + + +//! Sets the zoom speed +void CSceneNodeAnimatorCameraMaya::setZoomSpeed(f32 speed) +{ + ZoomSpeed = speed; +} + + +//! Gets the rotation speed +f32 CSceneNodeAnimatorCameraMaya::getRotateSpeed() const +{ + return RotateSpeed; +} + + +// Gets the movement speed +f32 CSceneNodeAnimatorCameraMaya::getMoveSpeed() const +{ + return TranslateSpeed; +} + + +//! Gets the zoom speed +f32 CSceneNodeAnimatorCameraMaya::getZoomSpeed() const +{ + return ZoomSpeed; +} + +ISceneNodeAnimator* CSceneNodeAnimatorCameraMaya::createClone(ISceneNode* node, ISceneManager* newManager) +{ + CSceneNodeAnimatorCameraMaya * newAnimator = + new CSceneNodeAnimatorCameraMaya(CursorControl, RotateSpeed, ZoomSpeed, TranslateSpeed); + return newAnimator; +} + +} // end namespace +} // end namespace + diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorCameraMaya.h b/src/dep/src/irrlicht/CSceneNodeAnimatorCameraMaya.h index 39010f3..c83d23e 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorCameraMaya.h +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorCameraMaya.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -99,6 +99,7 @@ namespace scene f32 CurrentZoom; f32 RotX, RotY; core::vector3df OldTarget; + core::vector3df LastCameraTarget; // to find out if the camera target was moved outside this animator scene::ICameraSceneNode* OldCamera; core::position2df MousePos; diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorCollisionResponse.cpp b/src/dep/src/irrlicht/CSceneNodeAnimatorCollisionResponse.cpp index 5aad546..3f51b6d 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorCollisionResponse.cpp +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorCollisionResponse.cpp @@ -1,246 +1,303 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "CSceneNodeAnimatorCollisionResponse.h" -#include "ISceneCollisionManager.h" -#include "ISceneManager.h" -#include "ICameraSceneNode.h" -#include "os.h" - -namespace irr -{ -namespace scene -{ - -//! constructor -CSceneNodeAnimatorCollisionResponse::CSceneNodeAnimatorCollisionResponse( - ISceneManager* scenemanager, - ITriangleSelector* world, ISceneNode* object, - const core::vector3df& ellipsoidRadius, - const core::vector3df& gravityPerSecond, - const core::vector3df& ellipsoidTranslation, - f32 slidingSpeed) -: Radius(ellipsoidRadius), Gravity(gravityPerSecond), Translation(ellipsoidTranslation), - World(world), Object(object), SceneManager(scenemanager), LastTime(0), - SlidingSpeed(slidingSpeed), Falling(false), IsCamera(false), - AnimateCameraTarget(true) -{ - #ifdef _DEBUG - setDebugName("CSceneNodeAnimatorCollisionResponse"); - #endif - - if (World) - World->grab(); - - setNode(Object); -} - - -//! destructor -CSceneNodeAnimatorCollisionResponse::~CSceneNodeAnimatorCollisionResponse() -{ - if (World) - World->drop(); -} - - -//! Returns if the attached scene node is falling, which means that -//! there is no blocking wall from the scene node in the direction of -//! the gravity. -bool CSceneNodeAnimatorCollisionResponse::isFalling() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return Falling; -} - - -//! Sets the radius of the ellipsoid with which collision detection and -//! response is done. -void CSceneNodeAnimatorCollisionResponse::setEllipsoidRadius( - const core::vector3df& radius) -{ - Radius = radius; -} - - -//! Returns the radius of the ellipsoid with wich the collision detection and -//! response is done. -core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidRadius() const -{ - return Radius; -} - - -//! Sets the gravity of the environment. -void CSceneNodeAnimatorCollisionResponse::setGravity(const core::vector3df& gravity) -{ - Gravity = gravity; -} - - -//! Returns current vector of gravity. -core::vector3df CSceneNodeAnimatorCollisionResponse::getGravity() const -{ - return Gravity; -} - - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CSceneNodeAnimatorCollisionResponse.h" +#include "ISceneCollisionManager.h" +#include "ISceneManager.h" +#include "ICameraSceneNode.h" +#include "os.h" + +namespace irr +{ +namespace scene +{ + +//! constructor +CSceneNodeAnimatorCollisionResponse::CSceneNodeAnimatorCollisionResponse( + ISceneManager* scenemanager, + ITriangleSelector* world, ISceneNode* object, + const core::vector3df& ellipsoidRadius, + const core::vector3df& gravityPerSecond, + const core::vector3df& ellipsoidTranslation, + f32 slidingSpeed) +: Radius(ellipsoidRadius), Gravity(gravityPerSecond), Translation(ellipsoidTranslation), + World(world), Object(object), SceneManager(scenemanager), LastTime(0), + SlidingSpeed(slidingSpeed), CollisionCallback(0), + Falling(false), IsCamera(false), AnimateCameraTarget(true), CollisionOccurred(false), + FirstUpdate(true) +{ + #ifdef _DEBUG + setDebugName("CSceneNodeAnimatorCollisionResponse"); + #endif + + if (World) + World->grab(); + + setNode(Object); +} + + +//! destructor +CSceneNodeAnimatorCollisionResponse::~CSceneNodeAnimatorCollisionResponse() +{ + if (World) + World->drop(); + + if (CollisionCallback) + CollisionCallback->drop(); +} + + +//! Returns if the attached scene node is falling, which means that +//! there is no blocking wall from the scene node in the direction of +//! the gravity. +bool CSceneNodeAnimatorCollisionResponse::isFalling() const +{ + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Falling; +} + + +//! Sets the radius of the ellipsoid with which collision detection and +//! response is done. +void CSceneNodeAnimatorCollisionResponse::setEllipsoidRadius( + const core::vector3df& radius) +{ + Radius = radius; + FirstUpdate = true; +} + + +//! Returns the radius of the ellipsoid with wich the collision detection and +//! response is done. +core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidRadius() const +{ + return Radius; +} + + +//! Sets the gravity of the environment. +void CSceneNodeAnimatorCollisionResponse::setGravity(const core::vector3df& gravity) +{ + Gravity = gravity; + FirstUpdate = true; +} + + +//! Returns current vector of gravity. +core::vector3df CSceneNodeAnimatorCollisionResponse::getGravity() const +{ + return Gravity; +} + + //! 'Jump' the animator, by adding a jump speed opposite to its gravity void CSceneNodeAnimatorCollisionResponse::jump(f32 jumpSpeed) { FallingVelocity -= (core::vector3df(Gravity).normalize()) * jumpSpeed; Falling = true; -} - - -//! Sets the translation of the ellipsoid for collision detection. -void CSceneNodeAnimatorCollisionResponse::setEllipsoidTranslation(const core::vector3df &translation) -{ - Translation = translation; -} - - -//! Returns the translation of the ellipsoid for collision detection. -core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidTranslation() const -{ - return Translation; -} - - -//! Sets a triangle selector holding all triangles of the world with which -//! the scene node may collide. -void CSceneNodeAnimatorCollisionResponse::setWorld(ITriangleSelector* newWorld) -{ - Falling = false; - - LastTime = os::Timer::getTime(); - - if (World) - World->drop(); - - World = newWorld; - if (World) - World->grab(); - -} - - -//! Returns the current triangle selector containing all triangles for -//! collision detection. -ITriangleSelector* CSceneNodeAnimatorCollisionResponse::getWorld() const -{ - return World; -} - - -void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 timeMs) -{ - if (node != Object) - { - setNode(node); - return; - } - - if (!World) - return; - - u32 diff = timeMs - LastTime; - LastTime = timeMs; - - core::vector3df pos = Object->getPosition(); - core::vector3df vel = pos - LastPosition; - - FallingVelocity += Gravity * (f32)diff * 0.001f; - - core::triangle3df triangle = RefTriangle; - - core::vector3df force = vel + FallingVelocity; - - const core::vector3df nullVector ( 0.f, 0.f, 0.f ); - - if ( force != nullVector ) - { - // TODO: divide SlidingSpeed by frame time - - bool f = false; - pos = SceneManager->getSceneCollisionManager()->getCollisionResultPosition( - World, LastPosition-Translation, - Radius, vel, triangle, f, SlidingSpeed, FallingVelocity); - - pos += Translation; - - if (f)//triangle == RefTriangle) - { - Falling = true; - } - else - { - Falling = false; - FallingVelocity.set(0, 0, 0); - } - - Object->setPosition(pos); - } - - // move camera target - if (AnimateCameraTarget && IsCamera) - { - const core::vector3df pdiff = Object->getPosition() - LastPosition - vel; - ICameraSceneNode* cam = (ICameraSceneNode*)Object; - cam->setTarget(cam->getTarget() + pdiff); - } - - LastPosition = Object->getPosition(); -} - - -void CSceneNodeAnimatorCollisionResponse::setNode(ISceneNode* node) -{ - Object = node; - - if (Object) - { - LastPosition = Object->getPosition(); - IsCamera = (Object->getType() == ESNT_CAMERA); - } - - LastTime = os::Timer::getTime(); -} - - -//! Writes attributes of the scene node animator. -void CSceneNodeAnimatorCollisionResponse::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const -{ - out->addVector3d("Radius", Radius); - out->addVector3d("Gravity", Gravity); - out->addVector3d("Translation", Translation); - out->addBool("AnimateCameraTarget", AnimateCameraTarget); -} - - -//! Reads attributes of the scene node animator. -void CSceneNodeAnimatorCollisionResponse::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) -{ - Radius = in->getAttributeAsVector3d("Radius"); - Gravity = in->getAttributeAsVector3d("Gravity"); - Translation = in->getAttributeAsVector3d("Translation"); - AnimateCameraTarget = in->getAttributeAsBool("AnimateCameraTarget"); -} - - -ISceneNodeAnimator* CSceneNodeAnimatorCollisionResponse::createClone(ISceneNode* node, ISceneManager* newManager) -{ - if (!newManager) newManager = SceneManager; - - CSceneNodeAnimatorCollisionResponse * newAnimator = - new CSceneNodeAnimatorCollisionResponse(newManager, World, Object, Radius, (Gravity * 1000.0f), Translation, - SlidingSpeed); - - return newAnimator; -} - - -} // end namespace scene -} // end namespace irr - +} + + +//! Sets the translation of the ellipsoid for collision detection. +void CSceneNodeAnimatorCollisionResponse::setEllipsoidTranslation(const core::vector3df &translation) +{ + Translation = translation; +} + + +//! Returns the translation of the ellipsoid for collision detection. +core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidTranslation() const +{ + return Translation; +} + + +//! Sets a triangle selector holding all triangles of the world with which +//! the scene node may collide. +void CSceneNodeAnimatorCollisionResponse::setWorld(ITriangleSelector* newWorld) +{ + if (newWorld) + newWorld->grab(); + + if (World) + World->drop(); + + World = newWorld; + + FirstUpdate = true; +} + + +//! Returns the current triangle selector containing all triangles for +//! collision detection. +ITriangleSelector* CSceneNodeAnimatorCollisionResponse::getWorld() const +{ + return World; +} + + +void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 timeMs) +{ + CollisionOccurred = false; + + if (node != Object) + setNode(node); + + if(!Object || !World) + return; + + // trigger reset + if ( timeMs == 0 ) + { + FirstUpdate = true; + timeMs = LastTime; + } + + if ( FirstUpdate ) + { + LastPosition = Object->getPosition(); + Falling = false; + LastTime = timeMs; + FallingVelocity.set ( 0, 0, 0 ); + + FirstUpdate = false; + } + + const u32 diff = timeMs - LastTime; + LastTime = timeMs; + + CollisionResultPosition = Object->getPosition(); + core::vector3df vel = CollisionResultPosition - LastPosition; + + FallingVelocity += Gravity * (f32)diff * 0.001f; + + CollisionTriangle = RefTriangle; + CollisionPoint = core::vector3df(); + CollisionResultPosition = core::vector3df(); + CollisionNode = 0; + + core::vector3df force = vel + FallingVelocity; + + if ( AnimateCameraTarget ) + { + // TODO: divide SlidingSpeed by frame time + + bool f = false; + CollisionResultPosition + = SceneManager->getSceneCollisionManager()->getCollisionResultPosition( + World, LastPosition-Translation, + Radius, vel, CollisionTriangle, CollisionPoint, f, + CollisionNode, SlidingSpeed, FallingVelocity); + + CollisionOccurred = (CollisionTriangle != RefTriangle); + + CollisionResultPosition += Translation; + + if (f)//CollisionTriangle == RefTriangle) + { + Falling = true; + } + else + { + Falling = false; + FallingVelocity.set(0, 0, 0); + } + + bool collisionConsumed = false; + + if (CollisionOccurred && CollisionCallback) + collisionConsumed = CollisionCallback->onCollision(*this); + + if(!collisionConsumed) + Object->setPosition(CollisionResultPosition); + } + + // move camera target + if (AnimateCameraTarget && IsCamera) + { + const core::vector3df pdiff = Object->getPosition() - LastPosition - vel; + ICameraSceneNode* cam = (ICameraSceneNode*)Object; + cam->setTarget(cam->getTarget() + pdiff); + } + + LastPosition = Object->getPosition(); +} + + +void CSceneNodeAnimatorCollisionResponse::setNode(ISceneNode* node) +{ + Object = node; + + if (Object) + { + LastPosition = Object->getPosition(); + IsCamera = (Object->getType() == ESNT_CAMERA); + } + + LastTime = os::Timer::getTime(); +} + + +//! Writes attributes of the scene node animator. +void CSceneNodeAnimatorCollisionResponse::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + out->addVector3d("Radius", Radius); + out->addVector3d("Gravity", Gravity); + out->addVector3d("Translation", Translation); + out->addBool("AnimateCameraTarget", AnimateCameraTarget); +} + + +//! Reads attributes of the scene node animator. +void CSceneNodeAnimatorCollisionResponse::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + Radius = in->getAttributeAsVector3d("Radius"); + Gravity = in->getAttributeAsVector3d("Gravity"); + Translation = in->getAttributeAsVector3d("Translation"); + AnimateCameraTarget = in->getAttributeAsBool("AnimateCameraTarget"); +} + + +ISceneNodeAnimator* CSceneNodeAnimatorCollisionResponse::createClone(ISceneNode* node, ISceneManager* newManager) +{ + if (!newManager) newManager = SceneManager; + + CSceneNodeAnimatorCollisionResponse * newAnimator = + new CSceneNodeAnimatorCollisionResponse(newManager, World, Object, Radius, + (Gravity * 1000.0f), Translation, SlidingSpeed); + + return newAnimator; +} + +void CSceneNodeAnimatorCollisionResponse::setCollisionCallback(ICollisionCallback* callback) +{ + if ( CollisionCallback == callback ) + return; + + if (CollisionCallback) + CollisionCallback->drop(); + + CollisionCallback = callback; + + if (CollisionCallback) + CollisionCallback->grab(); +} + +//! Should the Target react on collision ( default = true ) +void CSceneNodeAnimatorCollisionResponse::setAnimateTarget ( bool enable ) +{ + AnimateCameraTarget = enable; + FirstUpdate = true; +} + +//! Should the Target react on collision ( default = true ) +bool CSceneNodeAnimatorCollisionResponse::getAnimateTarget () const +{ + return AnimateCameraTarget; +} + +} // end namespace scene +} // end namespace irr + diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorCollisionResponse.h b/src/dep/src/irrlicht/CSceneNodeAnimatorCollisionResponse.h index 6058be1..19d490c 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorCollisionResponse.h +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorCollisionResponse.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.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 @@ -54,6 +54,10 @@ namespace scene //! 'Jump' the animator, by adding a jump speed opposite to its gravity virtual void jump(f32 jumpSpeed); + //! Should the Target react on collision ( default = true ) + virtual void setAnimateTarget ( bool enable ); + virtual bool getAnimateTarget () const; + //! Returns current vector of gravity. virtual core::vector3df getGravity() const; @@ -82,13 +86,39 @@ 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; } + + //! Returns true if a collision occurred during the last animateNode() + virtual bool collisionOccurred() const { return CollisionOccurred; } + + //! Returns the last point of collision. + virtual const core::vector3df & getCollisionPoint() const { return CollisionPoint; } + + //! Returns the last triangle that caused a collision. + virtual const core::triangle3df & getCollisionTriangle() const { return CollisionTriangle; } + + virtual const core::vector3df & getCollisionResultPosition(void) const { return CollisionResultPosition; } + + virtual const ISceneNode* getCollisionNode(void) const { return CollisionNode; } + + + //! Sets a callback interface which will be called if a collision occurs. + /** \param callback: collision callback handler that will be called when a collision + occurs. Set this to 0 to disable the callback. + */ + virtual void setCollisionCallback(ICollisionCallback* callback); + private: void setNode(ISceneNode* node); @@ -100,15 +130,24 @@ namespace scene core::vector3df LastPosition; core::triangle3df RefTriangle; - + ITriangleSelector* World; ISceneNode* Object; ISceneManager* SceneManager; u32 LastTime; f32 SlidingSpeed; + + core::vector3df CollisionPoint; + core::triangle3df CollisionTriangle; + core::vector3df CollisionResultPosition; + const ISceneNode * CollisionNode; + ICollisionCallback* CollisionCallback; + bool Falling; bool IsCamera; bool AnimateCameraTarget; + bool CollisionOccurred; + bool FirstUpdate; }; } // end namespace scene diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorDelete.cpp b/src/dep/src/irrlicht/CSceneNodeAnimatorDelete.cpp index 68f09a2..1e66a6d 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorDelete.cpp +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorDelete.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -13,7 +13,7 @@ namespace scene //! constructor CSceneNodeAnimatorDelete::CSceneNodeAnimatorDelete(ISceneManager* manager, u32 time) -: DeleteTime(time), SceneManager(manager) +: ISceneNodeAnimatorFinishing(time), SceneManager(manager) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorDelete"); @@ -21,33 +21,31 @@ CSceneNodeAnimatorDelete::CSceneNodeAnimatorDelete(ISceneManager* manager, u32 t } - -//! destructor -CSceneNodeAnimatorDelete::~CSceneNodeAnimatorDelete() -{ -} - - - //! animates a scene node void CSceneNodeAnimatorDelete::animateNode(ISceneNode* node, u32 timeMs) { - if (timeMs > DeleteTime && node && SceneManager) + if (timeMs > FinishTime) { - // don't delete if scene manager is attached to an editor - if (!SceneManager->getParameters()->getAttributeAsBool(IRR_SCENE_MANAGER_IS_EDITOR)) - SceneManager->addToDeletionQueue(node); + HasFinished = true; + if(node && SceneManager) + { + // don't delete if scene manager is attached to an editor + if (!SceneManager->getParameters()->getAttributeAsBool(IRR_SCENE_MANAGER_IS_EDITOR)) + SceneManager->addToDeletionQueue(node); + } } } + ISceneNodeAnimator* CSceneNodeAnimatorDelete::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorDelete * newAnimator = - new CSceneNodeAnimatorDelete(SceneManager, DeleteTime); + new CSceneNodeAnimatorDelete(SceneManager, FinishTime); return newAnimator; } + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorDelete.h b/src/dep/src/irrlicht/CSceneNodeAnimatorDelete.h index 36a933c..4d3394c 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorDelete.h +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorDelete.h @@ -1,50 +1,46 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __C_SCENE_NODE_ANIMATOR_DELETE_H_INCLUDED__ -#define __C_SCENE_NODE_ANIMATOR_DELETE_H_INCLUDED__ - -#include "ISceneNode.h" - -namespace irr -{ -namespace scene -{ - class CSceneNodeAnimatorDelete : public ISceneNodeAnimator - { - public: - - //! constructor - CSceneNodeAnimatorDelete(ISceneManager* manager, u32 when); - - //! destructor - virtual ~CSceneNodeAnimatorDelete(); - - //! animates a scene node - virtual void animateNode(ISceneNode* node, u32 timeMs); - - //! Returns type of the scene node animator - virtual ESCENE_NODE_ANIMATOR_TYPE getType() const - { - return ESNAT_DELETION; - } - - //! 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); - - private: - - u32 DeleteTime; - ISceneManager* SceneManager; - }; - - -} // end namespace scene -} // end namespace irr - -#endif - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_SCENE_NODE_ANIMATOR_DELETE_H_INCLUDED__ +#define __C_SCENE_NODE_ANIMATOR_DELETE_H_INCLUDED__ + +#include "ISceneNodeAnimatorFinishing.h" + +namespace irr +{ +namespace scene +{ + class CSceneNodeAnimatorDelete : public ISceneNodeAnimatorFinishing + { + public: + + //! constructor + CSceneNodeAnimatorDelete(ISceneManager* manager, u32 when); + + //! animates a scene node + virtual void animateNode(ISceneNode* node, u32 timeMs); + + //! Returns type of the scene node animator + virtual ESCENE_NODE_ANIMATOR_TYPE getType() const + { + return ESNAT_DELETION; + } + + //! 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); + + private: + + ISceneManager* SceneManager; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorFlyCircle.cpp b/src/dep/src/irrlicht/CSceneNodeAnimatorFlyCircle.cpp index 79d877c..55c235f 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorFlyCircle.cpp +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorFlyCircle.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,9 +9,13 @@ namespace irr namespace scene { + //! constructor -CSceneNodeAnimatorFlyCircle::CSceneNodeAnimatorFlyCircle(u32 time, const core::vector3df& center, f32 radius, f32 speed, const core::vector3df& direction) -: Center(center), Direction(direction), Radius(radius), Speed(speed), StartTime(time) +CSceneNodeAnimatorFlyCircle::CSceneNodeAnimatorFlyCircle(u32 time, + const core::vector3df& center, f32 radius, f32 speed, + const core::vector3df& direction, f32 radiusEllipsoid) + : Center(center), Direction(direction), Radius(radius), + RadiusEllipsoid(radiusEllipsoid), Speed(speed), StartTime(time) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorFlyCircle"); @@ -38,9 +42,17 @@ void CSceneNodeAnimatorFlyCircle::animateNode(ISceneNode* node, u32 timeMs) if ( 0 == node ) return; - const f32 t = (timeMs-StartTime) * Speed; + f32 time; - node->setPosition(Center + Radius * ((VecU*cosf(t)) + (VecV*sinf(t)))); + // Check for the condition where the StartTime is in the future. + if(StartTime > timeMs) + time = ((s32)timeMs - (s32)StartTime) * Speed; + else + time = (timeMs-StartTime) * Speed; + +// node->setPosition(Center + Radius * ((VecU*cosf(time)) + (VecV*sinf(time)))); + f32 r2 = RadiusEllipsoid == 0.f ? Radius : RadiusEllipsoid; + node->setPosition(Center + (Radius*cosf(time)*VecU) + (r2*sinf(time)*VecV ) ); } @@ -51,6 +63,7 @@ void CSceneNodeAnimatorFlyCircle::serializeAttributes(io::IAttributes* out, io:: out->addFloat("Radius", Radius); out->addFloat("Speed", Speed); out->addVector3d("Direction", Direction); + out->addFloat("RadiusEllipsoid", Radius); } @@ -67,17 +80,21 @@ void CSceneNodeAnimatorFlyCircle::deserializeAttributes(io::IAttributes* in, io: Direction.set(0,1,0); // irrlicht 1.1 backwards compatibility else Direction.normalize(); + + RadiusEllipsoid = in->getAttributeAsFloat("RadiusEllipsoid"); init(); } + ISceneNodeAnimator* CSceneNodeAnimatorFlyCircle::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorFlyCircle * newAnimator = - new CSceneNodeAnimatorFlyCircle(StartTime, Center, Radius, Speed, Direction); + new CSceneNodeAnimatorFlyCircle(StartTime, Center, Radius, Speed, Direction, RadiusEllipsoid); return newAnimator; } + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorFlyCircle.h b/src/dep/src/irrlicht/CSceneNodeAnimatorFlyCircle.h index 3c1fe38..ee5ae56 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorFlyCircle.h +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorFlyCircle.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,7 +18,8 @@ namespace scene //! constructor CSceneNodeAnimatorFlyCircle(u32 time, const core::vector3df& center, f32 radius, - f32 speed, const core::vector3df& direction); + f32 speed, const core::vector3df& direction, + f32 radiusEllipsoid); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); @@ -50,6 +51,7 @@ namespace scene core::vector3df VecU; core::vector3df VecV; f32 Radius; + f32 RadiusEllipsoid; f32 Speed; u32 StartTime; }; diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorFlyStraight.cpp b/src/dep/src/irrlicht/CSceneNodeAnimatorFlyStraight.cpp index cb419e2..3b5e93b 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorFlyStraight.cpp +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorFlyStraight.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -13,35 +13,27 @@ namespace scene //! constructor CSceneNodeAnimatorFlyStraight::CSceneNodeAnimatorFlyStraight(const core::vector3df& startPoint, const core::vector3df& endPoint, u32 timeForWay, - bool loop, u32 now) -: Start(startPoint), End(endPoint), WayLength(0.0f), TimeFactor(0.0f), StartTime(now), TimeForWay(timeForWay), Loop(loop) + bool loop, u32 now, bool pingpong) +: ISceneNodeAnimatorFinishing(now + timeForWay), + Start(startPoint), End(endPoint), TimeFactor(0.0f), StartTime(now), + TimeForWay(timeForWay), Loop(loop), PingPong(pingpong) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorFlyStraight"); #endif - recalculateImidiateValues(); + recalculateIntermediateValues(); } -void CSceneNodeAnimatorFlyStraight::recalculateImidiateValues() +void CSceneNodeAnimatorFlyStraight::recalculateIntermediateValues() { Vector = End - Start; - WayLength = (f32)Vector.getLength(); + TimeFactor = (f32)Vector.getLength() / TimeForWay; Vector.normalize(); - - TimeFactor = WayLength / TimeForWay; } - -//! destructor -CSceneNodeAnimatorFlyStraight::~CSceneNodeAnimatorFlyStraight() -{ -} - - - //! animates a scene node void CSceneNodeAnimatorFlyStraight::animateNode(ISceneNode* node, u32 timeMs) { @@ -50,12 +42,34 @@ void CSceneNodeAnimatorFlyStraight::animateNode(ISceneNode* node, u32 timeMs) u32 t = (timeMs-StartTime); - core::vector3df pos = Start; + core::vector3df pos; - if (!Loop && t >= TimeForWay) + if (!Loop && !PingPong && t >= TimeForWay) + { pos = End; + HasFinished = true; + } + else if (!Loop && PingPong && t >= TimeForWay * 2.f ) + { + pos = Start; + HasFinished = true; + } else - pos += Vector * (f32)fmod((f32)t, (f32)TimeForWay) * TimeFactor; + { + f32 phase = fmodf( (f32) t, (f32) TimeForWay ); + core::vector3df rel = Vector * phase * TimeFactor; + const bool pong = PingPong && fmodf( (f32) t, (f32) TimeForWay*2.f ) >= TimeForWay; + + if ( !pong ) + { + pos += Start + rel; + } + else + { + pos = End - rel; + } + } + node->setPosition(pos); } @@ -67,6 +81,7 @@ void CSceneNodeAnimatorFlyStraight::serializeAttributes(io::IAttributes* out, io out->addVector3d("End", End); out->addInt("TimeForWay", TimeForWay); out->addBool("Loop", Loop); + out->addBool("PingPong", PingPong); } @@ -77,18 +92,21 @@ void CSceneNodeAnimatorFlyStraight::deserializeAttributes(io::IAttributes* in, i End = in->getAttributeAsVector3d("End"); TimeForWay = in->getAttributeAsInt("TimeForWay"); Loop = in->getAttributeAsBool("Loop"); + PingPong = in->getAttributeAsBool("PingPong"); - recalculateImidiateValues(); + recalculateIntermediateValues(); } + ISceneNodeAnimator* CSceneNodeAnimatorFlyStraight::createClone(ISceneNode* node, ISceneManager* newManager) { - CSceneNodeAnimatorFlyStraight * newAnimator = - new CSceneNodeAnimatorFlyStraight(Start, End, TimeForWay, Loop, StartTime); + CSceneNodeAnimatorFlyStraight * newAnimator = + new CSceneNodeAnimatorFlyStraight(Start, End, TimeForWay, Loop, StartTime, PingPong); return newAnimator; } + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorFlyStraight.h b/src/dep/src/irrlicht/CSceneNodeAnimatorFlyStraight.h index b412978..3316455 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorFlyStraight.h +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorFlyStraight.h @@ -1,17 +1,17 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_FLY_STRAIGHT_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_FLY_STRAIGHT_H_INCLUDED__ -#include "ISceneNode.h" +#include "ISceneNodeAnimatorFinishing.h" namespace irr { namespace scene { - class CSceneNodeAnimatorFlyStraight : public ISceneNodeAnimator + class CSceneNodeAnimatorFlyStraight : public ISceneNodeAnimatorFinishing { public: @@ -19,10 +19,7 @@ namespace scene CSceneNodeAnimatorFlyStraight(const core::vector3df& startPoint, const core::vector3df& endPoint, u32 timeForWay, - bool loop, u32 now); - - //! destructor - virtual ~CSceneNodeAnimatorFlyStraight(); + bool loop, u32 now, bool pingpong); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); @@ -35,25 +32,24 @@ namespace scene //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_FLY_STRAIGHT; } - + //! Creates a clone of this animator. /** Please note that you will have to drop - (IReferenceCounted::drop()) the returned pointer after calling - this. */ + (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); private: - void recalculateImidiateValues(); + void recalculateIntermediateValues(); core::vector3df Start; core::vector3df End; core::vector3df Vector; - f32 WayLength; f32 TimeFactor; u32 StartTime; u32 TimeForWay; bool Loop; + bool PingPong; }; diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorFollowSpline.cpp b/src/dep/src/irrlicht/CSceneNodeAnimatorFollowSpline.cpp index 63aeb38..9016ada 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorFollowSpline.cpp +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorFollowSpline.cpp @@ -1,131 +1,161 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "CSceneNodeAnimatorFollowSpline.h" - -namespace irr -{ -namespace scene -{ - -//! constructor -CSceneNodeAnimatorFollowSpline::CSceneNodeAnimatorFollowSpline(u32 time, - const core::array& points, f32 speed, - f32 tightness) -: Points(points), Speed(speed), Tightness(tightness), StartTime(time) -{ - #ifdef _DEBUG - setDebugName("CSceneNodeAnimatorFollowSpline"); - #endif -} - - -inline s32 CSceneNodeAnimatorFollowSpline::clamp(s32 idx, s32 size) -{ - return ( idx<0 ? size+idx : ( idx>=size ? idx-size : idx ) ); -} - - -//! animates a scene node -void CSceneNodeAnimatorFollowSpline::animateNode(ISceneNode* node, u32 timeMs) -{ - const u32 pSize = Points.size(); - if (pSize==0) - return; - if (pSize==1) - { - node->setPosition(Points[0]); - return; - } - - const f32 dt = ( (timeMs-StartTime) * Speed * 0.001f ); - const f32 u = core::fract ( dt ); - const s32 idx = core::floor32( dt ) % pSize; - //const f32 u = 0.001f * fmodf( dt, 1000.0f ); - - const core::vector3df& p0 = Points[ clamp( idx - 1, pSize ) ]; - const core::vector3df& p1 = Points[ clamp( idx + 0, pSize ) ]; // starting point - const core::vector3df& p2 = Points[ clamp( idx + 1, pSize ) ]; // end point - const core::vector3df& p3 = Points[ clamp( idx + 2, pSize ) ]; - - // hermite polynomials - const f32 h1 = 2.0f * u * u * u - 3.0f * u * u + 1.0f; - const f32 h2 = -2.0f * u * u * u + 3.0f * u * u; - const f32 h3 = u * u * u - 2.0f * u * u + u; - const f32 h4 = u * u * u - u * u; - - // tangents - const core::vector3df t1 = ( p2 - p0 ) * Tightness; - const core::vector3df t2 = ( p3 - p1 ) * Tightness; - - // interpolated point - node->setPosition(p1 * h1 + p2 * h2 + t1 * h3 + t2 * h4); -} - - -//! Writes attributes of the scene node animator. -void CSceneNodeAnimatorFollowSpline::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const -{ - out->addFloat("Speed", Speed); - out->addFloat("Tightness", Tightness); - - u32 count = Points.size(); - - if ( options && (options->Flags & io::EARWF_FOR_EDITOR)) - { - // add one point in addition when serializing for editors - // to make it easier to add points quickly - count += 1; - } - - for (u32 i=0; iaddVector3d(tname.c_str(), igetAttributeAsFloat("Speed"); - Tightness = in->getAttributeAsFloat("Tightness"); - Points.clear(); - - for(u32 i=1; true; ++i) - { - core::stringc pname = "Point"; - pname += i; - - if (in->existsAttribute(pname.c_str())) - Points.push_back(in->getAttributeAsVector3d(pname.c_str())); - else - break; - } - - // remove last point if double entry from editor - if ( options && (options->Flags & io::EARWF_FOR_EDITOR) && - Points.size() > 2 && Points.getLast() == core::vector3df(0,0,0)) - { - Points.erase(Points.size()-1); - - if (Points.size() > 2 && Points.getLast() == core::vector3df(0,0,0)) - Points.erase(Points.size()-1); - } -} - -ISceneNodeAnimator* CSceneNodeAnimatorFollowSpline::createClone(ISceneNode* node, ISceneManager* newManager) -{ - CSceneNodeAnimatorFollowSpline * newAnimator = - new CSceneNodeAnimatorFollowSpline(StartTime, Points, Speed, Tightness); - - return newAnimator; -} - -} // end namespace scene -} // end namespace irr - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CSceneNodeAnimatorFollowSpline.h" + +namespace irr +{ +namespace scene +{ + + +//! constructor +CSceneNodeAnimatorFollowSpline::CSceneNodeAnimatorFollowSpline(u32 time, + const core::array& points, f32 speed, + f32 tightness, bool loop, bool pingpong) +: ISceneNodeAnimatorFinishing(0), Points(points), Speed(speed), Tightness(tightness), StartTime(time) +, Loop(loop), PingPong(pingpong) +{ + #ifdef _DEBUG + setDebugName("CSceneNodeAnimatorFollowSpline"); + #endif +} + + +inline s32 CSceneNodeAnimatorFollowSpline::clamp(s32 idx, s32 size) +{ + return ( idx<0 ? size+idx : ( idx>=size ? idx-size : idx ) ); +} + + +//! animates a scene node +void CSceneNodeAnimatorFollowSpline::animateNode(ISceneNode* node, u32 timeMs) +{ + if(!node) + return; + + const u32 pSize = Points.size(); + if (pSize==0) + { + if ( !Loop ) + HasFinished = true; + return; + } + if (pSize==1) + { + if ( timeMs > StartTime ) + { + node->setPosition(Points[0]); + if ( !Loop ) + HasFinished = true; + } + return; + } + + const f32 dt = ( (timeMs-StartTime) * Speed * 0.001f ); + const s32 unwrappedIdx = core::floor32( dt ); + if ( !Loop && unwrappedIdx >= (s32)pSize-1 ) + { + node->setPosition(Points[pSize-1]); + HasFinished = true; + return; + } + const bool pong = PingPong && (unwrappedIdx/(pSize-1))%2; + const f32 u = pong ? 1.f-core::fract ( dt ) : core::fract ( dt ); + const s32 idx = pong ? (pSize-2) - (unwrappedIdx % (pSize-1)) + : (PingPong ? unwrappedIdx % (pSize-1) + : unwrappedIdx % pSize); + //const f32 u = 0.001f * fmodf( dt, 1000.0f ); + + const core::vector3df& p0 = Points[ clamp( idx - 1, pSize ) ]; + const core::vector3df& p1 = Points[ clamp( idx + 0, pSize ) ]; // starting point + const core::vector3df& p2 = Points[ clamp( idx + 1, pSize ) ]; // end point + const core::vector3df& p3 = Points[ clamp( idx + 2, pSize ) ]; + + // hermite polynomials + const f32 h1 = 2.0f * u * u * u - 3.0f * u * u + 1.0f; + const f32 h2 = -2.0f * u * u * u + 3.0f * u * u; + const f32 h3 = u * u * u - 2.0f * u * u + u; + const f32 h4 = u * u * u - u * u; + + // tangents + const core::vector3df t1 = ( p2 - p0 ) * Tightness; + const core::vector3df t2 = ( p3 - p1 ) * Tightness; + + // interpolated point + node->setPosition(p1 * h1 + p2 * h2 + t1 * h3 + t2 * h4); +} + + +//! Writes attributes of the scene node animator. +void CSceneNodeAnimatorFollowSpline::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + out->addFloat("Speed", Speed); + out->addFloat("Tightness", Tightness); + out->addBool("Loop", Loop); + out->addBool("PingPong", PingPong); + + u32 count = Points.size(); + + if ( options && (options->Flags & io::EARWF_FOR_EDITOR)) + { + // add one point in addition when serializing for editors + // to make it easier to add points quickly + count += 1; + } + + for (u32 i=0; iaddVector3d(tname.c_str(), igetAttributeAsFloat("Speed"); + Tightness = in->getAttributeAsFloat("Tightness"); + Loop = in->getAttributeAsBool("Loop"); + PingPong = in->getAttributeAsBool("PingPong"); + Points.clear(); + + for(u32 i=1; true; ++i) + { + core::stringc pname = "Point"; + pname += i; + + if (in->existsAttribute(pname.c_str())) + Points.push_back(in->getAttributeAsVector3d(pname.c_str())); + else + break; + } + + // remove last point if double entry from editor + if ( options && (options->Flags & io::EARWF_FOR_EDITOR) && + Points.size() > 2 && Points.getLast() == core::vector3df(0,0,0)) + { + Points.erase(Points.size()-1); + + if (Points.size() > 2 && Points.getLast() == core::vector3df(0,0,0)) + Points.erase(Points.size()-1); + } +} + + +ISceneNodeAnimator* CSceneNodeAnimatorFollowSpline::createClone(ISceneNode* node, ISceneManager* newManager) +{ + CSceneNodeAnimatorFollowSpline * newAnimator = + new CSceneNodeAnimatorFollowSpline(StartTime, Points, Speed, Tightness); + + return newAnimator; +} + + +} // end namespace scene +} // end namespace irr + diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorFollowSpline.h b/src/dep/src/irrlicht/CSceneNodeAnimatorFollowSpline.h index 6c9d80c..de20e21 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorFollowSpline.h +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorFollowSpline.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -7,21 +7,22 @@ #include "ISceneNode.h" #include "irrArray.h" +#include "ISceneNodeAnimatorFinishing.h" namespace irr { namespace scene { - //! Scene node animator based free code Matthias Gall wrote and sent in. (Most of + //! Scene node animator based free code Matthias Gall wrote and sent in. (Most of //! this code is written by him, I only modified bits.) - class CSceneNodeAnimatorFollowSpline : public ISceneNodeAnimator + class CSceneNodeAnimatorFollowSpline : public ISceneNodeAnimatorFinishing { public: - + //! constructor - CSceneNodeAnimatorFollowSpline(u32 startTime, + CSceneNodeAnimatorFollowSpline(u32 startTime, const core::array< core::vector3df >& points, - f32 speed = 1.0f, f32 tightness = 0.5f); + f32 speed = 1.0f, f32 tightness = 0.5f, bool loop=true, bool pingpong=false); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); @@ -34,7 +35,7 @@ namespace scene //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_FOLLOW_SPLINE; } - + //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling @@ -50,6 +51,8 @@ namespace scene f32 Speed; f32 Tightness; u32 StartTime; + bool Loop; + bool PingPong; }; diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorRotation.cpp b/src/dep/src/irrlicht/CSceneNodeAnimatorRotation.cpp index 8aab8ab..0f37d6d 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorRotation.cpp +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorRotation.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -9,6 +9,7 @@ namespace irr namespace scene { + //! constructor CSceneNodeAnimatorRotation::CSceneNodeAnimatorRotation(u32 time, const core::vector3df& rotation) : Rotation(rotation), StartTime(time) @@ -19,25 +20,25 @@ CSceneNodeAnimatorRotation::CSceneNodeAnimatorRotation(u32 time, const core::vec } -//! destructor -CSceneNodeAnimatorRotation::~CSceneNodeAnimatorRotation() -{ -} - - - //! animates a scene node void CSceneNodeAnimatorRotation::animateNode(ISceneNode* node, u32 timeMs) { if (node) // thanks to warui for this fix { - u32 diffTime = timeMs - StartTime; + const u32 diffTime = timeMs - StartTime; if (diffTime != 0) { - core::vector3df NewRotation = node->getRotation(); - NewRotation += Rotation* ((diffTime)/10.0f); - node->setRotation(NewRotation); + // clip the rotation to small values, to avoid + // precision problems with huge floats. + core::vector3df rot = node->getRotation() + Rotation*(diffTime*0.1f); + if (rot.X>360.f) + rot.X=fmodf(rot.X, 360.f); + if (rot.Y>360.f) + rot.Y=fmodf(rot.Y, 360.f); + if (rot.Z>360.f) + rot.Z=fmodf(rot.Z, 360.f); + node->setRotation(rot); StartTime=timeMs; } } @@ -50,12 +51,14 @@ void CSceneNodeAnimatorRotation::serializeAttributes(io::IAttributes* out, io::S out->addVector3d("Rotation", Rotation); } + //! Reads attributes of the scene node animator. void CSceneNodeAnimatorRotation::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Rotation = in->getAttributeAsVector3d("Rotation"); } + ISceneNodeAnimator* CSceneNodeAnimatorRotation::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorRotation * newAnimator = @@ -64,6 +67,7 @@ ISceneNodeAnimator* CSceneNodeAnimatorRotation::createClone(ISceneNode* node, IS return newAnimator; } + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorRotation.h b/src/dep/src/irrlicht/CSceneNodeAnimatorRotation.h index 78dfdbd..a9cf781 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorRotation.h +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorRotation.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,9 +18,6 @@ namespace scene //! constructor CSceneNodeAnimatorRotation(u32 time, const core::vector3df& rotation); - //! destructor - virtual ~CSceneNodeAnimatorRotation(); - //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); @@ -35,8 +32,7 @@ namespace scene //! Creates a clone of this animator. /** Please note that you will have to drop - (IReferenceCounted::drop()) the returned pointer after calling - this. */ + (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); private: diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorTexture.cpp b/src/dep/src/irrlicht/CSceneNodeAnimatorTexture.cpp index c569e6b..a462276 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorTexture.cpp +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorTexture.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -14,7 +14,8 @@ namespace scene //! constructor CSceneNodeAnimatorTexture::CSceneNodeAnimatorTexture(const core::array& textures, s32 timePerFrame, bool loop, u32 now) -: TimePerFrame(timePerFrame), StartTime(now), Loop(loop) +: ISceneNodeAnimatorFinishing(0), + TimePerFrame(timePerFrame), StartTime(now), Loop(loop) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorTexture"); @@ -28,11 +29,10 @@ CSceneNodeAnimatorTexture::CSceneNodeAnimatorTexture(const core::array= EndTime) + if (!Loop && timeMs >= FinishTime) + { idx = Textures.size() - 1; + HasFinished = true; + } else + { idx = (t/TimePerFrame) % Textures.size(); + } if (idx < Textures.size()) node->setMaterialTexture(0, Textures[idx]); @@ -91,6 +97,7 @@ void CSceneNodeAnimatorTexture::serializeAttributes(io::IAttributes* out, io::SA } } + //! Reads attributes of the scene node animator. void CSceneNodeAnimatorTexture::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { @@ -118,6 +125,7 @@ void CSceneNodeAnimatorTexture::deserializeAttributes(io::IAttributes* in, io::S } } + ISceneNodeAnimator* CSceneNodeAnimatorTexture::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorTexture * newAnimator = @@ -126,6 +134,7 @@ ISceneNodeAnimator* CSceneNodeAnimatorTexture::createClone(ISceneNode* node, ISc return newAnimator; } + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CSceneNodeAnimatorTexture.h b/src/dep/src/irrlicht/CSceneNodeAnimatorTexture.h index 9617891..74947f9 100644 --- a/src/dep/src/irrlicht/CSceneNodeAnimatorTexture.h +++ b/src/dep/src/irrlicht/CSceneNodeAnimatorTexture.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -6,13 +6,13 @@ #define __C_SCENE_NODE_ANIMATOR_TEXTURE_H_INCLUDED__ #include "irrArray.h" -#include "ISceneNode.h" +#include "ISceneNodeAnimatorFinishing.h" namespace irr { namespace scene { - class CSceneNodeAnimatorTexture : public ISceneNodeAnimator + class CSceneNodeAnimatorTexture : public ISceneNodeAnimatorFinishing { public: @@ -48,7 +48,6 @@ namespace scene core::array Textures; u32 TimePerFrame; u32 StartTime; - u32 EndTime; bool Loop; }; diff --git a/src/dep/src/irrlicht/CShadowVolumeSceneNode.cpp b/src/dep/src/irrlicht/CShadowVolumeSceneNode.cpp index 397b3ee..cc84c4e 100644 --- a/src/dep/src/irrlicht/CShadowVolumeSceneNode.cpp +++ b/src/dep/src/irrlicht/CShadowVolumeSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,10 +17,8 @@ namespace scene //! constructor CShadowVolumeSceneNode::CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent, ISceneManager* mgr, s32 id, bool zfailmethod, f32 infinity) -: IShadowVolumeSceneNode(parent, mgr, id), Vertices(0), Indices(0), - Adjacency(0), Edges(0), FaceData(0), ShadowMesh(0), - IndexCountAllocated(0), VertexCountAllocated(0), - IndexCount(0), VertexCount(0), EdgeCount(0), ShadowVolumesUsed(0), +: IShadowVolumeSceneNode(parent, mgr, id), + ShadowMesh(0), IndexCount(0), VertexCount(0), ShadowVolumesUsed(0), Infinity(infinity), UseZFailMethod(zfailmethod) { #ifdef _DEBUG @@ -37,15 +35,8 @@ CShadowVolumeSceneNode::~CShadowVolumeSceneNode() if (ShadowMesh) ShadowMesh->drop(); - delete [] Edges; - for (u32 i=0; i (u32)ShadowVolumesUsed) + if (ShadowVolumes.size() > ShadowVolumesUsed) { // get the next unused buffer svp = &ShadowVolumes[ShadowVolumesUsed]; @@ -84,16 +75,12 @@ void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light) ++ShadowVolumesUsed; } - const s32 faceCount = (s32)(IndexCount / 3); + const u32 faceCount = IndexCount / 3; - if (!Edges || faceCount * 6 > EdgeCount) - { - delete [] Edges; - EdgeCount = faceCount * 6; - Edges = new u16[EdgeCount]; - } + if (faceCount * 6 > Edges.size()) + Edges.set_used(faceCount*6); - s32 numEdges = 0; + u32 numEdges = 0; const core::vector3df ls = light * Infinity; // light scaled //if (UseZFailMethod) @@ -106,7 +93,7 @@ void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light) // is used createZPassVolume(faceCount, numEdges, light, svp, UseZFailMethod); - for (s32 i=0; idrop(); ShadowMesh = mesh; @@ -263,8 +252,8 @@ void CShadowVolumeSceneNode::setShadowMesh(const IMesh* mesh) void CShadowVolumeSceneNode::updateShadowVolumes() { - const s32 oldIndexCount = IndexCount; - const s32 oldVertexCount = VertexCount; + const u32 oldIndexCount = IndexCount; + const u32 oldVertexCount = VertexCount; VertexCount = 0; IndexCount = 0; @@ -277,8 +266,8 @@ void CShadowVolumeSceneNode::updateShadowVolumes() // calculate total amount of vertices and indices u32 i; - s32 totalVertices = 0; - s32 totalIndices = 0; + u32 totalVertices = 0; + u32 totalIndices = 0; const u32 bufcnt = mesh->getMeshBufferCount(); for (i=0; i VertexCountAllocated) - { - delete [] Vertices; - Vertices = new core::vector3df[totalVertices]; - VertexCountAllocated = totalVertices; - } + if (totalVertices > Vertices.size()) + Vertices.set_used(totalVertices); - if (totalIndices > IndexCountAllocated) + if (totalIndices > Indices.size()) { - delete [] Indices; - Indices = new u16[totalIndices]; - IndexCountAllocated = totalIndices; + Indices.set_used(totalIndices); if (UseZFailMethod) - { - delete [] FaceData; - FaceData = new bool[totalIndices / 3]; - } + FaceData.set_used(totalIndices / 3); } // copy mesh @@ -327,8 +307,7 @@ void CShadowVolumeSceneNode::updateShadowVolumes() } // recalculate adjacency if necessary - if (oldVertexCount != VertexCount && - oldIndexCount != IndexCount && UseZFailMethod) + if (oldVertexCount != VertexCount && oldIndexCount != IndexCount && UseZFailMethod) calculateAdjacency(); // create as much shadow volumes as there are lights but @@ -336,9 +315,9 @@ void CShadowVolumeSceneNode::updateShadowVolumes() const u32 lights = SceneManager->getVideoDriver()->getDynamicLightCount(); core::matrix4 mat = Parent->getAbsoluteTransformation(); + mat.makeInverse(); const core::vector3df parentpos = Parent->getAbsolutePosition(); core::vector3df lpos; - mat.makeInverse(); // TODO: Only correct for point lights. for (i=0; isetTransform(video::ETS_WORLD, Parent->getAbsoluteTransformation()); - for (s32 i=0; idrawStencilShadowVolume(ShadowVolumes[i].vertices, ShadowVolumes[i].count, UseZFailMethod); -/* if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) { video::SMaterial mat; @@ -388,12 +366,12 @@ void CShadowVolumeSceneNode::render() mat.Wireframe = true; mat.ZBuffer = true; driver->setMaterial(mat); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); - for (s32 i=0; idrawVertexPrimitiveList(ShadowVolumes[i].vertices, ShadowVolumes[i].count,0,0,video::EVT_STANDARD,scene::EPT_LINES); } -*/ } @@ -407,17 +385,14 @@ const core::aabbox3d& CShadowVolumeSceneNode::getBoundingBox() const //! Generates adjacency information based on mesh indices. void CShadowVolumeSceneNode::calculateAdjacency(f32 epsilon) { - delete [] Adjacency; - Adjacency = new u16[IndexCount]; + Adjacency.set_used(IndexCount); epsilon *= epsilon; - f32 t = 0; - // go through all faces and fetch their three neighbours - for (s32 f=0; f ShadowVolumes; - core::vector3df* Vertices; - u16* Indices; - u16* Adjacency; - u16* Edges; + core::array Vertices; + core::array Indices; + core::array Adjacency; + core::array Edges; // used for zfail method, if face is front facing - bool* FaceData; + core::array FaceData; const scene::IMesh* ShadowMesh; - s32 IndexCountAllocated; - s32 VertexCountAllocated; - s32 IndexCount; - s32 VertexCount; + u32 IndexCount; + u32 VertexCount; - s32 EdgeCount; - - s32 ShadowVolumesUsed; + u32 ShadowVolumesUsed; f32 Infinity; diff --git a/src/dep/src/irrlicht/CSkinnedMesh.cpp b/src/dep/src/irrlicht/CSkinnedMesh.cpp index 971244b..1f24c83 100644 --- a/src/dep/src/irrlicht/CSkinnedMesh.cpp +++ b/src/dep/src/irrlicht/CSkinnedMesh.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,9 +18,11 @@ namespace scene //! constructor CSkinnedMesh::CSkinnedMesh() -: SkinningBuffers(0), HasAnimation(0), PreparedForSkinning(0), - AnimationFrames(0.f), LastAnimatedFrame(0.f), LastSkinnedFrame(0.f), - BoneControlUsed(false), AnimateNormals(true), HardwareSkinning(0), InterpolationMode(EIM_LINEAR) +: SkinningBuffers(0), AnimationFrames(0.f), + LastAnimatedFrame(0.f), LastSkinnedFrame(0.f), + InterpolationMode(EIM_LINEAR), + HasAnimation(false), PreparedForSkinning(false), + BoneControlUsed(false), AnimateNormals(true), HardwareSkinning(false) { #ifdef _DEBUG setDebugName("CSkinnedMesh"); @@ -60,7 +62,6 @@ IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 return this; animateMesh((f32)frame, 1.0f); - buildAll_LocalAnimatedMatrices(); skinMesh(); return this; } @@ -115,18 +116,18 @@ void CSkinnedMesh::animateMesh(f32 frame, f32 blend) joint->Animatedscale = core::lerp(oldScale, scale, blend); joint->Animatedrotation.slerp(oldRotation, rotation, blend); } - - //Note: - //_LocalAnimatedMatrix needs to be built at some point, but this function may be called lots of times for - //one render (to play two animations at the same time) _LocalAnimatedMatrix only needs to be built once. - //a call to buildAllLocalAnimatedMatrices is needed before skinning the mesh, and before the user gets the joints to move - - //---------------- - // Temp! - buildAll_LocalAnimatedMatrices(); - //----------------- } + //Note: + //_LocalAnimatedMatrix needs to be built at some point, but this function may be called lots of times for + //one render (to play two animations at the same time) _LocalAnimatedMatrix only needs to be built once. + //a call to buildAllLocalAnimatedMatrices is needed before skinning the mesh, and before the user gets the joints to move + + //---------------- + // Temp! + buildAll_LocalAnimatedMatrices(); + //----------------- + updateBoundingBox(); } @@ -459,8 +460,8 @@ void CSkinnedMesh::skinMesh() for (i=0; isize(); ++i) (*SkinningBuffers)[i]->setDirty(EBT_VERTEX); - } + updateBoundingBox(); } @@ -710,8 +711,6 @@ bool CSkinnedMesh::setHardwareSkinning(bool on) LocalBuffers[buffer_id]->boundingBoxNeedsRecalculated(); } } - - } HardwareSkinning=on; @@ -1125,7 +1124,7 @@ void CSkinnedMesh::updateBoundingBox(void) } -scene::SSkinMeshBuffer *CSkinnedMesh::createBuffer() +scene::SSkinMeshBuffer *CSkinnedMesh::addMeshBuffer() { scene::SSkinMeshBuffer *buffer=new scene::SSkinMeshBuffer(); LocalBuffers.push_back(buffer); @@ -1133,7 +1132,7 @@ scene::SSkinMeshBuffer *CSkinnedMesh::createBuffer() } -CSkinnedMesh::SJoint *CSkinnedMesh::createJoint(SJoint *parent) +CSkinnedMesh::SJoint *CSkinnedMesh::addJoint(SJoint *parent) { SJoint *joint=new SJoint; @@ -1152,7 +1151,7 @@ CSkinnedMesh::SJoint *CSkinnedMesh::createJoint(SJoint *parent) } -CSkinnedMesh::SPositionKey *CSkinnedMesh::createPositionKey(SJoint *joint) +CSkinnedMesh::SPositionKey *CSkinnedMesh::addPositionKey(SJoint *joint) { if (!joint) return 0; @@ -1162,7 +1161,7 @@ CSkinnedMesh::SPositionKey *CSkinnedMesh::createPositionKey(SJoint *joint) } -CSkinnedMesh::SScaleKey *CSkinnedMesh::createScaleKey(SJoint *joint) +CSkinnedMesh::SScaleKey *CSkinnedMesh::addScaleKey(SJoint *joint) { if (!joint) return 0; @@ -1172,7 +1171,7 @@ CSkinnedMesh::SScaleKey *CSkinnedMesh::createScaleKey(SJoint *joint) } -CSkinnedMesh::SRotationKey *CSkinnedMesh::createRotationKey(SJoint *joint) +CSkinnedMesh::SRotationKey *CSkinnedMesh::addRotationKey(SJoint *joint) { if (!joint) return 0; @@ -1182,7 +1181,7 @@ CSkinnedMesh::SRotationKey *CSkinnedMesh::createRotationKey(SJoint *joint) } -CSkinnedMesh::SWeight *CSkinnedMesh::createWeight(SJoint *joint) +CSkinnedMesh::SWeight *CSkinnedMesh::addWeight(SJoint *joint) { if (!joint) return 0; @@ -1255,17 +1254,13 @@ void CSkinnedMesh::recoverJointsFromMesh(core::array &JointChil SJoint *joint=AllJoints[i]; node->setPosition( joint->LocalAnimatedMatrix.getTranslation() ); node->setRotation( joint->LocalAnimatedMatrix.getRotationDegrees() ); - - //node->setScale( joint->LocalAnimatedMatrix.getScale() ); + node->setScale( joint->LocalAnimatedMatrix.getScale() ); node->positionHint=joint->positionHint; node->scaleHint=joint->scaleHint; node->rotationHint=joint->rotationHint; - //node->setAbsoluteTransformation(joint->GlobalMatrix); //not going to work - - //Note: This updateAbsolutePosition will not work well if joints are not nested like b3d - //node->updateAbsolutePosition(); + node->updateAbsolutePosition(); } } @@ -1277,19 +1272,15 @@ void CSkinnedMesh::transferJointsToMesh(const core::array &Join const IBoneSceneNode* const node=JointChildSceneNodes[i]; SJoint *joint=AllJoints[i]; - joint->LocalAnimatedMatrix.setTranslation(node->getPosition()); joint->LocalAnimatedMatrix.setRotationDegrees(node->getRotation()); - - //joint->LocalAnimatedMatrix.setScale( node->getScale() ); + joint->LocalAnimatedMatrix.setTranslation(node->getPosition()); + joint->LocalAnimatedMatrix *= core::matrix4().setScale(node->getScale()); joint->positionHint=node->positionHint; joint->scaleHint=node->scaleHint; joint->rotationHint=node->rotationHint; - if (node->getSkinningSpace()==EBSS_GLOBAL) - joint->GlobalSkinningSpace=true; - else - joint->GlobalSkinningSpace=false; + joint->GlobalSkinningSpace=(node->getSkinningSpace()==EBSS_GLOBAL); } //Remove cache, temp... LastAnimatedFrame=-1; @@ -1364,7 +1355,7 @@ void CSkinnedMesh::convertMeshToTangents() { if (LocalBuffers[b]) { - LocalBuffers[b]->MoveTo_Tangents(); + LocalBuffers[b]->convertToTangents(); const s32 idxCnt = LocalBuffers[b]->getIndexCount(); @@ -1449,12 +1440,6 @@ void CSkinnedMesh::calculateTangents( } - - - - - - } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CSkinnedMesh.h b/src/dep/src/irrlicht/CSkinnedMesh.h index 9ce64ab..00d8f89 100644 --- a/src/dep/src/irrlicht/CSkinnedMesh.h +++ b/src/dep/src/irrlicht/CSkinnedMesh.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -134,20 +134,25 @@ namespace scene //! loaders should call this after populating the mesh virtual void finalize(); - virtual SSkinMeshBuffer *createBuffer(); + //! Adds a new meshbuffer to the mesh, access it as last one + virtual SSkinMeshBuffer *addMeshBuffer(); - virtual SJoint *createJoint(SJoint *parent=0); + //! Adds a new joint to the mesh, access it as last one + virtual SJoint *addJoint(SJoint *parent=0); - virtual SPositionKey *createPositionKey(SJoint *joint); - virtual SRotationKey *createRotationKey(SJoint *joint); - virtual SScaleKey *createScaleKey(SJoint *joint); + //! Adds a new position key to the mesh, access it as last one + virtual SPositionKey *addPositionKey(SJoint *joint); + //! Adds a new rotation key to the mesh, access it as last one + virtual SRotationKey *addRotationKey(SJoint *joint); + //! Adds a new scale key to the mesh, access it as last one + virtual SScaleKey *addScaleKey(SJoint *joint); - virtual SWeight *createWeight(SJoint *joint); + //! Adds a new weight to the mesh, access it as last one + virtual SWeight *addWeight(SJoint *joint); virtual void updateBoundingBox(void); private: - void checkForAnimation(); void normalizeWeights(); @@ -177,26 +182,22 @@ private: core::array AllJoints; core::array RootJoints; - bool HasAnimation; + core::aabbox3d BoundingBox; - bool PreparedForSkinning; + core::array< core::array > Vertices_Moved; f32 AnimationFrames; f32 LastAnimatedFrame; f32 LastSkinnedFrame; - bool BoneControlUsed; - - bool AnimateNormals; - - bool HardwareSkinning; - E_INTERPOLATION_MODE InterpolationMode; - core::aabbox3d BoundingBox; - - core::array< core::array > Vertices_Moved; + bool HasAnimation; + bool PreparedForSkinning; + bool BoneControlUsed; + bool AnimateNormals; + bool HardwareSkinning; }; } // end namespace scene @@ -204,5 +205,3 @@ private: #endif - - diff --git a/src/dep/src/irrlicht/CSkyBoxSceneNode.cpp b/src/dep/src/irrlicht/CSkyBoxSceneNode.cpp index eda6bee..37b6eda 100644 --- a/src/dep/src/irrlicht/CSkyBoxSceneNode.cpp +++ b/src/dep/src/irrlicht/CSkyBoxSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -38,9 +38,11 @@ CSkyBoxSceneNode::CSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom video::SMaterial mat; mat.Lighting = false; - mat.ZBuffer = false; + mat.ZBuffer = video::ECFN_NEVER; mat.ZWriteEnable = false; - mat.TextureLayer[0].TextureWrap = video::ETC_CLAMP; + mat.AntiAliasing=0; + mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; + mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; /* Hey, I am no artist, but look at that cool ASCII art I made! ;) @@ -140,7 +142,7 @@ void CSkyBoxSceneNode::render() core::matrix4 translate(AbsoluteTransformation); translate.setTranslation(camera->getAbsolutePosition()); - + // Draw the sky box between the near and far clip plane const f32 viewDistance = (camera->getNearValue() + camera->getFarValue()) * 0.5f; core::matrix4 scale; @@ -190,8 +192,10 @@ void CSkyBoxSceneNode::render() if ( tex ) { - core::rect rctDest(core::position2d(-1,0), driver->getCurrentRenderTargetSize()); - core::rect rctSrc(core::position2d(0,0), tex->getSize()); + core::rect rctDest(core::position2d(-1,0), + core::dimension2di(driver->getCurrentRenderTargetSize())); + core::rect rctSrc(core::position2d(0,0), + core::dimension2di(tex->getSize())); driver->draw2DImage(tex, rctDest, rctSrc); } @@ -240,7 +244,7 @@ ISceneNode* CSkyBoxSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; - CSkyBoxSceneNode* nb = new CSkyBoxSceneNode(0,0,0,0,0,0, newParent, + CSkyBoxSceneNode* nb = new CSkyBoxSceneNode(0,0,0,0,0,0, newParent, newManager, ID); nb->cloneMembers(this, newManager); @@ -248,7 +252,8 @@ ISceneNode* CSkyBoxSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan for (u32 i=0; i<6; ++i) nb->Material[i] = Material[i]; - nb->drop(); + if ( newParent ) + nb->drop(); return nb; } diff --git a/src/dep/src/irrlicht/CSkyBoxSceneNode.h b/src/dep/src/irrlicht/CSkyBoxSceneNode.h index 7d9fa12..02af8a4 100644 --- a/src/dep/src/irrlicht/CSkyBoxSceneNode.h +++ b/src/dep/src/irrlicht/CSkyBoxSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CSkyDomeSceneNode.cpp b/src/dep/src/irrlicht/CSkyDomeSceneNode.cpp index 0d6837b..8f44d8e 100644 --- a/src/dep/src/irrlicht/CSkyDomeSceneNode.cpp +++ b/src/dep/src/irrlicht/CSkyDomeSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // Code for this scene node has been contributed by Anders la Cour-Harbo (alc) @@ -7,6 +7,7 @@ #include "IVideoDriver.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" +#include "IAnimatedMesh.h" #include "os.h" namespace irr @@ -30,82 +31,33 @@ namespace scene parameters stretches the image to fit the chosen "sphere-size". */ CSkyDomeSceneNode::CSkyDomeSceneNode(video::ITexture* sky, u32 horiRes, u32 vertRes, - f64 texturePercentage, f64 spherePercentage, ISceneNode* parent, ISceneManager* mgr, s32 id) - : ISceneNode(parent, mgr, id), Buffer(0) + f32 texturePercentage, f32 spherePercentage, f32 radius, + ISceneNode* parent, ISceneManager* mgr, s32 id) + : ISceneNode(parent, mgr, id), Buffer(0), + HorizontalResolution(horiRes), VerticalResolution(vertRes), + TexturePercentage(texturePercentage), + SpherePercentage(spherePercentage), Radius(radius) { #ifdef _DEBUG setDebugName("CSkyDomeSceneNode"); #endif - f64 radius = 1000.0; /* Adjust this to get more or less perspective distorsion. */ - f64 azimuth, azimuth_step; - f64 elevation, elevation_step; - u32 k; - - video::S3DVertex vtx; - - AutomaticCullingState = scene::EAC_OFF; + setAutomaticCulling(scene::EAC_OFF); Buffer = new SMeshBuffer(); Buffer->Material.Lighting = false; - Buffer->Material.ZBuffer = false; + Buffer->Material.ZBuffer = video::ECFN_NEVER; Buffer->Material.ZWriteEnable = false; + Buffer->Material.AntiAliasing = video::EAAM_OFF; Buffer->Material.setTexture(0, sky); Buffer->BoundingBox.MaxEdge.set(0,0,0); Buffer->BoundingBox.MinEdge.set(0,0,0); - azimuth_step = 2.*core::PI64/(f64)horiRes; - if (spherePercentage<0.) - spherePercentage=-spherePercentage; - if (spherePercentage>2.) - spherePercentage=2.; - elevation_step = spherePercentage*core::PI64/2./(f64)vertRes; + Buffer->Vertices.clear(); + Buffer->Indices.clear(); - Buffer->Vertices.reallocate((horiRes+1)*(vertRes+1)); - Buffer->Indices.reallocate(3*(2*vertRes-1)*horiRes); - - vtx.Color.set(255,255,255,255); - vtx.Normal.set(0.0f,0.0f,0.0f); - - const f32 tcV = (f32)texturePercentage/(f32)vertRes; - for (k = 0, azimuth = 0; k <= horiRes; ++k) - { - elevation = core::PI64/2.; - const f32 tcU = (f32)k/(f32)horiRes; - const f64 sinA = sin(azimuth); - const f64 cosA = cos(azimuth); - for (u32 j = 0; j <= vertRes; ++j) - { - const f64 cosEr = radius*cos(elevation); - vtx.Pos.set((f32) (cosEr*sinA), - (f32) (radius*sin(elevation)+50.0f), - (f32) (cosEr*cosA)); - - vtx.TCoords.set(tcU, (f32)j*tcV); - - Buffer->Vertices.push_back(vtx); - elevation -= elevation_step; - } - azimuth += azimuth_step; - } - - for (k = 0; k < horiRes; ++k) - { - Buffer->Indices.push_back(vertRes+2+(vertRes+1)*k); - Buffer->Indices.push_back(1+(vertRes+1)*k); - Buffer->Indices.push_back(0+(vertRes+1)*k); - - for (u32 j = 1; j < vertRes; ++j) - { - Buffer->Indices.push_back(vertRes+2+(vertRes+1)*k+j); - Buffer->Indices.push_back(1+(vertRes+1)*k+j); - Buffer->Indices.push_back(0+(vertRes+1)*k+j); - - Buffer->Indices.push_back(vertRes+1+(vertRes+1)*k+j); - Buffer->Indices.push_back(vertRes+2+(vertRes+1)*k+j); - Buffer->Indices.push_back(0+(vertRes+1)*k+j); - } - } + // regenerate the mesh + generateMesh(); } @@ -116,6 +68,68 @@ CSkyDomeSceneNode::~CSkyDomeSceneNode() } +void CSkyDomeSceneNode::generateMesh() +{ + f32 azimuth; + u32 k; + + const f32 azimuth_step = (core::PI * 2.f) / HorizontalResolution; + if (SpherePercentage < 0.f) + SpherePercentage = -SpherePercentage; + if (SpherePercentage > 2.f) + SpherePercentage = 2.f; + const f32 elevation_step = SpherePercentage * core::HALF_PI / (f32)VerticalResolution; + + Buffer->Vertices.reallocate( (HorizontalResolution + 1) * (VerticalResolution + 1) ); + Buffer->Indices.reallocate(3 * (2*VerticalResolution - 1) * HorizontalResolution); + + video::S3DVertex vtx; + vtx.Color.set(255,255,255,255); + vtx.Normal.set(0.0f,-1.f,0.0f); + + const f32 tcV = TexturePercentage / VerticalResolution; + for (k = 0, azimuth = 0; k <= HorizontalResolution; ++k) + { + f32 elevation = core::HALF_PI; + const f32 tcU = (f32)k / (f32)HorizontalResolution; + const f32 sinA = sinf(azimuth); + const f32 cosA = cosf(azimuth); + for (u32 j = 0; j <= VerticalResolution; ++j) + { + const f32 cosEr = Radius * cosf(elevation); + vtx.Pos.set(cosEr*sinA, Radius*sinf(elevation), cosEr*cosA); + vtx.TCoords.set(tcU, j*tcV); + + vtx.Normal = -vtx.Pos; + vtx.Normal.normalize(); + + Buffer->Vertices.push_back(vtx); + elevation -= elevation_step; + } + azimuth += azimuth_step; + } + + for (k = 0; k < HorizontalResolution; ++k) + { + Buffer->Indices.push_back(VerticalResolution + 2 + (VerticalResolution + 1)*k); + Buffer->Indices.push_back(1 + (VerticalResolution + 1)*k); + Buffer->Indices.push_back(0 + (VerticalResolution + 1)*k); + + for (u32 j = 1; j < VerticalResolution; ++j) + { + Buffer->Indices.push_back(VerticalResolution + 2 + (VerticalResolution + 1)*k + j); + Buffer->Indices.push_back(1 + (VerticalResolution + 1)*k + j); + Buffer->Indices.push_back(0 + (VerticalResolution + 1)*k + j); + + Buffer->Indices.push_back(VerticalResolution + 1 + (VerticalResolution + 1)*k + j); + Buffer->Indices.push_back(VerticalResolution + 2 + (VerticalResolution + 1)*k + j); + Buffer->Indices.push_back(0 + (VerticalResolution + 1)*k + j); + } + } + Buffer->setHardwareMappingHint(scene::EHM_STATIC); +} + + //! renders the node. void CSkyDomeSceneNode::render() { @@ -135,6 +149,59 @@ void CSkyDomeSceneNode::render() driver->setMaterial(Buffer->Material); driver->drawMeshBuffer(Buffer); } + + // for debug purposes only: + if ( DebugDataVisible ) + { + video::SMaterial m; + m.Lighting = false; + driver->setMaterial(m); + + if ( DebugDataVisible & scene::EDS_NORMALS ) + { + IAnimatedMesh * arrow = SceneManager->addArrowMesh ( + "__debugnormal2", 0xFFECEC00, + 0xFF999900, 4, 8, 1.f * 40.f, 0.6f * 40.f, 0.05f * 40.f, 0.3f * 40.f); + if ( 0 == arrow ) + { + arrow = SceneManager->getMesh ( "__debugnormal2" ); + } + IMesh *mesh = arrow->getMesh(0); + + // find a good scaling factor + core::matrix4 m2; + + // draw normals + const scene::IMeshBuffer* mb = Buffer; + const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); + const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); + for ( u32 i=0; i != mb->getVertexCount(); ++i ) + { + // align to v->Normal + core::quaternion quatRot(v->Normal.X, 0.f, -v->Normal.X, 1+v->Normal.Y); + quatRot.normalize(); + quatRot.getMatrix(m2, v->Pos); + + m2 = AbsoluteTransformation * m2; + + driver->setTransform(video::ETS_WORLD, m2); + for (u32 a = 0; a != mesh->getMeshBufferCount(); ++a) + driver->drawMeshBuffer(mesh->getMeshBuffer(a)); + + v = (const video::S3DVertex*) ( (u8*) v + vSize ); + } + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + } + + // show mesh + if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) + { + m.Wireframe = true; + driver->setMaterial(m); + + driver->drawMeshBuffer(Buffer); + } + } } @@ -148,7 +215,9 @@ const core::aabbox3d& CSkyDomeSceneNode::getBoundingBox() const void CSkyDomeSceneNode::OnRegisterSceneNode() { if (IsVisible) - SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX); + { + SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX ); + } ISceneNode::OnRegisterSceneNode(); } @@ -172,6 +241,52 @@ u32 CSkyDomeSceneNode::getMaterialCount() const } -} +//! Writes attributes of the scene node. +void CSkyDomeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + ISceneNode::serializeAttributes(out, options); + + out->addInt ("HorizontalResolution", HorizontalResolution); + out->addInt ("VerticalResolution", VerticalResolution); + out->addFloat("TexturePercentage", TexturePercentage); + out->addFloat("SpherePercentage", SpherePercentage); + out->addFloat("Radius", Radius); } + +//! Reads attributes of the scene node. +void CSkyDomeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + HorizontalResolution = in->getAttributeAsInt ("HorizontalResolution"); + VerticalResolution = in->getAttributeAsInt ("VerticalResolution"); + TexturePercentage = in->getAttributeAsFloat("TexturePercentage"); + SpherePercentage = in->getAttributeAsFloat("SpherePercentage"); + Radius = in->getAttributeAsFloat("Radius"); + + ISceneNode::deserializeAttributes(in, options); + + // regenerate the mesh + generateMesh(); +} + +//! Creates a clone of this scene node and its children. +ISceneNode* CSkyDomeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) +{ + if (!newParent) + newParent = Parent; + if (!newManager) + newManager = SceneManager; + + CSkyDomeSceneNode* nb = new CSkyDomeSceneNode(Buffer->Material.TextureLayer[0].Texture, HorizontalResolution, VerticalResolution, TexturePercentage, + SpherePercentage, Radius, newParent, newManager, ID); + + nb->cloneMembers(this, newManager); + + if ( newParent ) + nb->drop(); + return nb; +} + + +} // namespace scene +} // namespace irr diff --git a/src/dep/src/irrlicht/CSkyDomeSceneNode.h b/src/dep/src/irrlicht/CSkyDomeSceneNode.h index 11090d1..4077cf5 100644 --- a/src/dep/src/irrlicht/CSkyDomeSceneNode.h +++ b/src/dep/src/irrlicht/CSkyDomeSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // Code for this scene node has been contributed by Anders la Cour-Harbo (alc) @@ -18,18 +18,28 @@ class CSkyDomeSceneNode : public ISceneNode { public: CSkyDomeSceneNode(video::ITexture* texture, u32 horiRes, u32 vertRes, - f64 texturePercentage, f64 spherePercentage, - ISceneNode* root, ISceneManager* smgr, s32 id); + f32 texturePercentage, f32 spherePercentage, f32 radius, + ISceneNode* parent, ISceneManager* smgr, s32 id); virtual ~CSkyDomeSceneNode(); virtual void OnRegisterSceneNode(); virtual void render(); virtual const core::aabbox3d& getBoundingBox() const; virtual video::SMaterial& getMaterial(u32 i); virtual u32 getMaterialCount() const; - virtual ESCENE_NODE_TYPE getType() const { return ESNT_SKY_BOX; } + virtual ESCENE_NODE_TYPE getType() const { return ESNT_SKY_DOME; } + + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); private: + + void generateMesh(); + SMeshBuffer* Buffer; + + u32 HorizontalResolution, VerticalResolution; + f32 TexturePercentage, SpherePercentage, Radius; }; diff --git a/src/dep/src/irrlicht/CSoftware2MaterialRenderer.h b/src/dep/src/irrlicht/CSoftware2MaterialRenderer.h index 7057230..87ff48f 100644 --- a/src/dep/src/irrlicht/CSoftware2MaterialRenderer.h +++ b/src/dep/src/irrlicht/CSoftware2MaterialRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CSoftwareDriver.cpp b/src/dep/src/irrlicht/CSoftwareDriver.cpp index 9893927..ae1b2d1 100644 --- a/src/dep/src/irrlicht/CSoftwareDriver.cpp +++ b/src/dep/src/irrlicht/CSoftwareDriver.cpp @@ -1,10 +1,10 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h +#include "IrrCompileConfig.h" #include "CSoftwareDriver.h" -#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ #include "CSoftwareTexture.h" @@ -18,7 +18,7 @@ namespace video //! constructor -CSoftwareDriver::CSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) +CSoftwareDriver::CSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) : CNullDriver(io, windowSize), BackBuffer(0), Presenter(presenter), WindowId(0), SceneSourceRect(0), RenderTargetTexture(0), RenderTargetSurface(0), CurrentTriangleRenderer(0), ZBuffer(0), Texture(0) @@ -133,7 +133,7 @@ void CSoftwareDriver::selectRightTriangleRenderer() renderer = ETR_TEXTURE_GOURAUD_ADD; } else - if (!Material.ZBuffer && !Material.ZWriteEnable) + if ((Material.ZBuffer==ECFN_NEVER) && !Material.ZWriteEnable) renderer = ETR_TEXTURE_GOURAUD_NOZ; else { @@ -168,7 +168,6 @@ bool CSoftwareDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const } - //! sets transformation void CSoftwareDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { @@ -176,10 +175,8 @@ void CSoftwareDriver::setTransform(E_TRANSFORMATION_STATE state, const core::mat } - - //! sets the current Texture -bool CSoftwareDriver::setTexture(video::ITexture* texture) +bool CSoftwareDriver::setActiveTexture(u32 stage, video::ITexture* texture) { if (texture && texture->getDriverType() != EDT_SOFTWARE) { @@ -200,15 +197,15 @@ bool CSoftwareDriver::setTexture(video::ITexture* texture) } - //! sets a material void CSoftwareDriver::setMaterial(const SMaterial& material) { Material = material; + OverrideMaterial.apply(Material); for (u32 i = 0; i < 1; ++i) { - setTexture(Material.getTexture(i)); + setActiveTexture(i, Material.getTexture(i)); setTransform ((E_TRANSFORMATION_STATE) ( ETS_TEXTURE_0 + i ), material.getTextureMatrix(i)); } @@ -217,10 +214,10 @@ void CSoftwareDriver::setMaterial(const SMaterial& material) //! clears the zbuffer bool CSoftwareDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, - void* windowId, core::rect* sourceRect) + const SExposedVideoData& videoData, core::rect* sourceRect) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); - WindowId=windowId; + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + WindowId=videoData.D3D9.HWnd; SceneSourceRect = sourceRect; if (backBuffer && BackBuffer) @@ -242,6 +239,14 @@ bool CSoftwareDriver::endScene() } +//! returns a device dependent texture from a software surface (IImage) +//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES +ITexture* CSoftwareDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) +{ + return new CSoftwareTexture(surface, name, false, mipmapData); +} + + //! sets a render target bool CSoftwareDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color) @@ -305,7 +310,6 @@ void CSoftwareDriver::setRenderTarget(video::CImage* image) } - //! sets a viewport void CSoftwareDriver::setViewPort(const core::rect& area) { @@ -316,7 +320,7 @@ void CSoftwareDriver::setViewPort(const core::rect& area) core::rect rendert(0,0,RenderTargetSize.Width,RenderTargetSize.Height); ViewPort.clipAgainst(rendert); - ViewPortSize = ViewPort.getSize(); + ViewPortSize = core::dimension2du(ViewPort.getSize()); Render2DTranslation.X = (ViewPortSize.Width / 2) + ViewPort.UpperLeftCorner.X; Render2DTranslation.Y = ViewPort.UpperLeftCorner.Y + ViewPortSize.Height - (ViewPortSize.Height / 2);// + ViewPort.UpperLeftCorner.Y; @@ -324,6 +328,7 @@ void CSoftwareDriver::setViewPort(const core::rect& area) CurrentTriangleRenderer->setRenderTarget(RenderTargetSurface, ViewPort); } + void CSoftwareDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) @@ -342,10 +347,9 @@ void CSoftwareDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCo break; } } - - } + //! draws a vertex primitive list void CSoftwareDriver::drawVertexPrimitiveList16(const void* vertices, u32 vertexCount, const u16* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType) { @@ -453,6 +457,8 @@ void CSoftwareDriver::drawVertexPrimitiveList16(const void* vertices, u32 vertex case scene::EPT_TRIANGLES: indexPointer=indexList; break; + default: + return; } switch (vType) { @@ -469,7 +475,6 @@ void CSoftwareDriver::drawVertexPrimitiveList16(const void* vertices, u32 vertex } - template void CSoftwareDriver::drawClippedIndexedTriangleListT(const VERTEXTYPE* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) @@ -660,7 +665,7 @@ void CSoftwareDriver::drawClippedIndexedTriangleListT(const VERTEXTYPE* vertices const VERTEXTYPE* currentVertex = clippedVertices.pointer(); S2DVertex* tp = &TransformedPoints[0]; - core::dimension2d textureSize(0,0); + core::dimension2d textureSize(0,0); f32 zDiv; if (Texture) @@ -740,10 +745,10 @@ void CSoftwareDriver::clipTriangle(f32* transformedPos) //! Only used by the internal engine. Used to notify the driver that //! the window was resized. -void CSoftwareDriver::OnResize(const core::dimension2d& size) +void CSoftwareDriver::OnResize(const core::dimension2d& size) { // make sure width and height are multiples of 2 - core::dimension2d realSize(size); + core::dimension2d realSize(size); if (realSize.Width % 2) realSize.Width += 1; @@ -753,10 +758,11 @@ void CSoftwareDriver::OnResize(const core::dimension2d& size) if (ScreenSize != realSize) { - if (ViewPort.getWidth() == ScreenSize.Width && - ViewPort.getHeight() == ScreenSize.Height) + if (ViewPort.getWidth() == (s32)ScreenSize.Width && + ViewPort.getHeight() == (s32)ScreenSize.Height) { - ViewPort = core::rect(core::position2d(0,0), realSize); + ViewPort = core::rect(core::position2d(0,0), + core::dimension2di(realSize)); } ScreenSize = realSize; @@ -773,7 +779,7 @@ void CSoftwareDriver::OnResize(const core::dimension2d& size) } //! returns the current render target size -const core::dimension2d& CSoftwareDriver::getCurrentRenderTargetSize() const +const core::dimension2d& CSoftwareDriver::getCurrentRenderTargetSize() const { return RenderTargetSize; } @@ -795,10 +801,10 @@ void CSoftwareDriver::draw2DImage(const video::ITexture* texture, const core::po if (useAlphaChannelOfTexture) ((CSoftwareTexture*)texture)->getImage()->copyToWithAlpha( - ((CImage*)RenderTargetSurface), destPos, sourceRect, color, clipRect); + RenderTargetSurface, destPos, sourceRect, color, clipRect); else ((CSoftwareTexture*)texture)->getImage()->copyTo( - ((CImage*)RenderTargetSurface), destPos, sourceRect, clipRect); + RenderTargetSurface, destPos, sourceRect, clipRect); } } @@ -806,18 +812,19 @@ void CSoftwareDriver::draw2DImage(const video::ITexture* texture, const core::po //! Draws a 2d line. void CSoftwareDriver::draw2DLine(const core::position2d& start, - const core::position2d& end, - SColor color) + const core::position2d& end, + SColor color) { - ((CImage*)RenderTargetSurface)->drawLine(start, end, color ); + RenderTargetSurface->drawLine(start, end, color ); } + //! Draws a pixel void CSoftwareDriver::drawPixel(u32 x, u32 y, const SColor & color) { - ((CImage*)BackBuffer)->setPixel(x, y, color); + BackBuffer->setPixel(x, y, color, true); } - + //! draw a 2d rectangle void CSoftwareDriver::draw2DRectangle(SColor color, const core::rect& pos, @@ -832,14 +839,14 @@ void CSoftwareDriver::draw2DRectangle(SColor color, const core::rect& pos, if(!p.isValid()) return; - ((CImage*)RenderTargetSurface)->drawRectangle(p, color); + RenderTargetSurface->drawRectangle(p, color); } else { if(!pos.isValid()) return; - ((CImage*)RenderTargetSurface)->drawRectangle(pos, color); + RenderTargetSurface->drawRectangle(pos, color); } } @@ -858,7 +865,7 @@ void CSoftwareDriver::draw2DRectangle(const core::rect& pos, //! driver, it would return "Direct3D8.1". const wchar_t* CSoftwareDriver::getName() const { - return L"Irrlicht Software Device 1.0"; + return L"Irrlicht Software Driver 1.0"; } @@ -887,11 +894,11 @@ const core::matrix4& CSoftwareDriver::getTransform(E_TRANSFORMATION_STATE state) //! Creates a render target texture. -ITexture* CSoftwareDriver::addRenderTargetTexture(const core::dimension2d& size, const c8* name) +ITexture* CSoftwareDriver::addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, + const ECOLOR_FORMAT format) { CImage* img = new CImage(video::ECF_A1R5G5B5, size); - if (!name) - name="rt"; ITexture* tex = new CSoftwareTexture(img, name, true); img->drop(); addTexture(tex); @@ -912,7 +919,11 @@ void CSoftwareDriver::clearZBuffer() IImage* CSoftwareDriver::createScreenShot() { if (BackBuffer) - return new CImage(BackBuffer->getColorFormat(), BackBuffer); + { + CImage* tmp = new CImage(BackBuffer->getColorFormat(), BackBuffer->getDimension()); + BackBuffer->copyTo(tmp); + return tmp; + } else return 0; } @@ -938,7 +949,7 @@ namespace video //! creates a video driver -IVideoDriver* createSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) +IVideoDriver* createSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CSoftwareDriver(windowSize, fullscreen, io, presenter); @@ -950,3 +961,4 @@ IVideoDriver* createSoftwareDriver(const core::dimension2d& windowSize, boo } // end namespace video } // end namespace irr + diff --git a/src/dep/src/irrlicht/CSoftwareDriver.h b/src/dep/src/irrlicht/CSoftwareDriver.h index 7494ea2..110a630 100644 --- a/src/dep/src/irrlicht/CSoftwareDriver.h +++ b/src/dep/src/irrlicht/CSoftwareDriver.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -19,7 +19,7 @@ namespace video public: //! constructor - CSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter); + CSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter); //! destructor virtual ~CSoftwareDriver(); @@ -42,7 +42,7 @@ namespace video //! clears the zbuffer virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! presents the rendered scene on the screen, returns false if failed @@ -50,10 +50,10 @@ namespace video //! Only used by the internal engine. Used to notify the driver that //! the window was resized. - virtual void OnResize(const core::dimension2d& size); + virtual void OnResize(const core::dimension2d& size); //! returns size of the current render target - virtual const core::dimension2d& getCurrentRenderTargetSize() const; + virtual const core::dimension2d& getCurrentRenderTargetSize() const; //! draws a vertex primitive list void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, @@ -84,7 +84,7 @@ namespace video SColor color=SColor(255,255,255,255)); //! Draws a single pixel - virtual void drawPixel(u32 x, u32 y, const SColor & color); + virtual void drawPixel(u32 x, u32 y, const SColor & color); //! \return Returns the name of the video driver. Example: In case of the Direct3D8 //! driver, it would return "Direct3D8.1". @@ -99,9 +99,13 @@ namespace video //! Returns the transformation set by setTransform virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; + //! returns a device dependent texture from a software surface (IImage) + //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); + //! Creates a render target texture. - virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Clears the ZBuffer. virtual void clearZBuffer(); @@ -120,7 +124,7 @@ namespace video void setRenderTarget(video::CImage* image); //! sets the current Texture - bool setTexture(video::ITexture* texture); + bool setActiveTexture(u32 stage, video::ITexture* texture); //! switches to a triangle renderer void switchToTriangleRenderer(ETriangleRenderer renderer); @@ -150,10 +154,10 @@ namespace video core::array TransformedPoints; video::ITexture* RenderTargetTexture; - video::IImage* RenderTargetSurface; + video::CImage* RenderTargetSurface; core::position2d Render2DTranslation; - core::dimension2d RenderTargetSize; - core::dimension2d ViewPortSize; + core::dimension2d RenderTargetSize; + core::dimension2d ViewPortSize; core::matrix4 TransformationMatrix[ETS_COUNT]; @@ -174,4 +178,3 @@ namespace video #endif - diff --git a/src/dep/src/irrlicht/CSoftwareDriver2.cpp b/src/dep/src/irrlicht/CSoftwareDriver2.cpp index 8b96646..eb5363a 100644 --- a/src/dep/src/irrlicht/CSoftwareDriver2.cpp +++ b/src/dep/src/irrlicht/CSoftwareDriver2.cpp @@ -1,10 +1,9 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "CSoftwareDriver2.h" - #include "IrrCompileConfig.h" +#include "CSoftwareDriver2.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ @@ -25,7 +24,7 @@ namespace video //! constructor -CBurningVideoDriver::CBurningVideoDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) +CBurningVideoDriver::CBurningVideoDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) : CNullDriver(io, windowSize), BackBuffer(0), Presenter(presenter), WindowId(0), SceneSourceRect(0), RenderTargetTexture(0), RenderTargetSurface(0), CurrentShader(0), @@ -57,7 +56,7 @@ CBurningVideoDriver::CBurningVideoDriver(const core::dimension2d& windowSiz //BurningShader[ETR_TEXTURE_FLAT] = createTriangleRendererTextureFlat2(DepthBuffer); //BurningShader[ETR_TEXTURE_FLAT_WIRE] = createTriangleRendererTextureFlatWire2(DepthBuffer); BurningShader[ETR_TEXTURE_GOURAUD] = createTriangleRendererTextureGouraud2(DepthBuffer); - BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP] = createTriangleRendererTextureLightMap2_M1(DepthBuffer); + BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M1] = createTriangleRendererTextureLightMap2_M1(DepthBuffer); BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M2] = createTriangleRendererTextureLightMap2_M2(DepthBuffer); BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M4] = createTriangleRendererGTextureLightMap2_M4(DepthBuffer); BurningShader[ETR_TEXTURE_LIGHTMAP_M4] = createTriangleRendererTextureLightMap2_M4(DepthBuffer); @@ -114,13 +113,12 @@ CBurningVideoDriver::CBurningVideoDriver(const core::dimension2d& windowSiz umr->drop (); // select render target - setRenderTarget(BackBuffer); - LightSpace.Global_AmbientLight.set ( 0.f, 0.f, 0.f, 0.f ); + //reset Lightspace + LightSpace.reset (); // select the right renderer - //CurrentShader = BurningShader[ETR_REFERENCE]; setCurrentShader(); } @@ -151,42 +149,42 @@ CBurningVideoDriver::~CBurningVideoDriver() } -//! void selects the right triangle renderer based on the render states. +/*! + selects the right triangle renderer based on the render states. +*/ void CBurningVideoDriver::setCurrentShader() { - EBurningFFShader shader = ETR_TEXTURE_GOURAUD; + ITexture *texture0 = Material.org.getTexture(0); + ITexture *texture1 = Material.org.getTexture(1); + + bool zMaterialTest = Material.org.ZBuffer != ECFN_NEVER && + Material.org.ZWriteEnable && + ( AllowZWriteOnTransparent || !Material.org.isTransparent() ); + + EBurningFFShader shader = zMaterialTest ? ETR_TEXTURE_GOURAUD : ETR_TEXTURE_GOURAUD_NOZ; + + TransformationFlag[ ETS_TEXTURE_0] &= ~(ETF_TEXGEN_CAMERA_NORMAL|ETF_TEXGEN_CAMERA_REFLECTION); + LightSpace.Flags &= ~VERTEXTRANSFORM; - bool zMaterialTest = true; switch ( Material.org.MaterialType ) { case EMT_ONETEXTURE_BLEND: shader = ETR_TEXTURE_BLEND; - zMaterialTest = false; break; case EMT_TRANSPARENT_ALPHA_CHANNEL_REF: + Material.org.MaterialTypeParam = 0.5f; + // fall through case EMT_TRANSPARENT_ALPHA_CHANNEL: - if ( Material.org.ZBuffer ) + if ( texture0 && texture0->hasAlpha () ) { - shader = ETR_TEXTURE_GOURAUD_ALPHA; + shader = zMaterialTest ? ETR_TEXTURE_GOURAUD_ALPHA : ETR_TEXTURE_GOURAUD_ALPHA_NOZ; + break; } - else - { - shader = ETR_TEXTURE_GOURAUD_ALPHA_NOZ; - } - zMaterialTest = false; - break; + // fall through case EMT_TRANSPARENT_ADD_COLOR: - if ( Material.org.ZBuffer ) - { - shader = ETR_TEXTURE_GOURAUD_ADD; - } - else - { - shader = ETR_TEXTURE_GOURAUD_ADD_NO_Z; - } - zMaterialTest = false; + shader = zMaterialTest ? ETR_TEXTURE_GOURAUD_ADD : ETR_TEXTURE_GOURAUD_ADD_NO_Z; break; case EMT_TRANSPARENT_VERTEX_ALPHA: @@ -195,7 +193,7 @@ void CBurningVideoDriver::setCurrentShader() case EMT_LIGHTMAP: case EMT_LIGHTMAP_LIGHTING: - shader = ETR_TEXTURE_GOURAUD_LIGHTMAP; + shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1; break; case EMT_LIGHTMAP_M2: @@ -204,16 +202,16 @@ void CBurningVideoDriver::setCurrentShader() break; case EMT_LIGHTMAP_LIGHTING_M4: - if ( Material.org.getTexture(1) ) + if ( texture1 ) shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M4; break; case EMT_LIGHTMAP_M4: - if ( Material.org.getTexture(1) ) + if ( texture1 ) shader = ETR_TEXTURE_LIGHTMAP_M4; break; case EMT_LIGHTMAP_ADD: - if ( Material.org.getTexture(1) ) + if ( texture1 ) shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD; break; @@ -221,17 +219,22 @@ void CBurningVideoDriver::setCurrentShader() shader = ETR_TEXTURE_GOURAUD_DETAIL_MAP; break; + case EMT_SPHERE_MAP: + TransformationFlag[ ETS_TEXTURE_0] |= ETF_TEXGEN_CAMERA_REFLECTION; // ETF_TEXGEN_CAMERA_NORMAL; + LightSpace.Flags |= VERTEXTRANSFORM; + break; + case EMT_REFLECTION_2_LAYER: + shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1; + TransformationFlag[ ETS_TEXTURE_1] |= ETF_TEXGEN_CAMERA_REFLECTION; + LightSpace.Flags |= VERTEXTRANSFORM; + break; + default: break; } - if ( zMaterialTest && !Material.org.ZBuffer && !Material.org.ZWriteEnable) - { - shader = ETR_TEXTURE_GOURAUD_NOZ; - } - - if ( 0 == Material.org.getTexture(0) ) + if ( !texture0 ) { shader = ETR_GOURAUD; } @@ -248,28 +251,21 @@ void CBurningVideoDriver::setCurrentShader() if ( CurrentShader ) { CurrentShader->setZCompareFunc ( Material.org.ZBuffer ); + CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); + CurrentShader->setMaterial ( Material ); + switch ( shader ) { case ETR_TEXTURE_GOURAUD_ALPHA: case ETR_TEXTURE_GOURAUD_ALPHA_NOZ: + case ETR_TEXTURE_BLEND: CurrentShader->setParam ( 0, Material.org.MaterialTypeParam ); break; - - case EMT_ONETEXTURE_BLEND: - { - E_BLEND_FACTOR srcFact,dstFact; - E_MODULATE_FUNC modulate; - unpack_texureBlendFunc ( srcFact, dstFact, modulate, Material.org.MaterialTypeParam ); - CurrentShader->setParam ( 0, Material.org.MaterialTypeParam ); - } - break; default: break; } - - CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); - CurrentShader->setMaterial ( Material ); } + } @@ -306,97 +302,61 @@ bool CBurningVideoDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const //! sets transformation void CBurningVideoDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { - Transformation[state].m = mat; - Transformation[state].isIdentity = mat.isIdentity(); + Transformation[state] = mat; + core::setbit_cond ( TransformationFlag[state], mat.isIdentity(), ETF_IDENTITY ); switch ( state ) { case ETS_VIEW: - Transformation[ETS_VIEW_PROJECTION].m.setbyproduct_nocheck ( - Transformation[ETS_PROJECTION].m, - Transformation[ETS_VIEW].m + Transformation[ETS_VIEW_PROJECTION].setbyproduct_nocheck ( + Transformation[ETS_PROJECTION], + Transformation[ETS_VIEW] ); + getCameraPosWorldSpace (); break; case ETS_WORLD: - if ( Transformation[state].isIdentity ) + if ( TransformationFlag[state] & ETF_IDENTITY ) { Transformation[ETS_CURRENT] = Transformation[ETS_VIEW_PROJECTION]; } else { - Transformation[ETS_CURRENT].m.setbyproduct_nocheck ( - Transformation[ETS_VIEW_PROJECTION].m, - Transformation[ETS_WORLD].m + Transformation[ETS_CURRENT].setbyproduct_nocheck ( + Transformation[ETS_VIEW_PROJECTION], + Transformation[ETS_WORLD] ); } - Transformation[ETS_CURRENT].isIdentity = 0; - -#ifdef SOFTWARE_DRIVER_2_LIGHTING - if ( Material.org.Lighting ) - { - if ( Transformation[state].isIdentity ) - { - Transformation[ETS_WORLD_VIEW] = Transformation[ETS_VIEW]; - } - else - { - Transformation[ETS_WORLD_VIEW].m.setbyproduct_nocheck ( - Transformation[ETS_VIEW].m, - Transformation[ETS_WORLD].m - ); - } - - core::matrix4 m2 ( Transformation[ETS_WORLD_VIEW].m ); - m2.makeInverse (); - m2.getTransposed ( Transformation[ETS_WORLD_VIEW_INVERSE_TRANSPOSED].m ); - } -#endif + TransformationFlag[ETS_CURRENT] = 0; break; + case ETS_TEXTURE_0: + case ETS_TEXTURE_1: + case ETS_TEXTURE_2: + case ETS_TEXTURE_3: + if ( 0 == (TransformationFlag[state] & ETF_IDENTITY ) ) + LightSpace.Flags |= VERTEXTRANSFORM; default: break; } } -//! sets a material -void CBurningVideoDriver::setMaterial(const SMaterial& material) -{ - Material.org = material; - - Material.AmbientColor.setA8R8G8B8 ( Material.org.AmbientColor.color ); - Material.DiffuseColor.setA8R8G8B8 ( Material.org.DiffuseColor.color ); - Material.EmissiveColor.setA8R8G8B8 ( Material.org.EmissiveColor.color ); - Material.SpecularColor.setA8R8G8B8 ( Material.org.SpecularColor.color ); - - Material.SpecularEnabled = Material.org.Shininess != 0.f; - if (Material.SpecularEnabled) - Material.org.NormalizeNormals = true; - - for (u32 i = 0; i < 2; ++i) - { - setTransform((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), - material.getTextureMatrix(i)); - } - - setCurrentShader(); -} - - //! clears the zbuffer bool CBurningVideoDriver::beginScene(bool backBuffer, bool zBuffer, - SColor color, void* windowId, core::rect* sourceRect) + SColor color, const SExposedVideoData& videoData, + core::rect* sourceRect) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); - WindowId = windowId; + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + WindowId = videoData.D3D9.HWnd; SceneSourceRect = sourceRect; if (backBuffer && BackBuffer) BackBuffer->fill(color); - if (DepthBuffer && zBuffer) + if (zBuffer && DepthBuffer) DepthBuffer->clear(); + memset ( TransformationFlag, 0, sizeof ( TransformationFlag ) ); return true; } @@ -441,7 +401,7 @@ bool CBurningVideoDriver::setRenderTarget(video::ITexture* texture, bool clearBa DepthBuffer->clear(); if (clearBackBuffer) - ((video::CImage*)RenderTargetSurface)->fill( color ); + RenderTargetSurface->fill( color ); } return true; @@ -480,7 +440,7 @@ void CBurningVideoDriver::setViewPort(const core::rect& area) core::rect rendert(0,0,RenderTargetSize.Width,RenderTargetSize.Height); ViewPort.clipAgainst(rendert); - Transformation [ ETS_CLIPSCALE ].m.buildNDCToDCMatrix ( ViewPort, 1 ); + Transformation [ ETS_CLIPSCALE ].buildNDCToDCMatrix ( ViewPort, 1 ); if (CurrentShader) @@ -569,10 +529,22 @@ REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) c REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) const { u32 flag = 0; + + if ( v->Pos.z <= v->Pos.w ) flag |= 1; + if (-v->Pos.z <= v->Pos.w ) flag |= 2; + + if ( v->Pos.x <= v->Pos.w ) flag |= 4; + if (-v->Pos.x <= v->Pos.w ) flag |= 8; + + if ( v->Pos.y <= v->Pos.w ) flag |= 16; + if (-v->Pos.y <= v->Pos.w ) flag |= 32; + +/* for ( u32 i = 0; i!= 6; ++i ) { core::setbit_cond( flag, v->Pos.dotProduct ( NDCPlane[i] ) <= 0.f, 1 << i ); } +*/ return flag; } @@ -684,8 +656,8 @@ inline void CBurningVideoDriver::ndc_2_dc_and_project ( s4DVertex *dest,s4DVerte const f32 iw = core::reciprocal ( w ); // to device coordinates - dest[g].Pos.x = iw * ( source[g].Pos.x * Transformation [ ETS_CLIPSCALE ].m[ 0] + w * Transformation [ ETS_CLIPSCALE ].m[12] ); - dest[g].Pos.y = iw * ( source[g].Pos.y * Transformation [ ETS_CLIPSCALE ].m[ 5] + w * Transformation [ ETS_CLIPSCALE ].m[13] ); + dest[g].Pos.x = iw * ( source[g].Pos.x * Transformation [ ETS_CLIPSCALE ][ 0] + w * Transformation [ ETS_CLIPSCALE ][12] ); + dest[g].Pos.y = iw * ( source[g].Pos.y * Transformation [ ETS_CLIPSCALE ][ 5] + w * Transformation [ ETS_CLIPSCALE ][13] ); #ifndef SOFTWARE_DRIVER_2_USE_WBUFFER dest[g].Pos.z = iw * source[g].Pos.z; @@ -723,8 +695,9 @@ inline void CBurningVideoDriver::ndc_2_dc_and_project2 ( const s4DVertex **v, co const f32 iw = core::reciprocal ( w ); // to device coordinates - a[1].Pos.x = iw * ( a->Pos.x * Transformation [ ETS_CLIPSCALE ].m[ 0] + w * Transformation [ ETS_CLIPSCALE ].m[12] ); - a[1].Pos.y = iw * ( a->Pos.y * Transformation [ ETS_CLIPSCALE ].m[ 5] + w * Transformation [ ETS_CLIPSCALE ].m[13] ); + const f32 * p = Transformation [ ETS_CLIPSCALE ].pointer(); + a[1].Pos.x = iw * ( a->Pos.x * p[ 0] + w * p[12] ); + a[1].Pos.y = iw * ( a->Pos.y * p[ 5] + w * p[13] ); #ifndef SOFTWARE_DRIVER_2_USE_WBUFFER a[1].Pos.z = a->Pos.z * iw; @@ -790,12 +763,12 @@ inline f32 CBurningVideoDriver::texelarea2 ( const s4DVertex **v, s32 tex ) cons /*! */ -inline void CBurningVideoDriver::select_polygon_mipmap ( s4DVertex *v, u32 vIn, s32 tex ) +inline void CBurningVideoDriver::select_polygon_mipmap ( s4DVertex *v, u32 vIn, u32 tex, const core::dimension2du& texSize ) { f32 f[2]; - f[0] = (f32) MAT_TEXTURE ( tex )->getSize().Width; - f[1] = (f32) MAT_TEXTURE ( tex )->getSize().Height; + f[0] = (f32) texSize.Width - 0.25f; + f[1] = (f32) texSize.Height - 0.25f; #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT for ( u32 g = 0; g != vIn; g += 2 ) @@ -812,12 +785,12 @@ inline void CBurningVideoDriver::select_polygon_mipmap ( s4DVertex *v, u32 vIn, #endif } -inline void CBurningVideoDriver::select_polygon_mipmap2 ( s4DVertex **v, s32 tex ) const +inline void CBurningVideoDriver::select_polygon_mipmap2 ( s4DVertex **v, u32 tex, const core::dimension2du& texSize ) const { f32 f[2]; - f[0] = (f32) MAT_TEXTURE ( tex )->getSize().Width; - f[1] = (f32) MAT_TEXTURE ( tex )->getSize().Height; + f[0] = (f32) texSize.Width - 0.25f; + f[1] = (f32) texSize.Height - 0.25f; #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT (v[0] + 1 )->Tex[tex].x = v[0]->Tex[tex].x * ( v[0] + 1 )->Pos.w * f[0]; @@ -846,7 +819,8 @@ const SVSize CBurningVideoDriver::vSize[] = { { VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 1 }, { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex2TCoords),2 }, - { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertexTangents),2 } + { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertexTangents),2 }, + { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 2 }, }; @@ -874,25 +848,61 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, dest = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( destIndex << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); // transform Model * World * Camera * Projection * NDCSpace matrix - Transformation [ ETS_CURRENT].m.transformVect ( &dest->Pos.x, ((S3DVertex*) source )->Pos ); + const S3DVertex *base = ((S3DVertex*) source ); + Transformation [ ETS_CURRENT].transformVect ( &dest->Pos.x, base->Pos ); -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - // light Vertex - #ifdef SOFTWARE_DRIVER_2_LIGHTING - lightVertex ( dest, ((S3DVertex*) source ) ); +#if defined (SOFTWARE_DRIVER_2_LIGHTING) || defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) + + // vertex normal in light space + if ( Material.org.Lighting || (LightSpace.Flags & VERTEXTRANSFORM) ) + { + if ( TransformationFlag[ETS_WORLD] & ETF_IDENTITY ) + { + LightSpace.normal.set ( base->Normal.X, base->Normal.Y, base->Normal.Z, 1.f ); + LightSpace.vertex.set ( base->Pos.X, base->Pos.Y, base->Pos.Z, 1.f ); + } + else + { + Transformation[ETS_WORLD].rotateVect ( &LightSpace.normal.x, base->Normal ); + if ( LightSpace.Flags & NORMALIZE ) + LightSpace.normal.normalize_xyz(); + + // vertex in light space + if ( LightSpace.Flags & ( POINTLIGHT | FOG | SPECULAR | VERTEXTRANSFORM) ) + Transformation[ETS_WORLD].transformVect ( &LightSpace.vertex.x, base->Pos ); + } + + } +#endif + +#if defined ( SOFTWARE_DRIVER_2_USE_VERTEX_COLOR ) + // apply lighting model + #if defined (SOFTWARE_DRIVER_2_LIGHTING) + if ( Material.org.Lighting ) + { + lightVertex ( dest, base->Color.color ); + } + else + { + dest->Color[0].setA8R8G8B8 ( base->Color.color ); + } #else - dest->Color[0].setA8R8G8B8 ( ((S3DVertex*) source )->Color.color ); + dest->Color[0].setA8R8G8B8 ( base->Color.color ); #endif #endif - // transfer texture coordinates - if ( Transformation [ ETS_TEXTURE_0 ].isIdentity ) + // Texture Transform +#if !defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) + irr::memcpy32_small ( &dest->Tex[0],&base->TCoords, + vSize[VertexCache.vType].TexSize << 3 // * ( sizeof ( f32 ) * 2 ) + ); +#else + + if ( 0 == (LightSpace.Flags & VERTEXTRANSFORM) ) { - // only look on first transform - irr::memcpy32_small ( &dest->Tex[0], - &((S3DVertex*) source )->TCoords, - vSize[VertexCache.vType].TexSize * ( sizeof ( f32 ) * 2 ) + irr::memcpy32_small ( &dest->Tex[0],&base->TCoords, + vSize[VertexCache.vType].TexSize << 3 // * ( sizeof ( f32 ) * 2 ) ); } else @@ -908,33 +918,96 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, Uw Vw 0 0 */ - const core::vector2d *src = &((S3DVertex*) source )->TCoords; u32 t; + sVec4 n; + sVec2 srcT; for ( t = 0; t != vSize[VertexCache.vType].TexSize; ++t ) { - const core::matrix4& M = Transformation [ ETS_TEXTURE_0 + t ].m; - if ( Material.org.TextureLayer[t].TextureWrap==ETC_REPEAT ) + const core::matrix4& M = Transformation [ ETS_TEXTURE_0 + t ]; + + // texgen + if ( TransformationFlag [ ETS_TEXTURE_0 + t ] & (ETF_TEXGEN_CAMERA_NORMAL|ETF_TEXGEN_CAMERA_REFLECTION) ) { - dest->Tex[t].x = M[0] * src[t].X + M[4] * src[t].Y + M[8]; - dest->Tex[t].y = M[1] * src[t].X + M[5] * src[t].Y + M[9]; + n.x = LightSpace.campos.x - LightSpace.vertex.x; + n.y = LightSpace.campos.x - LightSpace.vertex.y; + n.z = LightSpace.campos.x - LightSpace.vertex.z; + n.normalize_xyz(); + n.x += LightSpace.normal.x; + n.y += LightSpace.normal.y; + n.z += LightSpace.normal.z; + n.normalize_xyz(); + + const f32 *view = Transformation[ETS_VIEW].pointer(); + + if ( TransformationFlag [ ETS_TEXTURE_0 + t ] & ETF_TEXGEN_CAMERA_REFLECTION ) + { + srcT.x = 0.5f * ( 1.f + (n.x * view[0] + n.y * view[4] + n.z * view[8] )); + srcT.y = 0.5f * ( 1.f + (n.x * view[1] + n.y * view[5] + n.z * view[9] )); + } + else + { + srcT.x = 0.5f * ( 1.f + (n.x * view[0] + n.y * view[1] + n.z * view[2] )); + srcT.y = 0.5f * ( 1.f + (n.x * view[4] + n.y * view[5] + n.z * view[6] )); + } } else { - f32 tx1, ty1; + irr::memcpy32_small ( &srcT,(&base->TCoords) + t, + sizeof ( f32 ) * 2 ); + } - tx1 = M[0] * src[t].X + M[4] * src[t].Y + M[8]; - ty1 = M[1] * src[t].X + M[5] * src[t].Y + M[9]; - - dest->Tex[t].x = tx1 <= 0.f ? 0.f : tx1 >= 1.f ? 1.f : tx1; - dest->Tex[t].y = ty1 <= 0.f ? 0.f : ty1 >= 1.f ? 1.f : ty1; - - //dest->Tex[t].x = core::clamp ( M[0] * src[t].X + M[4] * src[t].Y + M[8], 0.f, 1.f ); - //dest->Tex[t].y = core::clamp ( M[1] * src[t].X + M[5] * src[t].Y + M[9], 0.f, 1.f ); + switch ( Material.org.TextureLayer[t].TextureWrapU ) + { + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + case ETC_CLAMP_TO_BORDER: + dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); + break; + case ETC_MIRROR: + dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; + if (core::fract(dest->Tex[t].x)>0.5f) + dest->Tex[t].x=1.f-dest->Tex[t].x; + break; + case ETC_MIRROR_CLAMP: + case ETC_MIRROR_CLAMP_TO_EDGE: + case ETC_MIRROR_CLAMP_TO_BORDER: + dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); + if (core::fract(dest->Tex[t].x)>0.5f) + dest->Tex[t].x=1.f-dest->Tex[t].x; + break; + case ETC_REPEAT: + default: + dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; + break; + } + switch ( Material.org.TextureLayer[t].TextureWrapV ) + { + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + case ETC_CLAMP_TO_BORDER: + dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); + break; + case ETC_MIRROR: + dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; + if (core::fract(dest->Tex[t].y)>0.5f) + dest->Tex[t].y=1.f-dest->Tex[t].y; + break; + case ETC_MIRROR_CLAMP: + case ETC_MIRROR_CLAMP_TO_EDGE: + case ETC_MIRROR_CLAMP_TO_BORDER: + dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); + if (core::fract(dest->Tex[t].y)>0.5f) + dest->Tex[t].y=1.f-dest->Tex[t].y; + break; + case ETC_REPEAT: + default: + dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; + break; } } - } +#endif dest[0].flag = dest[1].flag = vSize[VertexCache.vType].Format; @@ -988,12 +1061,18 @@ REALINLINE void CBurningVideoDriver::VertexCache_get ( s4DVertex ** face ) u32 fillIndex = 0; u32 dIndex; u32 i; + u32 sourceIndex; while ( VertexCache.indicesIndex < VertexCache.indexCount && fillIndex < VERTEXCACHE_ELEMENT ) { - u32 sourceIndex = VertexCache.indices [ VertexCache.indicesIndex++ ]; + sourceIndex = VertexCache.iType == 1 ? + ((u16*)VertexCache.indices) [ VertexCache.indicesIndex ] : + ((u32*)VertexCache.indices) [ VertexCache.indicesIndex ]; + + + VertexCache.indicesIndex += 1; // if not exist, push back s32 exist = 0; @@ -1018,7 +1097,7 @@ REALINLINE void CBurningVideoDriver::VertexCache_get ( s4DVertex ** face ) VertexCache.info[i].hit = 0; } - // mark all exisiting + // mark all existing for ( i = 0; i!= fillIndex; ++i ) { for ( dIndex = 0; dIndex < VERTEXCACHE_ELEMENT; ++dIndex ) @@ -1053,20 +1132,44 @@ REALINLINE void CBurningVideoDriver::VertexCache_get ( s4DVertex ** face ) const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); - face[0] = VertexCache_getVertex ( VertexCache.indices[ i0 ] ); - face[1] = VertexCache_getVertex ( VertexCache.indices[ VertexCache.indicesRun + 1] ); - face[2] = VertexCache_getVertex ( VertexCache.indices[ VertexCache.indicesRun + 2] ); + if ( VertexCache.iType == 1 ) + { + const u16 *p = (const u16 *) VertexCache.indices; + face[0] = VertexCache_getVertex ( p[ i0 ] ); + face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); + face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); + } + else + { + const u32 *p = (const u32 *) VertexCache.indices; + face[0] = VertexCache_getVertex ( p[ i0 ] ); + face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); + face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); + } VertexCache.indicesRun += VertexCache.primitivePitch; } -REALINLINE void CBurningVideoDriver::VertexCache_get2 ( s4DVertex ** face ) +/*! +*/ +REALINLINE void CBurningVideoDriver::VertexCache_getbypass ( s4DVertex ** face ) { const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); - VertexCache_fill ( VertexCache.indices[ i0 ], 0 ); - VertexCache_fill ( VertexCache.indices[ VertexCache.indicesRun + 1], 1 ); - VertexCache_fill ( VertexCache.indices[ VertexCache.indicesRun + 2], 2 ); + if ( VertexCache.iType == 1 ) + { + const u16 *p = (const u16 *) VertexCache.indices; + VertexCache_fill ( p[ i0 ], 0 ); + VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 ); + VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 ); + } + else + { + const u32 *p = (const u32 *) VertexCache.indices; + VertexCache_fill ( p[ i0 ], 0 ); + VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 ); + VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 ); + } VertexCache.indicesRun += VertexCache.primitivePitch; @@ -1076,9 +1179,13 @@ REALINLINE void CBurningVideoDriver::VertexCache_get2 ( s4DVertex ** face ) } +/*! +*/ void CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCount, - const u16* indices, u32 primitiveCount, - E_VERTEX_TYPE vType,scene::E_PRIMITIVE_TYPE pType ) + const void* indices, u32 primitiveCount, + E_VERTEX_TYPE vType, + scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType) { VertexCache.vertices = vertices; VertexCache.vertexCount = vertexCount; @@ -1087,11 +1194,37 @@ void CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCo VertexCache.indicesIndex = 0; VertexCache.indicesRun = 0; - VertexCache.vType = vType; + if ( Material.org.MaterialType == video::EMT_REFLECTION_2_LAYER ) + VertexCache.vType = 3; + else + VertexCache.vType = vType; VertexCache.pType = pType; + VertexCache.iType = iType == EIT_16BIT ? 1 : 2; switch ( VertexCache.pType ) { + // most types here will not work as expected, only triangles/triangle_fan + // is known to work. + case scene::EPT_POINTS: + VertexCache.indexCount = primitiveCount; + VertexCache.primitivePitch = 1; + break; + case scene::EPT_LINE_STRIP: + VertexCache.indexCount = primitiveCount+1; + VertexCache.primitivePitch = 1; + break; + case scene::EPT_LINE_LOOP: + VertexCache.indexCount = primitiveCount+1; + VertexCache.primitivePitch = 1; + break; + case scene::EPT_LINES: + VertexCache.indexCount = 2*primitiveCount; + VertexCache.primitivePitch = 2; + break; + case scene::EPT_TRIANGLE_STRIP: + VertexCache.indexCount = primitiveCount+2; + VertexCache.primitivePitch = 1; + break; case scene::EPT_TRIANGLES: VertexCache.indexCount = primitiveCount + primitiveCount + primitiveCount; VertexCache.primitivePitch = 3; @@ -1100,10 +1233,25 @@ void CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCo VertexCache.indexCount = primitiveCount + 2; VertexCache.primitivePitch = 1; break; + case scene::EPT_QUAD_STRIP: + VertexCache.indexCount = 2*primitiveCount + 2; + VertexCache.primitivePitch = 2; + break; + case scene::EPT_QUADS: + VertexCache.indexCount = 4*primitiveCount; + VertexCache.primitivePitch = 4; + break; + case scene::EPT_POLYGON: + VertexCache.indexCount = primitiveCount+1; + VertexCache.primitivePitch = 1; + break; + case scene::EPT_POINT_SPRITES: + VertexCache.indexCount = primitiveCount; + VertexCache.primitivePitch = 1; + break; } irr::memset32 ( VertexCache.info, VERTEXCACHE_MISS, sizeof ( VertexCache.info ) ); - } @@ -1111,39 +1259,16 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) -{ - switch (iType) - { - case (EIT_16BIT): - { - drawVertexPrimitiveList16(vertices, vertexCount, (const u16*) indexList, primitiveCount, vType, pType); - break; - } - case (EIT_32BIT): - { - os::Printer::log("Software driver can not render 32bit buffers", ELL_ERROR); - break; - } - } - - -} - - - -//! draws a vertex primitive list -void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 vertexCount, const u16* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType) { if (!checkPrimitiveCount(primitiveCount)) return; - CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, EIT_16BIT); + CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); if ( 0 == CurrentShader ) return; - - VertexCache_reset ( vertices, vertexCount, indexList, primitiveCount, vType, pType ); + VertexCache_reset ( vertices, vertexCount, indexList, primitiveCount, vType, pType, iType ); const s4DVertex * face[3]; @@ -1151,6 +1276,7 @@ void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 ve s32 lodLevel; u32 i; u32 g; + video::CSoftwareTexture2* tex; for ( i = 0; i < (u32) primitiveCount; ++i ) { @@ -1178,15 +1304,15 @@ void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 ve for ( g = 0; g != vSize[VertexCache.vType].TexSize; ++g ) //for ( g = 0; g != BURNING_MATERIAL_MAX_TEXTURES; ++g ) { - if ( 0 == MAT_TEXTURE ( g ) ) + if ( 0 == (tex = MAT_TEXTURE ( g )) ) { CurrentShader->setTextureParam(g, 0, 0); continue; } lodLevel = s32_log2_f32 ( texelarea2 ( face, g ) * dc_area ); - CurrentShader->setTextureParam(g, MAT_TEXTURE ( g ), lodLevel); - select_polygon_mipmap2 ( (s4DVertex**) face, g ); + CurrentShader->setTextureParam(g, tex, lodLevel); + select_polygon_mipmap2 ( (s4DVertex**) face, g, tex->getSize() ); } @@ -1243,11 +1369,11 @@ void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 ve ( check[h].flag & 16 ) >> 4, ( check[h].flag & 32 ) >> 5 ); - os::Printer::print ( buf ); + os::Printer::log( buf ); } sprintf ( buf, "Vout: %d\n", vOut ); - os::Printer::print ( buf ); + os::Printer::log( buf ); int hold = 1; } @@ -1262,7 +1388,7 @@ void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 ve /* // TODO: don't stick on 32 Bit Pointer - #define PointerAsValue(x) ( (u32) (u32*) (x) ) + #define PointerAsValue(x) ( (u32) (u32*) (x) ) // if not complete inside clipping necessary if ( ( test & VERTEX4D_INSIDE ) != VERTEX4D_INSIDE ) @@ -1296,16 +1422,15 @@ void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 ve //for ( g = 0; g != BURNING_MATERIAL_MAX_TEXTURES; ++g ) for ( g = 0; g != vSize[VertexCache.vType].TexSize; ++g ) { - if ( 0 == MAT_TEXTURE ( g ) ) + if ( 0 == (tex = MAT_TEXTURE ( g )) ) { CurrentShader->setTextureParam(g, 0, 0); continue; } lodLevel = s32_log2_f32 ( texelarea ( CurrentOut.data, g ) / dc_area ); - - CurrentShader->setTextureParam(g, MAT_TEXTURE ( g ), lodLevel); - select_polygon_mipmap ( CurrentOut.data, vOut, g ); + CurrentShader->setTextureParam(g, tex, lodLevel); + select_polygon_mipmap ( CurrentOut.data, vOut, g, tex->getSize() ); } // re-tesselate ( triangle-fan, 0-1-2,0-2-3.. ) @@ -1326,10 +1451,12 @@ void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 ve vertexCount, primitiveCount, VertexCache.CacheMiss ); - os::Printer::print ( buf ); + os::Printer::log( buf ); */ + } + //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. @@ -1340,41 +1467,63 @@ void CBurningVideoDriver::setAmbientLight(const SColorf& color) //! adds a dynamic light -void CBurningVideoDriver::addDynamicLight(const SLight& dl) +s32 CBurningVideoDriver::addDynamicLight(const SLight& dl) { - if ( LightSpace.Light.size () >= getMaximalDynamicLightAmount () ) - return; + (void) CNullDriver::addDynamicLight( dl ); SBurningShaderLight l; - l.org = dl; +// l.org = dl; + l.Type = dl.Type; + l.LightIsOn = true; - // light in eye space - Transformation[ETS_VIEW].m.transformVect ( &l.posEyeSpace.x, l.org.Position ); - - l.constantAttenuation = l.org.Attenuation.X; - l.linearAttenuation = l.org.Attenuation.Y; - l.quadraticAttenuation = l.org.Attenuation.Z; - - l.AmbientColor.setColorf ( l.org.AmbientColor ); - l.DiffuseColor.setColorf ( l.org.DiffuseColor ); - l.SpecularColor.setColorf ( l.org.SpecularColor ); + l.AmbientColor.setColorf ( dl.AmbientColor ); + l.DiffuseColor.setColorf ( dl.DiffuseColor ); + l.SpecularColor.setColorf ( dl.SpecularColor ); switch ( dl.Type ) { case video::ELT_DIRECTIONAL: - { - l.posEyeSpace.normalize_xyz (); - } break; + l.pos.x = -dl.Direction.X; + l.pos.y = -dl.Direction.Y; + l.pos.z = -dl.Direction.Z; + l.pos.w = 1.f; + break; + case ELT_POINT: + case ELT_SPOT: + LightSpace.Flags |= POINTLIGHT; + l.pos.x = dl.Position.X; + l.pos.y = dl.Position.Y; + l.pos.z = dl.Position.Z; + l.pos.w = 1.f; +/* + l.radius = (1.f / dl.Attenuation.Y) * (1.f / dl.Attenuation.Y); + l.constantAttenuation = dl.Attenuation.X; + l.linearAttenuation = dl.Attenuation.Y; + l.quadraticAttenuation = dl.Attenuation.Z; +*/ + l.radius = dl.Radius * dl.Radius; + l.constantAttenuation = dl.Attenuation.X; + l.linearAttenuation = 1.f / dl.Radius; + l.quadraticAttenuation = dl.Attenuation.Z; + + break; } LightSpace.Light.push_back ( l ); - CNullDriver::addDynamicLight( l.org ); + return LightSpace.Light.size() - 1; +} + +//! Turns a dynamic light on or off +void CBurningVideoDriver::turnLightOn(s32 lightIndex, bool turnOn) +{ + if(lightIndex > -1 && lightIndex < (s32)LightSpace.Light.size()) + LightSpace.Light[lightIndex].LightIsOn = turnOn; } //! deletes all dynamic lights there are void CBurningVideoDriver::deleteAllDynamicLights() { - LightSpace.Light.set_used ( 0 ); + LightSpace.reset (); CNullDriver::deleteAllDynamicLights(); } @@ -1386,159 +1535,177 @@ u32 CBurningVideoDriver::getMaximalDynamicLightAmount() const } +//! sets a material +void CBurningVideoDriver::setMaterial(const SMaterial& material) +{ + Material.org = material; + +#ifdef SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM + for (u32 i = 0; i < 2; ++i) + { + setTransform((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), + material.getTextureMatrix(i)); + } +#endif + +#ifdef SOFTWARE_DRIVER_2_LIGHTING + Material.AmbientColor.setR8G8B8 ( Material.org.AmbientColor.color ); + Material.DiffuseColor.setR8G8B8 ( Material.org.DiffuseColor.color ); + Material.EmissiveColor.setR8G8B8 ( Material.org.EmissiveColor.color ); + Material.SpecularColor.setR8G8B8 ( Material.org.SpecularColor.color ); + + core::setbit_cond ( LightSpace.Flags, Material.org.Shininess != 0.f, SPECULAR ); + core::setbit_cond ( LightSpace.Flags, Material.org.FogEnable, FOG ); + core::setbit_cond ( LightSpace.Flags, Material.org.NormalizeNormals, NORMALIZE ); +#endif + + setCurrentShader(); +} + + +/*! + Camera Position in World Space +*/ +void CBurningVideoDriver::getCameraPosWorldSpace () +{ + Transformation[ETS_VIEW_INVERSE] = Transformation[ ETS_VIEW ]; + Transformation[ETS_VIEW_INVERSE].makeInverse (); + TransformationFlag[ETS_VIEW_INVERSE] = 0; + + const f32 *M = Transformation[ETS_VIEW_INVERSE].pointer (); + + /* The viewpoint is at (0., 0., 0.) in eye space. + Turning this into a vector [0 0 0 1] and multiply it by + the inverse of the view matrix, the resulting vector is the + object space location of the camera. + */ + + LightSpace.campos.x = M[12]; + LightSpace.campos.y = M[13]; + LightSpace.campos.z = M[14]; + LightSpace.campos.w = 1.f; +} #ifdef SOFTWARE_DRIVER_2_LIGHTING -/*! -*/ -void CBurningVideoDriver::lightVertex ( s4DVertex *dest, const S3DVertex *source ) +//! Sets the fog mode. +void CBurningVideoDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, + f32 end, f32 density, bool pixelFog, bool rangeFog) { - // apply lighting model - if ( false == Material.org.Lighting ) - { - // should use the DiffuseColor but using pre-lit vertex color - dest->Color[0].setA8R8G8B8 ( source->Color.color ); - return; - } + CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog); + LightSpace.FogColor.setA8R8G8B8 ( color.color ); +} + +/*! + applies lighting model +*/ +void CBurningVideoDriver::lightVertex ( s4DVertex *dest, u32 vertexargb ) +{ + sVec3 dColor; + + dColor = LightSpace.Global_AmbientLight; + dColor.add ( Material.EmissiveColor ); if ( Lights.size () == 0 ) { - dest->Color[0] = Material.EmissiveColor; + dColor.saturate( dest->Color[0], vertexargb); return; } - // eyespace -/* - core::matrix4 modelview = Transformation[ETS_WORLD].m * Transformation[ETS_VIEW].m; - - core::matrix4 m2 ( modelview ); - m2.makeInverse (); - core::matrix4 modelviewinversetransposed ( m2.getTransposed() ); -*/ - - sVec4 vertexEyeSpace; - sVec4 normalEyeSpace; - sVec4 vertexEyeSpaceUnit; - - // vertex in eye space - Transformation[ETS_WORLD_VIEW].m.transformVect ( &vertexEyeSpace.x, source->Pos ); - vertexEyeSpace.project_xyz (); - - vertexEyeSpaceUnit = vertexEyeSpace; - vertexEyeSpaceUnit.normalize_xyz(); - - // vertex normal in eye-space - //modelviewinversetransposed.transformVect ( &normalEyeSpace.x, source->Normal ); - Transformation[ETS_WORLD_VIEW_INVERSE_TRANSPOSED].m.rotateVect ( &normalEyeSpace.x, source->Normal ); - if ( Material.org.NormalizeNormals ) - { - normalEyeSpace.normalize_xyz(); - } - - - sVec4 ambient; - sVec4 diffuse; - sVec4 specular; + sVec3 ambient; + sVec3 diffuse; + sVec3 specular; // the universe started in darkness.. - ambient.set ( 0.f, 0.f, 0.f, 0.f ); - diffuse.set ( 0.f, 0.f, 0.f, 0.f ); - specular.set ( 0.f, 0.f, 0.f, 0.f ); + ambient.set ( 0.f, 0.f, 0.f ); + diffuse.set ( 0.f, 0.f, 0.f ); + specular.set ( 0.f, 0.f, 0.f ); - f32 attenuation = 1.f; u32 i; + f32 dot; + f32 len; + f32 attenuation; + sVec4 vp; // unit vector vertex to light + sVec4 lightHalf; // blinn-phong reflection + for ( i = 0; i!= LightSpace.Light.size (); ++i ) { const SBurningShaderLight &light = LightSpace.Light[i]; - sVec4 vp; // unit vector vertex to light - sVec4 lightHalf; // blinn-phong reflection + // accumulate ambient + ambient.add ( light.AmbientColor ); - - switch ( light.org.Type ) + switch ( light.Type ) { + case video::ELT_SPOT: case video::ELT_POINT: - { // surface to light - vp.x = light.posEyeSpace.x - vertexEyeSpace.x; - vp.y = light.posEyeSpace.y - vertexEyeSpace.y; - vp.z = light.posEyeSpace.z - vertexEyeSpace.z; + vp.x = light.pos.x - LightSpace.vertex.x; + vp.y = light.pos.y - LightSpace.vertex.y; + vp.z = light.pos.z - LightSpace.vertex.z; - // irrlicht attenuation model -#if 0 - const f32 d = vp.get_inverse_length_xyz(); + len = vp.get_length_xyz_square(); + if ( light.radius < len ) + continue; - vp.x *= d; - vp.y *= d; - vp.z *= d; - attenuation = light.org.Radius * d; + len = core::squareroot ( len ); -#else - const f32 d = vp.get_length_xyz(); - attenuation = core::reciprocal (light.constantAttenuation + - light.linearAttenuation * d + - light.quadraticAttenuation * d * d - ); + attenuation = light.constantAttenuation + ( 1.f - ( len * light.linearAttenuation ) ); - // normalize surface to light - vp.normalize_xyz(); -#endif + // build diffuse reflection - lightHalf.x = vp.x - vertexEyeSpaceUnit.x; - lightHalf.y = vp.y - vertexEyeSpaceUnit.y; - lightHalf.z = vp.z - vertexEyeSpaceUnit.z; + //angle between normal and light vector + vp.mulReciprocal ( len ); + dot = LightSpace.normal.dot_xyz ( vp ); + if ( dot < 0.f ) + continue; + + // diffuse component + diffuse.mulAdd ( light.DiffuseColor, dot * attenuation ); + + if ( !(LightSpace.Flags & SPECULAR) ) + continue; + + // build specular + // surface to view + lightHalf.x = LightSpace.campos.x - LightSpace.vertex.x; + lightHalf.y = LightSpace.campos.y - LightSpace.vertex.y; + lightHalf.z = LightSpace.campos.z - LightSpace.vertex.z; + lightHalf.normalize_xyz(); + lightHalf += vp; lightHalf.normalize_xyz(); - } break; + // specular + dot = LightSpace.normal.dot_xyz ( lightHalf ); + if ( dot < 0.f ) + continue; + + //specular += light.SpecularColor * ( powf ( Material.org.Shininess ,dot ) * attenuation ); + specular.mulAdd ( light.SpecularColor, dot * attenuation ); + break; case video::ELT_DIRECTIONAL: - { - attenuation = 1.f; - vp = light.posEyeSpace; - // half angle = lightvector + eye vector ( 0, 0, 1 ) - lightHalf.x = vp.x; - lightHalf.y = vp.y; - lightHalf.z = vp.z - 1.f; - lightHalf.normalize_xyz(); - } break; + //angle between normal and light vector + dot = LightSpace.normal.dot_xyz ( light.pos ); + if ( dot < 0.f ) + continue; + + // diffuse component + diffuse.mulAdd ( light.DiffuseColor, dot ); + break; } - // build diffuse reflection - - //angle between normal and light vector - f32 dotVP = core::max_ ( 0.f, normalEyeSpace.dot_xyz ( vp ) ); - f32 dotHV = core::max_ ( 0.f, normalEyeSpace.dot_xyz ( lightHalf ) ); - - f32 pf; - if ( dotVP == 0.0 ) - { - pf = 0.f; - } - else - { - pf = (f32)pow(dotHV, Material.org.Shininess ); - } - - // accumulate ambient - ambient += light.AmbientColor * attenuation; - diffuse += light.DiffuseColor * ( dotVP * attenuation ); - specular += light.SpecularColor * ( pf * attenuation ); - } - sVec4 dColor; + // sum up lights + dColor.mulAdd (ambient, Material.AmbientColor ); + dColor.mulAdd (diffuse, Material.DiffuseColor); + dColor.mulAdd (specular, Material.SpecularColor); - dColor = LightSpace.Global_AmbientLight; - dColor += Material.EmissiveColor; - dColor += ambient * Material.AmbientColor; - dColor += diffuse * Material.DiffuseColor; - dColor += specular * Material.SpecularColor; - dColor.saturate(); - - dest->Color[0] = dColor; + dColor.saturate ( dest->Color[0], vertexargb ); } #endif @@ -1568,20 +1735,21 @@ void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core } - //! Draws a 2d line. void CBurningVideoDriver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { - ((CImage*)BackBuffer)->drawLine(start, end, color ); + BackBuffer->drawLine(start, end, color ); } + //! Draws a pixel void CBurningVideoDriver::drawPixel(u32 x, u32 y, const SColor & color) { - ((CImage*)BackBuffer)->setPixel(x, y, color); -} + BackBuffer->setPixel(x, y, color, true); +} + //! draw an 2d rectangle void CBurningVideoDriver::draw2DRectangle(SColor color, const core::rect& pos, @@ -1610,10 +1778,10 @@ void CBurningVideoDriver::draw2DRectangle(SColor color, const core::rect& p //! Only used by the internal engine. Used to notify the driver that //! the window was resized. -void CBurningVideoDriver::OnResize(const core::dimension2d& size) +void CBurningVideoDriver::OnResize(const core::dimension2d& size) { // make sure width and height are multiples of 2 - core::dimension2d realSize(size); + core::dimension2d realSize(size); if (realSize.Width % 2) realSize.Width += 1; @@ -1623,10 +1791,13 @@ void CBurningVideoDriver::OnResize(const core::dimension2d& size) if (ScreenSize != realSize) { - if (ViewPort.getWidth() == ScreenSize.Width && - ViewPort.getHeight() == ScreenSize.Height) + if (ViewPort.getWidth() == (s32)ScreenSize.Width && + ViewPort.getHeight() == (s32)ScreenSize.Height) { - ViewPort = core::rect(core::position2d(0,0), realSize); + ViewPort.UpperLeftCorner.X = 0; + ViewPort.UpperLeftCorner.Y = 0; + ViewPort.LowerRightCorner.X = realSize.Width; + ViewPort.LowerRightCorner.X = realSize.Height; } ScreenSize = realSize; @@ -1644,7 +1815,7 @@ void CBurningVideoDriver::OnResize(const core::dimension2d& size) //! returns the current render target size -const core::dimension2d& CBurningVideoDriver::getCurrentRenderTargetSize() const +const core::dimension2d& CBurningVideoDriver::getCurrentRenderTargetSize() const { return RenderTargetSize; } @@ -1767,8 +1938,8 @@ void CBurningVideoDriver::draw2DRectangle(const core::rect& position, void CBurningVideoDriver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) { - Transformation [ ETS_CURRENT].m.transformVect ( &CurrentOut.data[0].Pos.x, start ); - Transformation [ ETS_CURRENT].m.transformVect ( &CurrentOut.data[2].Pos.x, end ); + Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[0].Pos.x, start ); + Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[2].Pos.x, end ); u32 g; u32 vOut; @@ -1816,16 +1987,22 @@ void CBurningVideoDriver::draw3DLine(const core::vector3df& start, const wchar_t* CBurningVideoDriver::getName() const { #ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL - return L"burnings video 0.39b"; + return L"Burning's Video 0.44 beautiful"; #elif defined ( BURNINGVIDEO_RENDERER_ULTRA_FAST ) - return L"burnings video 0.39uf"; + return L"Burning's Video 0.44 ultra fast"; #elif defined ( BURNINGVIDEO_RENDERER_FAST ) - return L"burnings video 0.39f"; + return L"Burning's Video 0.44 fast"; #else - return L"burnings video 0.39"; + return L"Burning's Video 0.44"; #endif } +//! Returns the graphics card vendor name. +core::stringc CBurningVideoDriver::getVendorInfo() +{ + return "Burning's Video: Ing. Thomas Alten (c) 2006-2010"; +} + //! Returns type of video driver E_DRIVER_TYPE CBurningVideoDriver::getDriverType() const @@ -1844,18 +2021,16 @@ ECOLOR_FORMAT CBurningVideoDriver::getColorFormat() const //! Returns the transformation set by setTransform const core::matrix4& CBurningVideoDriver::getTransform(E_TRANSFORMATION_STATE state) const { - return Transformation[state].m; + return Transformation[state]; } //! Creates a render target texture. -ITexture* CBurningVideoDriver::addRenderTargetTexture(const core::dimension2d& size, - const c8* name) +ITexture* CBurningVideoDriver::addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, const ECOLOR_FORMAT format) { CImage* img = new CImage(BURNINGSHADER_COLOR_FORMAT, size); - if (!name) - name="rt"; - ITexture* tex = new CSoftwareTexture2(img, name, false, true); + ITexture* tex = new CSoftwareTexture2(img, name, CSoftwareTexture2::IS_RENDERTARGET ); img->drop(); addTexture(tex); tex->drop(); @@ -1875,17 +2050,25 @@ void CBurningVideoDriver::clearZBuffer() IImage* CBurningVideoDriver::createScreenShot() { if (BackBuffer) - return new CImage(BackBuffer->getColorFormat(), BackBuffer); + { + CImage* tmp = new CImage(BackBuffer->getColorFormat(), BackBuffer->getDimension()); + BackBuffer->copyTo(tmp); + return tmp; + } else return 0; + } //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES -ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, const char* name) +ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { - return new CSoftwareTexture2(surface, name, getTextureCreationFlag(ETCF_CREATE_MIP_MAPS)); + return new CSoftwareTexture2( + surface, name, + (getTextureCreationFlag(ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0 ) | + (getTextureCreationFlag(ETCF_ALLOW_NON_POWER_2) ? 0 : CSoftwareTexture2::NP2_SIZE ), mipmapData); } @@ -1895,7 +2078,7 @@ ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, con //! call. u32 CBurningVideoDriver::getMaximalPrimitiveCount() const { - return 0x00800000; + return 0xFFFFFFFF; } @@ -1980,6 +2163,12 @@ void CBurningVideoDriver::drawStencilShadow(bool clearStencilBuffer, video::SCol } +core::dimension2du CBurningVideoDriver::getMaxTextureSize() const +{ + return core::dimension2du(SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE, SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE); +} + + } // end namespace video } // end namespace irr @@ -1991,7 +2180,7 @@ namespace video { //! creates a video driver -IVideoDriver* createSoftwareDriver2(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) +IVideoDriver* createSoftwareDriver2(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CBurningVideoDriver(windowSize, fullscreen, io, presenter); @@ -2004,3 +2193,4 @@ IVideoDriver* createSoftwareDriver2(const core::dimension2d& windowSize, bo } // end namespace video } // end namespace irr + diff --git a/src/dep/src/irrlicht/CSoftwareDriver2.h b/src/dep/src/irrlicht/CSoftwareDriver2.h index 3647111..0a37400 100644 --- a/src/dep/src/irrlicht/CSoftwareDriver2.h +++ b/src/dep/src/irrlicht/CSoftwareDriver2.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -21,7 +21,7 @@ namespace video public: //! constructor - CBurningVideoDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter); + CBurningVideoDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter); //! destructor virtual ~CBurningVideoDriver(); @@ -44,7 +44,7 @@ namespace video //! clears the zbuffer virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! presents the rendered scene on the screen, returns false if failed @@ -52,16 +52,23 @@ namespace video //! Only used by the internal engine. Used to notify the driver that //! the window was resized. - virtual void OnResize(const core::dimension2d& size); + virtual void OnResize(const core::dimension2d& size); //! returns size of the current render target - virtual const core::dimension2d& getCurrentRenderTargetSize() const; + virtual const core::dimension2d& getCurrentRenderTargetSize() const; //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); - //! adds a dynamic light - virtual void addDynamicLight(const SLight& light); + //! adds a dynamic light, returning an index to the light + //! \param light: the light data to use to create the light + //! \return An index to the light, or -1 if an error occurs + virtual s32 addDynamicLight(const SLight& light); + + //! Turns a dynamic light on or off + //! \param lightIndex: the index returned by addDynamicLight + //! \param turnOn: true to turn the light on, false to turn it off + virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; @@ -116,7 +123,8 @@ namespace video virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; //! Creates a render target texture. - virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const c8* name); + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Clears the DepthBuffer. virtual void clearZBuffer(); @@ -143,14 +151,15 @@ namespace video video::SColor leftDownEdge = video::SColor(0,0,0,0), video::SColor rightDownEdge = video::SColor(0,0,0,0)); + //! Returns the graphics card vendor name. + virtual core::stringc getVendorInfo(); + + //! Returns the maximum texture size supported. + virtual core::dimension2du getMaxTextureSize() const; + protected: - void drawVertexPrimitiveList16(const void* vertices, u32 vertexCount, - const u16* indexList, u32 primitiveCount, - E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType); - - //! sets a render target void setRenderTarget(video::CImage* image); @@ -159,7 +168,7 @@ namespace video //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); video::CImage* BackBuffer; video::IImagePresenter* Presenter; @@ -169,7 +178,7 @@ namespace video video::ITexture* RenderTargetTexture; video::IImage* RenderTargetSurface; - core::dimension2d RenderTargetSize; + core::dimension2d RenderTargetSize; //! selects the right triangle renderer based on the render states. void setCurrentShader(); @@ -186,24 +195,27 @@ namespace video -> combined CameraProjectionWorld -> ClipScale from NDC to DC Space */ - enum E_TRANSFORMATION_STATE_2 + enum E_TRANSFORMATION_STATE_BURNING_VIDEO { ETS_VIEW_PROJECTION = ETS_COUNT, - ETS_WORLD_VIEW, - ETS_WORLD_VIEW_INVERSE_TRANSPOSED, ETS_CURRENT, ETS_CLIPSCALE, + ETS_VIEW_INVERSE, - ETS2_COUNT + ETS_COUNT_BURNING }; - struct SMatrixStack + enum E_TRANSFORMATION_FLAG { - s32 isIdentity; - core::matrix4 m; + ETF_IDENTITY = 1, + ETF_TEXGEN_CAMERA_NORMAL = 2, + ETF_TEXGEN_CAMERA_REFLECTION = 4, }; + u32 TransformationFlag[ETS_COUNT_BURNING]; + core::matrix4 Transformation[ETS_COUNT_BURNING]; + + void getCameraPosWorldSpace (); - SMatrixStack Transformation[ETS2_COUNT]; // Vertex Cache static const SVSize vSize[]; @@ -211,10 +223,11 @@ namespace video SVertexCache VertexCache; void VertexCache_reset (const void* vertices, u32 vertexCount, - const u16* indices, u32 indexCount, - E_VERTEX_TYPE vType,scene::E_PRIMITIVE_TYPE pType); + const void* indices, u32 indexCount, + E_VERTEX_TYPE vType,scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType); void VertexCache_get ( s4DVertex ** face ); - void VertexCache_get2 ( s4DVertex ** face ); + void VertexCache_getbypass ( s4DVertex ** face ); void VertexCache_fill ( const u32 sourceIndex,const u32 destIndex ); s4DVertex * VertexCache_getVertex ( const u32 sourceIndex ); @@ -227,7 +240,11 @@ namespace video #ifdef SOFTWARE_DRIVER_2_LIGHTING - void lightVertex ( s4DVertex *dest, const S3DVertex *source ); + + void lightVertex ( s4DVertex *dest, u32 vertexargb ); + //! Sets the fog mode. + virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, + f32 end, f32 density, bool pixelFog, bool rangeFog); #endif @@ -237,21 +254,20 @@ namespace video void ndc_2_dc_and_project ( s4DVertex *dest,s4DVertex *source, u32 vIn ) const; f32 screenarea ( const s4DVertex *v0 ) const; - void select_polygon_mipmap ( s4DVertex *source, u32 vIn, s32 tex ); + void select_polygon_mipmap ( s4DVertex *source, u32 vIn, u32 tex, const core::dimension2du& texSize ); f32 texelarea ( const s4DVertex *v0, int tex ) const; void ndc_2_dc_and_project2 ( const s4DVertex **v, const u32 size ) const; f32 screenarea2 ( const s4DVertex **v ) const; f32 texelarea2 ( const s4DVertex **v, int tex ) const; - void select_polygon_mipmap2 ( s4DVertex **source, s32 tex ) const; + void select_polygon_mipmap2 ( s4DVertex **source, u32 tex, const core::dimension2du& texSize ) const; SBurningShaderLightSpace LightSpace; SBurningShaderMaterial Material; static const sVec4 NDCPlane[6]; - }; } // end namespace video @@ -260,4 +276,3 @@ namespace video #endif - diff --git a/src/dep/src/irrlicht/CSoftwareTexture.cpp b/src/dep/src/irrlicht/CSoftwareTexture.cpp index 5418100..1a92f89 100644 --- a/src/dep/src/irrlicht/CSoftwareTexture.cpp +++ b/src/dep/src/irrlicht/CSoftwareTexture.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -14,7 +14,8 @@ namespace video { //! constructor -CSoftwareTexture::CSoftwareTexture(IImage* image, const char* name, bool renderTarget) +CSoftwareTexture::CSoftwareTexture(IImage* image, const io::path& name, + bool renderTarget, void* mipmapData) : ITexture(name), Texture(0), IsRenderTarget(renderTarget) { #ifdef _DEBUG @@ -23,13 +24,11 @@ CSoftwareTexture::CSoftwareTexture(IImage* image, const char* name, bool renderT if (image) { - core::dimension2d optSize; OrigSize = image->getDimension(); + core::dimension2d optSize=OrigSize.getOptimalSize(); - optSize.Width = getTextureSizeFromSurfaceSize(OrigSize.Width); - optSize.Height = getTextureSizeFromSurfaceSize(OrigSize.Height); - - Image = new CImage(ECF_A1R5G5B5, image); + Image = new CImage(ECF_A1R5G5B5, OrigSize); + image->copyTo(Image); if (optSize == OrigSize) { @@ -59,7 +58,7 @@ CSoftwareTexture::~CSoftwareTexture() //! lock function -void* CSoftwareTexture::lock(bool readOnly) +void* CSoftwareTexture::lock(bool readOnly, u32 mipmapLevel) { return Image->lock(); } @@ -80,14 +79,14 @@ void CSoftwareTexture::unlock() //! Returns original size of the texture. -const core::dimension2d& CSoftwareTexture::getOriginalSize() const +const core::dimension2d& CSoftwareTexture::getOriginalSize() const { return OrigSize; } //! Returns (=size) of the texture. -const core::dimension2d& CSoftwareTexture::getSize() const +const core::dimension2d& CSoftwareTexture::getSize() const { return Image->getDimension(); } @@ -109,18 +108,6 @@ CImage* CSoftwareTexture::getTexture() -//! returns the size of a texture which would be the optimize size for rendering it -inline s32 CSoftwareTexture::getTextureSizeFromSurfaceSize(s32 size) const -{ - s32 ts = 0x01; - while(ts < size) - ts <<= 1; - - return ts; -} - - - //! returns driver type of texture (=the driver, who created the texture) E_DRIVER_TYPE CSoftwareTexture::getDriverType() const { @@ -146,7 +133,7 @@ u32 CSoftwareTexture::getPitch() const //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void CSoftwareTexture::regenerateMipMapLevels() +void CSoftwareTexture::regenerateMipMapLevels(void* mipmapData) { // our software textures don't have mip maps } diff --git a/src/dep/src/irrlicht/CSoftwareTexture.h b/src/dep/src/irrlicht/CSoftwareTexture.h index acd13c6..a5470e0 100644 --- a/src/dep/src/irrlicht/CSoftwareTexture.h +++ b/src/dep/src/irrlicht/CSoftwareTexture.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -21,22 +21,23 @@ class CSoftwareTexture : public ITexture public: //! constructor - CSoftwareTexture(IImage* surface, const char* name, bool renderTarget=false); + CSoftwareTexture(IImage* surface, const io::path& name, + bool renderTarget=false, void* mipmapData=0); //! destructor virtual ~CSoftwareTexture(); //! lock function - virtual void* lock(bool readOnly = false); + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0); //! unlock function virtual void unlock(); //! Returns original size of the texture. - virtual const core::dimension2d& getOriginalSize() const; + virtual const core::dimension2d& getOriginalSize() const; //! Returns (=size) of the texture. - virtual const core::dimension2d& getSize() const; + virtual const core::dimension2d& getSize() const; //! returns unoptimized surface virtual CImage* getImage(); @@ -53,21 +54,17 @@ public: //! returns pitch of texture (in bytes) virtual u32 getPitch() const; - //! Regenerates the mip map levels of the texture. Useful after locking and + //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture - virtual void regenerateMipMapLevels(); + virtual void regenerateMipMapLevels(void* mipmapData=0); //! is it a render target? virtual bool isRenderTarget() const; private: - - //! returns the size of a texture which would be the optimize size for rendering it - inline s32 getTextureSizeFromSurfaceSize(s32 size) const; - CImage* Image; CImage* Texture; - core::dimension2d OrigSize; + core::dimension2d OrigSize; bool IsRenderTarget; }; diff --git a/src/dep/src/irrlicht/CSoftwareTexture2.cpp b/src/dep/src/irrlicht/CSoftwareTexture2.cpp index 67895e1..48fd740 100644 --- a/src/dep/src/irrlicht/CSoftwareTexture2.cpp +++ b/src/dep/src/irrlicht/CSoftwareTexture2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,19 +12,20 @@ namespace irr { -namespace video +namespace video { //! constructor -CSoftwareTexture2::CSoftwareTexture2(IImage* image, const char* name, bool generateMipLevels, bool isRenderTarget) -: ITexture(name), MipMapLOD(0), HasMipMaps(generateMipLevels), IsRenderTarget(isRenderTarget) +CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, + u32 flags, void* mipmapData) + : ITexture(name), MipMapLOD(0), Flags ( flags ), OriginalFormat(video::ECF_UNKNOWN) { #ifdef _DEBUG setDebugName("CSoftwareTexture2"); #endif #ifndef SOFTWARE_DRIVER_2_MIPMAPPING - HasMipMaps = false; + Flags &= ~GEN_MIPMAP; #endif memset32 ( MipMap, 0, sizeof ( MipMap ) ); @@ -32,29 +33,42 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const char* name, bool gener if (image) { OrigSize = image->getDimension(); + OriginalFormat = image->getColorFormat(); + + core::setbit_cond(Flags, + image->getColorFormat () == video::ECF_A8R8G8B8 || + image->getColorFormat () == video::ECF_A1R5G5B5, + HAS_ALPHA); + + core::dimension2d optSize( + OrigSize.getOptimalSize( 0 != ( Flags & NP2_SIZE ), + false, false, + ( Flags & NP2_SIZE ) ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 0) + ); - core::dimension2d optSize( - OrigSize.getOptimalSize(true, false, false)); - if ( OrigSize == optSize ) { - MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image); + MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image->getDimension()); + image->copyTo(MipMap[0]); } else { - //os::Printer::log ( "Burningvideo: Warning Texture reformat", ELL_WARNING ); - MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize); + char buf[256]; + core::stringw showName ( name ); + snprintf ( buf, 256, "Burningvideo: Warning Texture %ls reformat %dx%d -> %dx%d,%d", + showName.c_str(), + OrigSize.Width, OrigSize.Height, optSize.Width, optSize.Height, + BURNINGSHADER_COLOR_FORMAT + ); - // temporary CImage needed - CImage * temp = new CImage ( BURNINGSHADER_COLOR_FORMAT, image ); - temp->copyToScalingBoxFilter ( MipMap[0], 0 ); - //temp->copyToScaling(MipMap[0]); - temp->drop (); + OrigSize = optSize; + os::Printer::log ( buf, ELL_WARNING ); + MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize); + image->copyToScalingBoxFilter ( MipMap[0],0, false ); } } - regenerateMipMapLevels(); - setCurrentMipMapLOD(0); + regenerateMipMapLevels(mipmapData); } @@ -69,37 +83,65 @@ CSoftwareTexture2::~CSoftwareTexture2() } -//! Regenerates the mip map levels of the texture. Useful after locking and +//! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void CSoftwareTexture2::regenerateMipMapLevels() +void CSoftwareTexture2::regenerateMipMapLevels(void* mipmapData) { - if ( !HasMipMaps ) + if ( !hasMipMaps () ) return; s32 i; // release - for ( i = 1; i!= SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) + for ( i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) { if ( MipMap[i] ) MipMap[i]->drop(); } - core::dimension2d newSize; - core::dimension2d currentSize; + core::dimension2d newSize; + core::dimension2d origSize=OrigSize; - i = 1; - CImage * c = MipMap[0]; - while ( i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX ) + for (i=1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) { - currentSize = c->getDimension(); - newSize.Width = core::s32_max ( 1, currentSize.Width >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); - newSize.Height = core::s32_max ( 1, currentSize.Height >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); + newSize = MipMap[i-1]->getDimension(); + newSize.Width = core::s32_max ( 1, newSize.Width >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); + newSize.Height = core::s32_max ( 1, newSize.Height >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); + origSize.Width = core::s32_max(1, origSize.Width >> 1); + origSize.Height = core::s32_max(1, origSize.Height >> 1); - MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); - MipMap[0]->copyToScalingBoxFilter( MipMap[i], 0 ); - c = MipMap[i]; - ++i; + if (mipmapData) + { + if (OriginalFormat != BURNINGSHADER_COLOR_FORMAT) + { + IImage* tmpImage = new CImage(OriginalFormat, origSize, mipmapData, true, false); + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); + if (origSize==newSize) + tmpImage->copyTo(MipMap[i]); + else + tmpImage->copyToScalingBoxFilter(MipMap[i]); + tmpImage->drop(); + } + else + { + if (origSize==newSize) + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize, mipmapData, false); + else + { + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); + IImage* tmpImage = new CImage(BURNINGSHADER_COLOR_FORMAT, origSize, mipmapData, true, false); + tmpImage->copyToScalingBoxFilter(MipMap[i]); + tmpImage->drop(); + } + } + mipmapData = (u8*)mipmapData+origSize.getArea()*IImage::getBitsPerPixelFromFormat(OriginalFormat)/8; + } + else + { + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); + MipMap[i]->fill ( 0 ); + MipMap[0]->copyToScalingBoxFilter( MipMap[i], 0, false ); + } } } @@ -108,4 +150,3 @@ void CSoftwareTexture2::regenerateMipMapLevels() } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ - diff --git a/src/dep/src/irrlicht/CSoftwareTexture2.h b/src/dep/src/irrlicht/CSoftwareTexture2.h index 3ef61aa..5a45952 100644 --- a/src/dep/src/irrlicht/CSoftwareTexture2.h +++ b/src/dep/src/irrlicht/CSoftwareTexture2.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -23,14 +23,23 @@ class CSoftwareTexture2 : public ITexture public: //! constructor - CSoftwareTexture2(IImage* surface, const char* name, bool generateMipLevels, bool isRenderTarget=false); + enum eTex2Flags + { + GEN_MIPMAP = 1, + IS_RENDERTARGET = 2, + NP2_SIZE = 4, + HAS_ALPHA = 8 + }; + CSoftwareTexture2(IImage* surface, const io::path& name, u32 flags, void* mipmapData=0); //! destructor virtual ~CSoftwareTexture2(); //! lock function - virtual void* lock(bool readOnly = false) + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0) { + if (Flags & GEN_MIPMAP) + MipMapLOD=mipmapLevel; return MipMap[MipMapLOD]->lock(); } @@ -41,7 +50,7 @@ public: } //! Returns original size of the texture. - virtual const core::dimension2d& getOriginalSize() const + virtual const core::dimension2d& getOriginalSize() const { //return MipMap[0]->getDimension(); return OrigSize; @@ -54,7 +63,7 @@ public: } //! Returns (=size) of the texture. - virtual const core::dimension2d& getSize() const + virtual const core::dimension2d& getSize() const { return MipMap[MipMapLOD]->getDimension(); } @@ -90,36 +99,36 @@ public: return MipMap[MipMapLOD]->getPitch(); } - //! Regenerates the mip map levels of the texture. Useful after locking and + //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture - virtual void regenerateMipMapLevels(); + virtual void regenerateMipMapLevels(void* mipmapData=0); - //! Select a Mipmap Level - virtual void setCurrentMipMapLOD ( s32 lod ) - { - if ( HasMipMaps ) - MipMapLOD = lod; - } - //! support mipmaps virtual bool hasMipMaps() const { - return HasMipMaps; + return (Flags & GEN_MIPMAP ) != 0; + } + + //! Returns if the texture has an alpha channel + virtual bool hasAlpha() const + { + return (Flags & HAS_ALPHA ) != 0; } //! is a render target virtual bool isRenderTarget() const { - return IsRenderTarget; + return (Flags & IS_RENDERTARGET) != 0; } private: - core::dimension2d OrigSize; + core::dimension2d OrigSize; CImage * MipMap[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; - s32 MipMapLOD; - bool HasMipMaps, IsRenderTarget; + u32 MipMapLOD; + u32 Flags; + ECOLOR_FORMAT OriginalFormat; }; diff --git a/src/dep/src/irrlicht/CSphereSceneNode.cpp b/src/dep/src/irrlicht/CSphereSceneNode.cpp index a37083b..c20acd2 100644 --- a/src/dep/src/irrlicht/CSphereSceneNode.cpp +++ b/src/dep/src/irrlicht/CSphereSceneNode.cpp @@ -1,11 +1,10 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSphereSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" -#include "CGeometryCreator.h" #include "S3DVertex.h" #include "os.h" @@ -24,7 +23,7 @@ CSphereSceneNode::CSphereSceneNode(f32 radius, u32 polyCountX, u32 polyCountY, I setDebugName("CSphereSceneNode"); #endif - Mesh = CGeometryCreator::createSphereMesh(radius, polyCountX, polyCountY); + Mesh = SceneManager->getGeometryCreator()->createSphereMesh(radius, polyCountX, polyCountY); } @@ -128,7 +127,7 @@ void CSphereSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribute { if (Mesh) Mesh->drop(); - Mesh = CGeometryCreator::createSphereMesh(Radius, PolyCountX, PolyCountY); + Mesh = SceneManager->getGeometryCreator()->createSphereMesh(Radius, PolyCountX, PolyCountY); } ISceneNode::deserializeAttributes(in, options); @@ -142,13 +141,14 @@ ISceneNode* CSphereSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan if (!newManager) newManager = SceneManager; - CSphereSceneNode* nb = new CSphereSceneNode(Radius, PolyCountX, PolyCountY, newParent, + CSphereSceneNode* nb = new CSphereSceneNode(Radius, PolyCountX, PolyCountY, newParent, newManager, ID, RelativeTranslation); nb->cloneMembers(this, newManager); nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial(); - nb->drop(); + if ( newParent ) + nb->drop(); return nb; } diff --git a/src/dep/src/irrlicht/CSphereSceneNode.h b/src/dep/src/irrlicht/CSphereSceneNode.h index 5b8e9da..267cf3d 100644 --- a/src/dep/src/irrlicht/CSphereSceneNode.h +++ b/src/dep/src/irrlicht/CSphereSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRFlat.cpp b/src/dep/src/irrlicht/CTRFlat.cpp index 800d966..ee27892 100644 --- a/src/dep/src/irrlicht/CTRFlat.cpp +++ b/src/dep/src/irrlicht/CTRFlat.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRFlatWire.cpp b/src/dep/src/irrlicht/CTRFlatWire.cpp index 4ea0b25..6840e6f 100644 --- a/src/dep/src/irrlicht/CTRFlatWire.cpp +++ b/src/dep/src/irrlicht/CTRFlatWire.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRGouraud.cpp b/src/dep/src/irrlicht/CTRGouraud.cpp index 508b421..43fdfa6 100644 --- a/src/dep/src/irrlicht/CTRGouraud.cpp +++ b/src/dep/src/irrlicht/CTRGouraud.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRGouraud2.cpp b/src/dep/src/irrlicht/CTRGouraud2.cpp index 93e1b59..fa3b5c1 100644 --- a/src/dep/src/irrlicht/CTRGouraud2.cpp +++ b/src/dep/src/irrlicht/CTRGouraud2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -185,10 +185,10 @@ void CTRGouraud2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -261,11 +261,13 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D if ( a->Pos.y > c->Pos.y ) swapVertexPointer(&a, &c); if ( b->Pos.y > c->Pos.y ) swapVertexPointer(&b, &c); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -274,11 +276,11 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -318,19 +320,6 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) @@ -627,19 +616,6 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif } diff --git a/src/dep/src/irrlicht/CTRGouraudAlpha2.cpp b/src/dep/src/irrlicht/CTRGouraudAlpha2.cpp index 9c42eff..ed1abc1 100644 --- a/src/dep/src/irrlicht/CTRGouraudAlpha2.cpp +++ b/src/dep/src/irrlicht/CTRGouraudAlpha2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -188,10 +188,10 @@ void CTRGouraudAlpha2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -269,28 +269,29 @@ void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -330,19 +331,6 @@ void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) @@ -639,20 +627,6 @@ void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } } // end namespace video diff --git a/src/dep/src/irrlicht/CTRGouraudAlphaNoZ2.cpp b/src/dep/src/irrlicht/CTRGouraudAlphaNoZ2.cpp index 7ab18fd..dfe576a 100644 --- a/src/dep/src/irrlicht/CTRGouraudAlphaNoZ2.cpp +++ b/src/dep/src/irrlicht/CTRGouraudAlphaNoZ2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -187,10 +187,10 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -271,28 +271,29 @@ void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,c { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -332,20 +333,6 @@ void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,c f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -641,20 +628,6 @@ void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,c } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } } // end namespace video diff --git a/src/dep/src/irrlicht/CTRGouraudWire.cpp b/src/dep/src/irrlicht/CTRGouraudWire.cpp index a6822d0..fc0fad8 100644 --- a/src/dep/src/irrlicht/CTRGouraudWire.cpp +++ b/src/dep/src/irrlicht/CTRGouraudWire.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRTextureBlend.cpp b/src/dep/src/irrlicht/CTRTextureBlend.cpp index 53b48ce..c5502e4 100644 --- a/src/dep/src/irrlicht/CTRTextureBlend.cpp +++ b/src/dep/src/irrlicht/CTRTextureBlend.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -33,7 +33,7 @@ #define CMP_W #define WRITE_W -//#define IPOL_C0 +#define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 @@ -87,15 +87,27 @@ public: virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); virtual void setZCompareFunc ( u32 func); + virtual void setParam ( u32 index, f32 value); + private: - void scanline_bilinear (); + // fragment shader + typedef void (CTRTextureBlend::*tFragmentShader) (); + void fragment_dst_color_zero (); + void fragment_dst_color_one (); + void fragment_dst_color_src_alpha (); + void fragment_dst_color_one_minus_dst_alpha (); + void fragment_zero_one_minus_scr_color (); + void fragment_src_color_src_alpha (); + void fragment_one_one_minus_src_alpha (); + void fragment_one_minus_dst_alpha_one(); + void fragment_src_alpha_one(); + tFragmentShader fragmentShader; sScanConvertData scan; sScanLineData line; u32 ZCompare; - }; //! constructor @@ -109,7 +121,8 @@ CTRTextureBlend::CTRTextureBlend(IDepthBuffer* zbuffer) ZCompare = 1; } - +/*! +*/ void CTRTextureBlend::setZCompareFunc ( u32 func) { ZCompare = func; @@ -117,7 +130,101 @@ void CTRTextureBlend::setZCompareFunc ( u32 func) /*! */ -void CTRTextureBlend::scanline_bilinear () +void CTRTextureBlend::setParam ( u32 index, f32 value) +{ + u8 showname = 0; + + E_BLEND_FACTOR srcFact,dstFact; + E_MODULATE_FUNC modulate; + u32 alphaSrc; + unpack_texureBlendFunc ( srcFact, dstFact, modulate, alphaSrc, value ); + + fragmentShader = 0; + + if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ZERO ) + { + fragmentShader = &CTRTextureBlend::fragment_dst_color_zero; + } + else + if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE ) + { + fragmentShader = &CTRTextureBlend::fragment_dst_color_one; + } + else + if ( srcFact == EBF_DST_COLOR && dstFact == EBF_SRC_ALPHA) + { + fragmentShader = &CTRTextureBlend::fragment_dst_color_src_alpha; + } + else + if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE_MINUS_DST_ALPHA) + { + fragmentShader = &CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha; + } + else + if ( srcFact == EBF_ZERO && dstFact == EBF_ONE_MINUS_SRC_COLOR ) + { + fragmentShader = &CTRTextureBlend::fragment_zero_one_minus_scr_color; + } + else + if ( srcFact == EBF_ONE && dstFact == EBF_ONE_MINUS_SRC_ALPHA) + { + fragmentShader = &CTRTextureBlend::fragment_one_one_minus_src_alpha; + } + else + if ( srcFact == EBF_ONE_MINUS_DST_ALPHA && dstFact == EBF_ONE ) + { + fragmentShader = &CTRTextureBlend::fragment_one_minus_dst_alpha_one; + } + else + if ( srcFact == EBF_SRC_ALPHA && dstFact == EBF_ONE ) + { + fragmentShader = &CTRTextureBlend::fragment_src_alpha_one; + } + else + if ( srcFact == EBF_SRC_COLOR && dstFact == EBF_SRC_ALPHA ) + { + fragmentShader = &CTRTextureBlend::fragment_src_color_src_alpha; + } + else + { + showname = 1; + fragmentShader = &CTRTextureBlend::fragment_dst_color_zero; + } + + static const c8 *n[] = + { + "gl_zero", + "gl_one", + "gl_dst_color", + "gl_one_minus_dst_color", + "gl_src_color", + "gl_one_minus_src_color", + "gl_src_alpha", + "gl_one_minus_src_alpha", + "gl_dst_alpha", + "gl_one_minus_dst_alpha", + "gl_src_alpha_saturate" + }; + + static E_BLEND_FACTOR lsrcFact = EBF_ZERO; + static E_BLEND_FACTOR ldstFact = EBF_ZERO; + + if ( showname && ( lsrcFact != srcFact || ldstFact != dstFact ) ) + { + char buf[128]; + snprintf ( buf, 128, "missing shader: %s %s",n[srcFact], n[dstFact] ); + os::Printer::log( buf, ELL_INFORMATION ); + + lsrcFact = srcFact; + ldstFact = dstFact; + } + +} + + +/*! +*/ +void CTRTextureBlend::fragment_dst_color_src_alpha () { tVideoSample *dst; @@ -141,7 +248,7 @@ void CTRTextureBlend::scanline_bilinear () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC; + sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; @@ -166,7 +273,7 @@ void CTRTextureBlend::scanline_bilinear () slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 - slopeC = (line.c[1] - line.c[0]) * invDeltaX; + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; @@ -184,7 +291,7 @@ void CTRTextureBlend::scanline_bilinear () line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 - line.c[0] += slopeC * subPixel; + line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; @@ -194,17 +301,17 @@ void CTRTextureBlend::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif - f32 inversew = FIX_POINT_F32_MUL; + f32 iw = FIX_POINT_F32_MUL; - tFixPoint r0, g0, b0; - tFixPoint r1, g1, b1; + tFixPoint a0, r0, g0, b0; + tFixPoint r1, g1, b1; s32 i; @@ -223,21 +330,21 @@ void CTRTextureBlend::scanline_bilinear () z[i] = line.w[0]; #endif -#ifdef INVERSEW - inversew = fix_inverse32 ( line.w[0] ); +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); #endif - getSample_texture ( r0, g0, b0, + getSample_texture ( (tFixPointu&) a0, (tFixPointu&)r0, (tFixPointu&)g0, (tFixPointu&)b0, &IT[0], - f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) + tofix ( line.t[0][0].x,iw), + tofix ( line.t[0][0].y,iw) ); - + color_to_fix ( r1, g1, b1, dst[i] ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ) + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); } @@ -246,6 +353,9 @@ void CTRTextureBlend::scanline_bilinear () #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; #endif } break; @@ -263,20 +373,158 @@ void CTRTextureBlend::scanline_bilinear () z[i] = line.w[0]; #endif -#ifdef INVERSEW - inversew = fix_inverse32 ( line.w[0] ); +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); #endif - getSample_texture ( r0, g0, b0, - &IT[0], - f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) - ); + getSample_texture ( (tFixPointu&) a0, (tFixPointu&)r0, (tFixPointu&)g0, (tFixPointu&)b0, + &IT[0], + tofix ( line.t[0][0].x,iw), + tofix ( line.t[0][0].y,iw) + ); + color_to_fix ( r1, g1, b1, dst[i] ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ) + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) + ); + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_src_color_src_alpha () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPointu a0, r0, g0, b0; + tFixPoint r1, g1, b1; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( a0, r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,iw), tofix ( line.t[0][0].y,iw) ); + color_to_fix ( r1, g1, b1, dst[i] ); + +// u32 check = imulFix_tex1( r0, r1 ); + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1( r0, r1 ) + imulFix_tex1( r1, a0 ) ), + clampfix_maxcolor ( imulFix_tex1( g0, g1 ) + imulFix_tex1( g1, a0 ) ), + clampfix_maxcolor ( imulFix_tex1( b0, b1 ) + imulFix_tex1( b1, a0 ) ) ); } @@ -285,38 +533,1493 @@ void CTRTextureBlend::scanline_bilinear () #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( (tFixPointu&) a0, (tFixPointu&)r0, (tFixPointu&)g0, (tFixPointu&)b0, + &IT[0], + tofix ( line.t[0][0].x,iw), + tofix ( line.t[0][0].y,iw) + ); + + color_to_fix ( r1, g1, b1, dst[i] ); + + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) + ); + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } +/*! +*/ +void CTRTextureBlend::fragment_one_one_minus_src_alpha() +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPointu a0,r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + a0 = FIX_POINT_ONE - a0; + + color_to_fix1 ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( r0 + imulFix ( r1, a0 ), r2 ), + imulFix ( g0 + imulFix ( g1, a0 ), g2 ), + imulFix ( b0 + imulFix ( b1, a0 ), b2 ) + ); +#else + dst[i] = fix_to_color ( r0 + imulFix ( r1, a0 ), + g0 + imulFix ( g1, a0 ), + b0 + imulFix ( b1, a0 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + a0 = FIX_POINT_ONE - a0; + + color_to_fix1 ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( r0 + imulFix ( r1, a0 ), r2 ), + imulFix ( g0 + imulFix ( g1, a0 ), g2 ), + imulFix ( b0 + imulFix ( b1, a0 ), b2 ) + ); +#else + dst[i] = fix_to_color ( r0 + imulFix ( r1, a0 ), + g0 + imulFix ( g1, a0 ), + b0 + imulFix ( b1, a0 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_one_minus_dst_alpha_one () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint a1, r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( a1, r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + a1 = FIX_POINT_ONE - a1; + dst[i] = fix_to_color ( imulFix ( imulFix ( r0, a1 ) + r1, r2 ), + imulFix ( imulFix ( g0, a1 ) + g1, g2 ), + imulFix ( imulFix ( b0, a1 ) + b1, b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r0, a1) + r0, + imulFix ( g0, a1) + g0, + imulFix ( b0, a1) + b0 + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( a1, r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + a1 = FIX_POINT_ONE - a1; + dst[i] = fix_to_color ( imulFix ( imulFix ( r0, a1 ) + r1, r2 ), + imulFix ( imulFix ( g0, a1 ) + g1, g2 ), + imulFix ( imulFix ( b0, a1 ) + b1, b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r0, a1) + r0, + imulFix ( g0, a1) + g0, + imulFix ( b0, a1) + b0 + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_src_alpha_one () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPointu a0, r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + if ( a0 > 0 ) + { + a0 >>= 8; + + color_to_fix ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix4_to_color ( a0, + clampfix_maxcolor ( imulFix (r0,a0 ) + r1), + clampfix_maxcolor ( imulFix (g0,a0 ) + g1), + clampfix_maxcolor ( imulFix (b0,a0 ) + b1) + ); + +/* + a0 >>= 8; + dst[i] = fix4_to_color ( a0, + imulFix ( imulFix ( r0, a0 ) + r1, r2 ), + imulFix ( imulFix ( g0, a0 ) + g1, g2 ), + imulFix ( imulFix ( b0, a0 ) + b1, b2 ) + ); +*/ +#else + dst[i] = fix4_to_color ( a0, + clampfix_maxcolor ( imulFix (r0,a0 ) + r1 ), + clampfix_maxcolor ( imulFix (g0,a0 ) + g1 ), + clampfix_maxcolor ( imulFix (b0,a0 ) + b1 ) + ); + +#endif + +#ifdef WRITE_W + //z[i] = line.w[0]; +#endif + } + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + { + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + if ( a0 > 0 ) + { + a0 >>= 8; + + color_to_fix ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix4_to_color ( a0, + clampfix_maxcolor ( imulFix ( imulFix (r0,a0 ) + r1, r2 ) ), + clampfix_maxcolor ( imulFix ( imulFix (g0,a0 ) + g1, g2 ) ), + clampfix_maxcolor ( imulFix ( imulFix (b0,a0 ) + b1, b2 ) ) + ); + +/* + a0 >>= 8; + dst[i] = fix4_to_color ( a0, + imulFix ( imulFix ( r0, a0 ) + r1, r2 ), + imulFix ( imulFix ( g0, a0 ) + g1, g2 ), + imulFix ( imulFix ( b0, a0 ) + b1, b2 ) + ); +*/ +#else + dst[i] = fix4_to_color ( a0, + clampfix_maxcolor ( imulFix (r0,a0 ) + r1 ), + clampfix_maxcolor ( imulFix (g0,a0 ) + g1 ), + clampfix_maxcolor ( imulFix (b0,a0 ) + b1 ) + ); + +#endif + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + } + } +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + + +/*! +*/ +void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint a1, r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( a1, r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + a1 = FIX_POINT_ONE - a1; + dst[i] = fix_to_color ( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), + imulFix ( imulFix ( g1, g0 + a1 ), g2 ), + imulFix ( imulFix ( b1, b0 + a1 ), b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r1, r0 + a1 ), + imulFix ( g1, g0 + a1 ), + imulFix ( b1, b0 + a1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( a1, r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + a1 = FIX_POINT_ONE - a1; + dst[i] = fix_to_color ( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), + imulFix ( imulFix ( g1, g0 + a1 ), g2 ), + imulFix ( imulFix ( b1, b0 + a1 ), b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r1, r0 + a1 ), + imulFix ( g1, g0 + a1 ), + imulFix ( b1, b0 + a1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_dst_color_zero () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( imulFix ( r0, r1 ), r2 ), + imulFix ( imulFix ( g0, g1 ), g2 ), + imulFix ( imulFix ( b0, b1 ), b2 ) ); +#else + dst[i] = fix_to_color ( imulFix ( r0, r1 ), + imulFix ( g0, g1 ), + imulFix ( b0, b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( imulFix ( r0, r1 ), r2 ), + imulFix ( imulFix ( g0, g1 ), g2 ), + imulFix ( imulFix ( b0, b1 ), b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r0, r1 ), + imulFix ( g0, g1 ), + imulFix ( b0, b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_dst_color_one () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), + clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) + ); + +#else + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), + clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), + clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) + ); + +#else + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), + clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) + ); + +#endif + + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_zero_one_minus_scr_color () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), + imulFix ( FIX_POINT_ONE - g0, g1 ), + imulFix ( FIX_POINT_ONE - b0, b1 ) + ); + +#else + dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), + imulFix ( FIX_POINT_ONE - g0, g1 ), + imulFix ( FIX_POINT_ONE - b0, b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), + imulFix ( FIX_POINT_ONE - g0, g1 ), + imulFix ( FIX_POINT_ONE - b0, b1 ) + ); + +#else + dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), + imulFix ( FIX_POINT_ONE - g0, g1 ), + imulFix ( FIX_POINT_ONE - b0, b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + + + void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { + if ( 0 == fragmentShader ) + return; + // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -334,8 +2037,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; - scan.c[0] = a->Color[0]; + scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; + scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -356,20 +2059,6 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -388,8 +2077,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; - scan.c[1] = a->Color[0]; + scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; + scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -424,8 +2113,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -457,8 +2146,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -472,7 +2161,7 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif // render a scanline - scanline_bilinear ( ); + (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -488,8 +2177,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -521,7 +2210,7 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 - scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; + scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; @@ -547,8 +2236,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; - scan.c[1] = b->Color[0]; + scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; + scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 @@ -584,8 +2273,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -617,8 +2306,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -632,7 +2321,7 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif // render a scanline - scanline_bilinear ( ); + (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -648,8 +2337,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -665,23 +2354,10 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } + } // end namespace video } // end namespace irr diff --git a/src/dep/src/irrlicht/CTRTextureDetailMap2.cpp b/src/dep/src/irrlicht/CTRTextureDetailMap2.cpp index 97f7dac..44da771 100644 --- a/src/dep/src/irrlicht/CTRTextureDetailMap2.cpp +++ b/src/dep/src/irrlicht/CTRTextureDetailMap2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -184,10 +184,10 @@ void CTRTextureDetailMap2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -216,16 +216,16 @@ void CTRTextureDetailMap2::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); - tx1 = f32_to_fixPoint ( line.t[1][0].x,inversew); - ty1 = f32_to_fixPoint ( line.t[1][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); + tx1 = tofix ( line.t[1][0].x,inversew); + ty1 = tofix ( line.t[1][0].y,inversew); #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); - tx1 = f32_to_fixPoint ( line.t[1][0].x ); - ty1 = f32_to_fixPoint ( line.t[1][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); + tx1 = tofix ( line.t[1][0].x ); + ty1 = tofix ( line.t[1][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); getSample_texture ( r1, g1, b1, &IT[1], tx1,ty1 ); @@ -275,14 +275,16 @@ void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b, { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -291,11 +293,11 @@ void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b, f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -335,20 +337,6 @@ void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b, f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -644,20 +632,6 @@ void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b, } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } } // end namespace video diff --git a/src/dep/src/irrlicht/CTRTextureFlat.cpp b/src/dep/src/irrlicht/CTRTextureFlat.cpp index f93216a..f09be28 100644 --- a/src/dep/src/irrlicht/CTRTextureFlat.cpp +++ b/src/dep/src/irrlicht/CTRTextureFlat.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRTextureFlatWire.cpp b/src/dep/src/irrlicht/CTRTextureFlatWire.cpp index d7b20ec..4186508 100644 --- a/src/dep/src/irrlicht/CTRTextureFlatWire.cpp +++ b/src/dep/src/irrlicht/CTRTextureFlatWire.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRTextureGouraud.cpp b/src/dep/src/irrlicht/CTRTextureGouraud.cpp index 24e7636..f12d077 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraud.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraud.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRTextureGouraud.h b/src/dep/src/irrlicht/CTRTextureGouraud.h index 715dc6a..6099a13 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraud.h +++ b/src/dep/src/irrlicht/CTRTextureGouraud.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRTextureGouraud2.cpp b/src/dep/src/irrlicht/CTRTextureGouraud2.cpp index e9d6765..bf5c477 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraud2.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraud2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -183,10 +183,10 @@ void CTRTextureGouraud2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -226,18 +226,18 @@ void CTRTextureGouraud2::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x, inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y, inversew); + tx0 = tofix ( line.t[0][0].x, inversew); + ty0 = tofix ( line.t[0][0].y, inversew); #ifdef IPOL_C0 - r1 = f32_to_fixPoint ( line.c[0][0].y ,inversew ); - g1 = f32_to_fixPoint ( line.c[0][0].z ,inversew ); - b1 = f32_to_fixPoint ( line.c[0][0].w ,inversew ); + r1 = tofix ( line.c[0][0].y ,inversew ); + g1 = tofix ( line.c[0][0].z ,inversew ); + b1 = tofix ( line.c[0][0].w ,inversew ); #endif #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #ifdef IPOL_C0 getTexel_plain2 ( r1, g1, b1, line.c[0][0] ); #endif @@ -287,28 +287,29 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -348,20 +349,6 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -657,20 +644,6 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } } // end namespace video diff --git a/src/dep/src/irrlicht/CTRTextureGouraudAdd.cpp b/src/dep/src/irrlicht/CTRTextureGouraudAdd.cpp index 2e845c5..9f92d71 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraudAdd.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraudAdd.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRTextureGouraudAdd2.cpp b/src/dep/src/irrlicht/CTRTextureGouraudAdd2.cpp index 78b72b0..60200fe 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraudAdd2.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraudAdd2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -183,10 +183,10 @@ void CTRTextureGouraudAdd2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -204,7 +204,6 @@ void CTRTextureGouraudAdd2::scanline_bilinear () tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; - tFixPoint r2, g2, b2; #endif @@ -219,13 +218,6 @@ void CTRTextureGouraudAdd2::scanline_bilinear () { -#ifdef WRITE_Z - z[i] = line.z[0]; -#endif -#ifdef WRITE_W - z[i] = line.w[0]; -#endif - #ifdef BURNINGVIDEO_RENDERER_FAST @@ -237,14 +229,14 @@ void CTRTextureGouraudAdd2::scanline_bilinear () dst[i] = PixelAdd32 ( dst[i], - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) ) + getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), + d + tofix ( line.t[0][0].y,inversew) ) ); #else dst[i] = PixelAdd32 ( dst[i], - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x), - d + f32_to_fixPoint ( line.t[0][0].y) ) + getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), + d + tofix ( line.t[0][0].y) ) ); #endif @@ -253,21 +245,27 @@ void CTRTextureGouraudAdd2::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); color_to_fix ( r1, g1, b1, dst[i] ); - r2 = clampfix_maxcolor ( r1 + r0 ); - g2 = clampfix_maxcolor ( g1 + g0 ); - b2 = clampfix_maxcolor ( b1 + b0 ); + dst[i] = fix_to_color ( clampfix_maxcolor ( r1 + r0 ), + clampfix_maxcolor ( g1 + g0 ), + clampfix_maxcolor ( b1 + b0 ) + ); +#endif - dst[i] = fix_to_color ( r2, g2, b2 ); +#ifdef WRITE_Z + z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; #endif } @@ -297,24 +295,26 @@ void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); - + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -354,20 +354,6 @@ void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { @@ -663,20 +649,6 @@ void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } diff --git a/src/dep/src/irrlicht/CTRTextureGouraudAddNoZ2.cpp b/src/dep/src/irrlicht/CTRTextureGouraudAddNoZ2.cpp index 3bd1516..e65c0b0 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraudAddNoZ2.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraudAddNoZ2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,9 +28,9 @@ #define SUBTEXEL #define INVERSE_W -//#define USE_ZBUFFER +#define USE_ZBUFFER #define IPOL_W -//#define CMP_W +#define CMP_W //#define WRITE_W //#define IPOL_C0 @@ -110,7 +110,7 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () { tVideoSample *dst; -#ifdef IPOL_Z +#ifdef USE_ZBUFFER fp24 *z; #endif @@ -183,10 +183,10 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; -#ifdef IPOL_Z - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -206,16 +206,19 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () { #ifdef CMP_Z if ( line.z[0] < z[i] ) +#endif +#ifdef CMP_W + if ( line.w[0] >= z[i] ) #endif { #ifdef IPOL_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); @@ -231,6 +234,9 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () #ifdef WRITE_Z z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; #endif } @@ -257,14 +263,16 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -273,11 +281,11 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -317,20 +325,6 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef IPOL_Z - lockedDepthBuffer = DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -626,20 +620,6 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex } } - RenderTarget->unlock(); - -#ifdef IPOL_Z - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } } // end namespace video diff --git a/src/dep/src/irrlicht/CTRTextureGouraudAlpha.cpp b/src/dep/src/irrlicht/CTRTextureGouraudAlpha.cpp index 240be1e..7cdb4de 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraudAlpha.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraudAlpha.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -33,7 +33,7 @@ #define CMP_W #define WRITE_W -//#define IPOL_C0 +#define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 @@ -147,7 +147,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC; + sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; @@ -172,7 +172,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 - slopeC = (line.c[1] - line.c[0]) * invDeltaX; + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; @@ -190,7 +190,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 - line.c[0] += slopeC * subPixel; + line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; @@ -200,10 +200,10 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -215,10 +215,14 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () u32 dIndex = ( line.y & 3 ) << 2; #else - tFixPointu a0; - tFixPointu r0, g0, b0; + tFixPoint a0; + tFixPoint r0, g0, b0; #endif +#ifdef IPOL_C0 + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; +#endif for ( s32 i = 0; i <= dx; ++i ) { @@ -239,20 +243,20 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () inversew = fix_inverse32 ( line.w[0] ); - u32 argb = getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) + u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), + d + tofix ( line.t[0][0].y,inversew) ); #else - u32 argb = getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x), - d + f32_to_fixPoint ( line.t[0][0].y) + u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), + d + tofix ( line.t[0][0].y) ); #endif const u32 alpha = ( argb >> 24 ); - if ( alpha >= AlphaRef ) + if ( alpha > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -267,15 +271,21 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () #else +#ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - - getSample_texture ( a0, r0, g0, b0, + getSample_texture ( (tFixPointu&) a0, (tFixPointu&) r0, (tFixPointu&)g0, (tFixPointu&)b0, &IT[0], - f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) + tofix ( line.t[0][0].x,inversew), + tofix ( line.t[0][0].y,inversew) ); - - if ( a0 >= AlphaRef ) +#else + getSample_texture ( (tFixPointu&) a0, (tFixPointu&) r0, (tFixPointu&)g0, (tFixPointu&)b0, + &IT[0], + tofix ( line.t[0][0].x), + tofix ( line.t[0][0].y) + ); +#endif + if ( (tFixPointu) a0 > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -284,10 +294,40 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () z[i] = line.w[0]; #endif +#ifdef INVERSE_W + getSample_color ( r2, g2, b2, line.c[0][0], inversew ); +#else + getSample_color ( r2, g2, b2, line.c[0][0] ); +#endif + r0 = imulFix ( r0, r2 ); + g0 = imulFix ( g0, g2 ); + b0 = imulFix ( b0, b2 ); + + color_to_fix ( r1, g1, b1, dst[i] ); + + a0 >>= 8; + + r2 = r1 + imulFix ( a0, r0 - r1 ); + g2 = g1 + imulFix ( a0, g0 - g1 ); + b2 = b1 + imulFix ( a0, b0 - b1 ); + dst[i] = fix4_to_color ( a0, r2, g2, b2 ); + +/* dst[i] = PixelBlend32 ( dst[i], fix_to_color ( r0,g0, b0 ), fixPointu_to_u32 ( a0 ) ); +*/ +/* + getSample_color ( r2, g2, b2, line.c[0][0], inversew * COLOR_MAX ); + color_to_fix ( r1, g1, b1, dst[i] ); + + r2 = r0 + imulFix ( a0, r1 - r0 ); + g2 = g0 + imulFix ( a0, g1 - g0 ); + b2 = b0 + imulFix ( a0, b1 - b0 ); + dst[i] = fix_to_color ( r2, g2, b2 ); +*/ + } #endif @@ -300,7 +340,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () line.w[0] += slopeW; #endif #ifdef IPOL_C0 - line.c[0] += slopeC; + line.c[0][0] += slopeC[0]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; @@ -316,28 +356,29 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -355,8 +396,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; - scan.c[0] = a->Color[0]; + scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; + scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -377,20 +418,6 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -409,8 +436,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; - scan.c[1] = a->Color[0]; + scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; + scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -445,8 +472,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -478,8 +505,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -509,8 +536,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -542,7 +569,7 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 - scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; + scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; @@ -568,8 +595,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; - scan.c[1] = b->Color[0]; + scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; + scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 @@ -605,8 +632,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -638,8 +665,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -669,8 +696,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -686,20 +713,6 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } diff --git a/src/dep/src/irrlicht/CTRTextureGouraudAlphaNoZ.cpp b/src/dep/src/irrlicht/CTRTextureGouraudAlphaNoZ.cpp index de71bf6..ddda90e 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraudAlphaNoZ.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraudAlphaNoZ.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -33,7 +33,7 @@ #define CMP_W //#define WRITE_W -//#define IPOL_C0 +#define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 @@ -147,7 +147,7 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC; + sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; @@ -172,7 +172,7 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 - slopeC = (line.c[1] - line.c[0]) * invDeltaX; + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; @@ -190,7 +190,7 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 - line.c[0] += slopeC * subPixel; + line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; @@ -200,10 +200,10 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -215,10 +215,14 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () u32 dIndex = ( line.y & 3 ) << 2; #else - tFixPointu a0; - tFixPointu r0, g0, b0; + tFixPoint a0; + tFixPoint r0, g0, b0; #endif +#ifdef IPOL_C0 + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; +#endif for ( s32 i = 0; i <= dx; ++i ) { @@ -239,20 +243,20 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () inversew = fix_inverse32 ( line.w[0] ); - u32 argb = getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) + u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), + d + tofix ( line.t[0][0].y,inversew) ); #else - u32 argb = getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x), - d + f32_to_fixPoint ( line.t[0][0].y) + u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), + d + tofix ( line.t[0][0].y) ); #endif const u32 alpha = ( argb >> 24 ); - if ( alpha >= AlphaRef ) + if ( alpha > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -267,15 +271,21 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #else +#ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - - getSample_texture ( a0, r0, g0, b0, + getSample_texture ( (tFixPointu&) a0, (tFixPointu&) r0, (tFixPointu&)g0, (tFixPointu&)b0, &IT[0], - f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) + tofix ( line.t[0][0].x,inversew), + tofix ( line.t[0][0].y,inversew) ); - - if ( a0 >= AlphaRef ) +#else + getSample_texture ( (tFixPointu&) a0, (tFixPointu&) r0, (tFixPointu&)g0, (tFixPointu&)b0, + &IT[0], + tofix ( line.t[0][0].x), + tofix ( line.t[0][0].y) + ); +#endif + if ( (tFixPointu) a0 > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -284,10 +294,40 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () z[i] = line.w[0]; #endif +#ifdef INVERSE_W + getSample_color ( r2, g2, b2, line.c[0][0], inversew ); +#else + getSample_color ( r2, g2, b2, line.c[0][0] ); +#endif + r0 = imulFix ( r0, r2 ); + g0 = imulFix ( g0, g2 ); + b0 = imulFix ( b0, b2 ); + + color_to_fix ( r1, g1, b1, dst[i] ); + + a0 >>= 8; + + r2 = r1 + imulFix ( a0, r0 - r1 ); + g2 = g1 + imulFix ( a0, g0 - g1 ); + b2 = b1 + imulFix ( a0, b0 - b1 ); + dst[i] = fix4_to_color ( a0, r2, g2, b2 ); + +/* dst[i] = PixelBlend32 ( dst[i], fix_to_color ( r0,g0, b0 ), fixPointu_to_u32 ( a0 ) ); +*/ +/* + getSample_color ( r2, g2, b2, line.c[0][0], inversew * COLOR_MAX ); + color_to_fix ( r1, g1, b1, dst[i] ); + + r2 = r0 + imulFix ( a0, r1 - r0 ); + g2 = g0 + imulFix ( a0, g1 - g0 ); + b2 = b0 + imulFix ( a0, b1 - b0 ); + dst[i] = fix_to_color ( r2, g2, b2 ); +*/ + } #endif @@ -300,7 +340,7 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () line.w[0] += slopeW; #endif #ifdef IPOL_C0 - line.c[0] += slopeC; + line.c[0][0] += slopeC[0]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; @@ -316,28 +356,29 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -355,8 +396,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif #ifdef IPOL_C0 - scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; - scan.c[0] = a->Color[0]; + scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; + scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -377,20 +418,6 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -409,8 +436,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif #ifdef IPOL_C0 - scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; - scan.c[1] = a->Color[0]; + scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; + scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -445,8 +472,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -478,8 +505,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -509,8 +536,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -542,7 +569,7 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 - scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; + scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; @@ -568,8 +595,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif #ifdef IPOL_C0 - scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; - scan.c[1] = b->Color[0]; + scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; + scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 @@ -605,8 +632,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -638,8 +665,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -669,8 +696,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -686,22 +713,10 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif } + } // end namespace video } // end namespace irr @@ -712,6 +727,7 @@ namespace irr namespace video { + //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudAlphaNoZ(IDepthBuffer* zbuffer) { diff --git a/src/dep/src/irrlicht/CTRTextureGouraudNoZ.cpp b/src/dep/src/irrlicht/CTRTextureGouraudNoZ.cpp index fa052f9..b0290a8 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraudNoZ.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraudNoZ.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRTextureGouraudNoZ2.cpp b/src/dep/src/irrlicht/CTRTextureGouraudNoZ2.cpp index 622e83c..593bbf4 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraudNoZ2.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraudNoZ2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -188,10 +188,10 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -216,11 +216,11 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #endif dst[i] = getTexel_plain ( &IT[0], tx0, ty0 ); @@ -259,28 +259,29 @@ void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -320,20 +321,6 @@ void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -629,20 +616,6 @@ void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } diff --git a/src/dep/src/irrlicht/CTRTextureGouraudVertexAlpha2.cpp b/src/dep/src/irrlicht/CTRTextureGouraudVertexAlpha2.cpp index 85ea2ee..eb65f2e 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraudVertexAlpha2.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraudVertexAlpha2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -182,10 +182,10 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -228,8 +228,8 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) dst[i] = PixelAdd32 ( dst[i], - getTexel_plain ( &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) ) + getTexel_plain ( &IT[0], tofix ( line.t[0][0].x,inversew), + tofix ( line.t[0][0].y,inversew) ) ); #else @@ -237,19 +237,19 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); #ifdef IPOL_C0 - a3 = f32_to_fixPoint ( line.c[0][0].y,inversew ); + a3 = tofix ( line.c[0][0].y,inversew ); #endif #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #ifdef IPOL_C0 - a3 = f32_to_fixPoint ( line.c[0][0].y ); + a3 = tofix ( line.c[0][0].y ); #endif @@ -302,28 +302,29 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -363,20 +364,6 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -672,20 +659,6 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } diff --git a/src/dep/src/irrlicht/CTRTextureGouraudWire.cpp b/src/dep/src/irrlicht/CTRTextureGouraudWire.cpp index 75cdbd3..d44cd41 100644 --- a/src/dep/src/irrlicht/CTRTextureGouraudWire.cpp +++ b/src/dep/src/irrlicht/CTRTextureGouraudWire.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTRTextureLightMap2_Add.cpp b/src/dep/src/irrlicht/CTRTextureLightMap2_Add.cpp index 88dea23..8f92890 100644 --- a/src/dep/src/irrlicht/CTRTextureLightMap2_Add.cpp +++ b/src/dep/src/irrlicht/CTRTextureLightMap2_Add.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -183,10 +183,10 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -229,19 +229,19 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; dst[i] = PixelAdd32 ( - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) ), - getTexel_plain ( &IT[1], d + f32_to_fixPoint ( line.t[1][0].x,inversew), - d + f32_to_fixPoint ( line.t[1][0].y,inversew) ) + getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), + d + tofix ( line.t[0][0].y,inversew) ), + getTexel_plain ( &IT[1], d + tofix ( line.t[1][0].x,inversew), + d + tofix ( line.t[1][0].y,inversew) ) ); #else const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; dst[i] = PixelAdd32 ( - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x), - d + f32_to_fixPoint ( line.t[0][0].y) ), - getTexel_plain ( &IT[1], d + f32_to_fixPoint ( line.t[1][0].x), - d + f32_to_fixPoint ( line.t[1][0].y) ) + getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), + d + tofix ( line.t[0][0].y) ), + getTexel_plain ( &IT[1], d + tofix ( line.t[1][0].x), + d + tofix ( line.t[1][0].y) ) ); #endif @@ -249,8 +249,8 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () #else const f32 inversew = fix_inverse32 ( line.w[0] ); - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[0][1].x,inversew), f32_to_fixPoint ( line.t[0][1].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[0][1].x,inversew), tofix ( line.t[0][1].y,inversew) ); dst[i] = fix_to_color ( clampfix_maxcolor ( r0 + r1 ), clampfix_maxcolor ( g0 + g1 ), @@ -283,28 +283,29 @@ void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -344,24 +345,6 @@ void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex f32 subPixel; #endif - // query access to TexMaps - - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - - - // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { @@ -657,19 +640,6 @@ void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif } diff --git a/src/dep/src/irrlicht/CTRTextureLightMap2_M1.cpp b/src/dep/src/irrlicht/CTRTextureLightMap2_M1.cpp index d1cf9ed..80d6875 100644 --- a/src/dep/src/irrlicht/CTRTextureLightMap2_M1.cpp +++ b/src/dep/src/irrlicht/CTRTextureLightMap2_M1.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -126,7 +126,7 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; @@ -172,7 +172,7 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () line.z[0] = a; line.z[1] = b; #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; @@ -186,6 +186,9 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; + tFixPoint r0, g0, b0; + tFixPoint r1, g1, b1; + #else // tFixPoint r0, g0, b0; @@ -217,26 +220,18 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; - dst[i] = PixelMul32 ( - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) ), - getTexel_plain ( &IT[1], d + f32_to_fixPoint ( line.t[1][0].x,inversew), - d + f32_to_fixPoint ( line.t[1][0].y,inversew) ) - ); - - + getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ); #else + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); - - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); - - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) ), - clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) ), - clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) ) - ); #endif + dst[i] = fix_to_color ( imulFix_tex1 ( r0, r1 ), + imulFix_tex1 ( g0, g1 ), + imulFix_tex1 ( b0, b1 ) + ); } #ifdef IPOL_W @@ -252,36 +247,35 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () - - void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { sScanConvertData scan; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -321,23 +315,6 @@ void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex * f32 subPixel; #endif - // query access to TexMaps - - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - - // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { @@ -634,20 +611,6 @@ void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex * } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } @@ -661,6 +624,8 @@ namespace irr namespace video { + + //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureLightMap2_M1(IDepthBuffer* zbuffer) { @@ -676,3 +641,4 @@ IBurningShader* createTriangleRendererTextureLightMap2_M1(IDepthBuffer* zbuffer) } // end namespace irr + diff --git a/src/dep/src/irrlicht/CTRTextureLightMap2_M2.cpp b/src/dep/src/irrlicht/CTRTextureLightMap2_M2.cpp index b32ea31..726f7d2 100644 --- a/src/dep/src/irrlicht/CTRTextureLightMap2_M2.cpp +++ b/src/dep/src/irrlicht/CTRTextureLightMap2_M2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -126,7 +126,7 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; @@ -172,7 +172,7 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () line.z[0] = a; line.z[1] = b; #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; @@ -220,11 +220,11 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; - getSample_texture ( r0, g0, b0, &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), d + f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], d + f32_to_fixPoint ( line.t[1][0].x,inversew), d + f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ); #else - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); #endif @@ -253,28 +253,29 @@ void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex * // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -314,23 +315,6 @@ void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex * f32 subPixel; #endif - // query access to TexMaps - - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - - // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { @@ -627,20 +611,6 @@ void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex * } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } diff --git a/src/dep/src/irrlicht/CTRTextureLightMap2_M4.cpp b/src/dep/src/irrlicht/CTRTextureLightMap2_M4.cpp index e096ec1..0e02f1a 100644 --- a/src/dep/src/irrlicht/CTRTextureLightMap2_M4.cpp +++ b/src/dep/src/irrlicht/CTRTextureLightMap2_M4.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -130,8 +130,8 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_mag () // search z-buffer for first not occulled pixel i = ( line.y * RenderTarget->getDimension().Width ) + xStart; - z = lockedDepthBuffer + i; - dst = lockedSurface + i; + z = (fp24*) DepthBuffer->lock() + i; + dst = (tVideoSample*)RenderTarget->lock() + i; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; @@ -224,11 +224,11 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_mag () const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; - getSample_texture ( r0, g0, b0, &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), d + f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], d + f32_to_fixPoint ( line.t[1][0].x,inversew), d + f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ); #else - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); #endif @@ -274,7 +274,7 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; @@ -320,7 +320,7 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () line.z[0] = a; line.z[1] = b; #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; @@ -354,8 +354,8 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () #endif - getTexel_fix ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getTexel_fix ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getTexel_fix ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getTexel_fix ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), @@ -458,10 +458,10 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -492,22 +492,22 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); - tx1 = f32_to_fixPoint ( line.t[1][0].x,inversew); - ty1 = f32_to_fixPoint ( line.t[1][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); + tx1 = tofix ( line.t[1][0].x,inversew); + ty1 = tofix ( line.t[1][0].y,inversew); #ifdef IPOL_C0 - r3 = f32_to_fixPoint ( line.c[0].y ,inversew ); - g3 = f32_to_fixPoint ( line.c[0].z ,inversew ); - b3 = f32_to_fixPoint ( line.c[0].w ,inversew ); + r3 = tofix ( line.c[0].y ,inversew ); + g3 = tofix ( line.c[0].z ,inversew ); + b3 = tofix ( line.c[0].w ,inversew ); #endif #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); - tx1 = f32_to_fixPoint ( line.t[1][0].x ); - ty1 = f32_to_fixPoint ( line.t[1][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); + tx1 = tofix ( line.t[1][0].x ); + ty1 = tofix ( line.t[1][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); @@ -581,28 +581,29 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVert // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -642,23 +643,6 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVert f32 subPixel; #endif - // query access to TexMaps - - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - - // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { @@ -955,20 +939,6 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVert } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } void CTRTextureLightMap2_M4::drawTriangle_Mag ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) @@ -984,28 +954,29 @@ void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex * // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -1045,22 +1016,6 @@ void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex * f32 subPixel; #endif - // query access to TexMaps - - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) @@ -1358,20 +1313,6 @@ void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex * } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } } // end namespace video diff --git a/src/dep/src/irrlicht/CTRTextureLightMapGouraud2_M4.cpp b/src/dep/src/irrlicht/CTRTextureLightMapGouraud2_M4.cpp index 421e31b..b4bab59 100644 --- a/src/dep/src/irrlicht/CTRTextureLightMapGouraud2_M4.cpp +++ b/src/dep/src/irrlicht/CTRTextureLightMapGouraud2_M4.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -183,10 +183,10 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -217,22 +217,28 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); - tx1 = f32_to_fixPoint ( line.t[1][0].x,inversew); - ty1 = f32_to_fixPoint ( line.t[1][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); + tx1 = tofix ( line.t[1][0].x,inversew); + ty1 = tofix ( line.t[1][0].y,inversew); #ifdef IPOL_C0 - r3 = f32_to_fixPoint ( line.c[0][0].y ,inversew ); - g3 = f32_to_fixPoint ( line.c[0][0].z ,inversew ); - b3 = f32_to_fixPoint ( line.c[0][0].w ,inversew ); + r3 = tofix ( line.c[0][0].y ,inversew ); + g3 = tofix ( line.c[0][0].z ,inversew ); + b3 = tofix ( line.c[0][0].w ,inversew ); #endif #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); - tx1 = f32_to_fixPoint ( line.t[1][0].x ); - ty1 = f32_to_fixPoint ( line.t[1][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); + tx1 = tofix ( line.t[1][0].x ); + ty1 = tofix ( line.t[1][0].y ); + +#ifdef IPOL_C0 + r3 = tofix ( line.c[0][0].y ); + g3 = tofix ( line.c[0][0].z ); + b3 = tofix ( line.c[0][0].w ); +#endif #endif getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); @@ -291,29 +297,29 @@ void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); - + scan.invDeltaY[0] = core::reciprocal( ca ); + scan.invDeltaY[1] = core::reciprocal( ba ); + scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_0 ( scan.invDeltaY[0] ) ) return; - // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; - temp[1] = a->Pos.y - c->Pos.y; + temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; - temp[3] = b->Pos.y - a->Pos.y; + temp[3] = ba; - scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge @@ -353,23 +359,6 @@ void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex f32 subPixel; #endif - // query access to TexMaps - - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - -#ifdef IPOL_T0 - IT[0].data = (tVideoSample*)IT[0].Texture->lock(); -#endif - -#ifdef IPOL_T1 - IT[1].data = (tVideoSample*)IT[1].Texture->lock(); -#endif - - // rasterize upper sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[1] ) @@ -669,20 +658,6 @@ void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex } } - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - -#ifdef IPOL_T0 - IT[0].Texture->unlock(); -#endif - -#ifdef IPOL_T1 - IT[1].Texture->unlock(); -#endif - } diff --git a/src/dep/src/irrlicht/CTRTextureWire2.cpp b/src/dep/src/irrlicht/CTRTextureWire2.cpp index 2309143..22f0ae0 100644 --- a/src/dep/src/irrlicht/CTRTextureWire2.cpp +++ b/src/dep/src/irrlicht/CTRTextureWire2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -169,9 +169,9 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b ) const if ( 0 == dx ) return; - dst = (tVideoSample*) ( (u8*) lockedSurface + ( aposy * pitch0 ) + (aposx << VIDEO_SAMPLE_GRANULARITY ) ); + dst = (tVideoSample*) ( (u8*) (tVideoSample*)RenderTarget->lock() + ( aposy * pitch0 ) + (aposx << VIDEO_SAMPLE_GRANULARITY ) ); #ifdef USE_ZBUFFER - z = (fp24*) ( (u8*) lockedDepthBuffer + ( aposy * pitch1 ) + (aposx << 2 ) ); + z = (fp24*) ( (u8*) (fp24*) DepthBuffer->lock() + ( aposy * pitch1 ) + (aposx << 2 ) ); #endif c = dx << 1; @@ -247,26 +247,13 @@ void CTRTextureWire2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); - - - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); renderLine ( a, b ); renderLine ( b, c ); renderLine ( a, c ); - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif - } @@ -278,18 +265,7 @@ void CTRTextureWire2::drawLine ( const s4DVertex *a,const s4DVertex *b) // sort on height, y if ( a->Pos.y > b->Pos.y ) swapVertexPointer(&a, &b); - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - renderLine ( a, b ); - RenderTarget->unlock(); - -#ifdef USE_ZBUFFER - DepthBuffer->unlock(); -#endif } diff --git a/src/dep/src/irrlicht/CTarReader.cpp b/src/dep/src/irrlicht/CTarReader.cpp new file mode 100644 index 0000000..e22ab3d --- /dev/null +++ b/src/dep/src/irrlicht/CTarReader.cpp @@ -0,0 +1,258 @@ +// Copyright (C) 2009-2010 Gaz Davidson +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CTarReader.h" + +#ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ + +#include "CFileList.h" +#include "CLimitReadFile.h" +#include "os.h" +#include "coreutil.h" +#if !defined(_IRR_WINDOWS_CE_PLATFORM_) +#include "errno.h" +#endif + +namespace irr +{ +namespace io +{ + +//! Constructor +CArchiveLoaderTAR::CArchiveLoaderTAR(io::IFileSystem* fs) +: FileSystem(fs) +{ + #ifdef _DEBUG + setDebugName("CArchiveLoaderTAR"); + #endif +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderTAR::isALoadableFileFormat(const io::path& filename) const +{ + return core::hasFileExtension(filename, "tar"); +} + +//! Check to see if the loader can create archives of this type. +bool CArchiveLoaderTAR::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const +{ + return fileType == EFAT_TAR; +} + +//! Creates an archive from the filename +/** \param file File handle to check. +\return Pointer to newly created archive, or 0 upon error. */ +IFileArchive* CArchiveLoaderTAR::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + io::IReadFile* file = FileSystem->createAndOpenFile(filename); + + if (file) + { + archive = createArchive(file, ignoreCase, ignorePaths); + file->drop(); + } + + return archive; +} + + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderTAR::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + if (file) + { + file->seek(0); + archive = new CTarReader(file, ignoreCase, ignorePaths); + } + return archive; +} + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderTAR::isALoadableFileFormat(io::IReadFile* file) const +{ + // TAR files consist of blocks of 512 bytes + // if it isn't a multiple of 512 then it's not a TAR file. + if (file->getSize() % 512) + return false; + + file->seek(0); + + // read header of first file + STarHeader fHead; + file->read(&fHead, sizeof(STarHeader)); + + u32 checksum = 0; + sscanf(fHead.Checksum, "%o", &checksum); + + // verify checksum + + // some old TAR writers assume that chars are signed, others assume unsigned + // USTAR archives have a longer header, old TAR archives end after linkname + + u32 checksum1=0; + s32 checksum2=0; + + // remember to blank the checksum field! + memset(fHead.Checksum, ' ', 8); + + // old header + for (u8* p = (u8*)(&fHead); p < (u8*)(&fHead.Magic[0]); ++p) + { + checksum1 += *p; + checksum2 += c8(*p); + } + + if (!strncmp(fHead.Magic, "ustar", 5)) + { + for (u8* p = (u8*)(&fHead.Magic[0]); p < (u8*)(&fHead) + sizeof(fHead); ++p) + { + checksum1 += *p; + checksum2 += c8(*p); + } + } + return checksum1 == checksum || checksum2 == (s32)checksum; +} + +/* + TAR Archive +*/ +CTarReader::CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths) + : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file) +{ + #ifdef _DEBUG + setDebugName("CTarReader"); + #endif + + if (File) + { + File->grab(); + + // fill the file list + populateFileList(); + + sort(); + } +} + + +CTarReader::~CTarReader() +{ + if (File) + File->drop(); +} + +const IFileList* CTarReader::getFileList() const +{ + return this; +} + + +u32 CTarReader::populateFileList() +{ + STarHeader fHead; + Files.clear(); + + u32 pos = 0; + while ( s32(pos + sizeof(STarHeader)) < File->getSize()) + { + // seek to next file header + File->seek(pos); + + // read the header + File->read(&fHead, sizeof(fHead)); + + // only add standard files for now + if (fHead.Link == ETLI_REGULAR_FILE || ETLI_REGULAR_FILE_OLD) + { + io::path fullPath = ""; + fullPath.reserve(255); + + // USTAR archives have a filename prefix + // may not be null terminated, copy carefully! + if (!strncmp(fHead.Magic, "ustar", 5)) + { + c8* np = fHead.FileNamePrefix; + while(*np && (np - fHead.FileNamePrefix) < 155) + fullPath.append(*np); + np++; + } + + // append the file name + c8* np = fHead.FileName; + while(*np && (np - fHead.FileName) < 100) + { + fullPath.append(*np); + np++; + } + + // get size + core::stringc sSize = ""; + sSize.reserve(12); + np = fHead.Size; + while(*np && (np - fHead.Size) < 12) + { + sSize.append(*np); + np++; + } + + u32 size = strtoul(sSize.c_str(), NULL, 8); +#if !defined(_IRR_WINDOWS_CE_PLATFORM_) + if (errno == ERANGE) + os::Printer::log("File too large", fullPath, ELL_WARNING); +#endif + + // save start position + u32 offset = pos + 512; + + // move to next file header block + pos = offset + (size / 512) * 512 + ((size % 512) ? 512 : 0); + + // add file to list + addItem(fullPath, size, false, Offsets.size()); + Offsets.push_back(offset); + } + else + { + // todo: ETLI_DIRECTORY, ETLI_LINK_TO_ARCHIVED_FILE + + // move to next block + pos += 512; + } + + } + + return Files.size(); +} + +//! opens a file by file name +IReadFile* CTarReader::createAndOpenFile(const io::path& filename) +{ + const s32 index = findFile(filename, false); + + if (index != -1) + return createAndOpenFile(index); + + return 0; +} + +//! opens a file by index +IReadFile* CTarReader::createAndOpenFile(u32 index) +{ + if (index < Files.size()) + return createLimitReadFile(Files[index].FullName, File, Offsets[Files[index].ID], Files[index].Size); + else + return 0; +} + +} // end namespace io +} // end namespace irr + +#endif // __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ diff --git a/src/dep/src/irrlicht/CTarReader.h b/src/dep/src/irrlicht/CTarReader.h new file mode 100644 index 0000000..a0ba182 --- /dev/null +++ b/src/dep/src/irrlicht/CTarReader.h @@ -0,0 +1,148 @@ +// Copyright (C) 2009-2010 Gaz Davidson +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_TAR_READER_H_INCLUDED__ +#define __C_TAR_READER_H_INCLUDED__ + +#include "IrrCompileConfig.h" + +#ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ + +#include "IReferenceCounted.h" +#include "IReadFile.h" +#include "irrArray.h" +#include "irrString.h" +#include "IFileSystem.h" +#include "CFileList.h" + +namespace irr +{ +namespace io +{ + +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( push, packing ) +# pragma pack( 1 ) +# define PACK_STRUCT +#elif defined( __GNUC__ ) +# define PACK_STRUCT __attribute__((packed)) +#else +# error compiler not supported +#endif + + enum E_TAR_LINK_INDICATOR + { + ETLI_REGULAR_FILE_OLD = 0 , + ETLI_REGULAR_FILE = '0', + ETLI_LINK_TO_ARCHIVED_FILE = '1', // Hard link + ETLI_SYMBOLIC_LINK = '2', + ETLI_CHAR_SPECIAL_DEVICE = '3', + ETLI_BLOCK_SPECIAL_DEVICE = '4', + ETLI_DIRECTORY = '5', + ETLI_FIFO_SPECIAL_FILE = '6', + ETLI_CONTIGUOUS_FILE = '7' + }; + + struct STarHeader + { + c8 FileName[100]; + c8 FileMode[8]; + c8 UserID[8]; + c8 GroupID[8]; + c8 Size[12]; + c8 ModifiedTime[12]; + c8 Checksum[8]; + c8 Link; + c8 LinkName[100]; + c8 Magic[6]; + c8 USTARVersion[2]; + c8 UserName[32]; + c8 GroupName[32]; + c8 DeviceMajor[8]; + c8 DeviceMinor[8]; + c8 FileNamePrefix[155]; + } PACK_STRUCT; + + +// Default alignment +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( pop, packing ) +#endif + +#undef PACK_STRUCT + + //! Archiveloader capable of loading ZIP Archives + class CArchiveLoaderTAR : public IArchiveLoader + { + public: + + //! Constructor + CArchiveLoaderTAR(io::IFileSystem* fs); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".tar") + virtual bool isALoadableFileFormat(const io::path& filename) const; + + //! Check if the file might be loaded by this class + /** Check might look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const; + + //! Check to see if the loader can create archives of this type. + /** Check based on the archive type. + \param fileType The archive type to check. + \return True if the archile loader supports this type, false if not */ + virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const; + + //! Creates an archive from the filename + /** \param file File handle to check. + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const; + + //! creates/loads an archive from the file. + //! \return Pointer to the created archive. Returns 0 if loading failed. + virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; + + private: + io::IFileSystem* FileSystem; + }; + + + + class CTarReader : public virtual IFileArchive, virtual CFileList + { + public: + + CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths); + + virtual ~CTarReader(); + + //! opens a file by file name + virtual IReadFile* createAndOpenFile(const io::path& filename); + + //! opens a file by index + virtual IReadFile* createAndOpenFile(u32 index); + + //! returns the list of files + virtual const IFileList* getFileList() const; + + //! get the class Type + virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_TAR; } + + private: + + u32 populateFileList(); + + IReadFile* File; + + //! Contains offsets of the files from the start of the archive file + core::array Offsets; + }; + +} // end namespace io +} // end namespace irr + +#endif // __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ +#endif // __C_TAR_READER_H_INCLUDED__ diff --git a/src/dep/src/irrlicht/CTerrainSceneNode.cpp b/src/dep/src/irrlicht/CTerrainSceneNode.cpp index 537b1ed..af9868c 100644 --- a/src/dep/src/irrlicht/CTerrainSceneNode.cpp +++ b/src/dep/src/irrlicht/CTerrainSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,7 +12,6 @@ #include "IVideoDriver.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" -#include "SMeshBufferLightMap.h" #include "SViewFrustum.h" #include "irrMath.h" #include "os.h" @@ -21,6 +20,8 @@ #include "IReadFile.h" #include "ITextSceneNode.h" #include "IAnimatedMesh.h" +#include "SMesh.h" +#include "CDynamicMeshBuffer.h" namespace irr { @@ -39,6 +40,7 @@ namespace scene OverrideDistanceThreshold(false), UseDefaultRotationPivot(true), ForceRecalculation(false), OldCameraPosition(core::vector3df(-99999.9f, -99999.9f, -99999.9f)), OldCameraRotation(core::vector3df(-99999.9f, -99999.9f, -99999.9f)), + OldCameraUp(core::vector3df(-99999.9f, -99999.9f, -99999.9f)), CameraMovementDelta(10.0f), CameraRotationDelta(1.0f),CameraFOVDelta(0.1f), TCoordScale1(1.0f), TCoordScale2(1.0f), FileSystem(fs) { @@ -46,12 +48,15 @@ namespace scene setDebugName("CTerrainSceneNode"); #endif + Mesh = new SMesh(); RenderBuffer = new CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); + RenderBuffer->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX); + RenderBuffer->setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX); if (FileSystem) FileSystem->grab(); - setAutomaticCulling( scene::EAC_OFF ); + setAutomaticCulling(scene::EAC_OFF); } @@ -63,6 +68,9 @@ namespace scene if (FileSystem) FileSystem->drop(); + if (Mesh) + Mesh->drop(); + if (RenderBuffer) RenderBuffer->drop(); } @@ -72,10 +80,10 @@ namespace scene bool CTerrainSceneNode::loadHeightMap(io::IReadFile* file, video::SColor vertexColor, s32 smoothFactor) { - if( !file ) + if (!file) return false; - Mesh.MeshBuffers.clear(); + Mesh->MeshBuffers.clear(); const u32 startTime = os::Timer::getRealTime(); video::IImage* heightMap = SceneManager->getVideoDriver()->createImageFromFile(file); @@ -90,34 +98,34 @@ namespace scene // Get the dimension of the heightmap data TerrainData.Size = heightMap->getDimension().Width; - switch( TerrainData.PatchSize ) + switch (TerrainData.PatchSize) { case ETPS_9: - if( TerrainData.MaxLOD > 3 ) + if (TerrainData.MaxLOD > 3) { TerrainData.MaxLOD = 3; } break; case ETPS_17: - if( TerrainData.MaxLOD > 4 ) + if (TerrainData.MaxLOD > 4) { TerrainData.MaxLOD = 4; } break; case ETPS_33: - if( TerrainData.MaxLOD > 5 ) + if (TerrainData.MaxLOD > 5) { TerrainData.MaxLOD = 5; } break; case ETPS_65: - if( TerrainData.MaxLOD > 6 ) + if (TerrainData.MaxLOD > 6) { TerrainData.MaxLOD = 6; } break; case ETPS_129: - if( TerrainData.MaxLOD > 7 ) + if (TerrainData.MaxLOD > 7) { TerrainData.MaxLOD = 7; } @@ -126,12 +134,10 @@ namespace scene // --- Generate vertex data from heightmap ---- // resize the vertex array for the mesh buffer one time (makes loading faster) - //SMeshBufferLightMap* mb = new SMeshBufferLightMap(); - 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); @@ -152,17 +158,17 @@ namespace scene s32 index = 0; float fx=0.f; float fx2=0.f; - for( s32 x = 0; x < TerrainData.Size; ++x ) + for (s32 x = 0; x < TerrainData.Size; ++x) { float fz=0.f; float fz2=0.f; - for( s32 z = 0; z < TerrainData.Size; ++z ) + for (s32 z = 0; z < TerrainData.Size; ++z) { video::S3DVertex2TCoords& vertex= static_cast(mb->getVertexBuffer().pointer())[index++]; vertex.Normal.set(0.0f, 1.0f, 0.0f); vertex.Color = vertexColor; vertex.Pos.X = fx; - vertex.Pos.Y = (f32) heightMap->getPixel(TerrainData.Size-x,z).getLuminance(); + vertex.Pos.Y = (f32) heightMap->getPixel(TerrainData.Size-x-1,z).getLuminance(); vertex.Pos.Z = fz; vertex.TCoords.X = vertex.TCoords2.X = 1.f-fx2; @@ -184,12 +190,12 @@ namespace scene calculateNormals(mb); // add the MeshBuffer to the mesh - Mesh.addMeshBuffer(mb); + Mesh->addMeshBuffer(mb); // We copy the data to the renderBuffer, after the normals have been calculated. RenderBuffer->getVertexBuffer().set_used(numVertices); - for( u32 i = 0; i < numVertices; ++i ) + for (u32 i = 0; i < numVertices; ++i) { RenderBuffer->getVertexBuffer()[i] = mb->getVertexBuffer()[i]; RenderBuffer->getVertexBuffer()[i].Pos *= TerrainData.Scale; @@ -232,7 +238,9 @@ namespace scene //! Initializes the terrain data. Loads the vertices from the heightMapFile - bool CTerrainSceneNode::loadHeightMapRAW( io::IReadFile* file, s32 bitsPerPixel, bool signedData, bool floatVals, s32 width, 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) return false; @@ -242,14 +250,14 @@ namespace scene // start reading const u32 startTime = os::Timer::getTime(); - Mesh.MeshBuffers.clear(); + Mesh->MeshBuffers.clear(); const s32 bytesPerPixel = bitsPerPixel / 8; // Get the dimension of the heightmap data const s32 filesize = file->getSize(); if (!width) - TerrainData.Size = core::floor32(sqrtf( (f32)( filesize / bytesPerPixel ) )); + TerrainData.Size = core::floor32(sqrtf((f32)(filesize / bytesPerPixel))); else { if ((filesize-file->getPos())/bytesPerPixel>width*width) @@ -260,34 +268,34 @@ namespace scene TerrainData.Size = width; } - switch( TerrainData.PatchSize ) + switch (TerrainData.PatchSize) { case ETPS_9: - if( TerrainData.MaxLOD > 3 ) + if (TerrainData.MaxLOD > 3) { TerrainData.MaxLOD = 3; } break; case ETPS_17: - if( TerrainData.MaxLOD > 4 ) + if (TerrainData.MaxLOD > 4) { TerrainData.MaxLOD = 4; } break; case ETPS_33: - if( TerrainData.MaxLOD > 5 ) + if (TerrainData.MaxLOD > 5) { TerrainData.MaxLOD = 5; } break; case ETPS_65: - if( TerrainData.MaxLOD > 6 ) + if (TerrainData.MaxLOD > 6) { TerrainData.MaxLOD = 6; } break; case ETPS_129: - if( TerrainData.MaxLOD > 7 ) + if (TerrainData.MaxLOD > 7) { TerrainData.MaxLOD = 7; } @@ -298,7 +306,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); @@ -322,17 +330,17 @@ namespace scene const f32 tdSize = 1.0f/(f32)(TerrainData.Size-1); float fx=0.f; float fx2=0.f; - for( s32 x = 0; x < TerrainData.Size; ++x ) + for (s32 x = 0; x < TerrainData.Size; ++x) { float fz=0.f; float fz2=0.f; - for( s32 z = 0; z < TerrainData.Size; ++z ) + for (s32 z = 0; z < TerrainData.Size; ++z) { bool failure=false; vertex.Pos.X = fx; if (floatVals) { - if( file->read( &vertex.Pos.Y, bytesPerPixel ) != bytesPerPixel ) + if (file->read(&vertex.Pos.Y, bytesPerPixel) != bytesPerPixel) failure=true; } else if (signedData) @@ -342,7 +350,7 @@ namespace scene case 1: { s8 val; - if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val; } @@ -350,7 +358,7 @@ namespace scene case 2: { s16 val; - if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val/256.f; } @@ -358,7 +366,7 @@ namespace scene case 4: { s32 val; - if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val/16777216.f; } @@ -372,7 +380,7 @@ namespace scene case 1: { u8 val; - if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val; } @@ -380,7 +388,7 @@ namespace scene case 2: { u16 val; - if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val/256.f; } @@ -388,7 +396,7 @@ namespace scene case 4: { u32 val; - if( file->read( &val, bytesPerPixel ) != bytesPerPixel ) + if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val/16777216.f; } @@ -406,7 +414,7 @@ namespace scene vertex.TCoords.X = vertex.TCoords2.X = 1.f-fx2; vertex.TCoords.Y = vertex.TCoords2.Y = fz2; - mb->getVertexBuffer().push_back( vertex ); + mb->getVertexBuffer().push_back(vertex); ++fz; fz2 += tdSize; } @@ -417,16 +425,16 @@ namespace scene smoothTerrain(mb, smoothFactor); // calculate smooth normals for the vertices - calculateNormals( mb ); + calculateNormals(mb); // add the MeshBuffer to the mesh - Mesh.addMeshBuffer( mb ); + Mesh->addMeshBuffer(mb); const u32 vertexCount = mb->getVertexCount(); // We copy the data to the renderBuffer, after the normals have been calculated. - RenderBuffer->getVertexBuffer().set_used( vertexCount ); + RenderBuffer->getVertexBuffer().set_used(vertexCount); - for( u32 i = 0; i < vertexCount; i++ ) + for (u32 i = 0; i < vertexCount; i++) { RenderBuffer->getVertexBuffer()[i] = mb->getVertexBuffer()[i]; RenderBuffer->getVertexBuffer()[i].Pos *= TerrainData.Scale; @@ -447,11 +455,12 @@ namespace scene // Rotate the vertices of the terrain by the rotation specified. Must be done // after calculating the terrain data, so we know what the current center of the // terrain is. - setRotation( TerrainData.Rotation ); + setRotation(TerrainData.Rotation); // Pre-allocate memory for indices - RenderBuffer->getIndexBuffer().set_used( TerrainData.PatchCount * TerrainData.PatchCount * - TerrainData.CalcPatchSize * TerrainData.CalcPatchSize * 6 ); + RenderBuffer->getIndexBuffer().set_used( + TerrainData.PatchCount*TerrainData.PatchCount* + TerrainData.CalcPatchSize*TerrainData.CalcPatchSize*6); const u32 endTime = os::Timer::getTime(); @@ -464,12 +473,31 @@ namespace scene } + //! Returns the mesh + IMesh* CTerrainSceneNode::getMesh() { return Mesh; } + + + //! Returns the material based on the zero based index i. + video::SMaterial& CTerrainSceneNode::getMaterial(u32 i) + { + return Mesh->getMeshBuffer(i)->getMaterial(); + } + + + //! Returns amount of materials used by this scene node ( always 1 ) + u32 CTerrainSceneNode::getMaterialCount() const + { + return Mesh->getMeshBufferCount(); + } + + //! Sets the scale of the scene node. //! \param scale: New scale of the node void CTerrainSceneNode::setScale(const core::vector3df& scale) { TerrainData.Scale = scale; applyTransformation(); + calculateNormals(RenderBuffer); ForceRecalculation = true; } @@ -488,7 +516,7 @@ namespace scene //! 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. - void CTerrainSceneNode::setRotationPivot( const core::vector3df& pivot ) + void CTerrainSceneNode::setRotationPivot(const core::vector3df& pivot) { UseDefaultRotationPivot = false; TerrainData.RotationPivot = pivot; @@ -505,28 +533,27 @@ namespace scene } - //! Apply transformation changes( scale, position, rotation ) + //! Apply transformation changes(scale, position, rotation) void CTerrainSceneNode::applyTransformation() { - if( !Mesh.getMeshBufferCount() ) + if (!Mesh->getMeshBufferCount()) return; TerrainData.Position = TerrainData.Position; - video::S3DVertex2TCoords* meshVertices = (video::S3DVertex2TCoords*)Mesh.getMeshBuffer(0)->getVertices(); - s32 vtxCount = Mesh.getMeshBuffer( 0 )->getVertexCount(); + s32 vtxCount = Mesh->getMeshBuffer(0)->getVertexCount(); core::matrix4 rotMatrix; - rotMatrix.setRotationDegrees( TerrainData.Rotation ); + rotMatrix.setRotationDegrees(TerrainData.Rotation); - for( s32 i = 0; i < vtxCount; ++i ) + for (s32 i = 0; i < vtxCount; ++i) { - RenderBuffer->getVertexBuffer()[i].Pos = meshVertices[i].Pos * TerrainData.Scale + TerrainData.Position; + RenderBuffer->getVertexBuffer()[i].Pos = Mesh->getMeshBuffer(0)->getPosition(i) * TerrainData.Scale + TerrainData.Position; RenderBuffer->getVertexBuffer()[i].Pos -= TerrainData.RotationPivot; - rotMatrix.inverseRotateVect( RenderBuffer->getVertexBuffer()[i].Pos ); + rotMatrix.inverseRotateVect(RenderBuffer->getVertexBuffer()[i].Pos); RenderBuffer->getVertexBuffer()[i].Pos += TerrainData.RotationPivot; } - calculateDistanceThresholds( true ); + calculateDistanceThresholds(true); calculatePatchData(); RenderBuffer->setDirty(EBT_VERTEX); @@ -552,25 +579,32 @@ namespace scene void CTerrainSceneNode::preRenderLODCalculations() { + scene::ICameraSceneNode * camera = SceneManager->getActiveCamera(); + if(!camera) + return; + SceneManager->registerNodeForRendering(this); // Do Not call ISceneNode::OnRegisterSceneNode(), this node should have no children // Determine the camera rotation, based on the camera direction. - const core::vector3df cameraPosition = SceneManager->getActiveCamera()->getAbsolutePosition(); - const core::vector3df cameraRotation = core::line3d(cameraPosition, SceneManager->getActiveCamera()->getTarget()).getVector().getHorizontalAngle(); + const core::vector3df cameraPosition = camera->getAbsolutePosition(); + const core::vector3df cameraRotation = core::line3d(cameraPosition, camera->getTarget()).getVector().getHorizontalAngle(); + core::vector3df cameraUp = camera->getUpVector(); + cameraUp.normalize(); const f32 CameraFOV = SceneManager->getActiveCamera()->getFOV(); // Only check on the Camera's Y Rotation if (!ForceRecalculation) { - if (( fabs(cameraRotation.X - OldCameraRotation.X) < CameraRotationDelta) && - ( fabs(cameraRotation.Y - OldCameraRotation.Y) < CameraRotationDelta)) + if ((fabsf(cameraRotation.X - OldCameraRotation.X) < CameraRotationDelta) && + (fabsf(cameraRotation.Y - OldCameraRotation.Y) < CameraRotationDelta)) { if ((fabs(cameraPosition.X - OldCameraPosition.X) < CameraMovementDelta) && (fabs(cameraPosition.Y - OldCameraPosition.Y) < CameraMovementDelta) && (fabs(cameraPosition.Z - OldCameraPosition.Z) < CameraMovementDelta)) { - if (fabs(CameraFOV-OldCameraFOV) < CameraFOVDelta) + if (fabs(CameraFOV-OldCameraFOV) < CameraFOVDelta && + cameraUp.dotProduct(OldCameraUp) > (1.f - (cos(core::DEGTORAD * CameraRotationDelta)))) { return; } @@ -580,6 +614,7 @@ namespace scene OldCameraPosition = cameraPosition; OldCameraRotation = cameraRotation; + OldCameraUp = cameraUp; OldCameraFOV = CameraFOV; const SViewFrustum* frustum = SceneManager->getActiveCamera()->getViewFrustum(); @@ -587,22 +622,22 @@ namespace scene // Determine each patches LOD based on distance from camera (and whether or not they are in // the view frustum). const s32 count = TerrainData.PatchCount * TerrainData.PatchCount; - for( s32 j = 0; j < count; ++j ) + for (s32 j = 0; j < count; ++j) { - if( frustum->getBoundingBox().intersectsWithBox( TerrainData.Patches[j].BoundingBox ) ) + if (frustum->getBoundingBox().intersectsWithBox(TerrainData.Patches[j].BoundingBox)) { const f32 distance = (cameraPosition.X - TerrainData.Patches[j].Center.X) * (cameraPosition.X - TerrainData.Patches[j].Center.X) + (cameraPosition.Y - TerrainData.Patches[j].Center.Y) * (cameraPosition.Y - TerrainData.Patches[j].Center.Y) + (cameraPosition.Z - TerrainData.Patches[j].Center.Z) * (cameraPosition.Z - TerrainData.Patches[j].Center.Z); - for( s32 i = TerrainData.MaxLOD - 1; i >= 0; --i ) + for (s32 i = TerrainData.MaxLOD - 1; i >= 0; --i) { - if( distance >= TerrainData.LODDistanceThreshold[i] ) + if (distance >= TerrainData.LODDistanceThreshold[i]) { TerrainData.Patches[j].CurrentLOD = i; break; } - //else if( i == 0 ) + //else if (i == 0) { // If we've turned off a patch from viewing, because of the frustum, and now we turn around and it's // too close, we need to turn it back on, at the highest LOD. The if above doesn't catch this. @@ -620,30 +655,17 @@ namespace scene void CTerrainSceneNode::preRenderIndicesCalculations() { - 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) - { + scene::IIndexBuffer& indexBuffer = RenderBuffer->getIndexBuffer(); IndicesToRender = 0; + indexBuffer.set_used(0); + s32 index = 0; // Then generate the indices for all patches that are visible. - for( s32 i = 0; i < TerrainData.PatchCount; ++i ) + for (s32 i = 0; i < TerrainData.PatchCount; ++i) { - for( s32 j = 0; j < TerrainData.PatchCount; ++j ) + for (s32 j = 0; j < TerrainData.PatchCount; ++j) { - const s32 index = i * TerrainData.PatchCount + j; - if( TerrainData.Patches[index].CurrentLOD >= 0 ) + if (TerrainData.Patches[index].CurrentLOD >= 0) { s32 x = 0; s32 z = 0; @@ -652,19 +674,20 @@ namespace scene const s32 step = 1 << TerrainData.Patches[index].CurrentLOD; // Loop through patch and generate indices - while( z < TerrainData.CalcPatchSize ) + while (z < TerrainData.CalcPatchSize) { - const s32 index11 = getIndex( j, i, index, x, z ); - const s32 index21 = getIndex( j, i, index, x + step, z ); - const s32 index12 = getIndex( j, i, index, x, z + step ); - const s32 index22 = getIndex( j, i, index, x + step, z + step ); + const s32 index11 = getIndex(j, i, index, x, z); + const s32 index21 = getIndex(j, i, index, x + step, z); + const s32 index12 = getIndex(j, i, index, x, z + step); + const s32 index22 = getIndex(j, i, index, x + step, z + step); - IndexBuffer[IndicesToRender++]= static_cast(index12); - IndexBuffer[IndicesToRender++]= static_cast(index11); - IndexBuffer[IndicesToRender++]= static_cast(index22); - IndexBuffer[IndicesToRender++]= static_cast(index22); - IndexBuffer[IndicesToRender++]= static_cast(index11); - IndexBuffer[IndicesToRender++]= static_cast(index21); + indexBuffer.push_back(index12); + indexBuffer.push_back(index11); + indexBuffer.push_back(index22); + indexBuffer.push_back(index22); + indexBuffer.push_back(index11); + indexBuffer.push_back(index21); + IndicesToRender+=6; // increment index position horizontally x += step; @@ -677,12 +700,13 @@ namespace scene } } } + ++index; } } RenderBuffer->setDirty(EBT_INDEX); - if ( DynamicSelectorUpdate && TriangleSelector ) + if (DynamicSelectorUpdate && TriangleSelector) { CTerrainTriangleSelector* selector = (CTerrainTriangleSelector*)TriangleSelector; selector->setTriangleData(this, -1); @@ -696,20 +720,20 @@ namespace scene if (!IsVisible || !SceneManager->getActiveCamera()) return; - if (!Mesh.getMeshBufferCount()) + if (!Mesh->getMeshBufferCount()) return; video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setTransform (video::ETS_WORLD, core::IdentityMatrix); - driver->setMaterial(Mesh.getMeshBuffer(0)->getMaterial()); + driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); RenderBuffer->getIndexBuffer().set_used(IndicesToRender); // For use with geomorphing driver->drawMeshBuffer(RenderBuffer); - RenderBuffer->getIndexBuffer().set_used( RenderBuffer->getIndexBuffer().allocated_size() ); + RenderBuffer->getIndexBuffer().set_used(RenderBuffer->getIndexBuffer().allocated_size()); // for debug purposes only: if (DebugDataVisible) @@ -718,15 +742,15 @@ namespace scene m.Lighting = false; driver->setMaterial(m); if (DebugDataVisible & scene::EDS_BBOX) - driver->draw3DBox( TerrainData.BoundingBox, video::SColor(255,255,255,255)); + driver->draw3DBox(TerrainData.BoundingBox, video::SColor(255,255,255,255)); const s32 count = TerrainData.PatchCount * TerrainData.PatchCount; s32 visible = 0; if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) { - for( s32 j = 0; j < count; ++j ) + for (s32 j = 0; j < count; ++j) { - driver->draw3DBox( TerrainData.Patches[j].BoundingBox, video::SColor(255,255,0,0)); + driver->draw3DBox(TerrainData.Patches[j].BoundingBox, video::SColor(255,255,0,0)); visible += (TerrainData.Patches[j].CurrentLOD >= 0); } } @@ -737,9 +761,9 @@ namespace scene "__debugnormal", 0xFFECEC00, 0xFF999900, 4, 8, 1.f, 0.6f, 0.05f, 0.3f); - if ( 0 == arrow ) + if (0 == arrow) { - arrow = SceneManager->getMesh( "__debugnormal" ); + arrow = SceneManager->getMesh( "__debugnormal"); } IMesh *mesh = arrow->getMesh(0); @@ -749,7 +773,7 @@ namespace scene // draw normals driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); - for ( u32 i=0; i != RenderBuffer->getVertexCount(); ++i ) + for (u32 i=0; i != RenderBuffer->getVertexCount(); ++i) { const core::vector3df& v = RenderBuffer->getNormal(i); // align to v->Normal @@ -768,7 +792,7 @@ namespace scene m2=AbsoluteTransformation*m2; driver->setTransform(video::ETS_WORLD, m2 ); - for ( u32 a = 0; a != mesh->getMeshBufferCount(); ++a ) + for (u32 a = 0; a != mesh->getMeshBufferCount(); ++a) driver->drawMeshBuffer(mesh->getMeshBuffer(a)); } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); @@ -797,7 +821,7 @@ namespace scene //! Return the bounding box of a patch - const core::aabbox3d& CTerrainSceneNode::getBoundingBox( s32 patchX, s32 patchZ ) const + const core::aabbox3d& CTerrainSceneNode::getBoundingBox(s32 patchX, s32 patchZ) const { return TerrainData.Patches[patchX * TerrainData.PatchCount + patchZ].BoundingBox; } @@ -808,19 +832,19 @@ namespace scene //! \param LOD: The Level Of Detail you want the indices from. void CTerrainSceneNode::getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD ) const { - if (!Mesh.getMeshBufferCount()) + if (!Mesh->getMeshBufferCount()) return; LOD = core::clamp(LOD, 0, TerrainData.MaxLOD - 1); - const u32 numVertices = Mesh.getMeshBuffer(0)->getVertexCount(); + const u32 numVertices = Mesh->getMeshBuffer(0)->getVertexCount(); mb.getVertexBuffer().reallocate(numVertices); - video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)Mesh.getMeshBuffer(0)->getVertices(); + video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)Mesh->getMeshBuffer(0)->getVertices(); for (u32 n=0; ngetIndexBuffer().getType() ); + mb.getIndexBuffer().setType(RenderBuffer->getIndexBuffer().getType()); // calculate the step we take for all patches, since LOD is the same const s32 step = 1 << LOD; @@ -837,17 +861,17 @@ namespace scene // Loop through patch and generate indices while (z < TerrainData.CalcPatchSize) { - const s32 index11 = getIndex( j, i, index, x, z ); - const s32 index21 = getIndex( j, i, index, x + step, z ); - const s32 index12 = getIndex( j, i, index, x, z + step ); - const s32 index22 = getIndex( j, i, index, x + step, z + step ); + const s32 index11 = getIndex(j, i, index, x, z); + const s32 index21 = getIndex(j, i, index, x + step, z); + const s32 index12 = getIndex(j, i, index, x, z + step); + const s32 index22 = getIndex(j, i, index, x + step, z + step); - mb.getIndexBuffer().push_back( index12 ); - mb.getIndexBuffer().push_back( index11 ); - mb.getIndexBuffer().push_back( index22 ); - mb.getIndexBuffer().push_back( index22 ); - mb.getIndexBuffer().push_back( index11 ); - mb.getIndexBuffer().push_back( index21 ); + mb.getIndexBuffer().push_back(index12); + mb.getIndexBuffer().push_back(index11); + mb.getIndexBuffer().push_back(index22); + mb.getIndexBuffer().push_back(index22); + mb.getIndexBuffer().push_back(index11); + mb.getIndexBuffer().push_back(index21); // increment index position horizontally x += step; @@ -874,17 +898,18 @@ namespace scene //! \return: Number if indices put into the buffer. s32 CTerrainSceneNode::getIndicesForPatch(core::array& indices, s32 patchX, s32 patchZ, s32 LOD) { - if ( patchX < 0 || patchX > TerrainData.PatchCount - 1 || patchZ < 0 || patchZ > TerrainData.PatchCount - 1 ) + if (patchX < 0 || patchX > TerrainData.PatchCount-1 || + patchZ < 0 || patchZ > TerrainData.PatchCount-1) return -1; - if ( LOD < -1 || LOD > TerrainData.MaxLOD - 1 ) + if (LOD < -1 || LOD > TerrainData.MaxLOD - 1) return -1; core::array cLODs; bool setLODs = false; // If LOD of -1 was passed in, use the CurrentLOD of the patch specified - if ( LOD == -1 ) + if (LOD == -1) { LOD = TerrainData.Patches[patchX * TerrainData.PatchCount + patchZ].CurrentLOD; } @@ -895,7 +920,7 @@ namespace scene setLODs = true; } - if ( LOD < 0 ) + if (LOD < 0) return -2; // Patch not visible, don't generate indices. // calculate the step we take for this LOD @@ -913,10 +938,10 @@ namespace scene s32 rv=0; while (z TerrainData.MaxLOD - 1 ) + if (LOD < 0 || LOD > TerrainData.MaxLOD - 1) return false; TerrainData.LODDistanceThreshold[LOD] = newDistance * newDistance; @@ -1007,7 +1032,7 @@ namespace scene if (RenderBuffer->getVertexType()==video::EVT_2TCOORDS) { - if ( resolution2 == 0 ) + if (resolution2 == 0) { ((video::S3DVertex2TCoords&)RenderBuffer->getVertexBuffer()[index]).TCoords2 = RenderBuffer->getVertexBuffer()[index].TCoords; } @@ -1039,47 +1064,47 @@ namespace scene { if (TerrainData.Patches[PatchIndex].Top && TerrainData.Patches[PatchIndex].CurrentLOD < TerrainData.Patches[PatchIndex].Top->CurrentLOD && - (vX % ( 1 << TerrainData.Patches[PatchIndex].Top->CurrentLOD)) != 0 ) + (vX % (1 << TerrainData.Patches[PatchIndex].Top->CurrentLOD)) != 0 ) { - vX -= vX % ( 1 << TerrainData.Patches[PatchIndex].Top->CurrentLOD ); + vX -= vX % (1 << TerrainData.Patches[PatchIndex].Top->CurrentLOD); } } else - if ( vZ == (u32)TerrainData.CalcPatchSize ) // bottom border + if (vZ == (u32)TerrainData.CalcPatchSize) // bottom border { if (TerrainData.Patches[PatchIndex].Bottom && TerrainData.Patches[PatchIndex].CurrentLOD < TerrainData.Patches[PatchIndex].Bottom->CurrentLOD && - (vX % ( 1 << TerrainData.Patches[PatchIndex].Bottom->CurrentLOD)) != 0) + (vX % (1 << TerrainData.Patches[PatchIndex].Bottom->CurrentLOD)) != 0) { - vX -= vX % ( 1 << TerrainData.Patches[PatchIndex].Bottom->CurrentLOD ); + vX -= vX % (1 << TerrainData.Patches[PatchIndex].Bottom->CurrentLOD); } } // left border - if ( vX == 0 ) + if (vX == 0) { if (TerrainData.Patches[PatchIndex].Left && TerrainData.Patches[PatchIndex].CurrentLOD < TerrainData.Patches[PatchIndex].Left->CurrentLOD && - ( vZ % ( 1 << TerrainData.Patches[PatchIndex].Left->CurrentLOD ) ) != 0) + (vZ % (1 << TerrainData.Patches[PatchIndex].Left->CurrentLOD)) != 0) { - vZ -= vZ % ( 1 << TerrainData.Patches[PatchIndex].Left->CurrentLOD ); + vZ -= vZ % (1 << TerrainData.Patches[PatchIndex].Left->CurrentLOD); } } else - if ( vX == (u32)TerrainData.CalcPatchSize ) // right border + if (vX == (u32)TerrainData.CalcPatchSize) // right border { if (TerrainData.Patches[PatchIndex].Right && TerrainData.Patches[PatchIndex].CurrentLOD < TerrainData.Patches[PatchIndex].Right->CurrentLOD && - ( vZ % ( 1 << TerrainData.Patches[PatchIndex].Right->CurrentLOD ) ) != 0) + (vZ % (1 << TerrainData.Patches[PatchIndex].Right->CurrentLOD)) != 0) { - vZ -= vZ % ( 1 << TerrainData.Patches[PatchIndex].Right->CurrentLOD ); + vZ -= vZ % (1 << TerrainData.Patches[PatchIndex].Right->CurrentLOD); } } - if ( vZ >= (u32)TerrainData.PatchSize ) + if (vZ >= (u32)TerrainData.PatchSize) vZ = TerrainData.CalcPatchSize; - if ( vX >= (u32)TerrainData.PatchSize ) + if (vX >= (u32)TerrainData.PatchSize) vX = TerrainData.CalcPatchSize; return (vZ + ((TerrainData.CalcPatchSize) * PatchZ)) * TerrainData.Size + @@ -1088,7 +1113,7 @@ namespace scene //! smooth the terrain - void CTerrainSceneNode::smoothTerrain(CDynamicMeshBuffer* mb, s32 smoothFactor) + void CTerrainSceneNode::smoothTerrain(IDynamicMeshBuffer* mb, s32 smoothFactor) { for (s32 run = 0; run < smoothFactor; ++run) { @@ -1098,10 +1123,10 @@ namespace scene for (s32 x = 1; x < TerrainData.Size - 1; ++x) { mb->getVertexBuffer()[x + yd].Pos.Y = - (mb->getVertexBuffer()[x-1 + yd].Pos.Y + - mb->getVertexBuffer()[x+1 + yd].Pos.Y + - mb->getVertexBuffer()[x + yd - TerrainData.Size].Pos.Y + - mb->getVertexBuffer()[x + yd - TerrainData.Size].Pos.Y) * 0.25f; + (mb->getVertexBuffer()[x-1 + yd].Pos.Y + //left + mb->getVertexBuffer()[x+1 + yd].Pos.Y + //right + mb->getVertexBuffer()[x + yd - TerrainData.Size].Pos.Y + //above + mb->getVertexBuffer()[x + yd + TerrainData.Size].Pos.Y) * 0.25f; //below } yd += TerrainData.Size; } @@ -1110,7 +1135,7 @@ namespace scene //! calculate smooth normals - void CTerrainSceneNode::calculateNormals( CDynamicMeshBuffer* mb ) + void CTerrainSceneNode::calculateNormals(IDynamicMeshBuffer* mb) { s32 count; core::vector3df a, b, c, t; @@ -1224,7 +1249,7 @@ namespace scene } else { - normal.set( 0.0f, 1.0f, 0.0f ); + normal.set(0.0f, 1.0f, 0.0f); } mb->getVertexBuffer()[x * TerrainData.Size + z].Normal = normal; @@ -1236,7 +1261,7 @@ namespace scene //! create patches, stuff that needs to be done only once for patches goes here. void CTerrainSceneNode::createPatches() { - TerrainData.PatchCount = (TerrainData.Size - 1) / ( TerrainData.CalcPatchSize ); + TerrainData.PatchCount = (TerrainData.Size - 1) / (TerrainData.CalcPatchSize); if (TerrainData.Patches) delete [] TerrainData.Patches; @@ -1251,9 +1276,9 @@ namespace scene // Reset the Terrains Bounding Box for re-calculation TerrainData.BoundingBox = core::aabbox3df(999999.9f, 999999.9f, 999999.9f, -999999.9f, -999999.9f, -999999.9f); - for( s32 x = 0; x < TerrainData.PatchCount; ++x ) + for (s32 x = 0; x < TerrainData.PatchCount; ++x) { - for( s32 z = 0; z < TerrainData.PatchCount; ++z ) + for (s32 z = 0; z < TerrainData.PatchCount; ++z) { const s32 index = x * TerrainData.PatchCount + z; TerrainData.Patches[index].CurrentLOD = 0; @@ -1262,38 +1287,38 @@ namespace scene TerrainData.Patches[index].BoundingBox = core::aabbox3df(999999.9f, 999999.9f, 999999.9f, -999999.9f, -999999.9f, -999999.9f); - for( s32 xx = x*(TerrainData.CalcPatchSize); xx <= ( x + 1 ) * TerrainData.CalcPatchSize; ++xx ) - for( s32 zz = z*(TerrainData.CalcPatchSize); zz <= ( z + 1 ) * TerrainData.CalcPatchSize; ++zz ) - TerrainData.Patches[index].BoundingBox.addInternalPoint( RenderBuffer->getVertexBuffer()[xx * TerrainData.Size + zz].Pos ); + for (s32 xx = x*(TerrainData.CalcPatchSize); xx <= (x + 1) * TerrainData.CalcPatchSize; ++xx) + for (s32 zz = z*(TerrainData.CalcPatchSize); zz <= (z + 1) * TerrainData.CalcPatchSize; ++zz) + TerrainData.Patches[index].BoundingBox.addInternalPoint(RenderBuffer->getVertexBuffer()[xx * TerrainData.Size + zz].Pos); // Reconfigure the bounding box of the terrain as a whole - TerrainData.BoundingBox.addInternalBox( TerrainData.Patches[index].BoundingBox ); + TerrainData.BoundingBox.addInternalBox(TerrainData.Patches[index].BoundingBox); // get center of Patch TerrainData.Patches[index].Center = TerrainData.Patches[index].BoundingBox.getCenter(); // Assign Neighbours // Top - if( x > 0 ) + if (x > 0) TerrainData.Patches[index].Top = &TerrainData.Patches[(x-1) * TerrainData.PatchCount + z]; else TerrainData.Patches[index].Top = 0; // Bottom - if( x < TerrainData.PatchCount - 1 ) + if (x < TerrainData.PatchCount - 1) TerrainData.Patches[index].Bottom = &TerrainData.Patches[(x+1) * TerrainData.PatchCount + z]; else TerrainData.Patches[index].Bottom = 0; // Left - if( z > 0 ) + if (z > 0) TerrainData.Patches[index].Left = &TerrainData.Patches[x * TerrainData.PatchCount + z - 1]; else TerrainData.Patches[index].Left = 0; // Right - if( z < TerrainData.PatchCount - 1 ) + if (z < TerrainData.PatchCount - 1) TerrainData.Patches[index].Right = &TerrainData.Patches[x * TerrainData.PatchCount + z + 1]; else TerrainData.Patches[index].Right = 0; @@ -1304,7 +1329,7 @@ namespace scene TerrainData.Center = TerrainData.BoundingBox.getCenter(); // if the default rotation pivot is still being used, update it. - if( UseDefaultRotationPivot ) + if (UseDefaultRotationPivot) { TerrainData.RotationPivot = TerrainData.Center; } @@ -1350,34 +1375,35 @@ namespace scene //! Gets the height f32 CTerrainSceneNode::getHeight(f32 x, f32 z) const { - if (!Mesh.getMeshBufferCount()) + if (!Mesh->getMeshBufferCount()) return 0; f32 height = -999999.9f; core::matrix4 rotMatrix; - rotMatrix.setRotationDegrees( TerrainData.Rotation ); - core::vector3df pos( x, 0.0f, z ); - rotMatrix.rotateVect( pos ); + rotMatrix.setRotationDegrees(TerrainData.Rotation); + core::vector3df pos(x, 0.0f, z); + rotMatrix.rotateVect(pos); pos -= TerrainData.Position; pos /= TerrainData.Scale; - s32 X(core::floor32( pos.X )); - s32 Z(core::floor32( pos.Z )); + s32 X(core::floor32(pos.X)); + s32 Z(core::floor32(pos.Z)); - if( X >= 0 && X < TerrainData.Size && Z >= 0 && Z < TerrainData.Size ) + if (X >= 0 && X < TerrainData.Size-1 && + Z >= 0 && Z < TerrainData.Size-1) { - const video::S3DVertex2TCoords* Vertices = (const video::S3DVertex2TCoords*)Mesh.getMeshBuffer(0)->getVertices(); + const video::S3DVertex2TCoords* Vertices = (const video::S3DVertex2TCoords*)Mesh->getMeshBuffer(0)->getVertices(); const core::vector3df& a = Vertices[X * TerrainData.Size + Z].Pos; const core::vector3df& b = Vertices[(X + 1) * TerrainData.Size + Z].Pos; - const core::vector3df& c = Vertices[X * TerrainData.Size + ( Z + 1 )].Pos; - const core::vector3df& d = Vertices[(X + 1) * TerrainData.Size + ( Z + 1 )].Pos; + const core::vector3df& c = Vertices[X * TerrainData.Size + (Z + 1)].Pos; + const core::vector3df& d = Vertices[(X + 1) * TerrainData.Size + (Z + 1)].Pos; // offset from integer position const f32 dx = pos.X - X; const f32 dz = pos.Z - Z; - if( dx > dz ) + if (dx > dz) height = a.Y + (d.Y - b.Y)*dz + (b.Y - a.Y)*dx; else height = a.Y + (d.Y - c.Y)*dx + (c.Y - a.Y)*dz; @@ -1406,7 +1432,7 @@ namespace scene void CTerrainSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - core::stringc newHeightmap = in->getAttributeAsString("Heightmap"); + io::path newHeightmap = in->getAttributeAsString("Heightmap"); f32 tcoordScale1 = in->getAttributeAsFloat("TextureScale1"); f32 tcoordScale2 = in->getAttributeAsFloat("TextureScale2"); @@ -1474,22 +1500,23 @@ namespace scene // copy materials - for (unsigned int m = 0; mgetMeshBufferCount(); ++m) { - if (nb->Mesh.getMeshBufferCount()>m && - nb->Mesh.getMeshBuffer(m) && - Mesh.getMeshBuffer(m)) + if (nb->Mesh->getMeshBufferCount()>m && + nb->Mesh->getMeshBuffer(m) && + Mesh->getMeshBuffer(m)) { - nb->Mesh.getMeshBuffer(m)->getMaterial() = - Mesh.getMeshBuffer(m)->getMaterial(); + nb->Mesh->getMeshBuffer(m)->getMaterial() = + Mesh->getMeshBuffer(m)->getMaterial(); } } - nb->RenderBuffer->Material = RenderBuffer->Material; + nb->RenderBuffer->getMaterial() = RenderBuffer->getMaterial(); // finish - nb->drop(); + if ( newParent ) + nb->drop(); return nb; } diff --git a/src/dep/src/irrlicht/CTerrainSceneNode.h b/src/dep/src/irrlicht/CTerrainSceneNode.h index 0c262ce..0ee1e61 100644 --- a/src/dep/src/irrlicht/CTerrainSceneNode.h +++ b/src/dep/src/irrlicht/CTerrainSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -10,8 +10,8 @@ #define __C_TERRAIN_SCENE_NODE_H__ #include "ITerrainSceneNode.h" -#include "SMesh.h" -#include "CDynamicMeshBuffer.h" +#include "IDynamicMeshBuffer.h" +#include "path.h" namespace irr { @@ -22,6 +22,7 @@ namespace io } namespace scene { + struct SMesh; class ITextSceneNode; //! A scene node for displaying terrain using the geo mip map algorithm. @@ -61,17 +62,11 @@ namespace scene //! 1 material. //! \param i: Zero based index i. UNUSED, left in for virtual purposes. //! \return Returns the single material this scene node uses. - virtual video::SMaterial& getMaterial ( u32 i ) - { - return Mesh.getMeshBuffer(i)->getMaterial(); - } + virtual video::SMaterial& getMaterial(u32 i); //! Returns amount of materials used by this scene node ( always 1 ) //! \return Returns current count of materials used by this scene node ( always 1 ) - virtual u32 getMaterialCount() const - { - return Mesh.getMeshBufferCount(); - } + virtual u32 getMaterialCount() const; //! Gets the last scaling factor applied to the scene node. This value only represents the //! last scaling factor presented to the node. For instance, if you make create the node @@ -135,7 +130,7 @@ namespace scene virtual u32 getIndexCount() const { return IndicesToRender; } //! Returns the mesh - virtual IMesh* getMesh() { return &Mesh; } + virtual IMesh* getMesh(); //! Returns a pointer to the buffer used by the terrain (most users will not need this) virtual IMeshBuffer* getRenderBuffer() { return RenderBuffer; } @@ -278,17 +273,14 @@ namespace scene virtual void preRenderLODCalculations(); virtual void preRenderIndicesCalculations(); - template - void preRenderIndicesCalculationsDirect(INDEX_TYPE* IndexBuffer); - //! get indices when generating index data for patches at varying levels of detail. u32 getIndex(const s32 PatchX, const s32 PatchZ, const s32 PatchIndex, u32 vX, u32 vZ) const; //! smooth the terrain - void smoothTerrain(CDynamicMeshBuffer* mb, s32 smoothFactor); + void smoothTerrain(IDynamicMeshBuffer* mb, s32 smoothFactor); //! calculate smooth normals - void calculateNormals(CDynamicMeshBuffer* mb); + void calculateNormals(IDynamicMeshBuffer* mb); //! create patches, stuff that needs to only be done once for patches goes here. void createPatches(); @@ -309,9 +301,9 @@ namespace scene void applyTransformation(); STerrainData TerrainData; - SMesh Mesh; + SMesh* Mesh; - CDynamicMeshBuffer *RenderBuffer; + IDynamicMeshBuffer *RenderBuffer; u32 VerticesToRender; u32 IndicesToRender; @@ -323,6 +315,7 @@ namespace scene core::vector3df OldCameraPosition; core::vector3df OldCameraRotation; + core::vector3df OldCameraUp; f32 OldCameraFOV; f32 CameraMovementDelta; f32 CameraRotationDelta; @@ -331,7 +324,7 @@ namespace scene // needed for (de)serialization f32 TCoordScale1; f32 TCoordScale2; - core::stringc HeightmapFile; + io::path HeightmapFile; io::IFileSystem* FileSystem; }; diff --git a/src/dep/src/irrlicht/CTerrainTriangleSelector.cpp b/src/dep/src/irrlicht/CTerrainTriangleSelector.cpp index fedeee1..f926089 100644 --- a/src/dep/src/irrlicht/CTerrainTriangleSelector.cpp +++ b/src/dep/src/irrlicht/CTerrainTriangleSelector.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -76,7 +76,7 @@ void CTerrainTriangleSelector::setTriangleData(ITerrainSceneNode* node, s32 LOD) //! Gets all triangles. void CTerrainTriangleSelector::getTriangles ( core::triangle3df* triangles, s32 arraySize, - s32& outTriangleCount, const core::matrix4* transform ) const + s32& outTriangleCount, const core::matrix4* transform) const { s32 count = TrianglePatches.TotalTriangles; diff --git a/src/dep/src/irrlicht/CTerrainTriangleSelector.h b/src/dep/src/irrlicht/CTerrainTriangleSelector.h index 013818b..27be890 100644 --- a/src/dep/src/irrlicht/CTerrainTriangleSelector.h +++ b/src/dep/src/irrlicht/CTerrainTriangleSelector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -52,6 +52,11 @@ public: //! Returns amount of all available triangles in this selector virtual s32 getTriangleCount() const; + //! Return the scene node associated with a given triangle. + /** ITerrainSceneNode is an ISceneNode, we just don't know it yet. */ + virtual const ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const + { return (ISceneNode*)SceneNode; } + private: friend class CTerrainSceneNode; diff --git a/src/dep/src/irrlicht/CTextSceneNode.cpp b/src/dep/src/irrlicht/CTextSceneNode.cpp index a7eb0fb..f754346 100644 --- a/src/dep/src/irrlicht/CTextSceneNode.cpp +++ b/src/dep/src/irrlicht/CTextSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,7 +24,7 @@ CTextSceneNode::CTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, video::SColor color) : ITextSceneNode(parent, mgr, id, position), Text(text), Color(color), Font(font), Coll(coll) - + { #ifdef _DEBUG setDebugName("CTextSceneNode"); @@ -57,7 +57,7 @@ void CTextSceneNode::render() if (!Font || !Coll) return; - core::position2d pos = Coll->getScreenCoordinatesFrom3DPosition(getAbsolutePosition(), + core::position2d pos = Coll->getScreenCoordinatesFrom3DPosition(getAbsolutePosition(), SceneManager->getActiveCamera()); core::rect r(pos, core::dimension2d(1,1)); @@ -89,7 +89,7 @@ void CTextSceneNode::setTextColor(video::SColor color) //! constructor -CBillboardTextSceneNode::CBillboardTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, +CBillboardTextSceneNode::CBillboardTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, gui::IGUIFont* font,const wchar_t* text, const core::vector3df& position, const core::dimension2d& size, video::SColor colorTop,video::SColor shade_bottom ) @@ -104,7 +104,7 @@ CBillboardTextSceneNode::CBillboardTextSceneNode(ISceneNode* parent, ISceneManag Material.MaterialTypeParam = 1.f / 255.f; Material.BackfaceCulling = false; Material.Lighting = false; - Material.ZBuffer = true; + Material.ZBuffer = video::ECFN_LESSEQUAL; Material.ZWriteEnable = false; if (font) @@ -154,6 +154,9 @@ CBillboardTextSceneNode::~CBillboardTextSceneNode() //! sets the text string void CBillboardTextSceneNode::setText(const wchar_t* text) { + if ( !Mesh ) + return; + Text = text; Symbol.clear(); @@ -199,7 +202,7 @@ void CBillboardTextSceneNode::setText(const wchar_t* text) tex[1] = (s.LowerRightCorner.Y * dim[1]) + 0.5f*dim[1]; tex[2] = (s.UpperLeftCorner.Y * dim[1]) - 0.5f*dim[1]; tex[3] = (s.UpperLeftCorner.X * dim[0]) - 0.5f*dim[0]; - + buf->Vertices[firstVert+0].TCoords.set(tex[0], tex[1]); buf->Vertices[firstVert+1].TCoords.set(tex[0], tex[2]); buf->Vertices[firstVert+2].TCoords.set(tex[3], tex[2]); @@ -218,7 +221,7 @@ void CBillboardTextSceneNode::setText(const wchar_t* text) buf->Indices[firstInd+5] = (u16)firstVert+2; wchar_t *tp = 0; - if (i>0) + if (i>0) tp = &Text[i-1]; info.Width = (f32)s.getWidth(); @@ -325,6 +328,9 @@ void CBillboardTextSceneNode::OnRegisterSceneNode() //! render void CBillboardTextSceneNode::render() { + if ( !Mesh ) + return; + video::IVideoDriver* driver = SceneManager->getVideoDriver(); // draw @@ -408,6 +414,9 @@ void CBillboardTextSceneNode::setTextColor(video::SColor color) //! \param overallColor: the color to set void CBillboardTextSceneNode::setColor(const video::SColor & overallColor) { + if ( !Mesh ) + return; + for ( u32 i = 0; i != Text.size (); ++i ) { const SSymbolInfo &info = Symbol[i]; @@ -425,6 +434,9 @@ void CBillboardTextSceneNode::setColor(const video::SColor & overallColor) //! \param bottomColor: the color to set the bottom vertices void CBillboardTextSceneNode::setColor(const video::SColor & topColor, const video::SColor & bottomColor) { + if ( !Mesh ) + return; + ColorBottom = bottomColor; ColorTop = topColor; for ( u32 i = 0; i != Text.size (); ++i ) diff --git a/src/dep/src/irrlicht/CTextSceneNode.h b/src/dep/src/irrlicht/CTextSceneNode.h index 8700a9c..10ed8a9 100644 --- a/src/dep/src/irrlicht/CTextSceneNode.h +++ b/src/dep/src/irrlicht/CTextSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTimer.h b/src/dep/src/irrlicht/CTimer.h index a106c50..fe0c5c0 100644 --- a/src/dep/src/irrlicht/CTimer.h +++ b/src/dep/src/irrlicht/CTimer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTriangleBBSelector.cpp b/src/dep/src/irrlicht/CTriangleBBSelector.cpp index 954472e..879c748 100644 --- a/src/dep/src/irrlicht/CTriangleBBSelector.cpp +++ b/src/dep/src/irrlicht/CTriangleBBSelector.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTriangleBBSelector.h b/src/dep/src/irrlicht/CTriangleBBSelector.h index f30b5eb..e2ea6b8 100644 --- a/src/dep/src/irrlicht/CTriangleBBSelector.h +++ b/src/dep/src/irrlicht/CTriangleBBSelector.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CTriangleSelector.cpp b/src/dep/src/irrlicht/CTriangleSelector.cpp index 635bc32..65eaafe 100644 --- a/src/dep/src/irrlicht/CTriangleSelector.cpp +++ b/src/dep/src/irrlicht/CTriangleSelector.cpp @@ -1,10 +1,11 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CTriangleSelector.h" #include "ISceneNode.h" #include "IMeshBuffer.h" +#include "IAnimatedMeshSceneNode.h" namespace irr { @@ -13,7 +14,7 @@ namespace scene //! constructor CTriangleSelector::CTriangleSelector(const ISceneNode* node) -: SceneNode(node) +: SceneNode(node), AnimatedNode(0), LastMeshFrame(-1) { #ifdef _DEBUG setDebugName("CTriangleSelector"); @@ -23,12 +24,37 @@ CTriangleSelector::CTriangleSelector(const ISceneNode* node) //! constructor CTriangleSelector::CTriangleSelector(const IMesh* mesh, const ISceneNode* node) -: SceneNode(node) +: SceneNode(node), AnimatedNode(0) { #ifdef _DEBUG setDebugName("CTriangleSelector"); #endif + createFromMesh(mesh); +} + +CTriangleSelector::CTriangleSelector(IAnimatedMeshSceneNode* node) +: SceneNode(reinterpret_cast(node)), AnimatedNode(node) +{ + #ifdef _DEBUG + setDebugName("CTriangleSelector"); + #endif + + if (!AnimatedNode) + return; + + IAnimatedMesh * animatedMesh = AnimatedNode->getMesh(); + if (!animatedMesh) + return; + + IMesh * mesh = animatedMesh->getMesh((s32)AnimatedNode->getFrameNr()); + + if (mesh) + createFromMesh(mesh); +} + +void CTriangleSelector::createFromMesh(const IMesh * mesh) +{ const u32 cnt = mesh->getMeshBufferCount(); u32 totalFaceCount = 0; for (u32 j=0; jgetMeshBufferCount(); + u32 triangleCount = 0; + + for (u32 i = 0; i < meshBuffers; ++i) + { + IMeshBuffer* buf = mesh->getMeshBuffer(i); + u32 idxCnt = buf->getIndexCount(); + const u16* indices = buf->getIndices(); + + switch (buf->getVertexType()) + { + case video::EVT_STANDARD: + { + video::S3DVertex* vtx = (video::S3DVertex*)buf->getVertices(); + for (u32 index = 0; index < idxCnt; index += 3) + { + core::triangle3df & tri = Triangles[triangleCount++]; + tri.pointA = vtx[indices[index + 0]].Pos; + tri.pointB = vtx[indices[index + 1]].Pos; + tri.pointC = vtx[indices[index + 2]].Pos; + } + } + break; + case video::EVT_2TCOORDS: + { + video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buf->getVertices(); + for (u32 index = 0; index < idxCnt; index += 3) + { + core::triangle3df & tri = Triangles[triangleCount++]; + tri.pointA = vtx[indices[index + 0]].Pos; + tri.pointB = vtx[indices[index + 1]].Pos; + tri.pointC = vtx[indices[index + 2]].Pos; + } + } + break; + case video::EVT_TANGENTS: + { + video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buf->getVertices(); + for (u32 index = 0; index < idxCnt; index += 3) + { + core::triangle3df & tri = Triangles[triangleCount++]; + tri.pointA = vtx[indices[index + 0]].Pos; + tri.pointB = vtx[indices[index + 1]].Pos; + tri.pointC = vtx[indices[index + 2]].Pos; + } + } + break; + } + } +} + //! constructor CTriangleSelector::CTriangleSelector(const core::aabbox3d& box, const ISceneNode* node) @@ -66,11 +148,36 @@ CTriangleSelector::CTriangleSelector(const core::aabbox3d& box, const IScen } + +void CTriangleSelector::update(void) const +{ + if (!AnimatedNode) + return; //< harmless no-op + + s32 currentFrame = (s32)AnimatedNode->getFrameNr(); + if (currentFrame == LastMeshFrame) + return; //< Nothing to do + + LastMeshFrame = currentFrame; + IAnimatedMesh * animatedMesh = AnimatedNode->getMesh(); + + if (animatedMesh) + { + IMesh * mesh = animatedMesh->getMesh(LastMeshFrame); + + if (mesh) + updateFromMesh(mesh); + } +} + //! Gets all triangles. void CTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform) const { + // Update my triangles if necessary + update(); + s32 cnt = Triangles.size(); if (cnt > arraySize) cnt = arraySize; @@ -85,10 +192,9 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles, for (s32 i=0; i& box, const ISceneNode* node); @@ -46,10 +51,26 @@ public: //! Returns amount of all available triangles in this selector virtual s32 getTriangleCount() const; + //! Return the scene node associated with a given triangle. + virtual const ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const { return SceneNode; } + protected: + //! Create from a mesh + virtual void createFromMesh(const IMesh* mesh); + + //! Update when the mesh has changed + virtual void updateFromMesh(const IMesh* mesh) const; + + //! Update the triangle selector, which will only have an effect if it + //! was built from an animated mesh and that mesh's frame has changed + //! since the last time it was updated. + virtual void update(void) const; const ISceneNode* SceneNode; mutable core::array Triangles; + + IAnimatedMeshSceneNode* AnimatedNode; + mutable s32 LastMeshFrame; }; } // end namespace scene diff --git a/src/dep/src/irrlicht/CVideoModeList.cpp b/src/dep/src/irrlicht/CVideoModeList.cpp index 4784eb5..5010c0c 100644 --- a/src/dep/src/irrlicht/CVideoModeList.cpp +++ b/src/dep/src/irrlicht/CVideoModeList.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -18,11 +18,11 @@ CVideoModeList::CVideoModeList() #endif Desktop.depth = 0; - Desktop.size = core::dimension2d(0,0); + Desktop.size = core::dimension2d(0,0); } -void CVideoModeList::setDesktop(s32 desktopDepth, const core::dimension2d& desktopSize) +void CVideoModeList::setDesktop(s32 desktopDepth, const core::dimension2d& desktopSize) { Desktop.depth = desktopDepth; Desktop.size = desktopSize; @@ -37,18 +37,18 @@ s32 CVideoModeList::getVideoModeCount() const //! Returns the screen size of a video mode in pixels. -core::dimension2d CVideoModeList::getVideoModeResolution(s32 modeNumber) const +core::dimension2d CVideoModeList::getVideoModeResolution(s32 modeNumber) const { if (modeNumber < 0 || modeNumber > (s32)VideoModes.size()) - return core::dimension2d(0,0); + return core::dimension2d(0,0); return VideoModes[modeNumber].size; } -core::dimension2d CVideoModeList::getVideoModeResolution( - const core::dimension2d& minSize, - const core::dimension2d& maxSize) const +core::dimension2d CVideoModeList::getVideoModeResolution( + const core::dimension2d& minSize, + const core::dimension2d& maxSize) const { u32 best=VideoModes.size(); // if only one or no mode @@ -96,7 +96,7 @@ s32 CVideoModeList::getVideoModeDepth(s32 modeNumber) const //! Returns current desktop screen resolution. -const core::dimension2d& CVideoModeList::getDesktopResolution() const +const core::dimension2d& CVideoModeList::getDesktopResolution() const { return Desktop.size; } @@ -110,7 +110,7 @@ s32 CVideoModeList::getDesktopDepth() const //! adds a new mode to the list -void CVideoModeList::addMode(const core::dimension2d& size, s32 depth) +void CVideoModeList::addMode(const core::dimension2d& size, s32 depth) { SVideoMode m; m.depth = depth; diff --git a/src/dep/src/irrlicht/CVideoModeList.h b/src/dep/src/irrlicht/CVideoModeList.h index e670e69..3755112 100644 --- a/src/dep/src/irrlicht/CVideoModeList.h +++ b/src/dep/src/irrlicht/CVideoModeList.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -25,30 +25,30 @@ namespace video virtual s32 getVideoModeCount() const; //! Returns the screen size of a video mode in pixels. - virtual core::dimension2d getVideoModeResolution(s32 modeNumber) const; + virtual core::dimension2d getVideoModeResolution(s32 modeNumber) const; //! Returns the screen size of an optimal video mode in pixels. - virtual core::dimension2d getVideoModeResolution(const core::dimension2d& minSize, const core::dimension2d& maxSize) const; + virtual core::dimension2d getVideoModeResolution(const core::dimension2d& minSize, const core::dimension2d& maxSize) const; //! Returns the pixel depth of a video mode in bits. virtual s32 getVideoModeDepth(s32 modeNumber) const; //! Returns current desktop screen resolution. - virtual const core::dimension2d& getDesktopResolution() const; + virtual const core::dimension2d& getDesktopResolution() const; //! Returns the pixel depth of a video mode in bits. virtual s32 getDesktopDepth() const; //! adds a new mode to the list - void addMode(const core::dimension2d& size, s32 depth); + void addMode(const core::dimension2d& size, s32 depth); - void setDesktop(s32 desktopDepth, const core::dimension2d& desktopSize); + void setDesktop(s32 desktopDepth, const core::dimension2d& desktopSize); private: struct SVideoMode { - core::dimension2d size; + core::dimension2d size; s32 depth; bool operator==(const SVideoMode& other) const @@ -59,9 +59,9 @@ namespace video bool operator <(const SVideoMode& other) const { return (size.Width < other.size.Width || - (size.Width == other.size.Width && + (size.Width == other.size.Width && size.Height < other.size.Height) || - (size.Width == other.size.Width && + (size.Width == other.size.Width && size.Height == other.size.Height && depth < other.depth)); } diff --git a/src/dep/src/irrlicht/CVolumeLightSceneNode.cpp b/src/dep/src/irrlicht/CVolumeLightSceneNode.cpp index 10396f5..c28ea8b 100644 --- a/src/dep/src/irrlicht/CVolumeLightSceneNode.cpp +++ b/src/dep/src/irrlicht/CVolumeLightSceneNode.cpp @@ -1,324 +1,202 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h -// -// created by Dean Wadsworth aka Varmint Dec 31 2007 - -#include "CVolumeLightSceneNode.h" -#include "IVideoDriver.h" -#include "ISceneManager.h" -#include "S3DVertex.h" -#include "os.h" - -namespace irr -{ -namespace scene -{ - -//! constructor -CVolumeLightSceneNode::CVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, - s32 id, const u32 subdivU, const u32 subdivV, - const video::SColor foot, - const video::SColor tail, - const core::vector3df& position, - const core::vector3df& rotation, const core::vector3df& scale) - : IVolumeLightSceneNode(parent, mgr, id, position, rotation, scale), - LPDistance(8.0f), SubdivideU(subdivU), SubdivideV(subdivV), - FootColour(foot), TailColour(tail), - LightDimensions(core::vector3df(1.0f, 1.2f, 1.0f)) -{ - #ifdef _DEBUG - setDebugName("CVolumeLightSceneNode"); - #endif - - Buffer = new SMeshBuffer(); - if (Buffer) - { - Buffer->setHardwareMappingHint(EHM_STATIC); - constructLight(); - } -} - - -CVolumeLightSceneNode::~CVolumeLightSceneNode() -{ - if (Buffer) - Buffer->drop(); -} - - -void CVolumeLightSceneNode::addToBuffer(const video::S3DVertex& v) -{ - const s32 tnidx = Buffer->Vertices.linear_reverse_search(v); - const bool alreadyIn = (tnidx != -1); - u16 nidx = (u16)tnidx; - if (!alreadyIn) { - nidx = (u16)Buffer->Vertices.size(); - Buffer->Indices.push_back(nidx); - Buffer->Vertices.push_back(v); - } else - Buffer->Indices.push_back(nidx); -} - - -void CVolumeLightSceneNode::constructLight() -{ - const core::vector3df lightPoint(0, -(LPDistance*LightDimensions.Y), 0); - const f32 ax = LightDimensions.X * 0.5f; // X Axis - const f32 az = LightDimensions.Z * 0.5f; // Z Axis - - Buffer->Vertices.clear(); - Buffer->Vertices.reallocate(6+12*(SubdivideU+SubdivideV)); - Buffer->Indices.clear(); - Buffer->Indices.reallocate(6+12*(SubdivideU+SubdivideV)); - //draw the bottom foot.. the glowing region - addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, FootColour, 0, 1)); - addToBuffer(video::S3DVertex(ax , 0, az, 0,0,0, FootColour, 1, 1)); - addToBuffer(video::S3DVertex(ax , 0,-az, 0,0,0, FootColour, 1, 0)); - - addToBuffer(video::S3DVertex(ax , 0,-az, 0,0,0, FootColour, 1, 0)); - addToBuffer(video::S3DVertex(-ax, 0,-az, 0,0,0, FootColour, 0, 0)); - addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, FootColour, 0, 1)); - - f32 tu = 0.f; - const f32 tuStep = 1.f/SubdivideU; - f32 bx = -ax; - const f32 bxStep = LightDimensions.X * tuStep; - // Slices in X/U space - for (u32 i = 0; i <= SubdivideU; ++i) - { - // These are the two endpoints for a slice at the foot - core::vector3df end1(bx, 0.0f, -az); - core::vector3df end2(bx, 0.0f, az); - - end1 -= lightPoint; // get a vector from point to lightsource - end1.normalize(); // normalize vector - end1 *= LightDimensions.Y; // multiply it out by shootlength - - end1.X += bx; // Add the original point location to the vector - end1.Z -= az; - - // Do it again for the other point. - end2 -= lightPoint; - end2.normalize(); - end2 *= LightDimensions.Y; - - end2.X += bx; - end2.Z += az; - - addToBuffer(video::S3DVertex(bx , 0, az, 0,0,0, FootColour, tu, 1)); - addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, FootColour, tu, 0)); - addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, TailColour, tu, 1)); - - addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, FootColour, tu, 0)); - addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, TailColour, tu, 0)); - addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, TailColour, tu, 1)); - - //back side - addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, TailColour, tu, 1)); - addToBuffer(video::S3DVertex(-bx , 0, -az, 0,0,0, FootColour, tu, 1)); - addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, FootColour, tu, 0)); - - addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, FootColour, tu, 0)); - addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, TailColour, tu, 0)); - addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, TailColour, tu, 1)); - tu += tuStep; - bx += bxStep; - } - - f32 tv = 0.f; - const f32 tvStep = 1.f/SubdivideV; - f32 bz = -az; - const f32 bzStep = LightDimensions.Z * tvStep; - // Slices in Z/V space - for(u32 i = 0; i <= SubdivideV; ++i) - { - // These are the two endpoints for a slice at the foot - core::vector3df end1(-ax, 0.0f, bz); - core::vector3df end2(ax, 0.0f, bz); - - end1 -= lightPoint; // get a vector from point to lightsource - end1.normalize(); // normalize vector - end1 *= LightDimensions.Y; // multiply it out by shootlength - - end1.X -= ax; // Add the original point location to the vector - end1.Z += bz; - - // Do it again for the other point. - end2 -= lightPoint; - end2.normalize(); - end2 *= LightDimensions.Y; - - end2.X += ax; - end2.Z += bz; - - addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, FootColour, 0, tv)); - addToBuffer(video::S3DVertex(ax , 0, bz, 0,0,0, FootColour, 1, tv)); - addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, TailColour, 1, tv)); - - addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, TailColour, 1, tv)); - addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, TailColour, 0, tv)); - addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, FootColour, 0, tv)); - - //back side - addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, FootColour, 0, tv)); - addToBuffer(video::S3DVertex(-ax , 0, -bz, 0,0,0, FootColour, 1, tv)); - addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, TailColour, 1, tv)); - - addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, TailColour, 1, tv)); - addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, TailColour, 0, tv)); - addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, FootColour, 0, tv)); - tv += tvStep; - bz += bzStep; - } - - Buffer->recalculateBoundingBox(); - - Buffer->Material.MaterialType = video::EMT_ONETEXTURE_BLEND; - Buffer->Material.MaterialTypeParam = pack_texureBlendFunc( video::EBF_SRC_COLOR, video::EBF_SRC_ALPHA, video::EMFN_MODULATE_1X ); - - Buffer->Material.Lighting = false; - Buffer->Material.ZWriteEnable = false; - - Buffer->setDirty(EBT_VERTEX_AND_INDEX); -} - - -//! renders the node. -void CVolumeLightSceneNode::render() -{ - if (!Buffer) - return; - - video::IVideoDriver* driver = SceneManager->getVideoDriver(); - driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); - - driver->setMaterial(Buffer->Material); - driver->drawMeshBuffer(Buffer); -} - - -//! returns the axis aligned bounding box of this node -const core::aabbox3d& CVolumeLightSceneNode::getBoundingBox() const -{ - return Buffer->BoundingBox; -} - - -void CVolumeLightSceneNode::OnRegisterSceneNode() -{ - if (IsVisible) - { - SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); - } - ISceneNode::OnRegisterSceneNode(); -} - - -//! returns the material based on the zero based index i. To get the amount -//! of materials used by this scene node, use getMaterialCount(). -//! This function is needed for inserting the node into the scene hirachy on a -//! optimal position for minimizing renderstate changes, but can also be used -//! to directly modify the material of a scene node. -video::SMaterial& CVolumeLightSceneNode::getMaterial(u32 i) -{ - return Buffer->Material; -} - - -//! returns amount of materials used by this scene node. -u32 CVolumeLightSceneNode::getMaterialCount() const -{ - return 1; -} - - -void CVolumeLightSceneNode::setSubDivideU (const u32 inU) -{ - SubdivideU = inU; - constructLight(); -} - - -void CVolumeLightSceneNode::setSubDivideV (const u32 inV) -{ - SubdivideV = inV; - constructLight(); -} - - -void CVolumeLightSceneNode::setFootColour(const video::SColor inColouf) -{ - FootColour = inColouf; - constructLight(); -} - - -void CVolumeLightSceneNode::setTailColour(const video::SColor inColouf) -{ - TailColour = inColouf; - constructLight(); -} - - -//! Writes attributes of the scene node. -void CVolumeLightSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const -{ - ISceneNode::serializeAttributes(out, options); - - out->addFloat("lpDistance", LPDistance); - out->addInt("subDivideU", SubdivideU); - out->addInt("subDivideV", SubdivideV); - - out->addColor("footColour", FootColour); - out->addColor("tailColour", TailColour); - - out->addVector3d("lightDimension", LightDimensions); -} - - -//! Reads attributes of the scene node. -void CVolumeLightSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) -{ - LPDistance = in->getAttributeAsFloat("lpDistance"); - LPDistance = core::max_(LPDistance, 8.0f); - - SubdivideU = in->getAttributeAsInt("subDivideU"); - SubdivideU = core::max_(SubdivideU, 1u); - - SubdivideV = in->getAttributeAsInt("subDivideV"); - SubdivideV = core::max_(SubdivideV, 1u); - - FootColour = in->getAttributeAsColor("footColour"); - TailColour = in->getAttributeAsColor("tailColour"); - - LightDimensions = in->getAttributeAsVector3d("lightDimension"); - - constructLight(); - - ISceneNode::deserializeAttributes(in, options); -} - - -//! Creates a clone of this scene node and its children. -ISceneNode* CVolumeLightSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) -{ - if (!newParent) - newParent = Parent; - if (!newManager) - newManager = SceneManager; - - CVolumeLightSceneNode* nb = new CVolumeLightSceneNode(newParent, - newManager, ID, SubdivideU, SubdivideV, FootColour, TailColour, RelativeTranslation); - - nb->cloneMembers(this, newManager); - nb->Buffer->Material = Buffer->Material; - - nb->drop(); - return nb; -} - - -} // end namespace scene -} // end namespace irr - +// Copyright (C) 2007-2010 Dean Wadsworth +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CVolumeLightSceneNode.h" +#include "IVideoDriver.h" +#include "ISceneManager.h" +#include "S3DVertex.h" +#include "os.h" + +namespace irr +{ +namespace scene +{ + +//! constructor +CVolumeLightSceneNode::CVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, + s32 id, const u32 subdivU, const u32 subdivV, + const video::SColor foot, + const video::SColor tail, + const core::vector3df& position, + const core::vector3df& rotation, const core::vector3df& scale) + : IVolumeLightSceneNode(parent, mgr, id, position, rotation, scale), + Mesh(0), LPDistance(8.0f), + SubdivideU(subdivU), SubdivideV(subdivV), + FootColor(foot), TailColor(tail), + LightDimensions(core::vector3df(1.0f, 1.2f, 1.0f)) +{ + #ifdef _DEBUG + setDebugName("CVolumeLightSceneNode"); + #endif + + constructLight(); +} + + +CVolumeLightSceneNode::~CVolumeLightSceneNode() +{ + if (Mesh) + Mesh->drop(); +} + + +void CVolumeLightSceneNode::constructLight() +{ + if (Mesh) + Mesh->drop(); + Mesh = SceneManager->getGeometryCreator()->createVolumeLightMesh(SubdivideU, SubdivideV, FootColor, TailColor, LPDistance, LightDimensions); +} + + +//! renders the node. +void CVolumeLightSceneNode::render() +{ + if (!Mesh) + return; + + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + + driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); + driver->drawMeshBuffer(Mesh->getMeshBuffer(0)); +} + + +//! returns the axis aligned bounding box of this node +const core::aabbox3d& CVolumeLightSceneNode::getBoundingBox() const +{ + return Mesh->getBoundingBox(); +} + + +void CVolumeLightSceneNode::OnRegisterSceneNode() +{ + if (IsVisible) + { + SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); + } + ISceneNode::OnRegisterSceneNode(); +} + + +//! returns the material based on the zero based index i. To get the amount +//! of materials used by this scene node, use getMaterialCount(). +//! This function is needed for inserting the node into the scene hirachy on a +//! optimal position for minimizing renderstate changes, but can also be used +//! to directly modify the material of a scene node. +video::SMaterial& CVolumeLightSceneNode::getMaterial(u32 i) +{ + return Mesh->getMeshBuffer(i)->getMaterial(); +} + + +//! returns amount of materials used by this scene node. +u32 CVolumeLightSceneNode::getMaterialCount() const +{ + return 1; +} + + +void CVolumeLightSceneNode::setSubDivideU (const u32 inU) +{ + if (inU != SubdivideU) + { + SubdivideU = inU; + constructLight(); + } +} + + +void CVolumeLightSceneNode::setSubDivideV (const u32 inV) +{ + if (inV != SubdivideV) + { + SubdivideV = inV; + constructLight(); + } +} + + +void CVolumeLightSceneNode::setFootColor(const video::SColor inColor) +{ + if (inColor != FootColor) + { + FootColor = inColor; + constructLight(); + } +} + + +void CVolumeLightSceneNode::setTailColor(const video::SColor inColor) +{ + if (inColor != TailColor) + { + TailColor = inColor; + constructLight(); + } +} + + +//! Writes attributes of the scene node. +void CVolumeLightSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + ISceneNode::serializeAttributes(out, options); + + out->addFloat("lpDistance", LPDistance); + out->addInt("subDivideU", SubdivideU); + out->addInt("subDivideV", SubdivideV); + + out->addColor("footColor", FootColor); + out->addColor("tailColor", TailColor); + + out->addVector3d("lightDimension", LightDimensions); +} + + +//! Reads attributes of the scene node. +void CVolumeLightSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + LPDistance = in->getAttributeAsFloat("lpDistance"); + LPDistance = core::max_(LPDistance, 8.0f); + + SubdivideU = in->getAttributeAsInt("subDivideU"); + SubdivideU = core::max_(SubdivideU, 1u); + + SubdivideV = in->getAttributeAsInt("subDivideV"); + SubdivideV = core::max_(SubdivideV, 1u); + + FootColor = in->getAttributeAsColor("footColor"); + TailColor = in->getAttributeAsColor("tailColor"); + + LightDimensions = in->getAttributeAsVector3d("lightDimension"); + + constructLight(); + + ISceneNode::deserializeAttributes(in, options); +} + + +//! Creates a clone of this scene node and its children. +ISceneNode* CVolumeLightSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) +{ + if (!newParent) + newParent = Parent; + if (!newManager) + newManager = SceneManager; + + CVolumeLightSceneNode* nb = new CVolumeLightSceneNode(newParent, + newManager, ID, SubdivideU, SubdivideV, FootColor, TailColor, RelativeTranslation); + + nb->cloneMembers(this, newManager); + nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial(); + + if ( newParent ) + nb->drop(); + return nb; +} + + +} // end namespace scene +} // end namespace irr + diff --git a/src/dep/src/irrlicht/CVolumeLightSceneNode.h b/src/dep/src/irrlicht/CVolumeLightSceneNode.h index 68ade2b..8eed83c 100644 --- a/src/dep/src/irrlicht/CVolumeLightSceneNode.h +++ b/src/dep/src/irrlicht/CVolumeLightSceneNode.h @@ -1,98 +1,93 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h -// -// created by Dean Wadsworth aka Varmint Dec 31 2007 - -#ifndef __VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ -#define __VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ - -#include "IVolumeLightSceneNode.h" -#include "SMeshBuffer.h" - -namespace irr -{ -namespace scene -{ - class CVolumeLightSceneNode : public IVolumeLightSceneNode - { - public: - - //! constructor - CVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, - const u32 subdivU = 32, const u32 subdivV = 32, - const video::SColor foot = video::SColor(51, 0, 230, 180), - const video::SColor tail = video::SColor(0, 0, 0, 0), - const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& rotation = core::vector3df(0,0,0), - const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); - - virtual ~CVolumeLightSceneNode(); - - virtual void OnRegisterSceneNode(); - - //! renders the node. - virtual void render(); - - //! returns the axis aligned bounding box of this node - virtual const core::aabbox3d& getBoundingBox() const; - - //! returns the material based on the zero based index i. To get the amount - //! of materials used by this scene node, use getMaterialCount(). - //! This function is needed for inserting the node into the scene hirachy on a - //! optimal position for minimizing renderstate changes, but can also be used - //! to directly modify the material of a scene node. - virtual video::SMaterial& getMaterial(u32 i); - - //! returns amount of materials used by this scene node. - virtual u32 getMaterialCount() const; - - //! Returns type of the scene node - virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; } - - //! Writes attributes of the scene node. - virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; - - //! Reads attributes of the scene node. - virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); - - //! Creates a clone of this scene node and its children. - virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); - - virtual void setSubDivideU (const u32 inU); - virtual void setSubDivideV (const u32 inV); - - virtual u32 getSubDivideU () const { return SubdivideU; } - virtual u32 getSubDivideV () const { return SubdivideV; } - - virtual void setFootColour(const video::SColor inColouf); - virtual void setTailColour(const video::SColor inColouf); - - virtual video::SColor getFootColour () const { return FootColour; } - virtual video::SColor getTailColour () const { return TailColour; } - - private: - void addToBuffer(const video::S3DVertex& v); - void constructLight(); - - SMeshBuffer* Buffer; - - f32 LPDistance; // Distance to hypothetical lightsource point -- affects fov angle - - u32 SubdivideU; // Number of subdivisions in U and V space. - u32 SubdivideV; // Controls the number of "slices" in the volume. - // NOTE : Total number of polygons = 2 + ((SubdivideU + 1) + (SubdivideV + 1)) * 2 - // Each slice being a quad plus the rectangular plane at the bottom. - - video::SColor FootColour; // Color at the source - video::SColor TailColour; // Color at the end. - - core::vector3df LightDimensions; // LightDimensions.Y Distance of shooting -- Length of beams - // LightDimensions.X and LightDimensions.Z determine the size/dimension of the plane - }; - -} // end namespace scene -} // end namespace irr - -#endif - +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h +// +// created by Dean Wadsworth aka Varmint Dec 31 2007 + +#ifndef __VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ +#define __VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ + +#include "IVolumeLightSceneNode.h" +#include "IMesh.h" + +namespace irr +{ +namespace scene +{ + class CVolumeLightSceneNode : public IVolumeLightSceneNode + { + public: + + //! constructor + CVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const u32 subdivU = 32, const u32 subdivV = 32, + const video::SColor foot = video::SColor(51, 0, 230, 180), + const video::SColor tail = video::SColor(0, 0, 0, 0), + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); + + virtual ~CVolumeLightSceneNode(); + + virtual void OnRegisterSceneNode(); + + //! renders the node. + virtual void render(); + + //! returns the axis aligned bounding box of this node + virtual const core::aabbox3d& getBoundingBox() const; + + //! returns the material based on the zero based index i. + virtual video::SMaterial& getMaterial(u32 i); + + //! returns amount of materials used by this scene node. + virtual u32 getMaterialCount() const; + + //! Returns type of the scene node + virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; } + + //! Writes attributes of the scene node. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; + + //! Reads attributes of the scene node. + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); + + //! Creates a clone of this scene node and its children. + virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); + + virtual void setSubDivideU(const u32 inU); + virtual void setSubDivideV(const u32 inV); + + virtual u32 getSubDivideU() const { return SubdivideU; } + virtual u32 getSubDivideV() const { return SubdivideV; } + + virtual void setFootColor(const video::SColor inColor); + virtual void setTailColor(const video::SColor inColor); + + virtual video::SColor getFootColor() const { return FootColor; } + virtual video::SColor getTailColor() const { return TailColor; } + + private: + void constructLight(); + + IMesh* Mesh; + + f32 LPDistance; // Distance to hypothetical lightsource point -- affects fov angle + + u32 SubdivideU; // Number of subdivisions in U and V space. + u32 SubdivideV; // Controls the number of "slices" in the volume. + // NOTE : Total number of polygons = 2 + ((SubdivideU + 1) + (SubdivideV + 1)) * 2 + // Each slice being a quad plus the rectangular plane at the bottom. + + video::SColor FootColor; // Color at the source + video::SColor TailColor; // Color at the end. + + core::vector3df LightDimensions; // LightDimensions.Y Distance of shooting -- Length of beams + // LightDimensions.X and LightDimensions.Z determine the size/dimension of the plane + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/src/dep/src/irrlicht/CWaterSurfaceSceneNode.cpp b/src/dep/src/irrlicht/CWaterSurfaceSceneNode.cpp index c83a2e3..98389f7 100644 --- a/src/dep/src/irrlicht/CWaterSurfaceSceneNode.cpp +++ b/src/dep/src/irrlicht/CWaterSurfaceSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -16,12 +16,13 @@ namespace scene { //! constructor -CWaterSurfaceSceneNode::CWaterSurfaceSceneNode(f32 waveHeight, f32 waveSpeed, f32 waveLength, +CWaterSurfaceSceneNode::CWaterSurfaceSceneNode(f32 waveHeight, f32 waveSpeed, f32 waveLength, IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) -: CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale), WaveLength(waveLength), - WaveSpeed(waveSpeed), WaveHeight(waveHeight), OriginalMesh(0) + : CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale), + WaveLength(waveLength), WaveSpeed(waveSpeed), WaveHeight(waveHeight), + OriginalMesh(0) { #ifdef _DEBUG setDebugName("CWaterSurfaceSceneNode"); @@ -38,7 +39,6 @@ CWaterSurfaceSceneNode::CWaterSurfaceSceneNode(f32 waveHeight, f32 waveSpeed, f3 } - //! destructor CWaterSurfaceSceneNode::~CWaterSurfaceSceneNode() { @@ -48,44 +48,48 @@ CWaterSurfaceSceneNode::~CWaterSurfaceSceneNode() } - //! frame void CWaterSurfaceSceneNode::OnRegisterSceneNode() { - if (IsVisible) - { - SceneManager->registerNodeForRendering(this); - - animateWaterSurface(); - - CMeshSceneNode::OnRegisterSceneNode(); - } + CMeshSceneNode::OnRegisterSceneNode(); } - -void CWaterSurfaceSceneNode::animateWaterSurface() +void CWaterSurfaceSceneNode::OnAnimate(u32 timeMs) { - if (!Mesh) - return; - - u32 meshBufferCount = Mesh->getMeshBufferCount(); - f32 time = os::Timer::getTime() / WaveSpeed; - - for (u32 b=0; bgetMeshBuffer(b)->getVertexCount(); + const u32 meshBufferCount = Mesh->getMeshBufferCount(); + const f32 time = timeMs / WaveSpeed; - for (u32 i=0; igetMeshBuffer(b)->getPosition(i), - OriginalMesh->getMeshBuffer(b)->getPosition(i), - time); - }// end for all mesh buffers + for (u32 b=0; bgetMeshBuffer(b)->getVertexCount(); - SceneManager->getMeshManipulator()->recalculateNormals(Mesh); + for (u32 i=0; igetMeshBuffer(b)->getPosition(i).Y = addWave( + OriginalMesh->getMeshBuffer(b)->getPosition(i), + time); + }// end for all mesh buffers + + SceneManager->getMeshManipulator()->recalculateNormals(Mesh); + } + CMeshSceneNode::OnAnimate(timeMs); } +void CWaterSurfaceSceneNode::setMesh(IMesh* mesh) +{ + CMeshSceneNode::setMesh(mesh); + if (!mesh) + return; + if (OriginalMesh) + OriginalMesh->drop(); + IMesh* clone = SceneManager->getMeshManipulator()->createMeshCopy(mesh); + OriginalMesh = mesh; + Mesh = clone; +} + //! Writes attributes of the scene node. void CWaterSurfaceSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const @@ -93,10 +97,10 @@ void CWaterSurfaceSceneNode::serializeAttributes(io::IAttributes* out, io::SAttr out->addFloat("WaveLength", WaveLength); out->addFloat("WaveSpeed", WaveSpeed); out->addFloat("WaveHeight", WaveHeight); - + CMeshSceneNode::serializeAttributes(out, options); // serialize original mesh - out->setAttribute("Mesh", SceneManager->getMeshCache()->getMeshFilename(OriginalMesh)); + out->setAttribute("Mesh", SceneManager->getMeshCache()->getMeshName(OriginalMesh).getPath().c_str()); } @@ -106,7 +110,7 @@ void CWaterSurfaceSceneNode::deserializeAttributes(io::IAttributes* in, io::SAtt WaveLength = in->getAttributeAsFloat("WaveLength"); WaveSpeed = in->getAttributeAsFloat("WaveSpeed"); WaveHeight = in->getAttributeAsFloat("WaveHeight"); - + if (Mesh) { Mesh->drop(); @@ -124,6 +128,14 @@ void CWaterSurfaceSceneNode::deserializeAttributes(io::IAttributes* in, io::SAtt } } + +f32 CWaterSurfaceSceneNode::addWave(const core::vector3df &source, f32 time) const +{ + return source.Y + + (sinf(((source.X/WaveLength) + time)) * WaveHeight) + + (cosf(((source.Z/WaveLength) + time)) * WaveHeight); +} + } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CWaterSurfaceSceneNode.h b/src/dep/src/irrlicht/CWaterSurfaceSceneNode.h index 6ccb053..d879985 100644 --- a/src/dep/src/irrlicht/CWaterSurfaceSceneNode.h +++ b/src/dep/src/irrlicht/CWaterSurfaceSceneNode.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -12,8 +12,6 @@ namespace irr namespace scene { - // TODO: It seems that we have to overwrite setMesh as it should replace - // OriginalMesh class CWaterSurfaceSceneNode : public CMeshSceneNode { public: @@ -28,9 +26,15 @@ namespace scene //! destructor virtual ~CWaterSurfaceSceneNode(); - //! frame + //! frame registration virtual void OnRegisterSceneNode(); + //! animated update + virtual void OnAnimate(u32 timeMs); + + //! Update mesh + virtual void setMesh(IMesh* mesh); + //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_WATER_SURFACE; } @@ -42,13 +46,7 @@ namespace scene private: - void animateWaterSurface(); - void addWave(core::vector3df& dest, const core::vector3df source, f32 time) - { - dest.Y = source.Y + - (sinf(((source.X/WaveLength) + time)) * WaveHeight) + - (cosf(((source.Z/WaveLength) + time)) * WaveHeight); - } + inline f32 addWave(const core::vector3df &source, f32 time) const; f32 WaveLength; f32 WaveSpeed; diff --git a/src/dep/src/irrlicht/CWriteFile.cpp b/src/dep/src/irrlicht/CWriteFile.cpp index 1dd1f61..4043dcd 100644 --- a/src/dep/src/irrlicht/CWriteFile.cpp +++ b/src/dep/src/irrlicht/CWriteFile.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,7 +11,7 @@ namespace io { -CWriteFile::CWriteFile(const c8* fileName, bool append) +CWriteFile::CWriteFile(const io::path& fileName, bool append) : FileSize(0) { #ifdef _DEBUG @@ -46,7 +46,7 @@ s32 CWriteFile::write(const void* buffer, u32 sizeToWrite) if (!isOpen()) return 0; - return fwrite(buffer, 1, sizeToWrite, File); + return (s32)fwrite(buffer, 1, sizeToWrite, File); } @@ -78,10 +78,14 @@ void CWriteFile::openFile(bool append) if (Filename.size() == 0) { File = 0; - return; + return; } +#if defined(_IRR_WCHAR_FILESYSTEM) + File = _wfopen(Filename.c_str(), append ? L"ab" : L"wb"); +#else File = fopen(Filename.c_str(), append ? "ab" : "wb"); +#endif if (File) { @@ -96,14 +100,14 @@ void CWriteFile::openFile(bool append) //! returns name of file -const c8* CWriteFile::getFileName() const +const io::path& CWriteFile::getFileName() const { - return Filename.c_str(); + return Filename; } -IWriteFile* createWriteFile(const c8* fileName, bool append) +IWriteFile* createWriteFile(const io::path& fileName, bool append) { CWriteFile* file = new CWriteFile(fileName, append); if (file->isOpen()) diff --git a/src/dep/src/irrlicht/CWriteFile.h b/src/dep/src/irrlicht/CWriteFile.h index e8dae3a..c0f0772 100644 --- a/src/dep/src/irrlicht/CWriteFile.h +++ b/src/dep/src/irrlicht/CWriteFile.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -22,8 +22,7 @@ namespace io { public: - CWriteFile(const wchar_t* fileName, bool append); - CWriteFile(const c8* fileName, bool append); + CWriteFile(const io::path& fileName, bool append); virtual ~CWriteFile(); @@ -37,7 +36,7 @@ namespace io virtual long getPos() const; //! Returns name of file. - virtual const c8* getFileName() const; + virtual const io::path& getFileName() const; //! returns if file is open bool isOpen() const; @@ -47,7 +46,7 @@ namespace io //! opens the file void openFile(bool append); - core::stringc Filename; + io::path Filename; FILE* File; long FileSize; }; diff --git a/src/dep/src/irrlicht/CXMLReader.cpp b/src/dep/src/irrlicht/CXMLReader.cpp index 6de37ab..6c19dc8 100644 --- a/src/dep/src/irrlicht/CXMLReader.cpp +++ b/src/dep/src/irrlicht/CXMLReader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CXMLReader.h b/src/dep/src/irrlicht/CXMLReader.h index 67005ff..155c4c0 100644 --- a/src/dep/src/irrlicht/CXMLReader.h +++ b/src/dep/src/irrlicht/CXMLReader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CXMLReaderImpl.h b/src/dep/src/irrlicht/CXMLReaderImpl.h index 11594ae..b259339 100644 --- a/src/dep/src/irrlicht/CXMLReaderImpl.h +++ b/src/dep/src/irrlicht/CXMLReaderImpl.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h @@ -139,14 +139,24 @@ public: //! Returns the value of an attribute as integer. int getAttributeValueAsInt(const char_type* name) const { - return (int)getAttributeValueAsFloat(name); + const SAttribute* attr = getAttributeByName(name); + if (!attr) + return 0; + + core::stringc c(attr->Value.c_str()); + return core::strtol10(c.c_str()); } //! Returns the value of an attribute as integer. int getAttributeValueAsInt(int idx) const { - return (int)getAttributeValueAsFloat(idx); + const char_type* attrvalue = getAttributeValue(idx); + if (!attrvalue) + return 0; + + core::stringc c(attrvalue); + return core::strtol10(c.c_str()); } @@ -555,7 +565,7 @@ private: long size = callback->getSize(); if (size<0) return false; - size += 4; // We need two terminating 0's at the end. + size += 4; // We need four terminating 0's at the end. // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4. char* data8 = new char[size]; @@ -588,35 +598,35 @@ private: { // UTF-32, big endian SourceFormat = ETF_UTF32_BE; - convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header + convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header } else if (size >= 4 && data32[0] == (char32)UTF32_LE) { // UTF-32, little endian SourceFormat = ETF_UTF32_LE; - convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header + convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header } else if (size >= 2 && data16[0] == UTF16_BE) { // UTF-16, big endian SourceFormat = ETF_UTF16_BE; - convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header + convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header } else if (size >= 2 && data16[0] == UTF16_LE) { // UTF-16, little endian SourceFormat = ETF_UTF16_LE; - convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header + convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header } else - if (size >= 3 && data8[0] == UTF8[0] && data8[1] == UTF8[1] && data8[2] == UTF8[2]) + if (size >= 3 && memcmp(data8,UTF8,3)==0) { // UTF-8 SourceFormat = ETF_UTF8; - convertTextData(data8+3, data8, size); // data8+3 because we need to skip the header + convertTextData(data8+3, data8, size-3); // data8+3 because we need to skip the header } else { diff --git a/src/dep/src/irrlicht/CXMLWriter.cpp b/src/dep/src/irrlicht/CXMLWriter.cpp index ffc7c4e..4076305 100644 --- a/src/dep/src/irrlicht/CXMLWriter.cpp +++ b/src/dep/src/irrlicht/CXMLWriter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CXMLWriter.h b/src/dep/src/irrlicht/CXMLWriter.h index f3667e0..05a17f6 100644 --- a/src/dep/src/irrlicht/CXMLWriter.h +++ b/src/dep/src/irrlicht/CXMLWriter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/CXMeshFileLoader.cpp b/src/dep/src/irrlicht/CXMeshFileLoader.cpp index 62a098d..8a9985a 100644 --- a/src/dep/src/irrlicht/CXMeshFileLoader.cpp +++ b/src/dep/src/irrlicht/CXMeshFileLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -28,9 +28,9 @@ namespace scene //! Constructor CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) -: SceneManager(smgr), FileSystem(fs), AnimatedMesh(0), MajorVersion(0), - MinorVersion(0), BinaryFormat(false), BinaryNumCount(0), Buffer(0), - P(0), End(0), FloatSize(0), CurFrame(0) +: SceneManager(smgr), FileSystem(fs), AllJoints(0), AnimatedMesh(0), + Buffer(0), P(0), End(0), BinaryNumCount(0), Line(0), + CurFrame(0), MajorVersion(0), MinorVersion(0), BinaryFormat(false), FloatSize(0) { #ifdef _DEBUG setDebugName("CXMeshFileLoader"); @@ -40,9 +40,9 @@ CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CXMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CXMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { - return strncmp(&filename[strlen(filename)-2], ".x", 2) == 0; + return core::hasFileExtension ( filename, "x" ); } @@ -116,7 +116,13 @@ bool CXMeshFileLoader::load(io::IReadFile* file) // default material if nothing loaded if (!mesh->Materials.size()) + { mesh->Materials.push_back(video::SMaterial()); + mesh->Materials[0].DiffuseColor.set(0xff777777); + mesh->Materials[0].Shininess=0.f; + mesh->Materials[0].SpecularColor.set(0xff777777); + mesh->Materials[0].EmissiveColor.set(0xff000000); + } u32 i; @@ -126,7 +132,7 @@ bool CXMeshFileLoader::load(io::IReadFile* file) #endif for (i=0; iMaterials.size(); ++i) { - mesh->Buffers.push_back( AnimatedMesh->createBuffer() ); + mesh->Buffers.push_back( AnimatedMesh->addMeshBuffer() ); mesh->Buffers.getLast()->Material = mesh->Materials[i]; if (!mesh->HasSkinning) @@ -139,6 +145,13 @@ bool CXMeshFileLoader::load(io::IReadFile* file) } } + if (!mesh->FaceMaterialIndices.size()) + { + mesh->FaceMaterialIndices.set_used(mesh->Indices.size() / 3); + for (i=0; iFaceMaterialIndices.size(); ++i) + mesh->FaceMaterialIndices[i]=0; + } + if (!mesh->HasVertexColors) { for (u32 j=0;jFaceMaterialIndices.size();++j) @@ -243,7 +256,7 @@ bool CXMeshFileLoader::load(io::IReadFile* file) { for (u32 k=1; k < verticesLinkBuffer[id].size(); ++k) { - ISkinnedMesh::SWeight* WeightClone = AnimatedMesh->createWeight(joint); + ISkinnedMesh::SWeight* WeightClone = AnimatedMesh->addWeight(joint); WeightClone->strength = weight.strength; WeightClone->vertex_id = verticesLinkIndex[id][k]; WeightClone->buffer_id = verticesLinkBuffer[id][k]; @@ -293,8 +306,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 +326,19 @@ 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] ); + // We have a problem with correct tcoord2 handling here + // crash fixed for now by checking the values + buffer->Vertices_2TCoords.getLast().TCoords2=(iTCoords2.size())?mesh->TCoords2[i]:mesh->Vertices[i].TCoords; + } + else + { + verticesLinkIndex[i] = buffer->Vertices_Standard.size(); + buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); + } } // count indices per buffer and reallocate @@ -415,7 +450,7 @@ bool CXMeshFileLoader::readFileIntoMemory(io::IReadFile* file) P = &Buffer[16]; readUntilEndOfLine(); - FilePath = stripPathFromString(file->getFileName(),true); + FilePath = FileSystem->getFileDir(file->getFileName()) + "/"; return true; } @@ -457,14 +492,11 @@ bool CXMeshFileLoader::parseDataObject() if (objectName == "Mesh") { // some meshes have no frames at all - //CurFrame = AnimatedMesh->createJoint(0); - - //CurFrame->Meshes.push_back(SXMesh()); - //return parseDataObjectMesh(CurFrame->Meshes.getLast()); + //CurFrame = AnimatedMesh->addJoint(0); SXMesh *mesh=new SXMesh; - //mesh->Buffer=AnimatedMesh->createBuffer(); + //mesh->Buffer=AnimatedMesh->addMeshBuffer(); Meshes.push_back(mesh); return parseDataObjectMesh(*mesh); @@ -507,8 +539,8 @@ bool CXMeshFileLoader::parseDataObjectTemplate() if (!readHeadOfDataObject(&name)) { os::Printer::log("Left delimiter in template data object missing.", - name.c_str(), ELL_ERROR); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + name.c_str(), ELL_WARNING); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -531,8 +563,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"); @@ -551,7 +582,7 @@ bool CXMeshFileLoader::parseDataObjectFrame( CSkinnedMesh::SJoint *Parent ) if (!readHeadOfDataObject(&name)) { os::Printer::log("No opening brace in Frame found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -575,7 +606,7 @@ bool CXMeshFileLoader::parseDataObjectFrame( CSkinnedMesh::SJoint *Parent ) #ifdef _XREADER_DEBUG os::Printer::log("creating joint ", name.c_str()); #endif - joint=AnimatedMesh->createJoint(Parent); + joint=AnimatedMesh->addJoint(Parent); joint->Name=name; JointID=AnimatedMesh->getAllJoints().size()-1; } @@ -602,7 +633,7 @@ bool CXMeshFileLoader::parseDataObjectFrame( CSkinnedMesh::SJoint *Parent ) if (objectName.size() == 0) { os::Printer::log("Unexpected ending found in Frame in x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } else @@ -665,7 +696,7 @@ bool CXMeshFileLoader::parseDataObjectTransformationMatrix(core::matrix4 &mat) if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Transformation Matrix found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -674,14 +705,13 @@ bool CXMeshFileLoader::parseDataObjectTransformationMatrix(core::matrix4 &mat) if (!checkForOneFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Transformation Matrix found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Transformation Matrix found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -699,7 +729,7 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) os::Printer::log("CXFileReader: Reading mesh"); #endif os::Printer::log("No opening brace in Mesh found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -721,8 +751,7 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) if (!checkForTwoFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Mesh Vertex Array found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } // read faces @@ -743,7 +772,7 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) if (fcnt < 3) { os::Printer::log("Invalid face count (<3) found in Mesh x file reader.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -751,7 +780,7 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) polygonfaces.set_used(fcnt); u32 triangles = (fcnt-2); mesh.Indices.set_used(mesh.Indices.size() + ((triangles-1)*3)); - mesh.IndexCountPerFace[k] = triangles * 3; + mesh.IndexCountPerFace[k] = (u16)(triangles * 3); for (u32 f=0; f>8)&0xf)*sizeof(core::vector2df); + for (u32 j=0; jgetAllJoints().size(); - joint=AnimatedMesh->createJoint(0); + joint=AnimatedMesh->addJoint(0); joint->Name=TransformNodeName; } @@ -1064,7 +1132,7 @@ bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh) mesh.WeightJoint.push_back(n); mesh.WeightNum.push_back(joint->Weights.size()); - CSkinnedMesh::SWeight *weight=AnimatedMesh->createWeight(joint); + CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(joint); weight->buffer_id=0; weight->vertex_id=readInt(); @@ -1087,14 +1155,13 @@ bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh) if (!checkForOneFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Skin Weights found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Skin Weights found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1111,7 +1178,7 @@ bool CXMeshFileLoader::parseDataObjectSkinMeshHeader(SXMesh& mesh) if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Skin Mesh header found in .x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1125,7 +1192,7 @@ bool CXMeshFileLoader::parseDataObjectSkinMeshHeader(SXMesh& mesh) if (!checkForClosingBrace()) { os::Printer::log("No closing brace in skin mesh header in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1142,7 +1209,7 @@ bool CXMeshFileLoader::parseDataObjectMeshNormals(SXMesh &mesh) if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Mesh Normals found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1158,8 +1225,7 @@ bool CXMeshFileLoader::parseDataObjectMeshNormals(SXMesh &mesh) if (!checkForTwoFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Mesh Normals Array found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } core::array normalIndices; @@ -1179,7 +1245,7 @@ bool CXMeshFileLoader::parseDataObjectMeshNormals(SXMesh &mesh) if (indexcount != mesh.IndexCountPerFace[k]) { os::Printer::log("Not matching normal and face index count found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1211,14 +1277,13 @@ bool CXMeshFileLoader::parseDataObjectMeshNormals(SXMesh &mesh) if (!checkForTwoFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Mesh Face Normals Array found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Mesh Normals found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1235,7 +1300,7 @@ bool CXMeshFileLoader::parseDataObjectMeshTextureCoords(SXMesh &mesh) if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Mesh Texture Coordinates found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1246,14 +1311,13 @@ bool CXMeshFileLoader::parseDataObjectMeshTextureCoords(SXMesh &mesh) if (!checkForTwoFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Mesh Texture Coordinates Array found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Mesh Texture Coordinates Array found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1270,7 +1334,7 @@ bool CXMeshFileLoader::parseDataObjectMeshVertexColors(SXMesh &mesh) if (!readHeadOfDataObject()) { os::Printer::log("No opening brace for Mesh Vertex Colors found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1282,7 +1346,7 @@ bool CXMeshFileLoader::parseDataObjectMeshVertexColors(SXMesh &mesh) if (Index>=mesh.Vertices.size()) { os::Printer::log("index value in parseDataObjectMeshVertexColors out of bounds", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } readRGBA(mesh.Vertices[Index].Color); @@ -1292,14 +1356,13 @@ bool CXMeshFileLoader::parseDataObjectMeshVertexColors(SXMesh &mesh) if (!checkForOneFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Mesh Vertex Colors Array found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Mesh Texture Coordinates Array found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1316,7 +1379,7 @@ bool CXMeshFileLoader::parseDataObjectMeshMaterialList(SXMesh &mesh) if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Mesh Material List found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1362,7 +1425,7 @@ bool CXMeshFileLoader::parseDataObjectMeshMaterialList(SXMesh &mesh) if (objectName.size() == 0) { os::Printer::log("Unexpected ending found in Mesh Material list in .x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } else @@ -1412,7 +1475,7 @@ bool CXMeshFileLoader::parseDataObjectMaterial(video::SMaterial& material) if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Mesh Material found in .x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1429,6 +1492,7 @@ bool CXMeshFileLoader::parseDataObjectMaterial(video::SMaterial& material) readRGB(material.EmissiveColor); checkForOneFollowingSemicolons(); // read other data objects + int textureLayer=0; while(true) { core::stringc objectName = getNextToken(); @@ -1436,7 +1500,7 @@ bool CXMeshFileLoader::parseDataObjectMaterial(video::SMaterial& material) if (objectName.size() == 0) { os::Printer::log("Unexpected ending found in Mesh Material in .x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } else @@ -1453,18 +1517,21 @@ bool CXMeshFileLoader::parseDataObjectMaterial(video::SMaterial& material) return false; // original name - if (FileSystem->existFile(TextureFileName.c_str())) - material.setTexture(0, SceneManager->getVideoDriver()->getTexture (TextureFileName.c_str())); + if (FileSystem->existFile(TextureFileName)) + material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); // mesh path else { - TextureFileName=FilePath + stripPathFromString(TextureFileName,false); - if (FileSystem->existFile(TextureFileName.c_str())) - material.setTexture(0, SceneManager->getVideoDriver()->getTexture(TextureFileName.c_str())); + TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); + if (FileSystem->existFile(TextureFileName)) + material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); // working directory else - material.setTexture(0, SceneManager->getVideoDriver()->getTexture(stripPathFromString(TextureFileName,false).c_str())); + material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); } + ++textureLayer; + if (textureLayer==2) + material.MaterialType=video::EMT_LIGHTMAP; } else if (objectName.equals_ignore_case("NormalmapFilename")) @@ -1475,18 +1542,20 @@ bool CXMeshFileLoader::parseDataObjectMaterial(video::SMaterial& material) return false; // original name - if (FileSystem->existFile(TextureFileName.c_str())) - material.setTexture(1, SceneManager->getVideoDriver()->getTexture (TextureFileName.c_str())); + if (FileSystem->existFile(TextureFileName)) + material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); // mesh path else { - TextureFileName=FilePath + stripPathFromString(TextureFileName,false); - if (FileSystem->existFile(TextureFileName.c_str())) - material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName.c_str())); + TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); + if (FileSystem->existFile(TextureFileName)) + material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); // working directory else - material.setTexture(1, SceneManager->getVideoDriver()->getTexture(stripPathFromString(TextureFileName,false).c_str())); + material.setTexture(1, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); } + if (textureLayer==1) + ++textureLayer; } else { @@ -1511,7 +1580,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationSet() if (!readHeadOfDataObject(&AnimationName)) { os::Printer::log("No opening brace in Animation Set found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1522,7 +1591,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationSet() if (objectName.size() == 0) { os::Printer::log("Unexpected ending found in Animation set in x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } else @@ -1556,7 +1625,7 @@ bool CXMeshFileLoader::parseDataObjectAnimation() if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Animation found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1573,7 +1642,7 @@ bool CXMeshFileLoader::parseDataObjectAnimation() if (objectName.size() == 0) { os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } else @@ -1603,7 +1672,7 @@ bool CXMeshFileLoader::parseDataObjectAnimation() if (!checkForClosingBrace()) { os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } } @@ -1637,7 +1706,7 @@ bool CXMeshFileLoader::parseDataObjectAnimation() #ifdef _XREADER_DEBUG os::Printer::log("creating joint for animation ", FrameName.c_str()); #endif - joint=AnimatedMesh->createJoint(0); + joint=AnimatedMesh->addJoint(0); joint->Name=FrameName; } @@ -1675,7 +1744,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Animation Key found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1686,7 +1755,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) if (keyType > 4) { os::Printer::log("Unknown key type found in Animation Key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1714,7 +1783,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) if (readInt() != 4) { os::Printer::log("Expected 4 numbers in animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1726,11 +1795,10 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) if (!checkForTwoFollowingSemicolons()) { os::Printer::log("No finishing semicolon after quaternion animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } - ISkinnedMesh::SRotationKey *key=AnimatedMesh->createRotationKey(joint); + ISkinnedMesh::SRotationKey *key=AnimatedMesh->addRotationKey(joint); key->frame=time; key->rotation.set(X,Y,Z,W); } @@ -1744,7 +1812,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) if (readInt() != 3) { os::Printer::log("Expected 3 numbers in animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1754,19 +1822,18 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) if (!checkForTwoFollowingSemicolons()) { os::Printer::log("No finishing semicolon after vector animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (keyType==2) { - ISkinnedMesh::SPositionKey *key=AnimatedMesh->createPositionKey(joint); + ISkinnedMesh::SPositionKey *key=AnimatedMesh->addPositionKey(joint); key->frame=time; key->position=vector; } else { - ISkinnedMesh::SScaleKey *key=AnimatedMesh->createScaleKey(joint); + ISkinnedMesh::SScaleKey *key=AnimatedMesh->addScaleKey(joint); key->frame=time; key->scale=vector; } @@ -1781,7 +1848,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) if (readInt() != 16) { os::Printer::log("Expected 16 numbers in animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1794,18 +1861,17 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) if (!checkForOneFollowingSemicolons()) { os::Printer::log("No finishing semicolon after matrix animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); - return false; + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } //core::vector3df rotation = mat.getRotationDegrees(); - ISkinnedMesh::SRotationKey *keyR=AnimatedMesh->createRotationKey(joint); + ISkinnedMesh::SRotationKey *keyR=AnimatedMesh->addRotationKey(joint); keyR->frame=time; keyR->rotation= core::quaternion(mat); - ISkinnedMesh::SPositionKey *keyP=AnimatedMesh->createPositionKey(joint); + ISkinnedMesh::SPositionKey *keyP=AnimatedMesh->addPositionKey(joint); keyP->frame=time; keyP->position=mat.getTranslation(); @@ -1818,7 +1884,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) scale.Y=1; if (scale.Z==0) scale.Z=1; - ISkinnedMesh::SScaleKey *keyS=AnimatedMesh->createScaleKey(joint); + ISkinnedMesh::SScaleKey *keyS=AnimatedMesh->addScaleKey(joint); keyS->frame=time; keyS->scale=scale; */ @@ -1833,7 +1899,7 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) if (!checkForClosingBrace()) { os::Printer::log("No closing brace in animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1850,21 +1916,21 @@ bool CXMeshFileLoader::parseDataObjectTextureFilename(core::stringc& texturename if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Texture filename found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } if (!getNextTokenAsString(texturename)) { os::Printer::log("Unknown syntax while reading texture filename string in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Texture filename found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_ERROR); + os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } @@ -1921,7 +1987,13 @@ bool CXMeshFileLoader::checkForOneFollowingSemicolons() if (BinaryFormat) return true; - return (getNextToken() == ";"); + if (getNextToken() == ";") + return true; + else + { + --P; + return false; + } } @@ -1934,7 +2006,10 @@ bool CXMeshFileLoader::checkForTwoFollowingSemicolons() for (u32 k=0; k<2; ++k) { if (getNextToken() != ";") + { + --P; return false; + } } return true; @@ -2183,9 +2258,11 @@ void CXMeshFileLoader::readUntilEndOfLine() u16 CXMeshFileLoader::readBinWord() { - u8 *Q = (u8 *)P; - u16 tmp = 0; - tmp = Q[0] + (Q[1] << 8); +#ifdef __BIG_ENDIAN__ + const u16 tmp = os::Byteswap::byteswap(*(u16 *)P); +#else + const u16 tmp = *(u16 *)P; +#endif P += 2; return tmp; } @@ -2193,9 +2270,11 @@ u16 CXMeshFileLoader::readBinWord() u32 CXMeshFileLoader::readBinDWord() { - u8 *Q = (u8 *)P; - u32 tmp = 0; - tmp = Q[0] + (Q[1] << 8) + (Q[2] << 16) + (Q[3] << 24); +#ifdef __BIG_ENDIAN__ + const u32 tmp = os::Byteswap::byteswap(*(u32 *)P); +#else + const u32 tmp = *(u32 *)P; +#endif P += 4; return tmp; } @@ -2207,7 +2286,7 @@ u32 CXMeshFileLoader::readInt() { if (!BinaryNumCount) { - u16 tmp = readBinWord(); // 0x06 or 0x03 + const u16 tmp = readBinWord(); // 0x06 or 0x03 if (tmp == 0x06) BinaryNumCount = readBinDWord(); else @@ -2230,7 +2309,7 @@ f32 CXMeshFileLoader::readFloat() { if (!BinaryNumCount) { - u16 tmp = readBinWord(); // 0x07 or 0x42 + const u16 tmp = readBinWord(); // 0x07 or 0x42 if (tmp == 0x07) BinaryNumCount = readBinDWord(); else @@ -2239,17 +2318,26 @@ f32 CXMeshFileLoader::readFloat() --BinaryNumCount; if (FloatSize == 8) { - char tmp[8]; - memcpy(tmp, P, 8); +#ifdef __BIG_ENDIAN__ + c8 ctmp[8]; + *((f32*)(ctmp+4)) = os::Byteswap::byteswap(*(f32 *)P); + *((f32*)(ctmp)) = os::Byteswap::byteswap(*(f32 *)P+4); + const f32 tmp = (f32)(*(f64 *)ctmp); +#else + const f32 tmp = (f32)(*(f64 *)P); +#endif P += 8; - return (f32)(*(f64 *)tmp); + return tmp; } else { - char tmp[4]; - memcpy(tmp, P, 4); +#ifdef __BIG_ENDIAN__ + const f32 tmp = os::Byteswap::byteswap(*(f32 *)P); +#else + const f32 tmp = *(f32 *)P; +#endif P += 4; - return *(f32 *)tmp; + return tmp; } } findNextNoneWhiteSpaceNumber(); @@ -2312,29 +2400,6 @@ bool CXMeshFileLoader::readMatrix(core::matrix4& mat) } -core::stringc CXMeshFileLoader::stripPathFromString(core::stringc string, bool returnPath) -{ - s32 slashIndex=string.findLast('/'); // forward slash - s32 backSlash=string.findLast('\\'); // back slash - - if (backSlash>slashIndex) - slashIndex=backSlash; - - if (slashIndex==-1)//no slashes found - { - if (returnPath) - return core::stringc(); //no path to return - else - return string; - } - - if (returnPath) - return string.subString(0, slashIndex + 1); - else - return string.subString(slashIndex+1, string.size() - (slashIndex+1)); -} - - } // end namespace scene } // end namespace irr diff --git a/src/dep/src/irrlicht/CXMeshFileLoader.h b/src/dep/src/irrlicht/CXMeshFileLoader.h index 8c298b9..75657dd 100644 --- a/src/dep/src/irrlicht/CXMeshFileLoader.h +++ b/src/dep/src/irrlicht/CXMeshFileLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -31,7 +31,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -62,11 +62,12 @@ public: u32 MaxSkinWeightsPerFace; u32 BoneCount; - core::array< u32 > IndexCountPerFace; // default 3, but could be more + core::array IndexCountPerFace; // default 3, but could be more core::array Buffers; core::array Vertices; + core::array TCoords2; core::array Indices; @@ -74,13 +75,13 @@ public: core::array Materials; // material array + core::array WeightJoint; + core::array WeightNum; + s32 AttachedJointID; bool HasSkinning; bool HasVertexColors; - - core::array WeightJoint; - core::array WeightNum; }; private: @@ -91,7 +92,6 @@ private: bool parseFile(); - bool parseDataObject(); bool parseDataObjectTemplate(); @@ -155,8 +155,6 @@ private: void readUntilEndOfLine(); - core::stringc stripPathFromString(core::stringc string, bool returnPath); - u16 readBinWord(); u32 readBinDWord(); u32 readInt(); @@ -167,35 +165,34 @@ private: bool readRGB(video::SColor& color); bool readRGBA(video::SColor& color); - ISceneManager* SceneManager; - io::IFileSystem* FileSystem; + ISceneManager* SceneManager; + io::IFileSystem* FileSystem; core::array *AllJoints; CSkinnedMesh* AnimatedMesh; - u32 MajorVersion; - u32 MinorVersion; - bool BinaryFormat; - // counter for number arrays in binary format - u32 BinaryNumCount; - c8* Buffer; const c8* P; c8* End; - c8 FloatSize; + // counter for number arrays in binary format + u32 BinaryNumCount; u32 Line; - core::stringc FilePath; + io::path FilePath; CSkinnedMesh::SJoint *CurFrame; core::array Meshes; core::array TemplateMaterials; + + u32 MajorVersion; + u32 MinorVersion; + bool BinaryFormat; + c8 FloatSize; }; } // end namespace scene } // end namespace irr #endif - diff --git a/src/dep/src/irrlicht/CZBuffer.cpp b/src/dep/src/irrlicht/CZBuffer.cpp index 1300bb8..d01fcfc 100644 --- a/src/dep/src/irrlicht/CZBuffer.cpp +++ b/src/dep/src/irrlicht/CZBuffer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -15,7 +15,7 @@ namespace video //! constructor -CZBuffer::CZBuffer(const core::dimension2d& size) +CZBuffer::CZBuffer(const core::dimension2d& size) : Buffer(0), BufferEnd(0), Size(0,0), TotalSize(0) { #ifdef _DEBUG @@ -44,7 +44,7 @@ void CZBuffer::clear() //! sets the new size of the zbuffer -void CZBuffer::setSize(const core::dimension2d& size) +void CZBuffer::setSize(const core::dimension2d& size) { if (size == Size) return; @@ -61,7 +61,7 @@ void CZBuffer::setSize(const core::dimension2d& size) //! returns the size of the zbuffer -const core::dimension2d& CZBuffer::getSize() const +const core::dimension2d& CZBuffer::getSize() const { return Size; } @@ -92,7 +92,7 @@ namespace video { //! creates a ZBuffer -IZBuffer* createZBuffer(const core::dimension2d& size) +IZBuffer* createZBuffer(const core::dimension2d& size) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CZBuffer(size); @@ -101,7 +101,7 @@ IZBuffer* createZBuffer(const core::dimension2d& size) #endif // _IRR_COMPILE_WITH_SOFTWARE_ } - + } // end namespace video } // end namespace irr diff --git a/src/dep/src/irrlicht/CZBuffer.h b/src/dep/src/irrlicht/CZBuffer.h index a1fb11f..91ed2af 100644 --- a/src/dep/src/irrlicht/CZBuffer.h +++ b/src/dep/src/irrlicht/CZBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -17,7 +17,7 @@ namespace video public: //! constructor - CZBuffer(const core::dimension2d& size); + CZBuffer(const core::dimension2d& size); //! destructor virtual ~CZBuffer(); @@ -26,10 +26,10 @@ namespace video virtual void clear(); //! sets the new size of the zbuffer - virtual void setSize(const core::dimension2d& size); + virtual void setSize(const core::dimension2d& size); //! returns the size of the zbuffer - virtual const core::dimension2d& getSize() const; + virtual const core::dimension2d& getSize() const; //! locks the zbuffer virtual TZBufferType* lock(); @@ -41,10 +41,10 @@ namespace video TZBufferType* Buffer; TZBufferType* BufferEnd; - core::dimension2d Size; + core::dimension2d Size; s32 TotalSize; }; - + } // end namespace video } // end namespace irr diff --git a/src/dep/src/irrlicht/CZipReader.cpp b/src/dep/src/irrlicht/CZipReader.cpp index d8f43a3..cc5e0fd 100644 --- a/src/dep/src/irrlicht/CZipReader.cpp +++ b/src/dep/src/irrlicht/CZipReader.cpp @@ -1,20 +1,45 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CZipReader.h" + +#include "os.h" + +// This method is used for error output from bzip2. +extern "C" void bz_internal_error(int errorCode) +{ + irr::os::Printer::log("Error in bzip2 handling", irr::core::stringc(errorCode), irr::ELL_ERROR); +} + +#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ + #include "CFileList.h" #include "CReadFile.h" -#include "os.h" +#include "coreutil.h" #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_ZLIB_ - #ifndef _IRR_USE_NON_SYSTEM_ZLIB_ - #include // use system lib - #else // _IRR_USE_NON_SYSTEM_ZLIB_ - #include "zlib/zlib.h" - #endif // _IRR_USE_NON_SYSTEM_ZLIB_ -#endif // _IRR_COMPILE_WITH_ZLIB_ + #ifndef _IRR_USE_NON_SYSTEM_ZLIB_ + #include // use system lib + #else + #include "zlib/zlib.h" + #endif + + #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ + #include "aesGladman/fileenc.h" + #endif + #ifdef _IRR_COMPILE_WITH_BZIP2_ + #ifndef _IRR_USE_NON_SYSTEM_BZLIB_ + #include + #else + #include "bzip2/bzlib.h" + #endif + #endif + #ifdef _IRR_COMPILE_WITH_LZMA_ + #include "lzma/LzmaDec.h" + #endif +#endif namespace irr { @@ -22,8 +47,98 @@ namespace io { -CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths) -: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths) +// ----------------------------------------------------------------------------- +// zip loader +// ----------------------------------------------------------------------------- + +//! Constructor +CArchiveLoaderZIP::CArchiveLoaderZIP(io::IFileSystem* fs) +: FileSystem(fs) +{ + #ifdef _DEBUG + setDebugName("CArchiveLoaderZIP"); + #endif +} + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderZIP::isALoadableFileFormat(const io::path& filename) const +{ + return core::hasFileExtension(filename, "zip", "pk3") || + core::hasFileExtension(filename, "gz", "tgz"); +} + +//! Check to see if the loader can create archives of this type. +bool CArchiveLoaderZIP::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const +{ + return (fileType == EFAT_ZIP || fileType == EFAT_GZIP); +} + + +//! Creates an archive from the filename +/** \param file File handle to check. +\return Pointer to newly created archive, or 0 upon error. */ +IFileArchive* CArchiveLoaderZIP::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + io::IReadFile* file = FileSystem->createAndOpenFile(filename); + + if (file) + { + archive = createArchive(file, ignoreCase, ignorePaths); + file->drop(); + } + + return archive; +} + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderZIP::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + if (file) + { + file->seek(0); + + u16 sig; + file->read(&sig, 2); + +#ifdef __BIG_ENDIAN__ + os::Byteswap::byteswap(sig); +#endif + + file->seek(0); + + bool isGZip = (sig == 0x8b1f); + + archive = new CZipReader(file, ignoreCase, ignorePaths, isGZip); + } + return archive; +} + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile* file) const +{ + SZIPFileHeader header; + + file->read( &header.Sig, 4 ); +#ifdef __BIG_ENDIAN__ + os::Byteswap::byteswap(header.Sig); +#endif + + return header.Sig == 0x04034b50 || // ZIP + (header.Sig&0xffff) == 0x8b1f; // gzip +} + +// ----------------------------------------------------------------------------- +// zip archive +// ----------------------------------------------------------------------------- + +CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths, bool isGZip) + : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file), IsGZip(isGZip) { #ifdef _DEBUG setDebugName("CZipReader"); @@ -33,11 +148,13 @@ CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths) { File->grab(); - // scan local headers - while (scanLocalHeader()); + // load file entries + if (IsGZip) + while (scanGZipHeader()) { } + else + while (scanZipHeader()) { } - // prepare file index for binary search - FileList.sort(); + sort(); } } @@ -48,64 +165,218 @@ CZipReader::~CZipReader() } - -//! splits filename from zip file into useful filenames and paths -void CZipReader::extractFilename(SZipFileEntry* entry) +//! get the archive type +E_FILE_ARCHIVE_TYPE CZipReader::getType() const { - s32 lorfn = entry->header.FilenameLength; // length of real file name - - if (!lorfn) - return; - - if (IgnoreCase) - entry->zipFileName.make_lower(); - - const c8* p = entry->zipFileName.c_str() + lorfn; - - // suche ein slash oder den anfang. - - while (*p!='/' && p!=entry->zipFileName.c_str()) - { - --p; - --lorfn; - } - - bool thereIsAPath = p != entry->zipFileName.c_str(); - - if (thereIsAPath) - { - // there is a path - ++p; - ++lorfn; - } - - entry->simpleFileName = p; - entry->path = ""; - - // pfad auch kopieren - if (thereIsAPath) - { - lorfn = (s32)(p - entry->zipFileName.c_str()); - - entry->path = entry->zipFileName.subString ( 0, lorfn ); - - //entry->path.append(entry->zipFileName, lorfn); - //entry->path.append ( "" ); - } - - if (!IgnorePaths) - entry->simpleFileName = entry->zipFileName; // thanks to Pr3t3nd3r for this fix + return IsGZip ? EFAT_GZIP : EFAT_ZIP; } +const IFileList* CZipReader::getFileList() const +{ + return this; +} +#if 0 +#include + +const c8 *sigName( u32 sig ) +{ + switch ( sig ) + { + case 0x04034b50: return "PK0304"; + case 0x02014b50: return "PK0102"; + case 0x06054b50: return "PK0506"; + } + return "unknown"; +} + +bool CZipReader::scanLocalHeader2() +{ + c8 buf [ 128 ]; + c8 *c; + + File->read( &temp.header.Sig, 4 ); + +#ifdef __BIG_ENDIAN__ + os::Byteswap::byteswap(temp.header.Sig); +#endif + + sprintf ( buf, "sig: %08x,%s,", temp.header.Sig, sigName ( temp.header.Sig ) ); + OutputDebugStringA ( buf ); + + // Local File Header + if ( temp.header.Sig == 0x04034b50 ) + { + File->read( &temp.header.VersionToExtract, sizeof( temp.header ) - 4 ); + + temp.zipFileName.reserve( temp.header.FilenameLength+2); + c = (c8*) temp.zipFileName.c_str(); + File->read( c, temp.header.FilenameLength); + c [ temp.header.FilenameLength ] = 0; + temp.zipFileName.verify(); + + sprintf ( buf, "%d,'%s'\n", temp.header.CompressionMethod, c ); + OutputDebugStringA ( buf ); + + if (temp.header.ExtraFieldLength) + { + File->seek( temp.header.ExtraFieldLength, true); + } + + if (temp.header.GeneralBitFlag & ZIP_INFO_IN_DATA_DESCRIPTOR) + { + // read data descriptor + File->seek(sizeof(SZIPFileDataDescriptor), true ); + } + + // compressed data + temp.fileDataPosition = File->getPos(); + File->seek( temp.header.DataDescriptor.CompressedSize, true); + FileList.push_back( temp ); + return true; + } + + // Central directory structure + if ( temp.header.Sig == 0x04034b50 ) + { + //SZIPFileCentralDirFileHeader h; + //File->read( &h, sizeof( h ) - 4 ); + return true; + } + + // End of central dir + if ( temp.header.Sig == 0x06054b50 ) + { + return true; + } + + // eof + if ( temp.header.Sig == 0x02014b50 ) + { + return false; + } + + return false; +} + +#endif //! scans for a local header, returns false if there is no more local file header. -bool CZipReader::scanLocalHeader() +//! The gzip file format seems to think that there can be multiple files in a gzip file +//! but none +bool CZipReader::scanGZipHeader() { - c8 tmp[1024]; - SZipFileEntry entry; - entry.fileDataPosition = 0; + entry.Offset = 0; + memset(&entry.header, 0, sizeof(SZIPFileHeader)); + + // read header + SGZIPMemberHeader header; + if (File->read(&header, sizeof(SGZIPMemberHeader)) == sizeof(SGZIPMemberHeader)) + { + +#ifdef __BIG_ENDIAN__ + os::Byteswap::byteswap(header.sig); + os::Byteswap::byteswap(header.time); +#endif + + // check header value + if (header.sig != 0x8b1f) + return false; + + // now get the file info + if (header.flags & EGZF_EXTRA_FIELDS) + { + // read lenth of extra data + u16 dataLen; + + File->read(&dataLen, 2); + +#ifdef __BIG_ENDIAN__ + os::Byteswap::byteswap(dataLen); +#endif + + // skip it + File->seek(dataLen, true); + } + + io::path ZipFileName = ""; + + if (header.flags & EGZF_FILE_NAME) + { + c8 c; + File->read(&c, 1); + while (c) + { + ZipFileName.append(c); + File->read(&c, 1); + } + } + else + { + // no file name? + ZipFileName = Path; + core::deletePathFromFilename(ZipFileName); + + // rename tgz to tar or remove gz extension + if (core::hasFileExtension(ZipFileName, "tgz")) + { + ZipFileName[ ZipFileName.size() - 2] = 'a'; + ZipFileName[ ZipFileName.size() - 1] = 'r'; + } + else if (core::hasFileExtension(ZipFileName, "gz")) + { + ZipFileName[ ZipFileName.size() - 3] = 0; + ZipFileName.validate(); + } + } + + if (header.flags & EGZF_COMMENT) + { + c8 c='a'; + while (c) + File->read(&c, 1); + } + + if (header.flags & EGZF_CRC16) + File->seek(2, true); + + // we are now at the start of the data blocks + entry.Offset = File->getPos(); + + entry.header.FilenameLength = ZipFileName.size(); + + entry.header.CompressionMethod = header.compressionMethod; + entry.header.DataDescriptor.CompressedSize = (File->getSize() - 8) - File->getPos(); + + // seek to file end + File->seek(entry.header.DataDescriptor.CompressedSize, true); + + // read CRC + File->read(&entry.header.DataDescriptor.CRC32, 4); + // read uncompressed size + File->read(&entry.header.DataDescriptor.UncompressedSize, 4); + +#ifdef __BIG_ENDIAN__ + os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32); + os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize); +#endif + + // now we've filled all the fields, this is just a standard deflate block + addItem(ZipFileName, entry.header.DataDescriptor.UncompressedSize, false, 0); + FileInfo.push_back(entry); + } + + // there's only one block of data in a gzip file + return false; +} + +//! scans for a local header, returns false if there is no more local file header. +bool CZipReader::scanZipHeader() +{ + io::path ZipFileName = ""; + SZipFileEntry entry; + entry.Offset = 0; memset(&entry.header, 0, sizeof(SZIPFileHeader)); File->read(&entry.header, sizeof(SZIPFileHeader)); @@ -128,20 +399,59 @@ bool CZipReader::scanLocalHeader() return false; // local file headers end here. // read filename - entry.zipFileName.reserve(entry.header.FilenameLength+2); - File->read(tmp, entry.header.FilenameLength); - tmp[entry.header.FilenameLength] = 0x0; - entry.zipFileName = tmp; - - extractFilename(&entry); + { + c8 *tmp = new c8 [ entry.header.FilenameLength + 2 ]; + File->read(tmp, entry.header.FilenameLength); + tmp[entry.header.FilenameLength] = 0; + ZipFileName = tmp; + delete [] tmp; + } +#ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ + // AES encryption + if ((entry.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (entry.header.CompressionMethod == 99)) + { + s16 restSize = entry.header.ExtraFieldLength; + SZipFileExtraHeader extraHeader; + while (restSize) + { + File->read(&extraHeader, sizeof(extraHeader)); +#ifdef __BIG_ENDIAN__ + extraHeader.ID = os::Byteswap::byteswap(extraHeader.ID); + extraHeader.Size = os::Byteswap::byteswap(extraHeader.Size); +#endif + restSize -= sizeof(extraHeader); + if (extraHeader.ID==(s16)0x9901) + { + SZipFileAESExtraData data; + File->read(&data, sizeof(data)); +#ifdef __BIG_ENDIAN__ + data.Version = os::Byteswap::byteswap(data.Version); + data.CompressionMode = os::Byteswap::byteswap(data.CompressionMode); +#endif + restSize -= sizeof(data); + if (data.Vendor[0]=='A' && data.Vendor[1]=='E') + { + // encode values into Sig + // AE-Version | Strength | ActualMode + entry.header.Sig = + ((data.Version & 0xff) << 24) | + (data.EncryptionStrength << 16) | + (data.CompressionMode); + File->seek(restSize, true); + break; + } + } + } + } // move forward length of extra field. - + else +#endif if (entry.header.ExtraFieldLength) File->seek(entry.header.ExtraFieldLength, true); // if bit 3 was set, read DataDescriptor, following after the compressed data - if (entry.header.GeneralBitFlag & ZIP_INFO_IN_DATA_DESCRITOR) + if (entry.header.GeneralBitFlag & ZIP_INFO_IN_DATA_DESCRIPTOR) { // read data descriptor File->read(&entry.header.DataDescriptor, sizeof(entry.header.DataDescriptor)); @@ -153,38 +463,46 @@ bool CZipReader::scanLocalHeader() } // store position in file - entry.fileDataPosition = File->getPos(); - + entry.Offset = File->getPos(); // move forward length of data File->seek(entry.header.DataDescriptor.CompressedSize, true); #ifdef _DEBUG - //os::Debuginfo::print("added file from archive", entry.simpleFileName.c_str()); + //os::Debuginfo::print("added file from archive", ZipFileName.c_str()); #endif - FileList.push_back(entry); + addItem(ZipFileName, entry.header.DataDescriptor.UncompressedSize, false, FileInfo.size()); + FileInfo.push_back(entry); return true; } - //! opens a file by file name -IReadFile* CZipReader::openFile(const c8* filename) +IReadFile* CZipReader::createAndOpenFile(const io::path& filename) { - s32 index = findFile(filename); + s32 index = findFile(filename, false); if (index != -1) - return openFile(index); + return createAndOpenFile(index); return 0; } - +#ifdef _IRR_COMPILE_WITH_LZMA_ +//! Used for LZMA decompression. The lib has no default memory management +namespace +{ + void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } + void SzFree(void *p, void *address) { p = p; free(address); } + ISzAlloc lzmaAlloc = { SzAlloc, SzFree }; +} +#endif //! opens a file by index -IReadFile* CZipReader::openFile(s32 index) +IReadFile* CZipReader::createAndOpenFile(u32 index) { + // Irrlicht supports 0, 8, 12, 14, 99 //0 - The file is stored (no compression) //1 - The file is Shrunk //2 - The file is Reduced with compression factor 1 @@ -196,45 +514,143 @@ IReadFile* CZipReader::openFile(s32 index) //8 - The file is Deflated //9 - Reserved for enhanced Deflating //10 - PKWARE Date Compression Library Imploding + //12 - bzip2 - Compression Method from libbz2, WinZip 10 + //14 - LZMA - Compression Method, WinZip 12 + //96 - Jpeg compression - Compression Method, WinZip 12 + //97 - WavPack - Compression Method, WinZip 11 + //98 - PPMd - Compression Method, WinZip 10 + //99 - AES encryption, WinZip 9 - switch(FileList[index].header.CompressionMethod) + const SZipFileEntry &e = FileInfo[Files[index].ID]; + wchar_t buf[64]; + s16 actualCompressionMethod=e.header.CompressionMethod; + IReadFile* decrypted=0; + u8* decryptedBuf=0; + u32 decryptedSize=e.header.DataDescriptor.CompressedSize; +#ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ + if ((e.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (e.header.CompressionMethod == 99)) + { + os::Printer::log("Reading encrypted file."); + u8 salt[16]={0}; + const u16 saltSize = (((e.header.Sig & 0x00ff0000) >>16)+1)*4; + File->seek(e.Offset); + File->read(salt, saltSize); + char pwVerification[2]; + char pwVerificationFile[2]; + File->read(pwVerification, 2); + fcrypt_ctx zctx; // the encryption context + int rc = fcrypt_init( + (e.header.Sig & 0x00ff0000) >>16, + (const unsigned char*)Password.c_str(), // the password + Password.size(), // number of bytes in password + salt, // the salt + (unsigned char*)pwVerificationFile, // on return contains password verifier + &zctx); // encryption context + if (strncmp(pwVerificationFile, pwVerification, 2)) + { + os::Printer::log("Wrong password"); + return 0; + } + decryptedSize= e.header.DataDescriptor.CompressedSize-saltSize-12; + decryptedBuf= new u8[decryptedSize]; + u32 c = 0; + while ((c+32768)<=decryptedSize) + { + File->read(decryptedBuf+c, 32768); + fcrypt_decrypt( + decryptedBuf+c, // pointer to the data to decrypt + 32768, // how many bytes to decrypt + &zctx); // decryption context + c+=32768; + } + File->read(decryptedBuf+c, decryptedSize-c); + fcrypt_decrypt( + decryptedBuf+c, // pointer to the data to decrypt + decryptedSize-c, // how many bytes to decrypt + &zctx); // decryption context + + char fileMAC[10]; + char resMAC[10]; + rc = fcrypt_end( + (unsigned char*)resMAC, // on return contains the authentication code + &zctx); // encryption context + if (rc != 10) + { + os::Printer::log("Error on encryption closing"); + delete [] decryptedBuf; + return 0; + } + File->read(fileMAC, 10); + if (strncmp(fileMAC, resMAC, 10)) + { + os::Printer::log("Error on encryption check"); + delete [] decryptedBuf; + return 0; + } + decrypted = io::createMemoryReadFile(decryptedBuf, decryptedSize, Files[index].FullName, true); + actualCompressionMethod = (e.header.Sig & 0xffff); +#if 0 + if ((e.header.Sig & 0xff000000)==0x01000000) + { + } + else if ((e.header.Sig & 0xff000000)==0x02000000) + { + } + else + { + os::Printer::log("Unknown encryption method"); + return 0; + } +#endif + } +#endif + switch(actualCompressionMethod) { case 0: // no compression { - File->seek(FileList[index].fileDataPosition); - return createLimitReadFile(FileList[index].simpleFileName.c_str(), File, FileList[index].header.DataDescriptor.UncompressedSize); + if (decrypted) + return decrypted; + else + return createLimitReadFile(Files[index].FullName, File, e.Offset, decryptedSize); } case 8: { #ifdef _IRR_COMPILE_WITH_ZLIB_ - - const u32 uncompressedSize = FileList[index].header.DataDescriptor.UncompressedSize; - const u32 compressedSize = FileList[index].header.DataDescriptor.CompressedSize; - void* pBuf = new c8[ uncompressedSize ]; + const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; + c8* pBuf = new c8[ uncompressedSize ]; if (!pBuf) { - os::Printer::log("Not enough memory for decompressing", FileList[index].simpleFileName.c_str(), ELL_ERROR); + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + if (decrypted) + decrypted->drop(); return 0; } - c8 *pcData = new c8[ compressedSize ]; + u8 *pcData = decryptedBuf; if (!pcData) { - os::Printer::log("Not enough memory for decompressing", FileList[index].simpleFileName.c_str(), ELL_ERROR); - return 0; + pcData = new u8[decryptedSize]; + if (!pcData) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } + + //memset(pcData, 0, decryptedSize); + File->seek(e.Offset); + File->read(pcData, decryptedSize); } - //memset(pcData, 0, compressedSize ); - File->seek(FileList[index].fileDataPosition); - File->read(pcData, compressedSize ); - // Setup the inflate stream. z_stream stream; s32 err; stream.next_in = (Bytef*)pcData; - stream.avail_in = (uInt)compressedSize; + stream.avail_in = (uInt)decryptedSize; stream.next_out = (Bytef*)pBuf; stream.avail_out = uncompressedSize; stream.zalloc = (alloc_func)0; @@ -252,231 +668,171 @@ IReadFile* CZipReader::openFile(s32 index) inflateEnd(&stream); } + if (decrypted) + decrypted->drop(); + else + delete[] pcData; - delete[] pcData; - if (err != Z_OK) { - os::Printer::log("Error decompressing", FileList[index].simpleFileName.c_str(), ELL_ERROR); - delete [] (c8*)pBuf; + swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; return 0; } else - return io::createMemoryReadFile(pBuf, uncompressedSize, FileList[index].zipFileName.c_str(), true); - + return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); + #else return 0; // zlib not compiled, we cannot decompress the data. #endif } + case 12: + { + #ifdef _IRR_COMPILE_WITH_BZIP2_ + + const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; + c8* pBuf = new c8[ uncompressedSize ]; + if (!pBuf) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + if (decrypted) + decrypted->drop(); + return 0; + } + + u8 *pcData = decryptedBuf; + if (!pcData) + { + pcData = new u8[decryptedSize]; + if (!pcData) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } + + //memset(pcData, 0, decryptedSize); + File->seek(e.Offset); + File->read(pcData, decryptedSize); + } + + bz_stream bz_ctx={0}; + /* use BZIP2's default memory allocation + bz_ctx->bzalloc = NULL; + bz_ctx->bzfree = NULL; + bz_ctx->opaque = NULL; + */ + int err = BZ2_bzDecompressInit(&bz_ctx, 0, 0); /* decompression */ + if(err != BZ_OK) + { + os::Printer::log("bzip2 decompression failed. File cannot be read.", ELL_ERROR); + return 0; + } + bz_ctx.next_in = (char*)pcData; + bz_ctx.avail_in = decryptedSize; + /* pass all input to decompressor */ + bz_ctx.next_out = pBuf; + bz_ctx.avail_out = uncompressedSize; + err = BZ2_bzDecompress(&bz_ctx); + err = BZ2_bzDecompressEnd(&bz_ctx); + + if (decrypted) + decrypted->drop(); + else + delete[] pcData; + + if (err != BZ_OK) + { + swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } + else + return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); + + #else + os::Printer::log("bzip2 decompression not supported. File cannot be read.", ELL_ERROR); + return 0; + #endif + } + case 14: + { + #ifdef _IRR_COMPILE_WITH_LZMA_ + + u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; + c8* pBuf = new c8[ uncompressedSize ]; + if (!pBuf) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + if (decrypted) + decrypted->drop(); + return 0; + } + + u8 *pcData = decryptedBuf; + if (!pcData) + { + pcData = new u8[decryptedSize]; + if (!pcData) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } + + //memset(pcData, 0, decryptedSize); + File->seek(e.Offset); + File->read(pcData, decryptedSize); + } + + ELzmaStatus status; + SizeT tmpDstSize = uncompressedSize; + SizeT tmpSrcSize = decryptedSize; + + int err = LzmaDecode((Byte*)pBuf, &tmpDstSize, + pcData, &tmpSrcSize, + 0, 0, LZMA_FINISH_END, &status, &lzmaAlloc); + uncompressedSize = tmpDstSize; // may be different to expected value + + if (decrypted) + decrypted->drop(); + else + delete[] pcData; + + if (err != SZ_OK) + { + swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } + else + return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); + + #else + os::Printer::log("lzma decompression not supported. File cannot be read.", ELL_ERROR); + return 0; + #endif + } + case 99: + // If we come here with an encrypted file, decryption support is missing + os::Printer::log("Decryption support not enabled. File cannot be read.", ELL_ERROR); + return 0; default: - os::Printer::log("file has unsupported compression method.", FileList[index].simpleFileName.c_str(), ELL_ERROR); + swprintf ( buf, 64, L"file has unsupported compression method. %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); return 0; }; -} - - - -//! returns count of files in archive -s32 CZipReader::getFileCount() -{ - return FileList.size(); -} - - - -//! returns data of file -const SZipFileEntry* CZipReader::getFileInfo(s32 index) const -{ - return &FileList[index]; -} - - - -//! deletes the path from a filename -void CZipReader::deletePathFromFilename(core::stringc& filename) -{ - // delete path from filename - const c8* p = filename.c_str() + filename.size(); - - // search for path separator or beginning - - while (*p!='/' && *p!='\\' && p!=filename.c_str()) - --p; - - if (p != filename.c_str()) - { - ++p; - filename = p; - } -} - - - -//! returns fileindex -s32 CZipReader::findFile(const c8* simpleFilename) -{ - SZipFileEntry entry; - entry.simpleFileName = simpleFilename; - - if (IgnoreCase) - entry.simpleFileName.make_lower(); - - if (IgnorePaths) - deletePathFromFilename(entry.simpleFileName); - - s32 res = FileList.binary_search(entry); - - #ifdef _DEBUG - if (res == -1) - { - for (u32 i=0; iisOpen()) - return file; - - file->drop(); - return 0; - -} - -//! returns fileindex -s32 CUnZipReader::findFile(const c8* filename) -{ - IReadFile *file = openFile ( filename ); - if ( 0 == file ) - return -1; - file->drop (); - return 1; -} - -#else - -CUnZipReader::CUnZipReader( IFileSystem * parent, const c8* basename, bool ignoreCase, bool ignorePaths) - : CZipReader( 0, ignoreCase, ignorePaths ), Parent ( parent ) -{ - strcpy ( Buf, Parent->getWorkingDirectory () ); - - Parent->changeWorkingDirectoryTo ( basename ); - buildDirectory ( ); - Parent->changeWorkingDirectoryTo ( Buf ); - - FileList.sort(); -} - -void CUnZipReader::buildDirectory ( ) -{ - IFileList * list = new CFileList(); - - SZipFileEntry entry; - - const u32 size = list->getFileCount(); - for (u32 i = 0; i!= size; ++i) - { - if ( false == list->isDirectory( i ) ) - { - entry.zipFileName = list->getFullFileName ( i ); - entry.header.FilenameLength = entry.zipFileName.size (); - extractFilename(&entry); - FileList.push_back(entry); - } - else - { - const c8 * rel = list->getFileName ( i ); - - if (strcmp( rel, "." ) && strcmp( rel, ".." )) - { - Parent->changeWorkingDirectoryTo ( rel ); - buildDirectory (); - Parent->changeWorkingDirectoryTo ( ".." ); - } - } - } - - list->drop (); -} - -//! opens a file by file name -IReadFile* CUnZipReader::openFile(const c8* filename) -{ - s32 index = -1; - - if ( IgnorePaths ) - { - index = findFile(filename); - } - else - if ( FileList.size () ) - { - const core::stringc search = FileList[0].path + filename; - index = findFile( search.c_str() ); - } - - if (index == -1) - return 0; - - return createReadFile(FileList[index].zipFileName.c_str() ); -} -#endif - - } // end namespace io } // end namespace irr +#endif // __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ diff --git a/src/dep/src/irrlicht/CZipReader.h b/src/dep/src/irrlicht/CZipReader.h index c206e79..d9af7e0 100644 --- a/src/dep/src/irrlicht/CZipReader.h +++ b/src/dep/src/irrlicht/CZipReader.h @@ -1,15 +1,19 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_ZIP_READER_H_INCLUDED__ #define __C_ZIP_READER_H_INCLUDED__ -#include "IReferenceCounted.h" +#include "IrrCompileConfig.h" + +#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ + #include "IReadFile.h" #include "irrArray.h" #include "irrString.h" #include "IFileSystem.h" +#include "CFileList.h" namespace irr { @@ -19,9 +23,9 @@ namespace io const s16 ZIP_FILE_ENCRYPTED = 0x0001; // the fields crc-32, compressed size and uncompressed size are set to // zero in the local header - const s16 ZIP_INFO_IN_DATA_DESCRITOR = 0x0008; + const s16 ZIP_INFO_IN_DATA_DESCRIPTOR = 0x0008; -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT @@ -34,14 +38,14 @@ namespace io struct SZIPFileDataDescriptor { - s32 CRC32; - s32 CompressedSize; - s32 UncompressedSize; + u32 CRC32; + u32 CompressedSize; + u32 UncompressedSize; } PACK_STRUCT; struct SZIPFileHeader { - s32 Sig; + u32 Sig; // 'PK0304' little endian (0x04034b50) s16 VersionToExtract; s16 GeneralBitFlag; s16 CompressionMethod; @@ -50,110 +54,181 @@ namespace io SZIPFileDataDescriptor DataDescriptor; s16 FilenameLength; s16 ExtraFieldLength; + // filename (variable size) + // extra field (variable size ) + } PACK_STRUCT; + + struct SZIPFileCentralDirFileHeader + { + u32 central_file_header_signature; // 'PK0102' (0x02014b50) + u16 version_made_by; + u16 version_needed_to_extract; + u16 general_purpose_bit_flag; + u16 compression_method; + u16 last_mod_file_time; + u16 last_mod_file_date; + u32 crc_32; + u32 compressed_size; + u32 uncompressed_size; + u16 filename_length; + u16 extra_field_length; + u16 file_comment_length; + u16 disk_number_start; + u16 internal_file_attributes; + u32 external_file_attributes; + u32 relative_offset_of_local_header; + + // filename (variable size) + // extra field (variable size) + // file comment (variable size) + + } PACK_STRUCT; + + struct SZIPFileCentralDirEnd + { + u32 sig; // 'PK0506' end_of central dir signature // (0x06054b50) + u16 numberDisk; // number of this disk + u16 numberStart; // number of the disk with the start of the central directory + u16 totalDisk; // total number of entries in the central dir on this disk + u16 totalEntries; // total number of entries in the central dir + u32 size; // size of the central directory + u32 offset; // offset of start of centraldirectory with respect to the starting disk number + u16 comment_length; // zipfile comment length + // zipfile comment (variable size) + } PACK_STRUCT; + + struct SZipFileExtraHeader + { + s16 ID; + s16 Size; + } PACK_STRUCT; + + struct SZipFileAESExtraData + { + s16 Version; + u8 Vendor[2]; + u8 EncryptionStrength; + s16 CompressionMode; + } PACK_STRUCT; + + enum E_GZIP_FLAGS + { + EGZF_TEXT_DAT = 1, + EGZF_CRC16 = 2, + EGZF_EXTRA_FIELDS = 4, + EGZF_FILE_NAME = 8, + EGZF_COMMENT = 16 + }; + + struct SGZIPMemberHeader + { + u16 sig; // 0x8b1f + u8 compressionMethod; // 8 = deflate + u8 flags; + u32 time; + u8 extraFlags; // slow compress = 2, fast compress = 4 + u8 operatingSystem; } PACK_STRUCT; // Default alignment -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #endif #undef PACK_STRUCT - + //! Contains extended info about zip files in the archive struct SZipFileEntry { - core::stringc zipFileName; - core::stringc simpleFileName; - core::stringc path; - s32 fileDataPosition; // position of compressed data in file + //! Position of data in the archive file + s32 Offset; + + //! The header for this file containing compression info etc SZIPFileHeader header; - - bool operator < (const SZipFileEntry& other) const - { - return simpleFileName < other.simpleFileName; - } - - - bool operator == (const SZipFileEntry& other) const - { - return simpleFileName == other.simpleFileName; - } }; + //! Archiveloader capable of loading ZIP Archives + class CArchiveLoaderZIP : public IArchiveLoader + { + public: + //! Constructor + CArchiveLoaderZIP(io::IFileSystem* fs); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".zip") + virtual bool isALoadableFileFormat(const io::path& filename) const; + + //! Check if the file might be loaded by this class + /** Check might look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const; + + //! Check to see if the loader can create archives of this type. + /** Check based on the archive type. + \param fileType The archive type to check. + \return True if the archile loader supports this type, false if not */ + virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const; + + //! Creates an archive from the filename + /** \param file File handle to check. + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const; + + //! creates/loads an archive from the file. + //! \return Pointer to the created archive. Returns 0 if loading failed. + virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; + + private: + io::IFileSystem* FileSystem; + }; /*! Zip file Reader written April 2002 by N.Gebhardt. - Doesn't decompress data, only reads the file and is able to - open uncompressed entries. */ - class CZipReader : public virtual IReferenceCounted + class CZipReader : public virtual IFileArchive, virtual CFileList { public: - CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths); + //! constructor + CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths, bool isGZip=false); + + //! destructor virtual ~CZipReader(); //! opens a file by file name - virtual IReadFile* openFile(const c8* filename); + virtual IReadFile* createAndOpenFile(const io::path& filename); //! opens a file by index - IReadFile* openFile(s32 index); + virtual IReadFile* createAndOpenFile(u32 index); - //! returns count of files in archive - s32 getFileCount(); + //! returns the list of files + virtual const IFileList* getFileList() const; - //! returns data of file - const SZipFileEntry* getFileInfo(s32 index) const; - - //! returns fileindex - s32 findFile(const c8* filename); - - private: - - //! scans for a local header, returns false if there is no more - //! local file header. - bool scanLocalHeader(); - IReadFile* File; + //! get the archive type + virtual E_FILE_ARCHIVE_TYPE getType() const; protected: - //! splits filename from zip file into useful filenames and paths - void extractFilename(SZipFileEntry* entry); + IReadFile* File; - //! deletes the path from a filename - void deletePathFromFilename(core::stringc& filename); + //! reads the next file header from a ZIP file, returns false if there are no more headers. + bool scanZipHeader(); + //! the same but for gzip files + bool scanGZipHeader(); - bool IgnoreCase; - bool IgnorePaths; - core::array FileList; + bool IsGZip; + + // holds extended info about files + core::array FileInfo; }; - class CUnZipReader : public CZipReader - { - public: - - CUnZipReader(IFileSystem *parent, const c8* basename, - bool ignoreCase, bool ignorePaths); - - //! opens a file by file name - virtual IReadFile* openFile(const c8* filename); - - //! returns fileindex - s32 findFile(const c8* filename); - - private: - - IFileSystem *Parent; - void buildDirectory (); - - core::stringc Base; - }; - } // end namespace io } // end namespace irr -#endif +#endif // __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ +#endif // __C_ZIP_READER_H_INCLUDED__ diff --git a/src/dep/src/irrlicht/IAttribute.h b/src/dep/src/irrlicht/IAttribute.h new file mode 100644 index 0000000..d7f3c8a --- /dev/null +++ b/src/dep/src/irrlicht/IAttribute.h @@ -0,0 +1,106 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_ATTRIBUTE_H_INCLUDED__ +#define __I_ATTRIBUTE_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "SColor.h" +#include "vector3d.h" +#include "vector2d.h" +#include "line2d.h" +#include "line3d.h" +#include "triangle3d.h" +#include "position2d.h" +#include "rect.h" +#include "matrix4.h" +#include "quaternion.h" +#include "plane3d.h" +#include "triangle3d.h" +#include "line2d.h" +#include "line3d.h" +#include "irrString.h" +#include "irrArray.h" +#include "EAttributes.h" + + +namespace irr +{ +namespace io +{ + +class IAttribute : public virtual IReferenceCounted +{ +public: + + virtual ~IAttribute() {}; + + virtual s32 getInt() { return 0; } + virtual f32 getFloat() { return 0; } + virtual video::SColorf getColorf() { return video::SColorf(1.0f,1.0f,1.0f,1.0f); } + virtual video::SColor getColor() { return video::SColor(255,255,255,255); } + virtual core::stringc getString() { return core::stringc(getStringW().c_str()); } + virtual core::stringw getStringW() { return core::stringw(); } + virtual core::array getArray() { return core::array(); }; + virtual bool getBool() { return false; } + virtual void getBinary(void* outdata, s32 maxLength) {}; + virtual core::vector3df getVector() { return core::vector3df(); } + virtual core::position2di getPosition() { return core::position2di(); } + virtual core::rect getRect() { return core::rect(); } + virtual core::quaternion getQuaternion(){ return core::quaternion(); } + virtual core::matrix4 getMatrix() { return core::matrix4(); } + virtual core::triangle3df getTriangle() { return core::triangle3df(); } + virtual core::vector2df getVector2d() { return core::vector2df(); } + virtual core::vector2di getVector2di() { return core::vector2di(); } + virtual core::line2df getLine2d() { return core::line2df(); } + virtual core::line2di getLine2di() { return core::line2di(); } + virtual core::line3df getLine3d() { return core::line3df(); } + virtual core::line3di getLine3di() { return core::line3di(); } + virtual core::dimension2du getDimension2d() { return core::dimension2du(); } + virtual core::aabbox3d getBBox() { return core::aabbox3d(); } + virtual core::plane3df getPlane() { return core::plane3df(); } + + virtual video::ITexture* getTexture() { return 0; } + virtual const char* getEnum() { return 0; } + virtual void* getUserPointer() { return 0; } + + virtual void setInt(s32 intValue) {}; + virtual void setFloat(f32 floatValue) {}; + virtual void setString(const char* text) {}; + virtual void setString(const wchar_t* text){ setString(core::stringc(text).c_str()); }; + virtual void setArray(const core::array& arr ) {}; + virtual void setColor(video::SColorf color) {}; + virtual void setColor(video::SColor color) {}; + virtual void setBool(bool boolValue) {}; + virtual void setBinary(void* data, s32 maxLenght) {}; + virtual void setVector(core::vector3df v) {}; + virtual void setPosition(core::position2di v) {}; + virtual void setRect(core::rect v) {}; + virtual void setQuaternion(core::quaternion v) {}; + virtual void setMatrix(core::matrix4 v) {}; + virtual void setTriangle(core::triangle3df v) {}; + virtual void setVector2d(core::vector2df v) {}; + virtual void setVector2d(core::vector2di v) {}; + virtual void setLine2d(core::line2df v) {}; + virtual void setLine2d(core::line2di v) {}; + virtual void setLine3d(core::line3df v) {}; + virtual void setLine3d(core::line3di v) {}; + virtual void setDimension2d(core::dimension2du v) {}; + virtual void setBBox(core::aabbox3d v) {}; + virtual void setPlane(core::plane3df v) {}; + virtual void setUserPointer(void* v) {}; + + virtual void setEnum(const char* enumValue, const char* const* enumerationLiterals) {}; + virtual void setTexture(video::ITexture*) {}; + + core::stringc Name; + + virtual E_ATTRIBUTE_TYPE getType() const = 0; + virtual const wchar_t* getTypeString() const = 0; +}; + +} // end namespace io +} // end namespace irr + +#endif diff --git a/src/dep/src/irrlicht/IBurningShader.cpp b/src/dep/src/irrlicht/IBurningShader.cpp index 26d9b85..9d4ce0c 100644 --- a/src/dep/src/irrlicht/IBurningShader.cpp +++ b/src/dep/src/irrlicht/IBurningShader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -10,11 +10,10 @@ namespace irr { - namespace video { - const tFixPointu IBurningShader::dithermask[ 4 * 4] = + const tFixPointu IBurningShader::dithermask[] = { 0x00,0x80,0x20,0xa0, 0xc0,0x40,0xe0,0x60, @@ -23,7 +22,7 @@ namespace video }; IBurningShader::IBurningShader(IDepthBuffer* zbuffer) - :RenderTarget(0),DepthBuffer(zbuffer) + : RenderTarget(0),DepthBuffer(zbuffer) { #ifdef _DEBUG setDebugName("IBurningShader"); @@ -61,16 +60,15 @@ namespace video if (RenderTarget) RenderTarget->drop(); - RenderTarget = surface; + RenderTarget = (video::CImage* ) surface; if (RenderTarget) { RenderTarget->grab(); - //lockedSurface = (tVideoSample*)RenderTarget->lock(); - //lockedDepthBuffer = DepthBuffer->lock(); + //(tVideoSample*)RenderTarget->lock() = (tVideoSample*)RenderTarget->lock(); + //(fp24*) DepthBuffer->lock() = DepthBuffer->lock(); } - } @@ -91,22 +89,19 @@ namespace video // select mignify and magnify ( lodLevel ) //SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS it->lodLevel = lodLevel; - it->Texture->setCurrentMipMapLOD ( - core::s32_clamp ( lodLevel + SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS, 0, SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1 ) - ); + it->data = (tVideoSample*) it->Texture->lock(true, + core::s32_clamp ( lodLevel + SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS, 0, SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1 )); // prepare for optimal fixpoint it->pitchlog2 = s32_log2_s32 ( it->Texture->getPitch() ); - const core::dimension2d &dim = it->Texture->getSize(); + const core::dimension2d &dim = it->Texture->getSize(); it->textureXMask = s32_to_fixPoint ( dim.Width - 1 ) & FIX_POINT_UNSIGNED_MASK; it->textureYMask = s32_to_fixPoint ( dim.Height - 1 ) & FIX_POINT_UNSIGNED_MASK; - it->data = (tVideoSample*) it->Texture->lock(); } } - } // end namespace video } // end namespace irr diff --git a/src/dep/src/irrlicht/IBurningShader.h b/src/dep/src/irrlicht/IBurningShader.h index a9b7976..8c44dc8 100644 --- a/src/dep/src/irrlicht/IBurningShader.h +++ b/src/dep/src/irrlicht/IBurningShader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -16,6 +16,7 @@ #include "irrArray.h" #include "SLight.h" #include "SMaterial.h" +#include "os.h" namespace irr @@ -26,35 +27,57 @@ namespace video struct SBurningShaderLight { - SLight org; + //SLight org; + bool LightIsOn; - sVec4 posEyeSpace; - - f32 constantAttenuation; + E_LIGHT_TYPE Type; + f32 radius; f32 linearAttenuation; + f32 constantAttenuation; f32 quadraticAttenuation; + sVec4 pos; - sVec4 AmbientColor; - sVec4 DiffuseColor; - sVec4 SpecularColor; + sVec3 AmbientColor; + sVec3 DiffuseColor; + sVec3 SpecularColor; + }; + + enum eLightFlags + { + ENABLED = 0x01, + POINTLIGHT = 0x02, + SPECULAR = 0x04, + FOG = 0x08, + NORMALIZE = 0x10, + VERTEXTRANSFORM = 0x20, }; struct SBurningShaderLightSpace { + void reset () + { + Light.set_used ( 0 ); + Global_AmbientLight.set ( 0.f, 0.f, 0.f ); + Flags = 0; + } core::array Light; - sVec4 Global_AmbientLight; + sVec3 Global_AmbientLight; + sVec4 FogColor; + sVec4 campos; + sVec4 vertex; + sVec4 normal; + u32 Flags; }; struct SBurningShaderMaterial { SMaterial org; - sVec4 AmbientColor; - sVec4 DiffuseColor; - sVec4 SpecularColor; - sVec4 EmissiveColor; + sVec3 AmbientColor; + sVec3 DiffuseColor; + sVec3 SpecularColor; + sVec3 EmissiveColor; - u32 SpecularEnabled; // == Power2 }; enum EBurningFFShader @@ -73,15 +96,14 @@ namespace video ETR_TEXTURE_GOURAUD_VERTEX_ALPHA, - ETR_TEXTURE_GOURAUD_LIGHTMAP, + ETR_TEXTURE_GOURAUD_LIGHTMAP_M1, ETR_TEXTURE_GOURAUD_LIGHTMAP_M2, - ETR_TEXTURE_LIGHTMAP_M4, ETR_TEXTURE_GOURAUD_LIGHTMAP_M4, - - ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD, + ETR_TEXTURE_LIGHTMAP_M4, ETR_TEXTURE_GOURAUD_DETAIL_MAP, - + ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD, + ETR_GOURAUD_ALPHA, ETR_GOURAUD_ALPHA_NOZ, @@ -119,12 +141,9 @@ namespace video protected: - video::IImage* RenderTarget; + video::CImage* RenderTarget; IDepthBuffer* DepthBuffer; - fp24* lockedDepthBuffer; - tVideoSample* lockedSurface; - sInternalTexture IT[ BURNING_MATERIAL_MAX_TEXTURES ]; static const tFixPointu dithermask[ 4 * 4]; diff --git a/src/dep/src/irrlicht/IDepthBuffer.h b/src/dep/src/irrlicht/IDepthBuffer.h index 8110cad..83a2606 100644 --- a/src/dep/src/irrlicht/IDepthBuffer.h +++ b/src/dep/src/irrlicht/IDepthBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2010 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,10 +24,10 @@ namespace video virtual void clear() = 0; //! sets the new size of the zbuffer - virtual void setSize(const core::dimension2d& size) = 0; + virtual void setSize(const core::dimension2d& size) = 0; //! returns the size of the zbuffer - virtual const core::dimension2d& getSize() const = 0; + virtual const core::dimension2d& getSize() const = 0; //! locks the zbuffer virtual void* lock() = 0; @@ -42,7 +42,7 @@ namespace video //! creates a ZBuffer - IDepthBuffer* createDepthBuffer(const core::dimension2d& size); + IDepthBuffer* createDepthBuffer(const core::dimension2d& size); } // end namespace video } // end namespace irr diff --git a/src/dep/src/irrlicht/IImagePresenter.h b/src/dep/src/irrlicht/IImagePresenter.h index ef01f69..191740a 100644 --- a/src/dep/src/irrlicht/IImagePresenter.h +++ b/src/dep/src/irrlicht/IImagePresenter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/ISceneNodeAnimatorFinishing.h b/src/dep/src/irrlicht/ISceneNodeAnimatorFinishing.h new file mode 100644 index 0000000..60d1033 --- /dev/null +++ b/src/dep/src/irrlicht/ISceneNodeAnimatorFinishing.h @@ -0,0 +1,36 @@ +// Copyright (C) 2002-2008 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_NODE_ANIMATOR_FINISHING_H_INCLUDED__ +#define __I_SCENE_NODE_ANIMATOR_FINISHING_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + //! This is an abstract base class for animators that have a discrete end time. + class ISceneNodeAnimatorFinishing : public ISceneNodeAnimator + { + public: + + //! constructor + ISceneNodeAnimatorFinishing(u32 finishTime) + : FinishTime(finishTime), HasFinished(false) { } + + virtual bool hasFinished(void) const { return HasFinished; } + + protected: + + u32 FinishTime; + bool HasFinished; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/src/dep/src/irrlicht/ITriangleRenderer.h b/src/dep/src/irrlicht/ITriangleRenderer.h index a42cfee..701025d 100644 --- a/src/dep/src/irrlicht/ITriangleRenderer.h +++ b/src/dep/src/irrlicht/ITriangleRenderer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h diff --git a/src/dep/src/irrlicht/IZBuffer.h b/src/dep/src/irrlicht/IZBuffer.h index 7df7678..7f3c853 100644 --- a/src/dep/src/irrlicht/IZBuffer.h +++ b/src/dep/src/irrlicht/IZBuffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2008 Nikolaus Gebhardt +// Copyright (C) 2002-2010 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -24,10 +24,10 @@ namespace video virtual void clear() = 0; //! sets the new size of the zbuffer - virtual void setSize(const core::dimension2d& size) = 0; + virtual void setSize(const core::dimension2d& size) = 0; //! returns the size of the zbuffer - virtual const core::dimension2d& getSize() const = 0; + virtual const core::dimension2d& getSize() const = 0; //! locks the zbuffer virtual TZBufferType* lock() = 0; @@ -38,7 +38,7 @@ namespace video //! creates a ZBuffer - IZBuffer* createZBuffer(const core::dimension2d& size); + IZBuffer* createZBuffer(const core::dimension2d& size); } // end namespace video } // end namespace irr diff --git a/src/dep/src/irrlicht/Irrlicht-gcc.cbp b/src/dep/src/irrlicht/Irrlicht-gcc.cbp index a310b02..9771900 100644 --- a/src/dep/src/irrlicht/Irrlicht-gcc.cbp +++ b/src/dep/src/irrlicht/Irrlicht-gcc.cbp @@ -7,8 +7,9 @@