Merged revisions 1309:1314 from 1.4 branch.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1315 dfc29bdd-3216-0410-991c-e03cc46cb475
master
hybrid 2008-04-12 23:02:15 +00:00
parent 6a0d4ea7b2
commit 0e63486fbe
7 changed files with 417 additions and 352 deletions

View File

@ -47,7 +47,39 @@ Changes in version 1.5 (... 2008)
- Finally added StarSonata patch with table element and TabControl additions. Table is based on MultiColor listbox by Acki, and has loads of changes by CuteAlien. - Finally added StarSonata patch with table element and TabControl additions. Table is based on MultiColor listbox by Acki, and has loads of changes by CuteAlien.
------------------------------------------- -------------------------------------------
Changes in version 1.4.1 (??? 2008) Changes in version 1.4.1 (??.4.2008)
- New JPG image writer version by Vitek.
- Texture matrix fixes, all methods should now work as expected.
- Some container methods now return the this pointer after member functions have been called on them, in order to allow call chains.
- Some new methods for SColorf access, for uniform API of all colors.
- bug fix for SMaterialLayer equality check. Did only check the TextureMatrix pointers, instead of the matrices.
- New getMesh method for the SceneManager, which takes an IReadFile instead of a filename.
- Support for flags _WIN32 and _WIN64 in addition to WIN32 and WIN64 added, this simplifies usage of Irrlicht headers under MSVC.
- Fixed a crash in GUIMeshViewer
- new string method findLastChar by Halifax
- GUIEditBox got the 1 pixel shift after click fixed.
- Some debug visualization has been fixed for skinned meshes
- Undef PI symbol before declaring core::PI to avoid compilation problems
- SAnimatedMesh now properly returns properties of Meshes[0] if those exist, such that it should be usable in place of an SMesh again.
- Fixed 2d initialisation in opengl and d3d9 driver. This should fix problems with render states mixing up and distrubing, e.g. skin effects.
- Avoid a crash when passing setSkin the current skin
- Fixed current frame calculation for non-looped animations. Bug reported by greenya.
- Fixed bug in CBillboardSceneNode::setColor, reported by rogerborg - Fixed bug in CBillboardSceneNode::setColor, reported by rogerborg
@ -82,7 +114,7 @@ Changes in version 1.4.1 (??? 2008)
- Function setbit was renamed to setbit_cond to avoid name clashes. - Function setbit was renamed to setbit_cond to avoid name clashes.
- Fixed .x animations with multiple references to the same joint from different meshes. - Fixed .x animations with multiple references to the same joint from different meshes. Fixed texture path problems.
- Support for Milkshape 1.8 files, also with multiple weights per joint. - Support for Milkshape 1.8 files, also with multiple weights per joint.

View File

@ -13,7 +13,7 @@ namespace irr
namespace video namespace video
{ {
//! Creates a 16 bit A1R5G5B5 color //! Creates a 16 bit A1R5G5B5 color
inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a) inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a=0xFF)
{ {
return ((a & 0x80) << 8 | return ((a & 0x80) << 8 |
(r & 0xF8) << 7 | (r & 0xF8) << 7 |
@ -25,20 +25,21 @@ namespace video
//! Creates a 16 bit A1R5G5B5 color //! Creates a 16 bit A1R5G5B5 color
inline u16 RGB16(u32 r, u32 g, u32 b) inline u16 RGB16(u32 r, u32 g, u32 b)
{ {
return RGBA16(r,g,b,0xFF); return RGBA16(r,g,b);
} }
//! Creates a 16 bit A1R5G5B5 color, based on 16 bit input values //! Creates a 16bit A1R5G5B5 color, based on 16bit input values
inline u16 RGB16from16(u16 r, u16 g, u16 b) inline u16 RGB16from16(u16 r, u16 g, u16 b)
{ {
return (r & 0x1F) << 10 | return (0x8000 |
(g & 0x1F) << 5 | (r & 0x1F) << 10 |
(b & 0x1F); (g & 0x1F) << 5 |
(b & 0x1F));
} }
//! Converts a 32 bit (X8R8G8B8) color to a 16 A1R5G5B5 color //! Converts a 32bit (X8R8G8B8) color to a 16bit A1R5G5B5 color
inline u16 X8R8G8B8toA1R5G5B5(u32 color) inline u16 X8R8G8B8toA1R5G5B5(u32 color)
{ {
return ( 0x8000 | return ( 0x8000 |
@ -48,7 +49,7 @@ namespace video
} }
//! Converts a 32 bit (A8R8G8B8) color to a 16 A1R5G5B5 color //! Converts a 32bit (A8R8G8B8) color to a 16bit A1R5G5B5 color
inline u16 A8R8G8B8toA1R5G5B5(u32 color) inline u16 A8R8G8B8toA1R5G5B5(u32 color)
{ {
return (( color & 0x80000000) >> 16| return (( color & 0x80000000) >> 16|
@ -58,7 +59,7 @@ namespace video
} }
//! Converts a 32 bit (A8R8G8B8) color to a 16 R5G6B5 color //! Converts a 32bit (A8R8G8B8) color to a 16bit R5G6B5 color
inline u16 A8R8G8B8toR5G6B5(u32 color) inline u16 A8R8G8B8toR5G6B5(u32 color)
{ {
return (( color & 0x00F80000) >> 8 | return (( color & 0x00F80000) >> 8 |
@ -68,7 +69,7 @@ namespace video
//! Returns A8R8G8B8 Color from A1R5G5B5 color //! Returns A8R8G8B8 Color from A1R5G5B5 color
//! build a nicer 32 Bit Color by extending dest lower bits with source high bits //! build a nicer 32bit Color by extending dest lower bits with source high bits
inline u32 A1R5G5B5toA8R8G8B8(u16 color) inline u32 A1R5G5B5toA8R8G8B8(u16 color)
{ {
return ( (( -( (s32) color & 0x00008000 ) >> (s32) 31 ) & 0xFF000000 ) | return ( (( -( (s32) color & 0x00008000 ) >> (s32) 31 ) & 0xFF000000 ) |
@ -164,12 +165,11 @@ namespace video
} }
//! Class representing a 32 bit ARGB color. //! Class representing a 32 bit ARGB color.
/** The color values for alpha, red, green, and blue are /** The color values for alpha, red, green, and blue are
stored in a single u32. So all four values may be between 0 and 255. stored in a single u32. So all four values may be between 0 and 255.
This class is used by most parts of the Irrlicht Engine This class is used by most parts of the Irrlicht Engine
to specify a color. Another way is using the class Colorf, which to specify a color. Another way is using the class SColorf, which
stores the color values in 4 floats. stores the color values in 4 floats.
*/ */
class SColor class SColor
@ -178,45 +178,45 @@ namespace video
//! Constructor of the Color. Does nothing. The color value //! Constructor of the Color. Does nothing. The color value
//! is not initialized to save time. //! is not initialized to save time.
inline SColor() {} SColor() {}
//! Constructs the color from 4 values representing the alpha, red, green and //! Constructs the color from 4 values representing the alpha, red, green and
//! blue components of the color. Must be values between 0 and 255. //! blue components of the color. Must be values between 0 and 255.
inline SColor (u32 a, u32 r, u32 g, u32 b) SColor (u32 a, u32 r, u32 g, u32 b)
: color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {} : color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {}
//! Constructs the color from a 32 bit value. Could be another color. //! Constructs the color from a 32 bit value. Could be another color.
inline SColor(u32 clr) SColor(u32 clr)
: color(clr) {} : color(clr) {}
//! Returns the alpha component of the color. The alpha component //! Returns the alpha component of the color. The alpha component
//! defines how transparent a color should be. //! defines how transparent a color should be.
//! 0 means not transparent (opaque), 255 means fully transparent. //! 255 means not transparent (opaque), 0 means fully transparent.
inline u32 getAlpha() const { return color>>24; } u32 getAlpha() const { return color>>24; }
//! Returns the red component of the color. //! Returns the red component of the color.
//! \return Returns a value between 0 and 255, specifying how red the color is. //! \return Returns a value between 0 and 255, specifying how red the color is.
//! 0 means no red, 255 means full red. //! 0 means no red, 255 means full red.
inline u32 getRed() const { return (color>>16) & 0xff; } u32 getRed() const { return (color>>16) & 0xff; }
//! Returns the green component of the color. //! Returns the green component of the color.
//! \return Returns a value between 0 and 255, specifying how green the color is. //! \return Returns a value between 0 and 255, specifying how green the color is.
//! 0 means no green, 255 means full green. //! 0 means no green, 255 means full green.
inline u32 getGreen() const { return (color>>8) & 0xff; } u32 getGreen() const { return (color>>8) & 0xff; }
//! Returns the blue component of the color. //! Returns the blue component of the color.
//! \return Returns a value between 0 and 255, specifying how blue the color is. //! \return Returns a value between 0 and 255, specifying how blue the color is.
//! 0 means no blue, 255 means full blue. //! 0 means no blue, 255 means full blue.
inline u32 getBlue() const { return color & 0xff; } u32 getBlue() const { return color & 0xff; }
//! Returns the luminance of the color. //! Returns the luminance of the color.
inline f32 getLuminance() const f32 getLuminance() const
{ {
return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue(); return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue();
} }
//! Returns the average intensity of the color. //! Returns the average intensity of the color.
inline u32 getAverage() const u32 getAverage() const
{ {
return ( getRed() + getGreen() + getBlue() ) / 3; return ( getRed() + getGreen() + getBlue() ) / 3;
} }
@ -224,33 +224,33 @@ namespace video
//! Sets the alpha component of the Color. The alpha component //! Sets the alpha component of the Color. The alpha component
//! defines how transparent a color should be. //! defines how transparent a color should be.
//! \param a: Has to be a value between 0 and 255. //! \param a: Has to be a value between 0 and 255.
//! 0 means not transparent (opaque), 255 means fully transparent. //! 255 means not transparent (opaque), 0 means fully transparent.
inline void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); } void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); }
//! Sets the red component of the Color. //! Sets the red component of the Color.
//! \param r: Has to be a value between 0 and 255. //! \param r: Has to be a value between 0 and 255.
//! 0 means no red (=black), 255 means full red. //! 0 means no red, 255 means full red.
inline void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); } void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); }
//! Sets the green component of the Color. //! Sets the green component of the Color.
//! \param g: Has to be a value between 0 and 255. //! \param g: Has to be a value between 0 and 255.
//! 0 means no green (=black), 255 means full green. //! 0 means no green, 255 means full green.
inline void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); } void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); }
//! Sets the blue component of the Color. //! Sets the blue component of the Color.
//! \param b: Has to be a value between 0 and 255. //! \param b: Has to be a value between 0 and 255.
//! 0 means no blue (=black), 255 means full blue. //! 0 means no blue, 255 means full blue.
inline void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); } void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); }
//! Calculates a 16 bit A1R5G5B5 value of this color. //! Calculates a 16 bit A1R5G5B5 value of this color.
//! \return Returns the 16 bit A1R5G5B5 value of this color. //! \return Returns the 16 bit A1R5G5B5 value of this color.
inline u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); }; u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); };
//! Converts color to OpenGL color format, //! Converts color to OpenGL color format,
//! from ARGB to RGBA in 4 byte components for endian aware //! from ARGB to RGBA in 4 byte components for endian aware
//! passing to OpenGL //! passing to OpenGL
//! \param dest: address where the 4x8 bit OpenGL color is stored. //! \param dest: address where the 4x8 bit OpenGL color is stored.
inline void toOpenGLColor(u8* dest) const void toOpenGLColor(u8* dest) const
{ {
*dest = getRed(); *dest = getRed();
*++dest = getGreen(); *++dest = getGreen();
@ -264,59 +264,49 @@ namespace video
//! \param a: Alpha component of the color. //! \param a: Alpha component of the color.
//! The alpha component defines how transparent a color should be. //! The alpha component defines how transparent a color should be.
//! Has to be a value between 0 and 255. //! Has to be a value between 0 and 255.
//! 0 means not transparent (opaque), 255 means fully transparent. //! 255 means not transparent (opaque), 0 means fully transparent.
//! \param r: Sets the red component of the Color. //! \param r: Sets the red component of the Color.
//! Has to be a value between 0 and 255. //! Has to be a value between 0 and 255.
//! 0 means no red (=black), 255 means full red. //! 0 means no red, 255 means full red.
//! \param g: Sets the green component of the Color. //! \param g: Sets the green component of the Color.
//! Has to be a value between 0 and 255. //! Has to be a value between 0 and 255.
//! 0 means no green (=black), 255 means full green. //! 0 means no green, 255 means full green.
//! \param b: Sets the blue component of the Color. //! \param b: Sets the blue component of the Color.
//! Has to be a value between 0 and 255. //! Has to be a value between 0 and 255.
//! 0 means no blue (=black), 255 means full blue. //! 0 means no blue, 255 means full blue.
inline void set(u32 a, u32 r, u32 g, u32 b) { color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)); } void set(u32 a, u32 r, u32 g, u32 b) { color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)); }
inline void set(u32 col) { color = col; } void set(u32 col) { color = col; }
//! Compares the color to another color. //! Compares the color to another color.
//! \return Returns true if the colors are the same, and false if not. //! \return Returns true if the colors are the same, and false if not.
inline bool operator==(const SColor& other) const { return other.color == color; } bool operator==(const SColor& other) const { return other.color == color; }
//! Compares the color to another color. //! Compares the color to another color.
//! \return Returns true if the colors are different, and false if they are the same. //! \return Returns true if the colors are different, and false if they are the same.
inline bool operator!=(const SColor& other) const { return other.color != color; } bool operator!=(const SColor& other) const { return other.color != color; }
//! comparison operator //! comparison operator
//! \return Returns true if this color is smaller than the other one //! \return Returns true if this color is smaller than the other one
inline bool operator<(const SColor& other) const { return (color < other.color); } bool operator<(const SColor& other) const { return (color < other.color); }
//! Adds two colors //! Adds two colors, result is clamped to 0..255 values
inline SColor operator+(const SColor& other) const //! \param other Color to add to this color
//! \return Addition of the two colors, clamped to 0..255 values
SColor operator+(const SColor& other) const
{ {
s32 a = getAlpha() + other.getAlpha(); return SColor(core::min_(getAlpha() + other.getAlpha(), 255u),
if (a > 255) core::min_(getRed() + other.getRed(), 255u),
a = 255; core::min_(getGreen() + other.getGreen(), 255u),
core::min_(getBlue() + other.getBlue(), 255u));
s32 r = getRed() + other.getRed();
if (r > 255)
r = 255;
s32 g = getGreen() + other.getGreen();
if (g > 255)
g = 255;
s32 b = getBlue() + other.getBlue();
if (b > 255)
b = 255;
return SColor(a,r,g,b);
} }
//! Interpolates the color with a f32 value to another color //! Interpolates the color with a f32 value to another color
//! \param other: Other color //! \param other: Other color
//! \param d: value between 0.0f and 1.0f //! \param d: value between 0.0f and 1.0f
//! \return Returns interpolated color. //! \return Returns interpolated color.
inline SColor getInterpolated(const SColor &other, f32 d) const SColor getInterpolated(const SColor &other, f32 d) const
{ {
d = core::clamp(d, 0.f, 1.f);
const f32 inv = 1.0f - d; const f32 inv = 1.0f - d;
return SColor((u32)(other.getAlpha()*inv + getAlpha()*d), return SColor((u32)(other.getAlpha()*inv + getAlpha()*d),
(u32)(other.getRed()*inv + getRed()*d), (u32)(other.getRed()*inv + getRed()*d),
@ -328,9 +318,10 @@ namespace video
/** \param c1: first color to interpolate with /** \param c1: first color to interpolate with
\param c2: second color to interpolate with \param c2: second color to interpolate with
\param d: value between 0.0f and 1.0f. */ \param d: value between 0.0f and 1.0f. */
inline SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, const f32 d) const SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, f32 d) const
{ {
// this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d; // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d;
d = core::clamp(d, 0.f, 1.f);
const f32 inv = 1.f - d; const f32 inv = 1.f - d;
const f32 mul0 = inv * inv; const f32 mul0 = inv * inv;
const f32 mul1 = 2.f * d * inv; const f32 mul1 = 2.f * d * inv;
@ -351,63 +342,43 @@ namespace video
/** The color values for red, green, blue /** The color values for red, green, blue
and alpha are each stored in a 32 bit floating point variable. and alpha are each stored in a 32 bit floating point variable.
So all four values may be between 0.0f and 1.0f. So all four values may be between 0.0f and 1.0f.
This class is rarely used by the Irrlicht Engine Another, faster way to define colors is using the class SColor, which
to specify a color. Another, faster way is using the class Color, which
stores the color values in a single 32 bit integer. stores the color values in a single 32 bit integer.
*/ */
class SColorf class SColorf
{ {
public: public:
//! Constructs a color from up to four color values: red, green, blue, and alpha.
//! Constructs a color. All colors are initialised with 0.0f, resulting
//! in a black color. alpha is 1.0f for no transparency.
SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {};
//! Constructs a color from three color values: red, green and blue.
//! \param r: Red color component. Should be a value between 0.0f meaning //! \param r: Red color component. Should be a value between 0.0f meaning
//! no red (=black) and 1.0f, meaning full red. //! no red and 1.0f, meaning full red.
//! \param g: Green color component. Should be a value between 0.0f meaning //! \param g: Green color component. Should be a value between 0.0f meaning
//! no green (=black) and 1.0f, meaning full green. //! no green and 1.0f, meaning full green.
//! \param b: Blue color component. Should be a value between 0.0f meaning //! \param b: Blue color component. Should be a value between 0.0f meaning
//! no blue (=black) and 1.0f, meaning full blue. //! no blue and 1.0f, meaning full blue.
SColorf(f32 r, f32 g, f32 b) : r(r), g(g), b(b), a(1.0f) {};
//! Constructs a color from four color values: red, green, blue, and alpha.
//! \param r: Red color component. Should be a value between 0.0f meaning
//! no red (=black) and 1.0f, meaning full red.
//! \param g: Green color component. Should be a value between 0.0f meaning
//! no green (=black) and 1.0f, meaning full green.
//! \param b: Blue color component. Should be a value between 0.0f meaning
//! no blue (=black) and 1.0f, meaning full blue.
//! \param a: Alpha color component of the color. //! \param a: Alpha color component of the color.
//! The alpha component defines how transparent a color should be. //! The alpha component defines how transparent a color should be.
//! Has to be a value between 0.0f and 1.0f, //! Has to be a value between 0.0f and 1.0f,
//! 0.0f means not transparent (opaque), 1.0f means fully transparent. //! 1.0f means not transparent (opaque), 0.0f means fully transparent.
SColorf(f32 r, f32 g, f32 b, f32 a) : r(r), g(g), b(b), a(a) {}; 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) {}
//! Constructs a color from 32 bit Color. //! Constructs a color from 32 bit Color.
//! \param c: 32 bit color value from which this Colorf class is //! \param c: 32 bit color from which this SColorf class is
//! constructed from. //! constructed from.
SColorf(SColor c) { const f32 inv = 1.0f / 255.0f; r = c.getRed() * inv; g = c.getGreen() * inv; b = c.getBlue() * inv; a = c.getAlpha() * inv; }; SColorf(SColor c)
{
const f32 inv = 1.0f / 255.0f;
r = c.getRed() * inv;
g = c.getGreen() * inv;
b = c.getBlue() * inv;
a = c.getAlpha() * inv;
}
//! Converts this color to a SColor without floats. //! Converts this color to a SColor without floats.
SColor toSColor() const SColor toSColor() const
{ {
return SColor((s32)(a*255.0f), (s32)(r*255.0f), (s32)(g*255.0f), (s32)(b*255.0f)); return SColor((u32)(a*255.0f), (u32)(r*255.0f), (u32)(g*255.0f), (u32)(b*255.0f));
} }
//! red color component
f32 r;
//! green color component
f32 g;
//! blue component
f32 b;
//! alpha color component
f32 a;
//! Sets three color components to new values at once. //! Sets three color components to new values at once.
//! \param rr: Red color component. Should be a value between 0.0f meaning //! \param rr: Red color component. Should be a value between 0.0f meaning
//! no red (=black) and 1.0f, meaning full red. //! no red (=black) and 1.0f, meaning full red.
@ -418,21 +389,23 @@ namespace video
void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; }; void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; };
//! Sets all four color components to new values at once. //! Sets all four color components to new values at once.
//! \param aa: Alpha component. //! \param aa: Alpha component. Should be a value between 0.0f meaning
//! fully transparent and 1.0f, meaning opaque.
//! \param rr: Red color component. Should be a value between 0.0f meaning //! \param rr: Red color component. Should be a value between 0.0f meaning
//! no red (=black) and 1.0f, meaning full red. //! no red and 1.0f, meaning full red.
//! \param gg: Green color component. Should be a value between 0.0f meaning //! \param gg: Green color component. Should be a value between 0.0f meaning
//! no green (=black) and 1.0f, meaning full green. //! no green and 1.0f, meaning full green.
//! \param bb: Blue color component. Should be a value between 0.0f meaning //! \param bb: Blue color component. Should be a value between 0.0f meaning
//! no blue (=black) and 1.0f, meaning full blue. //! no blue and 1.0f, meaning full blue.
void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; }; void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; };
//! Interpolates the color with a f32 value to another color //! Interpolates the color with a f32 value to another color
//! \param other: Other color //! \param other: Other color
//! \param d: value between 0.0f and 1.0f //! \param d: value between 0.0f and 1.0f
//! \return Returns interpolated color. //! \return Returns interpolated color.
inline SColorf getInterpolated(const SColorf &other, f32 d) const SColorf getInterpolated(const SColorf &other, f32 d) const
{ {
d = core::clamp(d, 0.f, 1.f);
const f32 inv = 1.0f - d; const f32 inv = 1.0f - d;
return SColorf(other.r*inv + r*d, return SColorf(other.r*inv + r*d,
other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d); other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d);
@ -442,8 +415,9 @@ namespace video
/** \param c1: first color to interpolate with /** \param c1: first color to interpolate with
\param c2: second color to interpolate with \param c2: second color to interpolate with
\param d: value between 0.0f and 1.0f. */ \param d: value between 0.0f and 1.0f. */
inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2, const f32 d) const inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2, f32 d) const
{ {
d = core::clamp(d, 0.f, 1.f);
// this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d; // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d;
const f32 inv = 1.f - d; const f32 inv = 1.f - d;
const f32 mul0 = inv * inv; const f32 mul0 = inv * inv;
@ -457,9 +431,8 @@ namespace video
} }
//! Sets a color component by index. R=0, G=1, B=2, A=3 //! Sets a color component by index. R=0, G=1, B=2, A=3
inline void setColorComponentValue(s32 index, f32 value) void setColorComponentValue(s32 index, f32 value)
{ {
switch(index) switch(index)
{ {
@ -469,8 +442,33 @@ namespace video
case 3: a = value; break; case 3: a = value; break;
} }
} }
//! Returns the alpha component of the color in the range 0.0 to 1.0
f32 getAlpha() const { return a; }
//! Returns the red component of the color in the range 0.0 to 1.0
f32 getRed() const { return r; }
//! Returns the green component of the color in the range 0.0 to 1.0
f32 getGreen() const { return g; }
//! Returns the blue component of the color in the range 0.0 to 1.0
f32 getBlue() const { return b; }
//! red color component
f32 r;
//! green color component
f32 g;
//! blue component
f32 b;
//! alpha color component
f32 a;
}; };
//! Class representing a color in HSV format //! Class representing a color in HSV format
/** The color values for hue, saturation, value /** The color values for hue, saturation, value
are stored in a 32 bit floating point variable. are stored in a 32 bit floating point variable.
@ -481,15 +479,15 @@ namespace video
SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f ) SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f )
: Hue ( h ), Saturation ( s ), Luminance ( l ) {} : Hue ( h ), Saturation ( s ), Luminance ( l ) {}
void setfromRGB ( const SColor &color ); // void setfromRGB ( const SColor &color );
void settoRGB ( SColor &color ) const; void settoRGB ( SColor &color ) const;
f32 Hue; f32 Hue;
f32 Saturation; f32 Saturation;
f32 Luminance; f32 Luminance;
private: private:
inline u32 toRGB1(f32 rm1, f32 rm2, f32 rh) const; inline u32 toRGB1(f32 rm1, f32 rm2, f32 rh) const;
}; };
@ -531,9 +529,12 @@ namespace video
while ( rh < 0.f ) while ( rh < 0.f )
rh += 2.f * core::PI; rh += 2.f * core::PI;
if (rh < 60.0f * core::DEGTORAD ) rm1 = rm1 + (rm2 - rm1) * rh / (60.0f * core::DEGTORAD); if (rh < 60.0f * core::DEGTORAD )
else if (rh < 180.0f * core::DEGTORAD ) rm1 = rm2; rm1 = rm1 + (rm2 - rm1) * rh / (60.0f * core::DEGTORAD);
else if (rh < 240.0f * core::DEGTORAD ) rm1 = rm1 + (rm2 - rm1) * ( ( 240.0f * core::DEGTORAD ) - rh) / (60.0f * core::DEGTORAD); else if (rh < 180.0f * core::DEGTORAD )
rm1 = rm2;
else if (rh < 240.0f * core::DEGTORAD )
rm1 = rm1 + (rm2 - rm1) * ( ( 240.0f * core::DEGTORAD ) - rh) / (60.0f * core::DEGTORAD);
return (u32) (rm1 * 255.f); return (u32) (rm1 * 255.f);
} }

View File

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

View File

@ -82,11 +82,11 @@ namespace core
CMatrix4<T>& operator-=(const CMatrix4<T>& other); CMatrix4<T>& operator-=(const CMatrix4<T>& other);
//! set this matrix to the product of two matrices //! set this matrix to the product of two matrices
inline void setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b ); inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
//! set this matrix to the product of two matrices, no logical optimation //! set this matrix to the product of two matrices, no logical optimation
//! use it if you know you never have a identity matrix //! use it if you know you never have a identity matrix
void setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b ); CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
//! Multiply by another matrix. //! Multiply by another matrix.
CMatrix4<T> operator*(const CMatrix4<T>& other) const; CMatrix4<T> operator*(const CMatrix4<T>& other) const;
@ -101,7 +101,7 @@ namespace core
CMatrix4<T>& operator*=(const T& scalar); CMatrix4<T>& operator*=(const T& scalar);
//! Set matrix to identity. //! Set matrix to identity.
inline void makeIdentity(); inline CMatrix4<T>& makeIdentity();
//! Returns true if the matrix is the identity matrix //! Returns true if the matrix is the identity matrix
inline bool isIdentity() const; inline bool isIdentity() const;
@ -110,31 +110,31 @@ namespace core
bool isIdentity_integer_base () const; bool isIdentity_integer_base () const;
//! Set the translation of the current matrix. Will erase any previous values. //! Set the translation of the current matrix. Will erase any previous values.
void setTranslation( const vector3d<T>& translation ); CMatrix4<T>& setTranslation( const vector3d<T>& translation );
//! Gets the current translation //! Gets the current translation
vector3d<T> getTranslation() const; vector3d<T> getTranslation() const;
//! Set the inverse translation of the current matrix. Will erase any previous values. //! Set the inverse translation of the current matrix. Will erase any previous values.
void setInverseTranslation( const vector3d<T>& translation ); CMatrix4<T>& setInverseTranslation( const vector3d<T>& translation );
//! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
inline void setRotationRadians( const vector3d<T>& rotation ); inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation );
//! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
void setRotationDegrees( const vector3d<T>& rotation ); CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation );
//! Returns the rotation, as set by setRotation(). This code was orginally written by by Chev. //! Returns the rotation, as set by setRotation(). This code was orginally written by by Chev.
core::vector3d<T> getRotationDegrees() const; core::vector3d<T> getRotationDegrees() const;
//! Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified. //! Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified.
inline void setInverseRotationRadians( const vector3d<T>& rotation ); inline CMatrix4<T>& setInverseRotationRadians( const vector3d<T>& rotation );
//! Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified. //! Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified.
void setInverseRotationDegrees( const vector3d<T>& rotation ); CMatrix4<T>& setInverseRotationDegrees( const vector3d<T>& rotation );
//! Set Scale //! Set Scale
void setScale( const vector3d<T>& scale ); CMatrix4<T>& setScale( const vector3d<T>& scale );
//! Get Scale //! Get Scale
core::vector3d<T> getScale() const; core::vector3d<T> getScale() const;
@ -203,39 +203,39 @@ namespace core
bool getInverse(CMatrix4<T>& out) const; bool getInverse(CMatrix4<T>& out) const;
//! Builds a right-handed perspective projection matrix based on a field of view //! Builds a right-handed perspective projection matrix based on a field of view
void buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
//! Builds a left-handed perspective projection matrix based on a field of view //! Builds a left-handed perspective projection matrix based on a field of view
void buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
//! Builds a right-handed perspective projection matrix. //! Builds a right-handed perspective projection matrix.
void buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
//! Builds a left-handed perspective projection matrix. //! Builds a left-handed perspective projection matrix.
void buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
//! Builds a left-handed orthogonal projection matrix. //! Builds a left-handed orthogonal projection matrix.
void buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); CMatrix4<T>& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
//! Builds a right-handed orthogonal projection matrix. //! Builds a right-handed orthogonal projection matrix.
void buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); CMatrix4<T>& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
//! Builds a left-handed look-at matrix. //! Builds a left-handed look-at matrix.
void buildCameraLookAtMatrixLH(const vector3df& position, const vector3df& target, const vector3df& upVector); CMatrix4<T>& buildCameraLookAtMatrixLH(const vector3df& position, const vector3df& target, const vector3df& upVector);
//! Builds a right-handed look-at matrix. //! Builds a right-handed look-at matrix.
void buildCameraLookAtMatrixRH(const vector3df& position, const vector3df& target, const vector3df& upVector); CMatrix4<T>& buildCameraLookAtMatrixRH(const vector3df& position, const vector3df& target, const vector3df& upVector);
//! Builds a matrix that flattens geometry into a plane. //! Builds a matrix that flattens geometry into a plane.
//! \param light: light source //! \param light: light source
//! \param plane: plane into which the geometry if flattened into //! \param plane: plane into which the geometry if flattened into
//! \param point: value between 0 and 1, describing the light source. //! \param point: value between 0 and 1, describing the light source.
//! If this is 1, it is a point light, if it is 0, it is a directional light. //! If this is 1, it is a point light, if it is 0, it is a directional light.
void buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f); CMatrix4<T>& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f);
//! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates. //! 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 von <-1,-1> <1,1> to the viewport <0,0><0,640> */
void buildNDCToDCMatrix( const core::rect<s32>& area, f32 zScale); CMatrix4<T>& buildNDCToDCMatrix( const core::rect<s32>& area, f32 zScale);
//! creates a new matrix as interpolated matrix from two other ones. //! creates a new matrix as interpolated matrix from two other ones.
//! \param b: other matrix to interpolate with //! \param b: other matrix to interpolate with
@ -252,21 +252,48 @@ namespace core
construct 2D Texture transformations construct 2D Texture transformations
rotate about center, scale, and transform. rotate about center, scale, and transform.
*/ */
void setTextureScale( f32 sx, f32 sy ); CMatrix4<T>& buildTextureTransform( f32 rotateRad,
void setTextureRotationCenter( f32 radAngle );
void setTextureScaleCenter( f32 sx, f32 sy );
void setTextureTranslate( f32 x, f32 y );
void setTextureTranslateTransposed( f32 x, f32 y );
void buildTextureTransform( f32 rotateRad,
const core::vector2df &rotatecenter, const core::vector2df &rotatecenter,
const core::vector2df &translate, const core::vector2df &translate,
const core::vector2df &scale); const core::vector2df &scale);
//! set texture transformation rotation
//! rotate about z axis, recenter at (0.5,0.5)
//! doesn't clear other elements than those affected
//! \param radAngle Angle in radians
//! \return Altered matrix
CMatrix4<T>& setTextureRotationCenter( f32 radAngle );
//! set texture transformation translation
//! doesn't clear other elements than those affected
//! \param x Offset on x axis
//! \param y Offset on y axis
//! \return Altered matrix
CMatrix4<T>& setTextureTranslate( f32 x, f32 y );
//! set texture transformation translation, using a transposed representation
//! doesn't clear other elements than those affected
//! \param x Offset on x axis
//! \param y Offset on y axis
//! \return Altered matrix
CMatrix4<T>& setTextureTranslateTransposed( f32 x, f32 y );
//! set texture transformation scale
//! doesn't clear other elements than those affected
//! \param sx Scale factor on x axis
//! \param sy Scale factor on y axis
//! \return Altered matrix
CMatrix4<T>& setTextureScale( f32 sx, f32 sy );
//! set texture transformation scale, and recenter at (0.5,0.5)
//! doesn't clear other elements than those affected
//! \param sx Scale factor on x axis
//! \param sy Scale factor on y axis
//! \return Altered matrix
CMatrix4<T>& setTextureScaleCenter( f32 sx, f32 sy );
//! sets all matrix data members at once //! sets all matrix data members at once
void setM(const T* data); CMatrix4<T>& setM(const T* data);
//! sets if the matrix is definitely identity matrix //! sets if the matrix is definitely identity matrix
void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix); void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix);
@ -479,17 +506,17 @@ namespace core
template <class T> template <class T>
inline CMatrix4<T>& CMatrix4<T>::operator*=(const CMatrix4<T>& other) inline CMatrix4<T>& CMatrix4<T>::operator*=(const CMatrix4<T>& other)
{ {
// do chacks on your own in order to avoid copy creation // do checks on your own in order to avoid copy creation
if ( !other.isIdentity() ) if ( !other.isIdentity() )
{ {
if ( this->isIdentity() ) if ( this->isIdentity() )
{ {
*this = other; return (*this = other);
} }
else else
{ {
CMatrix4<T> temp ( *this ); CMatrix4<T> temp ( *this );
setbyproduct_nocheck( temp, other ); return setbyproduct_nocheck( temp, other );
} }
} }
return *this; return *this;
@ -499,7 +526,7 @@ namespace core
// set this matrix to the product of two other matrices // set this matrix to the product of two other matrices
// goal is to reduce stack use and copy // goal is to reduce stack use and copy
template <class T> template <class T>
inline void CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b ) inline CMatrix4<T>& CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b )
{ {
const T *m1 = other_a.M; const T *m1 = other_a.M;
const T *m2 = other_b.M; const T *m2 = other_b.M;
@ -524,6 +551,7 @@ namespace core
M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*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]; M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
@ -531,20 +559,15 @@ namespace core
// set this matrix to the product of two other matrices // set this matrix to the product of two other matrices
// goal is to reduce stack use and copy // goal is to reduce stack use and copy
template <class T> template <class T>
inline void CMatrix4<T>::setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b ) inline CMatrix4<T>& CMatrix4<T>::setbyproduct(const CMatrix4<T>& other_a, const CMatrix4<T>& other_b )
{ {
if ( other_a.isIdentity () ) if ( other_a.isIdentity () )
{ return (*this = other_b);
*this = other_b;
return;
}
else else
if ( other_b.isIdentity () ) if ( other_b.isIdentity () )
{ return (*this = other_a);
*this = other_a; else
return; return setbyproduct_nocheck(other_a,other_b);
}
setbyproduct_nocheck(other_a,other_b);
} }
//! multiply by another matrix //! multiply by another matrix
@ -593,30 +616,33 @@ namespace core
template <class T> template <class T>
inline void CMatrix4<T>::setTranslation( const vector3d<T>& translation ) inline CMatrix4<T>& CMatrix4<T>::setTranslation( const vector3d<T>& translation )
{ {
M[12] = translation.X; M[12] = translation.X;
M[13] = translation.Y; M[13] = translation.Y;
M[14] = translation.Z; M[14] = translation.Z;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
template <class T> template <class T>
inline void CMatrix4<T>::setInverseTranslation( const vector3d<T>& translation ) inline CMatrix4<T>& CMatrix4<T>::setInverseTranslation( const vector3d<T>& translation )
{ {
M[12] = -translation.X; M[12] = -translation.X;
M[13] = -translation.Y; M[13] = -translation.Y;
M[14] = -translation.Z; M[14] = -translation.Z;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
template <class T> template <class T>
inline void CMatrix4<T>::setScale( const vector3d<T>& scale ) inline CMatrix4<T>& CMatrix4<T>::setScale( const vector3d<T>& scale )
{ {
M[0] = scale.X; M[0] = scale.X;
M[5] = scale.Y; M[5] = scale.Y;
M[10] = scale.Z; M[10] = scale.Z;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
template <class T> template <class T>
@ -626,33 +652,33 @@ namespace core
} }
template <class T> template <class T>
inline void CMatrix4<T>::setRotationDegrees( const vector3d<T>& rotation ) inline CMatrix4<T>& CMatrix4<T>::setRotationDegrees( const vector3d<T>& rotation )
{ {
setRotationRadians( rotation * core::DEGTORAD ); return setRotationRadians( rotation * core::DEGTORAD );
} }
template <class T> template <class T>
inline void CMatrix4<T>::setInverseRotationDegrees( const vector3d<T>& rotation ) inline CMatrix4<T>& CMatrix4<T>::setInverseRotationDegrees( const vector3d<T>& rotation )
{ {
setInverseRotationRadians( rotation * core::DEGTORAD ); return setInverseRotationRadians( rotation * core::DEGTORAD );
} }
template <class T> template <class T>
inline void CMatrix4<T>::setRotationRadians( const vector3d<T>& rotation ) inline CMatrix4<T>& CMatrix4<T>::setRotationRadians( const vector3d<T>& rotation )
{ {
f64 cr = cos( rotation.X ); const f64 cr = cos( rotation.X );
f64 sr = sin( rotation.X ); const f64 sr = sin( rotation.X );
f64 cp = cos( rotation.Y ); const f64 cp = cos( rotation.Y );
f64 sp = sin( rotation.Y ); const f64 sp = sin( rotation.Y );
f64 cy = cos( rotation.Z ); const f64 cy = cos( rotation.Z );
f64 sy = sin( rotation.Z ); const f64 sy = sin( rotation.Z );
M[0] = (T)( cp*cy ); M[0] = (T)( cp*cy );
M[1] = (T)( cp*sy ); M[1] = (T)( cp*sy );
M[2] = (T)( -sp ); M[2] = (T)( -sp );
f64 srsp = sr*sp; const f64 srsp = sr*sp;
f64 crsp = cr*sp; const f64 crsp = cr*sp;
M[4] = (T)( srsp*cy-cr*sy ); M[4] = (T)( srsp*cy-cr*sy );
M[5] = (T)( srsp*sy+cr*cy ); M[5] = (T)( srsp*sy+cr*cy );
@ -662,10 +688,10 @@ namespace core
M[9] = (T)( crsp*sy-sr*cy ); M[9] = (T)( crsp*sy-sr*cy );
M[10] = (T)( cr*cp ); M[10] = (T)( cr*cp );
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! Returns the rotation, as set by setRotation(). This code was sent //! Returns the rotation, as set by setRotation(). This code was sent
//! in by Chev. //! in by Chev.
template <class T> template <class T>
@ -674,18 +700,19 @@ namespace core
const CMatrix4<T> &mat = *this; const CMatrix4<T> &mat = *this;
f64 Y = -asin(mat(0,2)); f64 Y = -asin(mat(0,2));
f64 C = cos(Y); const f64 C = cos(Y);
Y *= RADTODEG64; Y *= RADTODEG64;
f64 rotx, roty, X, Z; f64 rotx, roty, X, Z;
if (fabs(C)>0.0005f) if (fabs(C)>0.0005f)
{ {
rotx = mat(2,2) / C; const T invC = 1.0/C;
roty = mat(1,2) / C; rotx = mat(2,2) * invC;
roty = mat(1,2) * invC;
X = atan2( roty, rotx ) * RADTODEG64; X = atan2( roty, rotx ) * RADTODEG64;
rotx = mat(0,0) / C; rotx = mat(0,0) * invC;
roty = mat(0,1) / C; roty = mat(0,1) * invC;
Z = atan2( roty, rotx ) * RADTODEG64; Z = atan2( roty, rotx ) * RADTODEG64;
} }
else else
@ -703,11 +730,12 @@ namespace core
if (Y < 0.0) Y += 360.0; if (Y < 0.0) Y += 360.0;
if (Z < 0.0) Z += 360.0; if (Z < 0.0) Z += 360.0;
return vector3d<T>((f32)X,(f32)Y,(f32)Z); return vector3d<T>((T)X,(T)Y,(T)Z);
} }
template <class T> template <class T>
inline void CMatrix4<T>::setInverseRotationRadians( const vector3d<T>& rotation ) inline CMatrix4<T>& CMatrix4<T>::setInverseRotationRadians( const vector3d<T>& rotation )
{ {
f64 cr = cos( rotation.X ); f64 cr = cos( rotation.X );
f64 sr = sin( rotation.X ); f64 sr = sin( rotation.X );
@ -731,17 +759,19 @@ namespace core
M[6] = (T)( crsp*sy-sr*cy ); M[6] = (T)( crsp*sy-sr*cy );
M[10] = (T)( cr*cp ); M[10] = (T)( cr*cp );
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
/*! /*!
*/ */
template <class T> template <class T>
inline void CMatrix4<T>::makeIdentity() inline CMatrix4<T>& CMatrix4<T>::makeIdentity()
{ {
memset(M, 0, 16*sizeof(T)); memset(M, 0, 16*sizeof(T));
M[0] = M[5] = M[10] = M[15] = (T)1; M[0] = M[5] = M[10] = M[15] = (T)1;
definitelyIdentityMatrix=true; definitelyIdentityMatrix=true;
return *this;
} }
@ -806,7 +836,6 @@ namespace core
} }
template <class T> template <class T>
inline void CMatrix4<T>::rotateVect( vector3df& vect ) const inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
{ {
@ -1166,10 +1195,10 @@ namespace core
//! Builds a right-handed perspective projection matrix based on a field of view //! Builds a right-handed perspective projection matrix based on a field of view
template <class T> template <class T>
inline void CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
{ {
f64 h = 1.0/tan(fieldOfViewRadians/2.0); const f64 h = 1.0/tan(fieldOfViewRadians/2.0);
T w = h / aspectRatio; const T w = h / aspectRatio;
M[0] = w; M[0] = w;
M[1] = 0; M[1] = 0;
@ -1193,16 +1222,17 @@ namespace core
// M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version // M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version
M[15] = 0; M[15] = 0;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! Builds a left-handed perspective projection matrix based on a field of view //! Builds a left-handed perspective projection matrix based on a field of view
template <class T> template <class T>
inline void CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
{ {
f64 h = 1.0/tan(fieldOfViewRadians/2.0); const f64 h = 1.0/tan(fieldOfViewRadians/2.0);
T w = (T)(h / aspectRatio); const T w = (T)(h / aspectRatio);
M[0] = w; M[0] = w;
M[1] = 0; M[1] = 0;
@ -1224,13 +1254,13 @@ namespace core
M[14] = (T)(-zNear*zFar/(zFar-zNear)); M[14] = (T)(-zNear*zFar/(zFar-zNear));
M[15] = 0; M[15] = 0;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! Builds a left-handed orthogonal projection matrix. //! Builds a left-handed orthogonal projection matrix.
template <class T> template <class T>
inline void CMatrix4<T>::buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
{ {
M[0] = (T)(2/widthOfViewVolume); M[0] = (T)(2/widthOfViewVolume);
M[1] = 0; M[1] = 0;
@ -1252,13 +1282,14 @@ namespace core
M[14] = (T)(zNear/(zNear-zFar)); M[14] = (T)(zNear/(zNear-zFar));
M[15] = 1; M[15] = 1;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! Builds a right-handed orthogonal projection matrix. //! Builds a right-handed orthogonal projection matrix.
template <class T> template <class T>
inline void CMatrix4<T>::buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
{ {
M[0] = (T)(2/widthOfViewVolume); M[0] = (T)(2/widthOfViewVolume);
M[1] = 0; M[1] = 0;
@ -1280,12 +1311,13 @@ namespace core
M[14] = (T)(zNear/(zNear-zFar)); M[14] = (T)(zNear/(zNear-zFar));
M[15] = -1; M[15] = -1;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! Builds a right-handed perspective projection matrix. //! Builds a right-handed perspective projection matrix.
template <class T> template <class T>
inline void CMatrix4<T>::buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
{ {
M[0] = (T)(2*zNear/widthOfViewVolume); M[0] = (T)(2*zNear/widthOfViewVolume);
M[1] = 0; M[1] = 0;
@ -1307,12 +1339,13 @@ namespace core
M[14] = (T)(zNear*zFar/(zNear-zFar)); M[14] = (T)(zNear*zFar/(zNear-zFar));
M[15] = 0; M[15] = 0;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! Builds a left-handed perspective projection matrix. //! Builds a left-handed perspective projection matrix.
template <class T> template <class T>
inline void CMatrix4<T>::buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
{ {
M[0] = (T)(2*zNear/widthOfViewVolume); M[0] = (T)(2*zNear/widthOfViewVolume);
M[1] = 0; M[1] = 0;
@ -1334,15 +1367,16 @@ namespace core
M[14] = (T)(zNear*zFar/(zNear-zFar)); M[14] = (T)(zNear*zFar/(zNear-zFar));
M[15] = 0; M[15] = 0;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! Builds a matrix that flattens geometry into a plane. //! Builds a matrix that flattens geometry into a plane.
template <class T> template <class T>
inline void CMatrix4<T>::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point) inline CMatrix4<T>& CMatrix4<T>::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point)
{ {
plane.Normal.normalize(); plane.Normal.normalize();
f32 d = plane.Normal.dotProduct(light); const f32 d = plane.Normal.dotProduct(light);
M[ 0] = (T)(-plane.Normal.X * light.X + d); M[ 0] = (T)(-plane.Normal.X * light.X + d);
M[ 1] = (T)(-plane.Normal.X * light.Y); M[ 1] = (T)(-plane.Normal.X * light.Y);
@ -1364,11 +1398,12 @@ namespace core
M[14] = (T)(-plane.D * light.Z); M[14] = (T)(-plane.D * light.Z);
M[15] = (T)(-plane.D * point + d); M[15] = (T)(-plane.D * point + d);
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! Builds a left-handed look-at matrix. //! Builds a left-handed look-at matrix.
template <class T> template <class T>
inline void CMatrix4<T>::buildCameraLookAtMatrixLH( inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixLH(
const vector3df& position, const vector3df& position,
const vector3df& target, const vector3df& target,
const vector3df& upVector) const vector3df& upVector)
@ -1401,13 +1436,14 @@ namespace core
M[14] = (T)-zaxis.dotProduct(position); M[14] = (T)-zaxis.dotProduct(position);
M[15] = 1; M[15] = 1;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! Builds a right-handed look-at matrix. //! Builds a right-handed look-at matrix.
template <class T> template <class T>
inline void CMatrix4<T>::buildCameraLookAtMatrixRH( inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixRH(
const vector3df& position, const vector3df& position,
const vector3df& target, const vector3df& target,
const vector3df& upVector) const vector3df& upVector)
@ -1440,10 +1476,12 @@ namespace core
M[14] = (T)-zaxis.dotProduct(position); M[14] = (T)-zaxis.dotProduct(position);
M[15] = 1; M[15] = 1;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! creates a new matrix as interpolated matrix from to other ones. //! creates a new matrix as interpolated matrix from this and the passed one.
//! \param b: Second matrix to interpolate with
//! \param time: Must be a value between 0 and 1. //! \param time: Must be a value between 0 and 1.
template <class T> template <class T>
inline CMatrix4<T> CMatrix4<T>::interpolate(const core::CMatrix4<T>& b, f32 time) const inline CMatrix4<T> CMatrix4<T>::interpolate(const core::CMatrix4<T>& b, f32 time) const
@ -1498,21 +1536,18 @@ namespace core
// used to scale <-1,-1><1,1> to viewport // used to scale <-1,-1><1,1> to viewport
template <class T> template <class T>
inline void CMatrix4<T>::buildNDCToDCMatrix( const core::rect<s32>& viewport, f32 zScale) inline CMatrix4<T>& CMatrix4<T>::buildNDCToDCMatrix( const core::rect<s32>& viewport, f32 zScale)
{ {
f32 scaleX = (viewport.getWidth() - 0.75f ) / 2.0f; const f32 scaleX = (viewport.getWidth() - 0.75f ) / 2.0f;
f32 scaleY = -(viewport.getHeight() - 0.75f ) / 2.0f; const f32 scaleY = -(viewport.getHeight() - 0.75f ) / 2.0f;
f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) / 2.0f ); const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) / 2.0f );
f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) / 2.0f ); const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) / 2.0f );
makeIdentity(); makeIdentity();
M[0] = (T)scaleX;
M[5] = (T)scaleY;
M[10] = (T)zScale;
M[12] = (T)dx; M[12] = (T)dx;
M[13] = (T)dy; M[13] = (T)dy;
definitelyIdentityMatrix=false; return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale));
} }
/*! /*!
@ -1527,7 +1562,7 @@ namespace core
*/ */
template <class T> template <class T>
inline void CMatrix4<T>::buildTextureTransform( f32 rotateRad, inline CMatrix4<T>& CMatrix4<T>::buildTextureTransform( f32 rotateRad,
const core::vector2df &rotatecenter, const core::vector2df &rotatecenter,
const core::vector2df &translate, const core::vector2df &translate,
const core::vector2df &scale) const core::vector2df &scale)
@ -1555,66 +1590,73 @@ namespace core
M[14] = 0; M[14] = 0;
M[15] = 1; M[15] = 1;
definitelyIdentityMatrix=false; definitelyIdentityMatrix=false;
return *this;
} }
//! rotate about z axis, center ( 0.5, 0.5 ) //! rotate about z axis, center ( 0.5, 0.5 )
template <class T> template <class T>
inline void CMatrix4<T>::setTextureRotationCenter( f32 rotateRad ) inline CMatrix4<T>& CMatrix4<T>::setTextureRotationCenter( f32 rotateRad )
{ {
const f32 c = cosf(rotateRad); const f32 c = cosf(rotateRad);
const f32 s = sinf(rotateRad); const f32 s = sinf(rotateRad);
M[0] = (T)c; M[0] = (T)c;
M[1] = (T)s; M[1] = (T)s;
M[2] = (T)(-0.5f * ( c + s) + 0.5f);
M[4] = (T)-s; M[4] = (T)-s;
M[5] = (T)c; M[5] = (T)c;
M[6] = (T)(-0.5f * (-s + c) + 0.5f);
definitelyIdentityMatrix=false; M[8] = (T)(0.5f * ( s - c) + 0.5f);
M[9] = (T)(-0.5f * ( s + c) + 0.5f);
definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f);
return *this;
} }
template <class T> template <class T>
inline void CMatrix4<T>::setTextureTranslate ( f32 x, f32 y ) inline CMatrix4<T>& CMatrix4<T>::setTextureTranslate ( f32 x, f32 y )
{ {
M[8] = (T)x; M[8] = (T)x;
M[9] = (T)y; M[9] = (T)y;
definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ; definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
return *this;
} }
template <class T> template <class T>
inline void CMatrix4<T>::setTextureTranslateTransposed ( f32 x, f32 y ) inline CMatrix4<T>& CMatrix4<T>::setTextureTranslateTransposed ( f32 x, f32 y )
{ {
M[2] = (T)x; M[2] = (T)x;
M[6] = (T)y; M[6] = (T)y;
definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ; definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ;
return *this;
} }
template <class T> template <class T>
inline void CMatrix4<T>::setTextureScale ( f32 sx, f32 sy ) inline CMatrix4<T>& CMatrix4<T>::setTextureScale ( f32 sx, f32 sy )
{ {
M[0] = (T)sx; M[0] = (T)sx;
M[5] = (T)sy; M[5] = (T)sy;
definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f) ; definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
return *this;
} }
template <class T> template <class T>
inline void CMatrix4<T>::setTextureScaleCenter( f32 sx, f32 sy ) inline CMatrix4<T>& CMatrix4<T>::setTextureScaleCenter( f32 sx, f32 sy )
{ {
M[0] = (T)sx; M[0] = (T)sx;
M[2] = (T)(-0.5f * sx + 0.5f);
M[5] = (T)sy; M[5] = (T)sy;
M[6] = (T)(-0.5f * sy + 0.5f); M[8] = (T)(0.5f - 0.5f * sx);
definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f) ; M[9] = (T)(0.5f - 0.5f * sy);
definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
return *this;
} }
//! sets all matrix data members at once //! sets all matrix data members at once
template <class T> template <class T>
inline void CMatrix4<T>::setM(const T* data) inline CMatrix4<T>& CMatrix4<T>::setM(const T* data)
{ {
for (u32 i = 0; i < 16; ++i) memcpy(M,data, 16*sizeof(T));
M[i] = data[i];
definitelyIdentityMatrix = false; definitelyIdentityMatrix = false;
return *this;
} }
//! sets if the matrix is definitely identity matrix //! sets if the matrix is definitely identity matrix

View File

@ -9,7 +9,6 @@
#include "CColorConverter.h" #include "CColorConverter.h"
#include "IWriteFile.h" #include "IWriteFile.h"
#include "CImage.h" #include "CImage.h"
#include "CColorConverter.h"
#include "irrString.h" #include "irrString.h"
#ifdef _IRR_COMPILE_WITH_LIBJPEG_ #ifdef _IRR_COMPILE_WITH_LIBJPEG_
@ -23,7 +22,6 @@ extern "C"
#include "jpeglib/jpeglib.h" #include "jpeglib/jpeglib.h"
#include "jpeglib/jerror.h" #include "jpeglib/jerror.h"
#endif #endif
#include <setjmp.h>
} }
@ -32,118 +30,156 @@ namespace irr
namespace video namespace video
{ {
// The writer uses a 4k buffer and flushes to disk each time it's filled
#define OUTPUT_BUF_SIZE 4096
typedef struct typedef struct
{ {
struct jpeg_destination_mgr pub; /* public fields */ struct jpeg_destination_mgr pub;/* public fields */
JOCTET * buffer; /* image buffer */ io::IWriteFile* file; /* target file */
u32 buffer_size; /* image buffer size */ JOCTET buffer[OUTPUT_BUF_SIZE]; /* image buffer */
} mem_destination_mgr; } mem_destination_mgr;
typedef mem_destination_mgr * mem_dest_ptr; typedef mem_destination_mgr * mem_dest_ptr;
void init_destination (j_compress_ptr cinfo)
// init
static void jpeg_init_destination(j_compress_ptr cinfo)
{
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
}
// flush to disk and reset buffer
static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo)
{ {
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
/* image buffer must be allocated before mem_dest routines are called. */ // for now just exit upon file error
if(dest->buffer == NULL) { if (dest->file->write(dest->buffer, OUTPUT_BUF_SIZE) != OUTPUT_BUF_SIZE)
//fprintf(stderr, "jmem_dest: init_destination: buffer not allocated\n"); ERREXIT (cinfo, JERR_FILE_WRITE);
}
dest->pub.next_output_byte = dest->buffer; dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = dest->buffer_size; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
return TRUE;
} }
boolean 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;
*/
// empty_output_buffer: buffer should not ever be full\n");
return FALSE;
}
void term_destination (j_compress_ptr cinfo)
{ {
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
size_t datacount = dest->buffer_size - dest->pub.free_in_buffer; const s32 datacount = 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);
} }
void jpeg_memory_dest (j_compress_ptr cinfo, u8 *jfif_buffer,
s32 buf_size) // set up buffer data
static void jpeg_file_dest(j_compress_ptr cinfo, io::IWriteFile* file)
{ {
mem_dest_ptr dest; if (cinfo->dest == NULL)
{ /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
JPOOL_PERMANENT,
sizeof(mem_destination_mgr));
}
if(jfif_buffer == NULL) { mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; /* for casting */
//fprintf(stderr, "jpeg_memory_dest: memory buffer needs to be allocated\n");
//ERREXIT(cinfo, JERR_BUFFER_SIZE);
return;
}
if (cinfo->dest == NULL) { /* first time for this JPEG object? */ /* Initialize method pointers */
cinfo->dest = (struct jpeg_destination_mgr *) dest->pub.init_destination = jpeg_init_destination;
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, dest->pub.empty_output_buffer = jpeg_empty_output_buffer;
(size_t) sizeof(mem_destination_mgr)); dest->pub.term_destination = jpeg_term_destination;
}
dest = (mem_dest_ptr) cinfo->dest; /* for casting */ /* Initialize private member */
dest->file = file;
/* Initialize method pointers */
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
/* Initialize private member */
dest->buffer = (JOCTET*)jfif_buffer;
dest->buffer_size = buf_size;
} }
/* write_JPEG_memory: store JPEG compressed image into memory. /* write_JPEG_memory: store JPEG compressed image into memory.
*/ */
void write_JPEG_memory (void *img_buf, s32 width, s32 height, u32 bpp, u32 pitch, static bool writeJPEGFile(io::IWriteFile* file, IImage* image, u32 quality)
u8 *jpeg_buffer, u32 jpeg_buffer_size,
s32 quality, u32 *jpeg_comp_size)
{ {
void (*format)(const void*, s32, void*) = 0;
switch( image->getColorFormat () )
{
case ECF_R8G8B8:
format = CColorConverter::convert_R8G8B8toR8G8B8;
break;
case ECF_A8R8G8B8:
format = CColorConverter::convert_A8R8G8B8toR8G8B8;
break;
case ECF_A1R5G5B5:
format = CColorConverter::convert_A1R5G5B5toB8G8R8;
break;
case ECF_R5G6B5:
format = CColorConverter::convert_R5G6B5toR8G8B8;
break;
}
// couldn't find a color converter
if ( 0 == format )
return false;
const core::dimension2di dim = image->getDimension();
struct jpeg_compress_struct cinfo; struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr; struct jpeg_error_mgr jerr;
/* More stuff */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
cinfo.err = jpeg_std_error(&jerr); cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo); jpeg_create_compress(&cinfo);
jpeg_memory_dest(&cinfo, jpeg_buffer, jpeg_buffer_size); jpeg_file_dest(&cinfo, file);
cinfo.image_width = width; cinfo.image_width = dim.Width;
cinfo.image_height = height; cinfo.image_height = dim.Height;
cinfo.input_components = bpp; cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB; cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo); jpeg_set_defaults(&cinfo);
if ( 0 == quality )
quality = 75;
jpeg_set_quality(&cinfo, quality, TRUE); jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE); jpeg_start_compress(&cinfo, TRUE);
while (cinfo.next_scanline < cinfo.image_height) u8 * dest = new u8[dim.Width*3];
if (dest)
{ {
row_pointer[0] = (u8*) img_buf + (cinfo.next_scanline * pitch ); const u32 pitch = image->getPitch();
jpeg_write_scanlines(&cinfo, row_pointer, 1); JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
} row_pointer[0] = dest;
/* Step 6: Finish compression */ u8* src = (u8*)image->lock();
jpeg_finish_compress(&cinfo);
while (cinfo.next_scanline < cinfo.image_height)
{ {
mem_dest_ptr dest = (mem_dest_ptr) cinfo.dest; // convert next line
*jpeg_comp_size = dest->buffer_size - dest->pub.free_in_buffer; format( src, dim.Width, dest );
src += pitch;
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
image->unlock();
delete [] dest;
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
} }
/* Step 7: Destroy */
jpeg_destroy_compress(&cinfo); jpeg_destroy_compress(&cinfo);
return (dest != 0);
} }
} // namespace video } // namespace video
} // namespace irr } // namespace irr
@ -169,63 +205,17 @@ CImageWriterJPG::CImageWriterJPG()
bool CImageWriterJPG::isAWriteableFileExtension(const c8* fileName) const bool CImageWriterJPG::isAWriteableFileExtension(const c8* fileName) const
{ {
return strstr(fileName, ".jpg") != 0 || strstr(fileName, ".jpeg") != 0; const char* dot = strrchr (fileName, '.');
return dot && (!strcmp (dot, ".jpg") || !strcmp (dot, ".jpeg"));
} }
bool CImageWriterJPG::writeImage(io::IWriteFile *file, IImage *input,u32 quality) const bool CImageWriterJPG::writeImage(io::IWriteFile *file, IImage *image, u32 quality) const
{ {
#ifndef _IRR_COMPILE_WITH_LIBJPEG_ #ifndef _IRR_COMPILE_WITH_LIBJPEG_
return false; return false;
#else #else
return writeJPEGFile(file, image, quality);
core::dimension2di dim = input->getDimension();
IImage * image = new CImage(ECF_R8G8B8, dim );
void (*format)(const void*, s32, void*) = 0;
switch( input->getColorFormat () )
{
case ECF_R8G8B8: format = CColorConverter::convert_R8G8B8toR8G8B8; break;
case ECF_A8R8G8B8: format = CColorConverter::convert_A8R8G8B8toR8G8B8; break;
case ECF_A1R5G5B5: format = CColorConverter::convert_A1R5G5B5toB8G8R8; break;
case ECF_R5G6B5: format = CColorConverter::convert_R5G6B5toR8G8B8; break;
}
// couldn't find a color converter
if ( 0 == format )
return false;
s32 y;
void *src = input->lock();
void *dst = image->lock();
for ( y = 0; y!= dim.Height; ++y )
{
format( src, dim.Width, dst );
src = (void*) ( (u8*) src + input->getPitch () );
dst = (void*) ( (u8*) dst + image->getPitch () );
}
input->unlock ();
image->unlock ();
// temp buffer
u32 destSize = image->getImageDataSizeInBytes ();
u8 * dest = new u8 [ destSize ];
if ( 0 == quality )
quality = 75;
write_JPEG_memory ( image->lock (), dim.Width, dim.Height,
image->getBytesPerPixel(), image->getPitch(),
dest, destSize,
quality,
&destSize);
file->write ( dest, destSize );
image->drop ();
delete [] dest;
return true;
#endif #endif
} }

View File

@ -78,7 +78,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
NULL, (png_error_ptr)png_cpexcept_error, NULL); NULL, (png_error_ptr)png_cpexcept_error, NULL);
if (!png_ptr) if (!png_ptr)
{ {
os::Printer::log("LOAD PNG: Internal PNG create write struct failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("PNGWriter: Internal PNG create write struct failure\n", file->getFileName(), ELL_ERROR);
return false; return false;
} }
@ -86,7 +86,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
png_infop info_ptr = png_create_info_struct(png_ptr); png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) if (!info_ptr)
{ {
os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("PNGWriter: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR);
png_destroy_write_struct(&png_ptr, NULL); png_destroy_write_struct(&png_ptr, NULL);
return false; return false;
} }
@ -132,7 +132,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
u8* tmpImage = new u8[image->getDimension().Height*lineWidth]; u8* tmpImage = new u8[image->getDimension().Height*lineWidth];
if (!tmpImage) if (!tmpImage)
{ {
os::Printer::log("LOAD PNG: Internal PNG create image failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("PNGWriter: Internal PNG create image failure\n", file->getFileName(), ELL_ERROR);
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
return false; return false;
} }
@ -161,7 +161,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
u8** RowPointers = new png_bytep[image->getDimension().Height]; u8** RowPointers = new png_bytep[image->getDimension().Height];
if (!RowPointers) if (!RowPointers)
{ {
os::Printer::log("LOAD PNG: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("PNGWriter: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR);
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
delete [] tmpImage; delete [] tmpImage;
return false; return false;

View File

@ -2272,7 +2272,7 @@ void COpenGLDriver::setFog(SColor c, bool linearFog, f32 start,
{ {
CNullDriver::setFog(c, linearFog, start, end, density, pixelFog, rangeFog); CNullDriver::setFog(c, linearFog, start, end, density, pixelFog, rangeFog);
glFogf(GL_FOG_MODE, linearFog ? GL_LINEAR : GL_EXP); glFogf(GL_FOG_MODE, GLfloat(linearFog ? GL_LINEAR : GL_EXP));
#ifdef GL_EXT_fog_coord #ifdef GL_EXT_fog_coord
if (FeatureAvailable[IRR_EXT_fog_coord]) if (FeatureAvailable[IRR_EXT_fog_coord])
glFogi(GL_FOG_COORDINATE_SOURCE, GL_FRAGMENT_DEPTH); glFogi(GL_FOG_COORDINATE_SOURCE, GL_FRAGMENT_DEPTH);