예제 #1
0
    //-----------------------------------------------------------------------
    Math::Math( unsigned int trigTableSize )
    {
        msAngleUnit = AU_DEGREE;
        mTrigTableSize = trigTableSize;
        mTrigTableFactor = mTrigTableSize / Math::TWO_PI;

        mSinTable = OGRE_ALLOC_T(Real, mTrigTableSize, MEMCATEGORY_GENERAL);
        mTanTable = OGRE_ALLOC_T(Real, mTrigTableSize, MEMCATEGORY_GENERAL);

        buildTrigTables();
    }
예제 #2
0
  void SplattingManager::createColourMap(Image& image, const ColourList& colours)
  {
    if (colours.size() > mImpl->numTextures)
      OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Given more colours than texture channels available.", __FUNCTION__);

#if OGRE_VERSION_MINOR > 4
    uchar* data = OGRE_ALLOC_T(uchar, mImpl->width*mImpl->height*3, MEMCATEGORY_GENERAL);
#else
    uchar* data = new uchar[mImpl->width*mImpl->height*3];
#endif

    for (size_t y = 0; y < mImpl->height; ++y)
    {
      for (size_t x = 0; x < mImpl->width; ++x)
      {
        ColourValue val (0, 0, 0);
        for (size_t i = 0; i < colours.size(); ++i)
        {
          size_t m = i / mImpl->channels;
          uint t = (uint) (i % mImpl->channels);
          val += colours[i] * (float(mImpl->maps[m]->getValue((uint)x, (uint)y, t)) / 255);
        }

        size_t pos = (x + y * mImpl->width) * 3;
        data[pos+0] = uchar(255*val.r);
        data[pos+1] = uchar(255*val.g);
        data[pos+2] = uchar(255*val.b);
      }
    }

    image.loadDynamicImage(data, mImpl->width, mImpl->height, 1, PF_BYTE_RGB, true);
  }
예제 #3
0
	//-----------------------------------------------------------------------------
	void ManualObject::resizeTempIndexBufferIfNeeded(size_t numInds)
	{
		size_t newSize = numInds * sizeof(uint32);
		if (newSize > mTempIndexSize || !mTempIndexBuffer)
		{
			if (!mTempIndexBuffer)
			{
				// init
				newSize = mTempIndexSize;
			}
			else
			{
				// increase to at least double current
				newSize = std::max(newSize, mTempIndexSize*2);
			}
			numInds = newSize / sizeof(uint32);
			uint32* tmp = mTempIndexBuffer;
			mTempIndexBuffer = OGRE_ALLOC_T(uint32, numInds, MEMCATEGORY_GEOMETRY);
			if (tmp)
			{
				memcpy(mTempIndexBuffer, tmp, mTempIndexSize);
				OGRE_FREE(tmp, MEMCATEGORY_GEOMETRY);
			}
			mTempIndexSize = newSize;
		}

	}
예제 #4
0
	//-----------------------------------------------------------------------------
	Image & Image::operator = ( const Image &img )
	{
		if( m_pBuffer && m_bAutoDelete )
		{
			OGRE_FREE(m_pBuffer, MEMCATEGORY_GENERAL);
			m_pBuffer = NULL;
		}
		m_uWidth = img.m_uWidth;
		m_uHeight = img.m_uHeight;
		m_uDepth = img.m_uDepth;
		m_eFormat = img.m_eFormat;
		m_uSize = img.m_uSize;
		m_uFlags = img.m_uFlags;
		m_ucPixelSize = img.m_ucPixelSize;
		m_uNumMipmaps = img.m_uNumMipmaps;
		m_bAutoDelete = img.m_bAutoDelete;
		//Only create/copy when previous data was not dynamic data
		if( m_bAutoDelete )
		{
			m_pBuffer = OGRE_ALLOC_T(uchar, m_uSize, MEMCATEGORY_GENERAL);
			memcpy( m_pBuffer, img.m_pBuffer, m_uSize );
		}
		else
		{
			m_pBuffer = img.m_pBuffer;
		}

		return *this;
	}
예제 #5
0
    //-----------------------------------------------------------------------------
    Image & Image::flipAroundX()
    {
        if( !mBuffer )
        {
            OGRE_EXCEPT( 
                Exception::ERR_INTERNAL_ERROR,
                "Can not flip an uninitialised texture",
                "Image::flipAroundX" );
        }
        
        mNumMipmaps = 0; // Image operations lose precomputed mipmaps

        size_t rowSpan = mWidth * mPixelSize;

        uchar *pTempBuffer = OGRE_ALLOC_T(uchar, rowSpan * mHeight, MEMCATEGORY_GENERAL);
        uchar *ptr1 = mBuffer, *ptr2 = pTempBuffer + ( ( mHeight - 1 ) * rowSpan );

        for( ushort i = 0; i < mHeight; i++ )
        {
            memcpy( ptr2, ptr1, rowSpan );
            ptr1 += rowSpan; ptr2 -= rowSpan;
        }

        memcpy( mBuffer, pTempBuffer, rowSpan * mHeight);

        OGRE_FREE(pTempBuffer, MEMCATEGORY_GENERAL);

        return *this;
    }
예제 #6
0
    //-----------------------------------------------------------------------------
    Image & Image::operator = ( const Image &img )
    {
        freeMemory();
        mWidth = img.mWidth;
        mHeight = img.mHeight;
        mDepth = img.mDepth;
        mFormat = img.mFormat;
        mBufSize = img.mBufSize;
        mFlags = img.mFlags;
        mPixelSize = img.mPixelSize;
        mNumMipmaps = img.mNumMipmaps;
        mAutoDelete = img.mAutoDelete;
        //Only create/copy when previous data was not dynamic data
        if( mAutoDelete )
        {
            mBuffer = OGRE_ALLOC_T(uchar, mBufSize, MEMCATEGORY_GENERAL);
            memcpy( mBuffer, img.mBuffer, mBufSize );
        }
        else
        {
            mBuffer = img.mBuffer;
        }

        return *this;
    }
예제 #7
0
  Image createMinimap(const Image& colourMap, const Image& lightMap)
  {
    if (colourMap.getWidth() != lightMap.getWidth() || colourMap.getHeight() != lightMap.getHeight())
      OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Images must have the same dimensions.", __FUNCTION__);

#if OGRE_VERSION_MINOR > 4
    uchar* data = OGRE_ALLOC_T(uchar, colourMap.getWidth()*colourMap.getHeight()*3, MEMCATEGORY_GENERAL);
#else
    uchar* data = new uchar[colourMap.getWidth()*colourMap.getHeight()*3];
#endif

    for (size_t y = 0; y < colourMap.getWidth(); ++y)
    {
      for (size_t x = 0; x < colourMap.getHeight(); ++x)
      {
        ColourValue val = const_cast<Image&>(colourMap).getColourAt((uint)x, (uint)y, 0) * const_cast<Image&>(lightMap).getColourAt((uint)x, (uint)y, 0);
        size_t pos = (x + y*colourMap.getWidth()) * 3;
        data[pos+0] = uchar(255*val.r);
        data[pos+1] = uchar(255*val.g);
        data[pos+2] = uchar(255*val.b);
      }
    }

    Image image;
    image.loadDynamicImage(data, colourMap.getWidth(), colourMap.getHeight(), 1, PF_BYTE_RGB, true);
    return image;
  }
예제 #8
0
    //---------------------------------------------------------------------
    DataStreamPtr FreeImageCodec::code(MemoryDataStreamPtr& input, Codec::CodecDataPtr& pData) const
    {        
		// Set error handler
		FreeImage_SetOutputMessage(FreeImageSaveErrorHandler);

		FIBITMAP* fiBitmap = encode(input, pData);

		// open memory chunk allocated by FreeImage
		FIMEMORY* mem = FreeImage_OpenMemory();
		// write data into memory
		FreeImage_SaveToMemory((FREE_IMAGE_FORMAT)mFreeImageType, fiBitmap, mem);
		// Grab data information
		BYTE* data;
		DWORD size;
		FreeImage_AcquireMemory(mem, &data, &size);
		// Copy data into our own buffer
		// Because we're asking MemoryDataStream to free this, must create in a compatible way
		BYTE* ourData = OGRE_ALLOC_T(BYTE, size, MEMCATEGORY_GENERAL);
		memcpy(ourData, data, size);
		// Wrap data in stream, tell it to free on close 
		DataStreamPtr outstream(OGRE_NEW MemoryDataStream(ourData, size, true));
		// Now free FreeImage memory buffers
		FreeImage_CloseMemory(mem);
		// Unload bitmap
		FreeImage_Unload(fiBitmap);

		return outstream;


    }
    //---------------------------------------------------------------------
	void DeflateStream::init()
	{
		mpZStream = OGRE_ALLOC_T(z_stream, 1, MEMCATEGORY_GENERAL);
		mpZStream->zalloc = OgreZalloc;
		mpZStream->zfree = OgreZfree;
		
		if (getAccessMode() == READ)
		{
			mpTmp = (unsigned char*)OGRE_MALLOC(OGRE_DEFLATE_TMP_SIZE, MEMCATEGORY_GENERAL);
			size_t restorePoint = mCompressedStream->tell();
			// read early chunk
			mpZStream->next_in = mpTmp;
			mpZStream->avail_in = mCompressedStream->read(mpTmp, OGRE_DEFLATE_TMP_SIZE);
			
			if (inflateInit(mpZStream) != Z_OK)
			{
				mIsCompressedValid = false;
			}
			else
				mIsCompressedValid = true;
			
			if (mIsCompressedValid)
			{
				// in fact, inflateInit on some implementations doesn't try to read
				// anything. We need to at least read something to test
				Bytef testOut[4];
				size_t savedIn = mpZStream->avail_in;
				mpZStream->avail_out = 4;
				mpZStream->next_out = testOut;
				if (inflate(mpZStream, Z_SYNC_FLUSH) != Z_OK)
					mIsCompressedValid = false;
				// restore for reading
				mpZStream->avail_in = savedIn;
				mpZStream->next_in = mpTmp;

				inflateReset(mpZStream);
			}

			if (!mIsCompressedValid)
			{
				// Not compressed data!
				// Fail gracefully, fall back on reading the underlying stream direct
				destroy();
				mCompressedStream->seek(restorePoint);
			}				
		}
		else 
		{
			// Write to temp file
			char tmpname[L_tmpnam];
			tmpnam(tmpname);
			mTempFileName = tmpname;
			std::fstream *f = OGRE_NEW_T(std::fstream, MEMCATEGORY_GENERAL)();
			f->open(tmpname, std::ios::binary | std::ios::out);
			mTmpWriteStream = DataStreamPtr(OGRE_NEW FileStreamDataStream(f));
			
		}

	}
//-----------------------------------------------------------------------------  
D3D9HardwarePixelBuffer::BufferResources* D3D9HardwarePixelBuffer::createBufferResources()
{
    BufferResources* newResources = OGRE_ALLOC_T(BufferResources, 1, MEMCATEGORY_RENDERSYS);

    memset(newResources, 0, sizeof(BufferResources));

    return newResources;
}
예제 #11
0
    void GlobalMap::clear()
    {
        Ogre::uchar* buffer =  OGRE_ALLOC_T(Ogre::uchar, mWidth * mHeight * 4, Ogre::MEMCATEGORY_GENERAL);
        memset(buffer, 0, mWidth * mHeight * 4);

        mOverlayImage.loadDynamicImage(&buffer[0], mWidth, mHeight, 1, Ogre::PF_A8B8G8R8, true); // pass ownership of buffer to image

        mOverlayTexture->load();
    }
예제 #12
0
    //-----------------------------------------------------------------------
    void RenderTarget::writeContentsToFile(const String& filename)
    {
        PixelFormat pf = suggestPixelFormat();

        uchar *data = OGRE_ALLOC_T(uchar, mWidth * mHeight * PixelUtil::getNumElemBytes(pf), MEMCATEGORY_RENDERSYS);
        PixelBox pb(mWidth, mHeight, 1, pf, data);

        copyContentsToMemory(pb);

        Image().loadDynamicImage(data, mWidth, mHeight, 1, pf, false, 1, 0).save(filename);

        OGRE_FREE(data, MEMCATEGORY_RENDERSYS);
    }
HalfFloatGridSource::HalfFloatGridSource(const String &serializedVolumeFile, const bool trilinearValue, const bool trilinearGradient, const bool sobelGradient) :
    GridSource(trilinearValue, trilinearGradient, sobelGradient)
{

    Timer t;
    DataStreamPtr streamRead = Root::getSingleton().openFileStream(serializedVolumeFile);
#if OGRE_NO_ZIP_ARCHIVE == 0
    DataStreamPtr uncompressStream(OGRE_NEW DeflateStream(serializedVolumeFile, streamRead));
    StreamSerialiser ser(uncompressStream);
#else
    StreamSerialiser ser(streamRead);
#endif
    if (!ser.readChunkBegin(VOLUME_CHUNK_ID, VOLUME_CHUNK_VERSION))
    {
        OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
                    "Invalid volume file given!",
                    __FUNCTION__);
    }

    // Read header
    Vector3 readFrom, readTo;
    ser.read(&readFrom);
    ser.read(&readTo);
    float voxelWidth;
    ser.read<float>(&voxelWidth);
    size_t width, height, depth;
    ser.read<size_t>(&width);
    ser.read<size_t>(&height);
    ser.read<size_t>(&depth);
    mWidth = static_cast<int>(width);
    mHeight = static_cast<int>(height);
    mDepth = static_cast<int>(depth);
    mDepthTimesHeight = static_cast<int>(mDepth * mHeight);

    Vector3 worldDimension = readTo - readFrom;
    mPosXScale = (Real)1.0 / (Real)worldDimension.x * (Real)mWidth;
    mPosYScale = (Real)1.0 / (Real)worldDimension.y * (Real)mHeight;
    mPosZScale = (Real)1.0 / (Real)worldDimension.z * (Real)mDepth;

    mVolumeSpaceToWorldSpaceFactor = (Real)worldDimension.x * (Real)mWidth;
    mMaxClampedAbsoluteDensity = 0;

    // Read data
    size_t elementCount = mWidth * mHeight * mDepth;
    mData = OGRE_ALLOC_T(uint16, elementCount, MEMCATEGORY_GENERAL);
    ser.read(mData, elementCount);

    ser.readChunkEnd(VOLUME_CHUNK_ID);

    LogManager::getSingleton().stream() << "Processed serialization in " << t.getMilliseconds() << "ms.";
}
예제 #14
0
파일: ETBrush.cpp 프로젝트: oksangman/Ant
  void saveBrushToImage(const Brush& brush, Image& image)
  {
    // save brush as a 16bit grayscale image
#if OGRE_VERSION_MINOR > 4
    ushort* data = (ushort*)OGRE_ALLOC_T(uchar, brush.getWidth()*brush.getHeight()*sizeof(ushort), MEMCATEGORY_GENERAL);
#else
    ushort* data = (ushort*)new uchar[brush.getWidth()*brush.getHeight()*sizeof(ushort)];
#endif
    for (size_t x = 0; x < brush.getWidth(); ++x)
      for (size_t y = 0; y < brush.getHeight(); ++y)
        data[y*brush.getWidth() + x] = ushort(brush.at(x, y) * 0xffff);

    // pass the data to the image, image takes over ownership
    image.loadDynamicImage((uchar*)data, brush.getWidth(), brush.getHeight(), 1, PF_L16, true);
  }
예제 #15
0
  // bool publishFrame(Ogre::RenderWindow * render_object, const std::string frame_id)
  bool publishFrame(Ogre::RenderTexture * render_object, const std::string frame_id)
  {
    if (pub_.getTopic() == "")
    {
      return false;
    }
    if (frame_id == "")
    {
      return false;
    }
    // RenderTarget::writeContentsToFile() used as example
    int height = render_object->getHeight();
    int width = render_object->getWidth();
    // the results of pixel format have to be used to determine
    // image.encoding
    Ogre::PixelFormat pf = render_object->suggestPixelFormat();
    uint pixelsize = Ogre::PixelUtil::getNumElemBytes(pf);
    uint datasize = width * height * pixelsize;

    // 1.05 multiplier is to avoid crash when the window is resized.
    // There should be a better solution.
    uchar *data = OGRE_ALLOC_T(uchar, datasize * 1.05, Ogre::MEMCATEGORY_RENDERSYS);
    Ogre::PixelBox pb(width, height, 1, pf, data);
    render_object->copyContentsToMemory(pb, Ogre::RenderTarget::FB_AUTO);

    sensor_msgs::Image image;
    image.header.stamp = ros::Time::now();
    image.header.seq = image_id_++;
    image.header.frame_id = frame_id;
    image.height = height;
    image.width = width;
    image.step = pixelsize * width;
    if (pixelsize == 3)
      image.encoding = sensor_msgs::image_encodings::RGB8;  // would break if pf changes
    else if (pixelsize == 4)
      image.encoding = sensor_msgs::image_encodings::RGBA8;  // would break if pf changes
    else
    {
      ROS_ERROR_STREAM("unknown pixe format " << pixelsize << " " << pf);
    }
    image.is_bigendian = (OGRE_ENDIAN == OGRE_ENDIAN_BIG);
    image.data.resize(datasize);
    memcpy(&image.data[0], data, datasize);
    pub_.publish(image);

    OGRE_FREE(data, Ogre::MEMCATEGORY_RENDERSYS);
  }
예제 #16
0
	//-----------------------------------------------------------------------------
	Image& Image::loadDynamicImage( uchar* pData, size_t uWidth, size_t uHeight, 
		size_t depth,
		PixelFormat eFormat, bool autoDelete, 
		size_t numFaces, size_t numMipMaps)
	{

		if( m_pBuffer && m_bAutoDelete )
		{
			OGRE_FREE(m_pBuffer, MEMCATEGORY_GENERAL);
			m_pBuffer = NULL;
		}
		// Set image metadata
		m_uWidth = uWidth;
		m_uHeight = uHeight;
		m_uDepth = depth;
		m_eFormat = eFormat;
		m_ucPixelSize = static_cast<uchar>(PixelUtil::getNumElemBytes( m_eFormat ));
		m_uNumMipmaps = numMipMaps;
		m_uFlags = 0;
		// Set flags
		if (PixelUtil::isCompressed(eFormat))
			m_uFlags |= IF_COMPRESSED;
		if (m_uDepth != 1)
			m_uFlags |= IF_3D_TEXTURE;
		if(numFaces == 6)
			m_uFlags |= IF_CUBEMAP;
		if(numFaces != 6 && numFaces != 1)
			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
			"Number of faces currently must be 6 or 1.", 
			"Image::loadDynamicImage");

		m_uSize = calculateSize(numMipMaps, numFaces, uWidth, uHeight, depth, eFormat);

		if (pData)
		{
			m_pBuffer = pData;
			m_bAutoDelete = autoDelete;
		}
		else
		{
			m_bAutoDelete = true;
			m_pBuffer = OGRE_ALLOC_T(Ogre::uchar, m_uSize, Ogre::MEMCATEGORY_RESOURCE);
		}

		return *this;

	}
예제 #17
0
  void SplattingManager::createBaseTexture(Image& image, size_t width, size_t height,
    ImageList textures, float repeatX, float repeatZ)
  {
    if (textures.size() > mImpl->numTextures)
      OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Given more textures than texture channels available.", "ET::SplattingManager::createBaseTexture");

    // first resize the textures according to the desired output size and the repeat values
    ushort scaleWidth = (ushort) (width / repeatX);
    ushort scaleHeight = (ushort) (height / repeatZ);
    for (ImageList::iterator it = textures.begin(); it != textures.end(); ++it)
      it->resize(scaleWidth, scaleHeight);

    // create the buffer to hold our generated base texture
#if OGRE_VERSION_MINOR > 4
    uchar* data = OGRE_ALLOC_T(uchar, width*height*3, MEMCATEGORY_GENERAL);
#else
    uchar* data = new uchar[width*height*3];
#endif
    size_t pos = 0;
    for (size_t y = 0; y < height; ++y)
    {
      for (size_t x = 0; x < width; ++x)
      {
        ColourValue val (0,0,0);
        int texX = (int) (x % scaleWidth);
        int texY = (int) (y % scaleHeight);
        for (size_t t = 0; t < textures.size(); ++t)
        {
          // get interpolated part of this texture at the current pixel
          float weight = mImpl->interpolateWeight(x, y, width, height, t);
          // get colour value of the texture image
          ColourValue col = textures[t].getColourAt(texX, texY, 0);
          // add to the pixel colour level
          val += weight*col;
        }

        // write colour to our buffer
        data[pos+0] = uchar(255*val.r);
        data[pos+1] = uchar(255*val.g);
        data[pos+2] = uchar(255*val.b);
        pos += 3;
      }
    }

    image.loadDynamicImage(data, width, height, 1, PF_BYTE_RGB, true);
  }
예제 #18
0
    //-----------------------------------------------------------------------------
    void Image::resize(ushort width, ushort height, Filter filter)
    {
        // resizing dynamic images is not supported
        assert(mAutoDelete);
        assert(mDepth == 1);

        // reassign buffer to temp image, make sure auto-delete is true
        Image temp;
        temp.loadDynamicImage(mBuffer, mWidth, mHeight, 1, mFormat, true);
        // do not delete[] mBuffer!  temp will destroy it

        // set new dimensions, allocate new buffer
        mWidth = width;
        mHeight = height;
        mBufSize = PixelUtil::getMemorySize(mWidth, mHeight, 1, mFormat);
        mBuffer = OGRE_ALLOC_T(uchar, mBufSize, MEMCATEGORY_GENERAL);
        mNumMipmaps = 0; // Loses precomputed mipmaps

        // scale the image from temp into our resized buffer
        Image::scale(temp.getPixelBox(), getPixelBox(), filter);
    }
예제 #19
0
	Vector4* SnowTerrain::convertNormalsToFloats(PixelBox* terrainNormals, bool compressed)
	{
		const size_t srcPixelSize = PixelUtil::getNumElemBytes(terrainNormals->format);
		const size_t dstPixelSize = PixelUtil::getNumElemBytes(PF_FLOAT32_RGBA);
		size_t w,h,d;
		w = terrainNormals->getWidth();
		h = terrainNormals->getHeight();
		d = terrainNormals->getDepth();

		assert(terrainNormals->getWidth() == mTerrainSize);
		size_t terrainNormalSize = terrainNormals->getWidth()*terrainNormals->getHeight();
		Vector4* terrainNormalDataCorrected = OGRE_ALLOC_T(Vector4, terrainNormalSize, MEMCATEGORY_GENERAL);

		size_t i = 0; size_t j = 0;
		uint8* pixelsBuffer = static_cast<uint8*>(terrainNormals->data);
		for(; i < terrainNormalSize * srcPixelSize && j < terrainNormalSize * sizeof(Vector4); i+=srcPixelSize)
		{
			uint8 r,g,b,a;
			PixelUtil::unpackColour(&r,&g,&b,&a, terrainNormals->format, static_cast<void*>(&pixelsBuffer[i]));
			float fr,fg,fb;
			if(compressed)
			{			
				//(signed) float packed/compressed into uint8, unpack
				fr = ((float)(r))/(0.5f * 255.0f) - 1.0f;
				fg = ((float)(g))/(0.5f * 255.0f) - 1.0f;
				fb = ((float)(b))/(0.5f * 255.0f) - 1.0f;
			}
			else
			{
				fr = ((float)(r))/255.0f;
				fg = ((float)(g))/255.0f;
				fb = ((float)(b))/255.0f;
			}
			Vector3 v = Vector3(fr, fg, fb);
			v.normalise();
			terrainNormalDataCorrected[j++] = Vector4(v);
		}

		return terrainNormalDataCorrected;
	}
예제 #20
0
    //-----------------------------------------------------------------------------
    Image & Image::loadRawData(
        DataStreamPtr& stream, 
        uint32 uWidth, uint32 uHeight, uint32 uDepth,
        PixelFormat eFormat,
        size_t numFaces, size_t numMipMaps)
    {

        size_t size = calculateSize(numMipMaps, numFaces, uWidth, uHeight, uDepth, eFormat);
        if (size != stream->size())
        {
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
                "Stream size does not match calculated image size", 
                "Image::loadRawData");
        }

        uchar *buffer = OGRE_ALLOC_T(uchar, size, MEMCATEGORY_GENERAL);
        stream->read(buffer, size);

        return loadDynamicImage(buffer,
            uWidth, uHeight, uDepth,
            eFormat, true, numFaces, numMipMaps);

    }
예제 #21
0
	//-----------------------------------------------------------------------
	void ConvexBody::clip( const Plane& pl, bool keepNegative )
	{
		if ( getPolygonCount() == 0 )
			return;

		// current will be used as the reference body
		ConvexBody current;
		current.moveDataFromBody(*this);
		
		OgreAssert( this->getPolygonCount() == 0, "Body not empty!" );
		OgreAssert( current.getPolygonCount() != 0, "Body empty!" );

		// holds all intersection edges for the different polygons
		Polygon::EdgeMap intersectionEdges;

		// clip all polygons by the intersection plane
		// add only valid or intersected polygons to *this
		for ( size_t iPoly = 0; iPoly < current.getPolygonCount(); ++iPoly )
		{

			// fetch vertex count and ignore polygons with less than three vertices
			// the polygon is not valid and won't be added
			const size_t vertexCount = current.getVertexCount( iPoly );
			if ( vertexCount < 3 )
				continue;

			// current polygon
			const Polygon& p = current.getPolygon( iPoly );

			// the polygon to assemble
			Polygon *pNew = allocatePolygon();

			// the intersection polygon (indeed it's an edge or it's empty)
			Polygon *pIntersect = allocatePolygon();
			
			// check if polygons lie inside or outside (or on the plane)
			// for each vertex check where it is situated in regard to the plane
			// three possibilities appear:
			Plane::Side clipSide = keepNegative ? Plane::POSITIVE_SIDE : Plane::NEGATIVE_SIDE;
			// - side is clipSide: vertex will be clipped
			// - side is !clipSide: vertex will be untouched
			// - side is NOSIDE:   vertex will be untouched
			Plane::Side *side = OGRE_ALLOC_T(Plane::Side, vertexCount, MEMCATEGORY_SCENE_CONTROL);
			for ( size_t iVertex = 0; iVertex < vertexCount; ++iVertex )
			{
				side[ iVertex ] = pl.getSide( p.getVertex( iVertex ) );
			}

			// now we check the side combinations for the current and the next vertex
			// four different combinations exist:
			// - both points inside (or on the plane): keep the second (add it to the body)
			// - both points outside: discard both (don't add them to the body)
			// - first vertex is inside, second is outside: add the intersection point
			// - first vertex is outside, second is inside: add the intersection point, then the second
			for ( size_t iVertex = 0; iVertex < vertexCount; ++iVertex )
			{
				// determine the next vertex
				size_t iNextVertex = ( iVertex + 1 ) % vertexCount;

				const Vector3& vCurrent = p.getVertex( iVertex );
				const Vector3& vNext    = p.getVertex( iNextVertex );

				// case 1: both points inside (store next)
				if ( side[ iVertex ]     != clipSide &&		// NEGATIVE or NONE
					 side[ iNextVertex ] != clipSide )		// NEGATIVE or NONE
				{
					// keep the second
					pNew->insertVertex( vNext );
				}

				// case 3: inside -> outside (store intersection)
				else if ( side[ iVertex ]		!= clipSide &&
						  side[ iNextVertex ]	== clipSide )
				{
					// Do an intersection with the plane. We use a ray with a start point and a direction.
					// The ray is forced to hit the plane with any option available (eigher current or next
					// is the starting point)

					// intersect from the outside vertex towards the inside one
					Vector3 vDirection = vCurrent - vNext;
					vDirection.normalise();
					Ray ray( vNext, vDirection );
					std::pair< bool, Real > intersect = ray.intersects( pl );

					// store intersection
					if ( intersect.first )
					{
						// convert distance to vector
						Vector3 vIntersect = ray.getPoint( intersect.second );	

						// store intersection
						pNew->insertVertex( vIntersect );
						pIntersect->insertVertex( vIntersect );
					}
				}

				// case 4: outside -> inside (store intersection, store next)
				else if ( side[ iVertex ]		== clipSide &&
					side[ iNextVertex ]			!= clipSide )
				{
					// Do an intersection with the plane. We use a ray with a start point and a direction.
					// The ray is forced to hit the plane with any option available (eigher current or next
					// is the starting point)

					// intersect from the outside vertex towards the inside one
					Vector3 vDirection = vNext - vCurrent;
					vDirection.normalise();
					Ray ray( vCurrent, vDirection );
					std::pair< bool, Real > intersect = ray.intersects( pl );

					// store intersection
					if ( intersect.first )
					{
						// convert distance to vector
						Vector3 vIntersect = ray.getPoint( intersect.second );

						// store intersection
						pNew->insertVertex( vIntersect );
						pIntersect->insertVertex( vIntersect );
					}

					pNew->insertVertex( vNext );

				}
				// else:
				// case 2: both outside (do nothing)
					
			}

			// insert the polygon only, if at least three vertices are present
			if ( pNew->getVertexCount() >= 3 )
			{
				// in case there are double vertices, remove them
				pNew->removeDuplicates();

				// in case there are still at least three vertices, insert the polygon
				if ( pNew->getVertexCount() >= 3 )
				{
					this->insertPolygon( pNew );
				}
				else
				{
					// delete pNew because it's empty or invalid
					freePolygon(pNew);
					pNew = 0;
				}
			}
			else
			{
				// delete pNew because it's empty or invalid
				freePolygon(pNew);
				pNew = 0;
			}

			// insert intersection polygon only, if there are two vertices present
			if ( pIntersect->getVertexCount() == 2 )
			{
				intersectionEdges.insert( Polygon::Edge( pIntersect->getVertex( 0 ),
														  pIntersect->getVertex( 1 ) ) );
			}

			// delete intersection polygon
			// vertices were copied (if there were any)
			freePolygon(pIntersect);
			pIntersect = 0;

			// delete side info
			OGRE_FREE(side, MEMCATEGORY_SCENE_CONTROL);
			side = 0;
		}

		// if the polygon was partially clipped, close it
		// at least three edges are needed for a polygon
		if ( intersectionEdges.size() >= 3 )
		{
			Polygon *pClosing = allocatePolygon();

			// Analyze the intersection list and insert the intersection points in ccw order
			// Each point is twice in the list because of the fact that we have a convex body
			// with convex polygons. All we have to do is order the edges (an even-odd pair)
			// in a ccw order. The plane normal shows us the direction.
			Polygon::EdgeMap::iterator it = intersectionEdges.begin();

			// check the cross product of the first two edges
			Vector3 vFirst  = it->first;
			Vector3 vSecond = it->second;

			// remove inserted edge
			intersectionEdges.erase( it );

			Vector3 vNext;

			// find mating edge
			if (findAndEraseEdgePair(vSecond, intersectionEdges, vNext))
			{
				// detect the orientation
				// the polygon must have the same normal direction as the plane and then n
				Vector3 vCross = ( vFirst - vSecond ).crossProduct( vNext - vSecond );
				bool frontside = ( pl.normal ).directionEquals( vCross, Degree( 1 ) );

				// first inserted vertex
				Vector3 firstVertex;
				// currently inserted vertex
				Vector3 currentVertex;
				// direction equals -> front side (walk ccw)
				if ( frontside )
				{
					// start with next as first vertex, then second, then first and continue with first to walk ccw
					pClosing->insertVertex( vNext );
					pClosing->insertVertex( vSecond );
					pClosing->insertVertex( vFirst );
					firstVertex		= vNext;
					currentVertex	= vFirst;

				#ifdef _DEBUG_INTERSECTION_LIST
					std::cout << "Plane: n=" << pl.normal << ", d=" << pl.d << std::endl;
					std::cout << "First inserted vertex: " << *next << std::endl;
					std::cout << "Second inserted vertex: " << *vSecond << std::endl;
					std::cout << "Third inserted vertex: " << *vFirst << std::endl;
				#endif
				}
				// direction does not equal -> back side (walk cw)
				else
				{
					// start with first as first vertex, then second, then next and continue with next to walk ccw
					pClosing->insertVertex( vFirst );
					pClosing->insertVertex( vSecond );
					pClosing->insertVertex( vNext );
					firstVertex		= vFirst;
					currentVertex	= vNext;

					#ifdef _DEBUG_INTERSECTION_LIST
						std::cout << "Plane: n=" << pl.normal << ", d=" << pl.d << std::endl;
						std::cout << "First inserted vertex: " << *vFirst << std::endl;
						std::cout << "Second inserted vertex: " << *vSecond << std::endl;
						std::cout << "Third inserted vertex: " << *next << std::endl;
					#endif
				}

				// search mating edges that have a point in common
				// continue this operation as long as edges are present
				while ( !intersectionEdges.empty() )
				{

					if (findAndEraseEdgePair(currentVertex, intersectionEdges, vNext))
					{
						// insert only if it's not the last (which equals the first) vertex
						if ( !intersectionEdges.empty() )
						{
							currentVertex = vNext;
							pClosing->insertVertex( vNext );
						}
					}
					else
					{
						// degenerated...
						break;
					}

				} // while intersectionEdges not empty

				// insert polygon (may be degenerated!)
				this->insertPolygon( pClosing );

			}
			// mating intersection edge NOT found!
			else
			{
				freePolygon(pClosing);
			}

		} // if intersectionEdges contains more than three elements
	}
예제 #22
0
//-----------------------------------------------------------------------
void AtlasImageTool::process (void)
{
	Ogre::Root root("", "", "atlas.log");
	Ogre::ResourceGroupManager::getSingleton().addResourceLocation(mImagePath, "FileSystem");
	Ogre::StringVector::iterator itInputFileName;
	Ogre::StringVector::iterator itFrame;
	Ogre::StringVector::iterator itAlpha;

	itAlpha = mAlpha.begin();
	if (mInputFrames.empty() || mInputFrames[0] == Ogre::StringUtil::BLANK)
	{
		// No Frames are assigned so just add them
		for (itInputFileName = mInputFileNames.begin(); itInputFileName != mInputFileNames.end(); ++itInputFileName)
		{
			Ogre::String imageFileName = *itInputFileName;
			Ogre::Image image;
			image.load(imageFileName, "General");

			if (itAlpha != mAlpha.end() && *itAlpha != Ogre::StringUtil::BLANK)
			{
				Ogre::Real alpha = Ogre::StringConverter::parseReal(*itAlpha);
				correctAlpha(image, alpha);
				itAlpha++;
			}

			mAtlasImage.addImage(&image);
		}
	}
	else
	{
		// Frames are assigned, so generate intermediate images
		itInputFileName = mInputFileNames.begin();
		Ogre::Real alpha = 1.0f;
		Ogre::String nextImageFileName = *itInputFileName;
		Ogre::Image nextImage;
		itFrame = mInputFrames.begin();
		size_t nextFrame = Ogre::StringConverter::parseUnsignedInt(*itFrame);
		nextImage.load(nextImageFileName, "General");
		size_t frameCounter = 0;

		if (!mAlpha.empty() && mAlpha[0] != Ogre::StringUtil::BLANK)
		{
			itAlpha = mAlpha.begin();
			Ogre::Real alpha = Ogre::StringConverter::parseReal(*itAlpha);
			correctAlpha(nextImage, alpha);
			itAlpha++;
		}

		mAtlasImage.addImage(&nextImage);
		frameCounter++;
		itInputFileName++;
		itFrame++;

		while (itInputFileName != mInputFileNames.end())
		{
			// Get the next filename
			Ogre::Image firstImage(nextImage);
			nextImageFileName = *itInputFileName;
			nextImage.load(nextImageFileName, "General");

			if (itAlpha != mAlpha.end() && *itAlpha != Ogre::StringUtil::BLANK)
			{
				Ogre::Real alpha = Ogre::StringConverter::parseReal(*itAlpha);
				correctAlpha(nextImage, alpha);
				itAlpha++;
			}

			if (itFrame != mInputFrames.end())
			{
				size_t firstFrame = nextFrame;
				nextFrame = Ogre::StringConverter::parseUnsignedInt(*itFrame);
				itFrame++;
				frameCounter++;

				// Generate and add interpolated images to the atlas image
				size_t numberOfFrames = nextFrame - firstFrame;
				for (size_t i = 1; i < numberOfFrames; ++i)
				{
					Ogre::Real fraction = (Ogre::Real)i / (Ogre::Real)numberOfFrames;
					Ogre::Image interpolatedImage;
					size_t pixelSize = Ogre::PixelUtil::getNumElemBytes(firstImage.getFormat());
					size_t bufferSize = firstImage.getWidth() * firstImage.getHeight() * pixelSize;
					Ogre::uchar* data = OGRE_ALLOC_T(Ogre::uchar, bufferSize, Ogre::MEMCATEGORY_GENERAL);
					interpolatedImage.loadDynamicImage(data, firstImage.getWidth(), firstImage.getHeight(), 1, firstImage.getFormat(), true);
					interpolate (interpolatedImage, firstImage, nextImage, fraction);
					mAtlasImage.addImage(&interpolatedImage);
					frameCounter++;
				}
			}
			mAtlasImage.addImage(&nextImage);
			frameCounter++;
			itInputFileName++;
		}
	}

	mAtlasImage._compile();
	mAtlasImage.save(mImagePath + "//" + mOutputImage);
}
예제 #23
0
void 
MaterialPreviewDialog::buildPreviewBitmap( const Ogre::String &texName )
{
	const Ogre::uchar BytePerPixel = 8;

	// 读取原始image
	Ogre::Image *oriImage = getPreviewImage(texName);
	// 源大纹理的大小
	size_t oriImageHeight = oriImage->getHeight();
	size_t oriImageWidth = oriImage->getWidth();

	Ogre::uchar *oriImageData = oriImage->getData();

	// 分配一个足够大的空间来保存新建的image的数据
	size_t newImagegetRowSpan = oriImageWidth*oriImage->getBPP()/BytePerPixel;  // 新建的image的行宽(单位为字节)
	Ogre::uchar *newImageData = OGRE_ALLOC_T(Ogre::uchar, oriImageHeight*newImagegetRowSpan, Ogre::MEMCATEGORY_GENERAL);//new Ogre::uchar[oriImageHeight*newImagegetRowSpan];

	Ogre::uchar *newImageDataPointer = newImageData;

	Ogre::uchar *oriImagedataPointer = oriImageData;

	// 把所选的纹理的数据提取出来,并创建一个新的image
	for ( Ogre::uint i=0; i<oriImageHeight; ++i )
	{
		memcpy(newImageDataPointer, oriImagedataPointer, newImagegetRowSpan);
		newImageDataPointer += newImagegetRowSpan;
		oriImagedataPointer += oriImage->getRowSpan();
	}

	Ogre::Image newImage;
	newImage.loadDynamicImage(newImageData,oriImageWidth,oriImageHeight,1,oriImage->getFormat(),true);

	// 如果所选纹理大于64*64,就先resize
	if ( oriImageWidth > mPreviewImageWidth || oriImageHeight > mPreviewImageHeight )
		newImage.resize(mPreviewImageWidth, mPreviewImageHeight);

	// 如果有alpha,要与黑白图进行混合
	if ( newImage.getHasAlpha() )
	{
		Ogre::ColourValue col;

		for ( int i=0; i<mPreviewImageWidth; ++i )
		{
			for ( int j=0; j<mPreviewImageWidth; ++j )
			{
				col = newImage.getColourAt(j,i,0);

				float alphaValue = col.a;

				unsigned char r = col.r*255 * alphaValue; 
				unsigned char g = col.g*255 * alphaValue; 
				unsigned char b = col.b*255 * alphaValue;

				// 设置到image中
				mCurrentPreviewImage.SetRGB(j,i,r,g,b);
			}
		}
	}
	// 没有alpha,就直接拷贝数据
	else
	{
		Ogre::ColourValue col;

		for ( int i=0; i<mPreviewImageWidth; ++i )
		{
			for ( int j=0; j<mPreviewImageWidth; ++j )
			{
				col = newImage.getColourAt(j,i,0);

				unsigned char r = col.r*255;
				unsigned char g = col.g*255;
				unsigned char b = col.b*255;

				// 设置到image中
				mCurrentPreviewImage.SetRGB(j,i,r,g,b);
			}
		}
	}
}
예제 #24
0
void 
BrushSelector::buildPreviewBitmap( const Fairy::TextureInfo texInfo )
{
    const Ogre::uchar BytePerPixel = 8;

    // 读取原始image
    Ogre::Image *oriImage = GetSceneManipulator()->getPreviewImage(texInfo.ownerTextureName);
    // 源大纹理的大小
    size_t oriImageHeight = oriImage->getHeight();
    size_t oriImageWidth = oriImage->getWidth();

    Ogre::uchar *oriImageData = oriImage->getData();
    // 所选纹理的大小
    size_t newImageWidth = texInfo.width*TexTileSize;
    size_t newImageHeight = texInfo.height*TexTileSize;

    // 分配一个足够大的空间来保存新建的image的数据
    size_t newImagegetRowSpan = newImageWidth*oriImage->getBPP()/BytePerPixel;  // 新建的image的行宽(单位为字节)
    Ogre::uchar *newImageData = OGRE_ALLOC_T(Ogre::uchar, oriImageHeight*newImagegetRowSpan, Ogre::MEMCATEGORY_GENERAL);//new Ogre::uchar[newImageHeight*newImagegetRowSpan];
    
    Ogre::uchar *newImageDataPointer = newImageData;
    // 得知起始像素点
    size_t startPoint = ( oriImageWidth * texInfo.topCorner + texInfo.leftCorner )
        * TexTileSize * oriImage->getBPP()/BytePerPixel;

    Ogre::uchar *oriImagedataPointer = oriImageData + startPoint;

    // 把所选的纹理的数据提取出来,并创建一个新的image
    for ( Ogre::uint i=0; i<newImageHeight; ++i )
    {
        memcpy(newImageDataPointer, oriImagedataPointer, newImagegetRowSpan);
        newImageDataPointer += newImagegetRowSpan;
        oriImagedataPointer += oriImage->getRowSpan();
    }

    Ogre::Image newImage;
    newImage.loadDynamicImage(newImageData,newImageWidth,newImageHeight,1,oriImage->getFormat(),true);

    // 如果所选纹理大于64*64,就先resize
    if ( texInfo.width > 1 || texInfo.height > 1 )
        newImage.resize(mPreviewImageWidth, mPreviewImageHeight);

    // 如果有alpha,要与黑白图进行混合
    if ( newImage.getHasAlpha() )
    {  
		Ogre::ColourValue col;

		for ( int i=0; i<mPreviewImageWidth; ++i )
		{
			for ( int j=0; j<mPreviewImageWidth; ++j )
			{
				col = newImage.getColourAt(j,i,0);

				float alphaValue = col.a;

				unsigned char r = col.r*255 * alphaValue + mBlackWhitePreviewImage.GetRed(i,j) * ( 1.0f - alphaValue);
				unsigned char g = col.g*255 * alphaValue + mBlackWhitePreviewImage.GetGreen(i,j) * ( 1.0f - alphaValue);
				unsigned char b = col.b*255 * alphaValue + mBlackWhitePreviewImage.GetBlue(i,j) * ( 1.0f - alphaValue);

				// 设置到image中
				mCurrentPreviewImage.SetRGB(j,i,r,g,b);
			}
		}
        // 设置到缩略图控件中
        mBrushesPreview->SetBitmap(mCurrentPreviewImage);
    }
    // 没有alpha,就直接拷贝数据
    else
    {
		Ogre::ColourValue col;

		for ( int i=0; i<mPreviewImageWidth; ++i )
		{
			for ( int j=0; j<mPreviewImageWidth; ++j )
			{
				col = newImage.getColourAt(j,i,0);

				unsigned char r = col.r*255;
				unsigned char g = col.g*255;
				unsigned char b = col.b*255;

				// 设置到image中
				mCurrentPreviewImage.SetRGB(j,i,r,g,b);
			}
		}

        mBrushesPreview->SetBitmap(mCurrentPreviewImage);    
    }
}
    //-------------------------------------------------------------------------
    void HeightmapTerrainPageSource::requestPage(ushort x, ushort y)
    {
        // Only 1 page provided
        if (x == 0 && y == 0 && !mPage)
        {
            // Convert the image data to unscaled floats
            ulong totalPageSize = mPageSize * mPageSize; 
            Real *heightData = OGRE_ALLOC_T(Real, totalPageSize, MEMCATEGORY_RESOURCE);
            const uchar* pOrigSrc, *pSrc;
            Real* pDest = heightData;
            Real invScale;
            bool is16bit = false;
            
            if (mIsRaw)
            {
                pOrigSrc = mRawData->getPtr();
                is16bit = (mRawBpp == 2);
            }
            else
            {
                PixelFormat pf = mImage.getFormat();
                if (pf != PF_L8 && pf != PF_L16)
                {
                    OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, 
                        "Error: Image is not a grayscale image.",
                        "HeightmapTerrainPageSource::requestPage" );
                }

                pOrigSrc = mImage.getData();
                is16bit = (pf == PF_L16);
            }
            // Determine mapping from fixed to floating
            ulong rowSize;
            if ( is16bit )
            {
                invScale = 1.0f / 65535.0f; 
                rowSize =  mPageSize * 2;
            }
            else 
            {
                invScale = 1.0f / 255.0f; 
                rowSize =  mPageSize;
            }
            // Read the data
            pSrc = pOrigSrc;
            for (ulong j = 0; j < mPageSize; ++j)
            {
                if (mFlipTerrain)
                {
                    // Work backwards 
                    pSrc = pOrigSrc + (rowSize * (mPageSize - j - 1));
                }
                for (ulong i = 0; i < mPageSize; ++i)
                {
                    if (is16bit)
                    {
                        #if OGRE_ENDIAN == OGRE_ENDIAN_BIG
                            ushort val = *pSrc++ << 8;
                            val += *pSrc++;
                        #else
                            ushort val = *pSrc++;
                            val += *pSrc++ << 8;
                        #endif
                        *pDest++ = Real(val) * invScale;
                    }
                    else
                    {
                        *pDest++ = Real(*pSrc++) * invScale;
                    }
                }
            }

            // Call listeners
            firePageConstructed(0, 0, heightData);
            // Now turn into TerrainPage
            // Note that we're using a single material for now
            if (mSceneManager)
            {
                mPage = buildPage(heightData, 
                    mSceneManager->getOptions().terrainMaterial);
                mSceneManager->attachPage(0, 0, mPage);
            }

            // Free temp store
            OGRE_FREE(heightData, MEMCATEGORY_RESOURCE);
        }
    }
    //-----------------------------------------------------------------------
    bool BspRaySceneQuery::processLeaf(const BspNode* leaf, const Ray& tracingRay, 
        RaySceneQueryListener* listener, Real maxDistance, Real traceDistance)
    {
        const BspNode::IntersectingObjectSet& objects = leaf->getObjects();

        BspNode::IntersectingObjectSet::const_iterator i, iend;
        iend = objects.end();
        //Check ray against objects
        for(i = objects.begin(); i != iend; ++i)
        {
            // cast away constness, constness of node is nothing to do with objects
            MovableObject* obj = const_cast<MovableObject*>(*i);
            // Skip this object if not enabled
            if(!(obj->getQueryFlags() & mQueryMask) ||
				!((obj->getTypeFlags() & mQueryTypeMask)))
                continue;

            // check we haven't reported this one already
            // (objects can be intersecting more than one node)
            if (mObjsThisQuery.find(obj) != mObjsThisQuery.end())
                continue;

            //Test object as bounding box
            std::pair<bool, Real> result = 
                tracingRay.intersects(obj->getWorldBoundingBox());
            // if the result came back positive and intersection point is inside
            // the node, fire the event handler
            if(result.first && result.second <= maxDistance)
            {
                if (!listener->queryResult(obj, result.second + traceDistance))
					return false;
            }
        }


        // Check ray against brushes
        if (mQueryTypeMask & SceneManager::WORLD_GEOMETRY_TYPE_MASK)
        {
            const BspNode::NodeBrushList& brushList = leaf->getSolidBrushes();
            BspNode::NodeBrushList::const_iterator bi, biend;
            biend = brushList.end();
            bool intersectedBrush = false;
            for (bi = brushList.begin(); bi != biend; ++bi)
            {
                BspNode::Brush* brush = *bi;
                

                std::pair<bool, Real> result = Math::intersects(tracingRay, brush->planes, true);
                // if the result came back positive and intersection point is inside
                // the node, check if this brush is closer
                if(result.first && result.second <= maxDistance)
                {
                    intersectedBrush = true;
                    if(mWorldFragmentType == SceneQuery::WFT_SINGLE_INTERSECTION)
                    {
                        // We're interested in a single intersection
                        // Have to create these 
                        SceneQuery::WorldFragment* wf = OGRE_ALLOC_T(SceneQuery::WorldFragment, 1, MEMCATEGORY_SCENE_CONTROL);
                        wf->fragmentType = SceneQuery::WFT_SINGLE_INTERSECTION;
                        wf->singleIntersection = tracingRay.getPoint(result.second);
                        // save this so we can clean up later
                        mSingleIntersections.push_back(wf);
                        if (!listener->queryResult(wf, result.second + traceDistance))
							return false;
                    }
                    else if (mWorldFragmentType ==  SceneQuery::WFT_PLANE_BOUNDED_REGION)
                    {
                        // We want the whole bounded volume
                        assert((*bi)->fragment.fragmentType == SceneQuery::WFT_PLANE_BOUNDED_REGION);
                        if (!listener->queryResult(const_cast<WorldFragment*>(&(brush->fragment)), 
                            result.second + traceDistance))
							return false; 

                    }
                }
            }
            if (intersectedBrush)
            {
                return false; // stop here
            }
        }

        return true;

    } 
예제 #27
0
  void createTerrainLightmap(const TerrainInfo& info, Image& image,
    size_t width, size_t height, Vector3 lightDir, const ColourValue& lightCol,
    const ColourValue& ambient, bool shadowed)
  {
    lightDir.normalise();

    // calculate lightmap by multiplying light dir with terrain normals

    // calculate the step size to use
    AxisAlignedBox extents = info.getExtents();
    Vector3 startPos = extents.getMinimum();
    Vector3 step = extents.getMaximum() - extents.getMinimum();
    step.x /= width;
    step.z /= height;
    Vector3 pos = startPos;

#if OGRE_VERSION_MINOR > 4
    // Ogre::Image uses the memory allocation macros internally in Shoggoth,
    // so we must use them as well.
    uchar* lightMap = OGRE_ALLOC_T(uchar, width*height*3, MEMCATEGORY_GENERAL);
#else
    uchar* lightMap = new uchar[width*height * 3];
#endif
    memset(lightMap, 255, width*height*3);

    for (size_t z = 0; z < height; ++z)
    {
      for (size_t x = 0; x < width; ++x)
      {
        size_t index = (z * width + x)*3;
        // calculate diffuse light from light source
        Vector3 norm = info.getNormalAt(pos.x, pos.z);
        float l = std::max(0.0f, -lightDir.dotProduct(norm));

        ColourValue v = ambient;
        v.r = std::min(1.0f, v.r+l*lightCol.r);
        v.g = std::min(1.0f, v.g+l*lightCol.g);
        v.b = std::min(1.0f, v.b+l*lightCol.b);
        lightMap[index+0] = (uchar) (255*v.r);
        lightMap[index+1] = (uchar) (255*v.g);
        lightMap[index+2] = (uchar) (255*v.b);

        pos.x += step.x;
      }
      pos.x = startPos.x;
      pos.z += step.z;
    }

    if (shadowed && (lightDir.x != 0 || lightDir.z != 0))
    {
      // add terrain shadows
      Impl::addTerrainShadowsToLightmap(lightMap, info, width, height, lightDir, ambient);
    }

    // use a box filter to smoothen the lightmap
    Impl::boxFilterLightmap(lightMap, width, height);

    // save lightmap to image
    image.loadDynamicImage(lightMap, width, height, 1, PF_BYTE_RGB, true);
    // ownership of lightMap was transfered to image, don't need to delete 
  }
예제 #28
0
    //-----------------------------------------------------------------------------
    Image & Image::flipAroundY()
    {
        if( !mBuffer )
        {
            OGRE_EXCEPT( 
                Exception::ERR_INTERNAL_ERROR,
                "Can not flip an uninitialised texture",
                "Image::flipAroundY" );
        }
        
        mNumMipmaps = 0; // Image operations lose precomputed mipmaps

        uchar   *pTempBuffer1 = NULL;
        ushort  *pTempBuffer2 = NULL;
        uchar   *pTempBuffer3 = NULL;
        uint    *pTempBuffer4 = NULL;

        uchar   *src1 = mBuffer;
        ushort  *src2 = (ushort *)mBuffer;
        uchar   *src3 = mBuffer;
        uint    *src4 = (uint *)mBuffer;

        ushort y;
        switch (mPixelSize)
        {
        case 1:
            pTempBuffer1 = OGRE_ALLOC_T(uchar, mWidth * mHeight, MEMCATEGORY_GENERAL);
            for (y = 0; y < mHeight; y++)
            {
                uchar *dst1 = (pTempBuffer1 + ((y * mWidth) + mWidth - 1));
                for (ushort x = 0; x < mWidth; x++)
                    memcpy(dst1--, src1++, sizeof(uchar));
            }

            memcpy(mBuffer, pTempBuffer1, mWidth * mHeight * sizeof(uchar));
            OGRE_FREE(pTempBuffer1, MEMCATEGORY_GENERAL);
            break;

        case 2:
            pTempBuffer2 = OGRE_ALLOC_T(ushort, mWidth * mHeight, MEMCATEGORY_GENERAL);
            for (y = 0; y < mHeight; y++)
            {
                ushort *dst2 = (pTempBuffer2 + ((y * mWidth) + mWidth - 1));
                for (ushort x = 0; x < mWidth; x++)
                    memcpy(dst2--, src2++, sizeof(ushort));
            }

            memcpy(mBuffer, pTempBuffer2, mWidth * mHeight * sizeof(ushort));
            OGRE_FREE(pTempBuffer2, MEMCATEGORY_GENERAL);
            break;

        case 3:
            pTempBuffer3 = OGRE_ALLOC_T(uchar, mWidth * mHeight * 3, MEMCATEGORY_GENERAL);
            for (y = 0; y < mHeight; y++)
            {
                size_t offset = ((y * mWidth) + (mWidth - 1)) * 3;
                uchar *dst3 = pTempBuffer3;
                dst3 += offset;
                for (size_t x = 0; x < mWidth; x++)
                {
                    memcpy(dst3, src3, sizeof(uchar) * 3);
                    dst3 -= 3; src3 += 3;
                }
            }

            memcpy(mBuffer, pTempBuffer3, mWidth * mHeight * sizeof(uchar) * 3);
            OGRE_FREE(pTempBuffer3, MEMCATEGORY_GENERAL);
            break;

        case 4:
            pTempBuffer4 = OGRE_ALLOC_T(uint, mWidth * mHeight, MEMCATEGORY_GENERAL);
            for (y = 0; y < mHeight; y++)
            {
                uint *dst4 = (pTempBuffer4 + ((y * mWidth) + mWidth - 1));
                for (ushort x = 0; x < mWidth; x++)
                    memcpy(dst4--, src4++, sizeof(uint));
            }

            memcpy(mBuffer, pTempBuffer4, mWidth * mHeight * sizeof(uint));
            OGRE_FREE(pTempBuffer4, MEMCATEGORY_GENERAL);
            break;

        default:
            OGRE_EXCEPT( 
                Exception::ERR_INTERNAL_ERROR,
                "Unknown pixel depth",
                "Image::flipAroundY" );
            break;
        }

        return *this;

    }
예제 #29
0
    //---------------------------------------------------------------------
    void DeflateStream::init()
    {
        mZStream = OGRE_ALLOC_T(z_stream, 1, MEMCATEGORY_GENERAL);
        mZStream->zalloc = OgreZalloc;
        mZStream->zfree = OgreZfree;
        
        if (getAccessMode() == READ)
        {
            mTmp = (unsigned char*)OGRE_MALLOC(OGRE_DEFLATE_TMP_SIZE, MEMCATEGORY_GENERAL);
            size_t restorePoint = mCompressedStream->tell();
            // read early chunk
            mZStream->next_in = mTmp;
            mZStream->avail_in = static_cast<uint>(mCompressedStream->read(mTmp, getAvailInForSinglePass()));
            
            if (inflateInit(mZStream) != Z_OK)
            {
                mIsCompressedValid = false;
            }
            else
                mIsCompressedValid = true;
            
            if (mIsCompressedValid)
            {
                // in fact, inflateInit on some implementations doesn't try to read
                // anything. We need to at least read something to test
                Bytef testOut[4];
                size_t savedIn = mZStream->avail_in;
                mZStream->avail_out = 4;
                mZStream->next_out = testOut;
                if (inflate(mZStream, Z_SYNC_FLUSH) != Z_OK)
                    mIsCompressedValid = false;
                // restore for reading
                mZStream->avail_in = static_cast<uint>(savedIn);
                mZStream->next_in = mTmp;

                inflateReset(mZStream);
            }

            if (!mIsCompressedValid)
            {
                // Not compressed data!
                // Fail gracefully, fall back on reading the underlying stream direct
                destroy();
                mCompressedStream->seek(restorePoint);
            }               
        }
        else 
        {
            if(mTempFileName.empty())
            {
                // Write to temp file
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WINRT
                char* tmpname = _tempnam(".", "ogre");
                if (!tmpname)
                {
                    // Having no file name here will cause various problems later.
                    OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Temporary file name generation failed.", "DeflateStream::init");
                }
                else
                {
                    mTempFileName = tmpname;
                    free(tmpname);
                }
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
                mTempFileName = macTempFileName();
#else
                char tmpname[] = "/tmp/ogreXXXXXX";
                if (mkstemp(tmpname) == -1)
                    OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Temporary file name generation failed.", "DeflateStream::init");

                mTempFileName = tmpname;
#endif
            }

            std::fstream *f = OGRE_NEW_T(std::fstream, MEMCATEGORY_GENERAL)();
            f->open(mTempFileName.c_str(), std::ios::binary | std::ios::out);
            mTmpWriteStream = DataStreamPtr(OGRE_NEW FileStreamDataStream(f));
            
        }

    }
예제 #30
0
	//---------------------------------------------------------------------
	FIBITMAP* FreeImageCodec::encode(MemoryDataStreamPtr& input, CodecDataPtr& pData) const
	{
		// Set error handler
		FreeImage_SetOutputMessage(FreeImageSaveErrorHandler);

		FIBITMAP* ret = 0;

		ImageData* pImgData = static_cast< ImageData * >( pData.getPointer() );
		PixelBox src(pImgData->width, pImgData->height, pImgData->depth, pImgData->format, input->getPtr());

		// The required format, which will adjust to the format
		// actually supported by FreeImage.
		PixelFormat requiredFormat = pImgData->format;

		// determine the settings
		FREE_IMAGE_TYPE imageType;
		PixelFormat determiningFormat = pImgData->format;

		switch(determiningFormat)
		{
		case PF_R5G6B5:
		case PF_B5G6R5:
		case PF_R8G8B8:
		case PF_B8G8R8:
		case PF_A8R8G8B8:
		case PF_X8R8G8B8:
		case PF_A8B8G8R8:
		case PF_X8B8G8R8:
		case PF_B8G8R8A8:
		case PF_R8G8B8A8:
		case PF_A4L4:
		case PF_BYTE_LA:
		case PF_R3G3B2:
		case PF_A4R4G4B4:
		case PF_A1R5G5B5:
		case PF_A2R10G10B10:
		case PF_A2B10G10R10:
			// I'd like to be able to use r/g/b masks to get FreeImage to load the data
			// in it's existing format, but that doesn't work, FreeImage needs to have
			// data in RGB[A] (big endian) and BGR[A] (little endian), always.
			if (PixelUtil::hasAlpha(determiningFormat))
			{
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				requiredFormat = PF_BYTE_RGBA;
#else
				requiredFormat = PF_BYTE_BGRA;
#endif
			}
			else
			{
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				requiredFormat = PF_BYTE_RGB;
#else
				requiredFormat = PF_BYTE_BGR;
#endif
			}
			// fall through
		case PF_L8:
		case PF_A8:
			imageType = FIT_BITMAP;
			break;

		case PF_L16:
			imageType = FIT_UINT16;
			break;

		case PF_SHORT_GR:
			requiredFormat = PF_SHORT_RGB;
			// fall through
		case PF_SHORT_RGB:
			imageType = FIT_RGB16;
			break;

		case PF_SHORT_RGBA:
			imageType = FIT_RGBA16;
			break;

		case PF_FLOAT16_R:
			requiredFormat = PF_FLOAT32_R;
			// fall through
		case PF_FLOAT32_R:
			imageType = FIT_FLOAT;
			break;

		case PF_FLOAT16_GR:
		case PF_FLOAT16_RGB:
		case PF_FLOAT32_GR:
			requiredFormat = PF_FLOAT32_RGB;
			// fall through
		case PF_FLOAT32_RGB:
			imageType = FIT_RGBF;
			break;

		case PF_FLOAT16_RGBA:
			requiredFormat = PF_FLOAT32_RGBA;
			// fall through
		case PF_FLOAT32_RGBA:
			imageType = FIT_RGBAF;
			break;

		default:
			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Invalid image format", "FreeImageCodec::encode");
		};

		// Check support for this image type & bit depth
		if (!FreeImage_FIFSupportsExportType((FREE_IMAGE_FORMAT)mFreeImageType, imageType) ||
			!FreeImage_FIFSupportsExportBPP((FREE_IMAGE_FORMAT)mFreeImageType, (int)PixelUtil::getNumElemBits(requiredFormat)))
		{
			// Ok, need to allocate a fallback
			// Only deal with RGBA -> RGB for now
			switch (requiredFormat)
			{
			case PF_BYTE_RGBA:
				requiredFormat = PF_BYTE_RGB;
				break;
			case PF_BYTE_BGRA:
				requiredFormat = PF_BYTE_BGR;
				break;
			default:
				break;
			};

		}

		bool conversionRequired = false;

		unsigned char* srcData = input->getPtr();

		// Check BPP
		unsigned bpp = static_cast<unsigned>(PixelUtil::getNumElemBits(requiredFormat));
		if (!FreeImage_FIFSupportsExportBPP((FREE_IMAGE_FORMAT)mFreeImageType, (int)bpp))
		{
			if (bpp == 32 && PixelUtil::hasAlpha(pImgData->format) && FreeImage_FIFSupportsExportBPP((FREE_IMAGE_FORMAT)mFreeImageType, 24))
			{
				// drop to 24 bit (lose alpha)
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				requiredFormat = PF_BYTE_RGB;
#else
				requiredFormat = PF_BYTE_BGR;
#endif
				bpp = 24;
			}
			else if (bpp == 128 && PixelUtil::hasAlpha(pImgData->format) && FreeImage_FIFSupportsExportBPP((FREE_IMAGE_FORMAT)mFreeImageType, 96))
			{
				// drop to 96-bit floating point
				requiredFormat = PF_FLOAT32_RGB;
			}
		}

		PixelBox convBox(pImgData->width, pImgData->height, 1, requiredFormat);
		if (requiredFormat != pImgData->format)
		{
			conversionRequired = true;
			// Allocate memory
			convBox.data = OGRE_ALLOC_T(uchar, convBox.getConsecutiveSize(), MEMCATEGORY_GENERAL);
			// perform conversion and reassign source
			PixelBox src(pImgData->width, pImgData->height, 1, pImgData->format, input->getPtr());
			PixelUtil::bulkPixelConversion(src, convBox);
			srcData = static_cast<unsigned char*>(convBox.data);

		}


		ret = FreeImage_AllocateT(
			imageType, 
			static_cast<int>(pImgData->width), 
			static_cast<int>(pImgData->height), 
			bpp);

		if (!ret)
		{
			if (conversionRequired)
				OGRE_FREE(convBox.data, MEMCATEGORY_GENERAL);

			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
				"FreeImage_AllocateT failed - possibly out of memory. ", 
				__FUNCTION__);
		}

		if (requiredFormat == PF_L8 || requiredFormat == PF_A8)
		{
			// Must explicitly tell FreeImage that this is greyscale by setting
			// a "grey" palette (otherwise it will save as a normal RGB
			// palettized image).
			FIBITMAP *tmp = FreeImage_ConvertToGreyscale(ret);
			FreeImage_Unload(ret);
			ret = tmp;
		}
		
		size_t dstPitch = FreeImage_GetPitch(ret);
		size_t srcPitch = pImgData->width * PixelUtil::getNumElemBytes(requiredFormat);


		// Copy data, invert scanlines and respect FreeImage pitch
		uchar* pSrc;
		uchar* pDst = FreeImage_GetBits(ret);
		for (size_t y = 0; y < pImgData->height; ++y)
		{
			pSrc = srcData + (pImgData->height - y - 1) * srcPitch;
			memcpy(pDst, pSrc, srcPitch);
			pDst += dstPitch;
		}

		if (conversionRequired)
		{
			// delete temporary conversion area
			OGRE_FREE(convBox.data, MEMCATEGORY_GENERAL);
		}

		return ret;
	}