Skip to content

Instantly share code, notes, and snippets.

@chronologicaldot
Created September 30, 2020 04:22
Show Gist options
  • Save chronologicaldot/c3239c12e44709cd7807d7a580411844 to your computer and use it in GitHub Desktop.
Save chronologicaldot/c3239c12e44709cd7807d7a580411844 to your computer and use it in GitHub Desktop.
C++ Irrlicht Mandelbrot
// Copyright 2014-2016 Nicolaus Anderson
template<class T>
struct ComplexNumber
{
T real;
T imag; // imaginary component
ComplexNumber()
: real( 0 )
, imag( 0 )
{}
ComplexNumber( const ComplexNumber& other )
: real( other.real )
, imag( other.imag )
{}
ComplexNumber( T realT, T imagT )
: real( realT )
, imag( imagT )
{}
void set( T realT, T imagT )
{
real = realT;
imag = imagT;
}
ComplexNumber& operator = ( const ComplexNumber<T>& other )
{
real = other.real;
imag = other.imag;
return *this;
}
ComplexNumber& operator = ( T& value )
{
real = value;
imag = T(0);
return *this;
}
bool operator == ( ComplexNumber& other )
{
return ( real == other.real && imag == other.imag );
}
bool operator == ( T& value )
{
return ( real == value && imag == T(0) );
}
// Basic operators for other == ComplexNumber
ComplexNumber& operator += ( ComplexNumber& other )
{
real += other.real;
imag += other.imag;
return *this;
}
ComplexNumber operator + ( ComplexNumber& other )
{
ComplexNumber temp(*this);
return (temp += other);
}
ComplexNumber& operator -= ( ComplexNumber& other )
{
real -= other.real;
imag -= other.imag;
return *this;
}
ComplexNumber operator - ( ComplexNumber& other )
{
ComplexNumber temp(*this);
return (temp -= other);
}
ComplexNumber& operator *= ( ComplexNumber& other )
{
T tempReal = real;
real = tempReal * other.real - imag * other.imag;
imag = tempReal * other.imag + imag * other.real;
return *this;
}
ComplexNumber operator * ( ComplexNumber& other )
{
ComplexNumber temp(*this);
return (temp *= other);
}
ComplexNumber& operator /= ( ComplexNumber& other )
{
/* Technically what's happening... (Multiply top and bottom by the complex conjugate of the divisor)*/
// ComplexNumber cconj = other; // complex conjugate
// cconj.imag *= -1;
// ComplexNumber oc = other*cconj; // eliminate imag from divisor
// real *= cconj.real / oc.real;
// imag *= cconj.imag / oc.real;
// Shorthand
T tReal = other.real * other.real + other.imag * other.imag;
real *= other.real / tReal;
imag *= -other.imag / tReal;
return *this;
}
ComplexNumber operator / ( ComplexNumber& other )
{
ComplexNumber temp(*this);
return (temp /= other);
}
// Basic operators for other == T
ComplexNumber& operator += ( T& other )
{
real += other;
return *this;
}
ComplexNumber operator + ( T& other )
{
ComplexNumber temp(*this);
return (temp += other);
}
ComplexNumber& operator -= ( T& other )
{
real -= other;
return *this;
}
ComplexNumber operator - ( T& other )
{
ComplexNumber temp(*this);
return (temp -= other);
}
ComplexNumber& operator *= ( T& other )
{
real *= other;
imag *= other;
return *this;
}
ComplexNumber operator * ( T& other )
{
ComplexNumber temp(*this);
return (temp *= other);
}
ComplexNumber& operator /= ( T& other )
{
real /= other;
imag /= other;
return *this;
}
ComplexNumber operator / ( T& other )
{
ComplexNumber temp(*this);
return (temp /= other);
}
};
#include <irrlicht.h>
#include "../IrrExtensions/math/ComplexNumber.h"
using namespace irr;
void renderFractalImage( video::IImage& );
video::SColor renderFractalPixel( f64, f64 );
template<class T>
T sqr( T n ) { return( n*n ); }
int main()
{
core::dimension2du screenSize(900,800);
IrrlichtDevice* device = createDevice(video::EDT_OPENGL, screenSize);
if ( !device ) {
return 1;
}
video::ECOLOR_FORMAT colorFormat = video::ECF_A8R8G8B8;
video::IImage* image = device->getVideoDriver()->createImage(colorFormat, screenSize);
renderFractalImage(*image);
io::path name("FractalImage.png");
video::ITexture* texture = device->getVideoDriver()->addTexture( name, image );
core::position2d<s32> screenPosition;
while ( device->run() ) {
device->getVideoDriver()->beginScene();
device->getVideoDriver()->draw2DImage( texture, screenPosition );
device->getVideoDriver()->endScene();
}
device->getVideoDriver()->writeImageToFile( image, name, 0 );
image->drop();
device->drop();
return 0;
}
void renderFractalImage( video::IImage& image )
{
core::dimension2du size = image.getDimension();
u32 x = 0, y = 0;
f64 real, imag;
const f64 zoom = 3;
for (x=0; x < size.Width; ++x) {
for (y=0; y < size.Height; ++y) {
real = (f64)x / (f64)size.Width - 0.75;
imag = (f64)y / (f64)size.Height - 0.5;
image.setPixel(x, y, renderFractalPixel(zoom*real, zoom*imag));
}
}
}
video::SColor renderFractalPixel( f64 real, f64 imag )
{
ComplexNumber<f64> z, z2, c( real, imag );
u32 i = 0;
f64 a = 0;
f64 r = 0;
for (; i < 50 && a <= 2; ++i) {
z2 = z;
z *= z2;
z += c;
a = sqr(z.real); // - sqr(z.imag);
}
if ( i == 50 )
return video::SColor(0xff0000ff);
else {
r = 255. - 2.55*i;
return video::SColor(255, (u32)r, (u32)r, (u32)r);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment