Commit 033a5187 authored by BrutPitt's avatar BrutPitt
Browse files

ver 1.6.0 WiP - reorganize attractorsBase (h/cpp) files : move fractals (IIM)...

ver 1.6.0 WiP - reorganize attractorsBase (h/cpp) files : move fractals (IIM) class, in separate files
parent 75eba236
//------------------------------------------------------------------------------
// Copyright (c) 2018-2020 Michele Morrone
// All rights reserved.
//
// https://michelemorrone.eu - https://BrutPitt.com
//
// twitter: https://twitter.com/BrutPitt - github: https://github.com/BrutPitt
//
// mailto:brutpitt@gmail.com - mailto:me@michelemorrone.eu
//
// This software is distributed under the terms of the BSD 2-Clause license
//------------------------------------------------------------------------------
#include "glWindow.h"
// stochastic adaptation of P.Nylander's Mathematica formula of JuliaBulb set
// http://bugman123.com/Hypercomplex/index.html
////////////////////////////////////////////////////////////////////////////
void juliaBulb_IIM::Step(vec4 &v, vec4 &vp)
{
auto radiciEq = [&](const vec3 &p, float sign1, float sign2) {
const float xQ = p.x * p.x, yQ = p.y * p.y, zQ = p.z * p.z;
const float r = sqrtf(xQ+yQ+zQ);
const float a = sign1 * sqrtf(yQ + xQ*(2.f+zQ/(xQ+yQ)) - 2.f*p.x*r);
const float b = sign2 * sqrtf(r - p.x - a) * .5f;
const float c = yQ*yQ + xQ * (yQ - zQ);
const float d = a * (p.x * (r+p.x) + yQ);
vp = vec4(b * ((p.x*yQ-d) * (xQ+yQ) - p.x*xQ*zQ) / (p.y*c),
b,
-p.z/sqrtf(2 * (r - d *(xQ+yQ)/c)),
0.f);
if(ifsPoint.active()) vp *= getIFSvec4(ifsPoint); // IFS point transforms
};
auto mainFunc = [&](vec4 &v, vec4 &vp) {
const uint32_t rnd = fRnd64.xorShift();
const vec4 c = ifsParam.active() ? kRnd+getIFSvec4(ifsParam) : kRnd; // IFS param transforms
vec4 tmpV((vec3)v-((vec3 )*kVal.data()+(vec3)c));
radiciEq(tmpV, (rnd&1) ? 1.f : -1.f, (rnd&2) ? 1.f : -1.f);
};
while(depth++<skipTop) { mainFunc(v,vp); v = vp; } // skip first "skipTop" points
preStep(v);
mainFunc(v,vp);
}
// stochastic adaptation of P.Nylander's Mathematica formula of JuliaBulb set
// http://bugman123.com/Hypercomplex/index.html
////////////////////////////////////////////////////////////////////////////
void juliaBulb4th_IIM::Step(vec4 &v, vec4 &vp)
{
auto radiciEq = [&](const vec3 &p, int kTheta, int kPhi) {
const float r = length(p);
const int absOrder = abs(degreeN);
const int k1 = (absOrder - (p.z<0 ? 0 : 1)), k2 = (3*absOrder + (p.z<0 ? 4 : 2));
const int dk = ((absOrder%2)==0 && (kPhi<<2)>k1 && (kPhi<<2)<k2) ? (sign(p.z) * ( (absOrder % 4) ? 1 : -1)) : 0;
const float theta = (atan2f(p.y,p.x) + (2 * kTheta + dk) * T_PI) / float(degreeN);
const float phi = (asinf(p.z/r) + (2 * kPhi - dk) * T_PI) / float(degreeN);
const float cosphi = cosf(phi);
vp = vec4(powf(r, 1.0f/float(degreeN)) * vec3(cosf(theta)*cosphi,sinf(theta)*cosphi,sinf(phi)), 0.f);
if(ifsPoint.active()) vp *= getIFSvec4(ifsPoint);
};
auto mainFunc = [&](vec4 &v, vec4 &vp) {
const vec4 c = ifsParam.active() ? kRnd+getIFSvec4(ifsParam) : kRnd; // IFS param transforms
radiciEq((vec3)v-((vec3 &)*kVal.data()+(vec3)c), fRnd64.xorShift() % degreeN, fRnd64.xorShift() % degreeN);
};
while(depth++<skipTop) { mainFunc(v,vp); v = vp; } // skip first "skipTop" points
preStep(v);
mainFunc(v,vp);
}
// stochastic adaptation of P.Nylander's Mathematica formula of quaternion Julia set
// http://bugman123.com/Hypercomplex/index.html
////////////////////////////////////////////////////////////////////////////
void quatJulia_IIM::Step(vec4 &v, vec4 &vp)
{
auto radiciEq = [&](const vec4 &p, float sign) {
const float xQ = p.x * p.x, yQ = p.y * p.y, zQ = p.z * p.z, wQ = p.w * p.w;
const float r = sqrtf(xQ + yQ + zQ + wQ);
const float a = sqrtf((p.x+r)*.5);
const float b = (r-p.x) * a / (yQ + zQ + wQ);
vp = sign * vec4(a, b*p.y, b*p.z, b*p.w);
if(ifsPoint.active()) vp *= getIFSvec4(ifsPoint); // IFS point transforms
};
auto mainFunc = [&](vec4 &v, vec4 &vp) {
const vec4 c = ifsParam.active() ? kRnd+getIFSvec4(ifsParam) : kRnd; // IFS param transforms
vec4 tmpV(v-((vec4 &)*kVal.data()+c));
radiciEq(tmpV, (fRnd64.xoroshiro128xx()&1) ? 1.f : -1.f);
};
while(depth++<skipTop) { mainFunc(v,vp); v = vp; } // skip first "skipTop" points
preStep(v);
mainFunc(v,vp);
}
// stochastic adaptation of P.Nylander's Mathematica formula of quaternion Julia set
// http://bugman123.com/Hypercomplex/index.html
////////////////////////////////////////////////////////////////////////////
void glynnJB_IIM::Step(vec4 &v, vec4 &vp)
{
//Glynn roots: {x,y,z}^(1/1.5) = {x,y,z}^(2/3)
const vec3 p = vec3(v)-(vec3(kVal[0], kVal[1], kVal[2])+vec3(kRnd)); // ((vec3 &)*kVal.data()+(vec3)kRnd);
const float xQ = p.x * p.x, yQ = p.y * p.y, zQ = p.z * p.z;
const float r = sqrtf(xQ+yQ+zQ);
const uint32_t rnd = fastRandom.KISS();
const uint32_t rndR = fastRandom.KISS();
const int px = rnd&0x10;
const int py = rnd&0x20;
const int pz = rnd&0x40;
const int pw = rnd&0x80;
//const bool isCone = bool(zQ > xQ + yQ);
const int isCone = rnd&1;
/*
auto powN = [&] (vec3 &p, float n) -> vec3 {
const float theta = n * atan2f(p.x, p.y);
const float phi = n * asinf(p.z/r);
return pow(vec3(r), r*vec3(cosf(theta) * cosf(phi), sinf(theta) * cosf(phi), sinf(phi)));
};
*/
auto numRadici = [&] () -> int {
return (isCone) ? rndR%3 : (px ? rndR%2 : 0);
};
auto radiciEq = [&] (int k) {
const float n = kVal[3];
float ktheta, kphi;
const float uno = kVal[4], due = kVal[5], zeroCinque = kVal[6], dueCinque = kVal[7];
if(!k) { ktheta = kphi = 0.0; }
else {
if(isCone) { ktheta=(py ? due:uno); kphi=0.0; }
else {
if(k==1) {
if(pw) {ktheta=due; kphi=0.0;} else {ktheta=zeroCinque; kphi=(pz?zeroCinque:dueCinque);}
}
else {
if(pw) {ktheta=uno; kphi=0.0;} else {ktheta=dueCinque; kphi=(pz?zeroCinque:dueCinque);}
}
}
}
const float theta = (atan2f(p.y,p.x)+ ktheta * T_PI)/n;
const float phi = (asinf(p.z/(r == 0.f ? FLT_EPSILON : r)) + kphi * T_PI)/n;
const float cosphi = cosf(phi);
vp = vec4(powf(r,1.0f/n) * vec3(cosf(theta)*cosphi,sinf(theta)*cosphi,sinf(phi)), 0.f);
};
preStep(v);
int nRad = numRadici();
radiciEq( nRad);
}
/*
void glynnJB_IIM::Step(vec4 &v, vec4 &vp)
{
//Glynn roots: {x,y,z}^(1/1.5) = {x,y,z}^(2/3)
const vec3 p = vec3(v)-(vec3(kVal[0], kVal[1], kVal[2])+vec3(kRnd)); // ((vec3 &)*kVal.data()+(vec3)kRnd);
const float xQ = p.x * p.x, yQ = p.y * p.y, zQ = p.z * p.z;
const float r = sqrtf(xQ+yQ+zQ);
const bool isCone = bool(zQ > xQ + yQ);
auto powN = [&] (vec3 &p, float n) -> vec3 {
const float theta = n * atan2f(p.x, p.y);
const float phi = n * asinf(p.z/r);
return pow(vec3(r), r*vec3(cosf(theta) * cosf(phi), sinf(theta) * cosf(phi), sinf(phi)));
};
auto numRadici = [&] () -> int {
const uint32_t rnd = fastRandom.KISS();
return (isCone) ? rnd%3 : (p.x > 0 ? rnd%2 : 0);
};
auto radiciEq = [&] (int k) {
const float n = 1.5f;
const uint32_t rnd = fastRandom.KISS();
float ktheta, kphi;
if(!k) { ktheta = kphi = 0.0; }
else {
if(!isCone) { ktheta=(p.y<0 ? 2.0:1.0); kphi=0.0; }
else {
if(k==1) {
if(p.x<0 && p.y<0) {ktheta=2.0; kphi=0.0;} else {ktheta=0.5; kphi=(p.z>0?0.5:2.5);}
}
else {
if(p.x<0 && p.y>0) {ktheta=1.0; kphi=0.0;} else {ktheta=2.5; kphi=(p.z>0?0.5:2.5);}
}
}
}
const float theta = (atan2f(p.y,p.x)+ ktheta * T_PI)/n;
const float phi = (asinf(p.z/(r == 0.f ? FLT_EPSILON : r)) + kphi * T_PI)/n;
const float cosphi = cosf(phi);
vp = vec4(powf(r,1.0f/n) * vec3(cosf(theta)*cosphi,sinf(theta)*cosphi,sinf(phi)), 0.f);
};
preStep(v);
int nRad = numRadici();
const uint32_t rnd = fastRandom.KISS();
radiciEq( nRad);
}
*/
//------------------------------------------------------------------------------
// Copyright (c) 2018-2020 Michele Morrone
// All rights reserved.
//
// https://michelemorrone.eu - https://BrutPitt.com
//
// twitter: https://twitter.com/BrutPitt - github: https://github.com/BrutPitt
//
// mailto:brutpitt@gmail.com - mailto:me@michelemorrone.eu
//
// This software is distributed under the terms of the BSD 2-Clause license
//------------------------------------------------------------------------------
#pragma once
class fractalIIMBase : public attractorScalarK
{
public:
bool ifsActive() { return ifsParam.active() || ifsPoint.active(); }
ifsBaseClass *getIFSParam() { return &ifsParam; }
ifsBaseClass *getIFSPoint() { return &ifsPoint; }
vec4 getIFSvec4(ifsBaseClass &ifs) {
if(ifs.getCurrentTransform()<0) return vec4(ifs.getInitValue()); // no active transforms: neutral value
else {
ifsDataStruct *ifsStruct = ifs.getTransfStruct(ifs.getCurrentTransform());
return ifsStruct->variationFunc(ifsStruct->variations) * ifsStruct->variationFactor;
}
}
static fastXS64 fRnd64;
protected:
fractalIIMBase() {
vMin = 0.f; vMax = 0.f; kMin = 0.f; kMax = 0.f;
m_POV = vec3( 0.f, 0, 7.f);
setFractalType();
}
inline void refreshRandoms(vec4 &v) {
depth = 0;
v = vVal[0] + (vMin == vMax ? vec4(vMin) :
vec4(fRnd64.xoroshiro128p_Range(vMin, vMax),
fRnd64.xoroshiro128p_Range(vMin, vMax),
fRnd64.xoroshiro128p_Range(vMin, vMax),
0.f /*fRnd64.xoroshiro128p_Range(vMin, vMax)*/));
kRnd = kMin == kMax ? vec4(kMin) :
vec4(fRnd64.xoroshiro128p_Range(kMin, kMax),
fRnd64.xoroshiro128p_Range(kMin, kMax),
fRnd64.xoroshiro128p_Range(kMin, kMax),
0.f /*fRnd64.xoroshiro128p_Range(kMin, kMax)*/);
}
inline void preStep(vec4 &v) { if(depth++>maxDepth) refreshRandoms(v); }
// Specific attractor values
void saveAdditionalData(Config &cfg);
void loadAdditionalData(Config &cfg);
virtual void additionalDataCtrls();
void drawDepthSkipButtons();
vec4 kRnd = vec4(0.f);
vec4 vIter;
int maxDepth = 50;
int degreeN = 2;
int skipTop = 10;
int depth = 0;
ifsBaseClass ifsPoint = ifsBaseClass(1.f), ifsParam = ifsBaseClass(0.f);
private:
};
class fractalIIM_Nth : public fractalIIMBase
{
public:
// Specific attractor values
virtual void additionalDataCtrls();
protected:
};
class juliaBulb_IIM : public fractalIIMBase
{
public:
juliaBulb_IIM() { stepFn = (stepPtrFn) &juliaBulb_IIM::Step; }
protected:
void Step(vec4 &v, vec4 &vp);
void startData();
};
class juliaBulb4th_IIM : public fractalIIM_Nth
{
public:
juliaBulb4th_IIM() { stepFn = (stepPtrFn) &juliaBulb4th_IIM::Step; }
protected:
void Step(vec4 &v, vec4 &vp);
void startData();
};
class fractalIIM_4D : public fractalIIMBase
{
public:
//void preStep(vec4 &v, vec4 &vp) { last4D = RANDOM(vMin, vMax); fractalIIMBase::preStep(v,vp); }
int getPtSize() { return attPt4D; }
virtual void initStep() {
attractorScalarK::initStep();
}
protected:
};
class BicomplexBase : public fractalIIM_4D
{
public:
typedef void (BicomplexBase::*magneticPtrFn)(const vec4 &, int);
void startData();
inline void radiciBicomplex(const vec4 &pt, vec4 &vp)
{
//static fastXS64_mt fff;
//fff.jump_xoroshiro128p();
const uint32_t rnd = fRnd64.xoroshiro128p();
const float sign1 = (rnd&2) ? 1.f : -1.f, sign2 = (rnd&1) ? 1.f : -1.f;
const vec4 c = ifsParam.active() ? kRnd+getIFSvec4(ifsParam) : kRnd; // IFS param transforms
const vec4 p(pt - ((vec4 &)*kVal.data()+c));
const std::complex<float> z1(p.x, p.y), z2(-p.w, p.z);
const std::complex<float> w1 = sign1 * sqrt(z1 - z2), w2 = sign2 *sqrt(z1 + z2);
vp = vec4(w1.real()+w2.real(), w1.imag()+w2.imag(), w2.imag()-w1.imag(), w1.real()-w2.real())*.5f;
if(ifsPoint.active()) vp *= getIFSvec4(ifsPoint); // IFS point transforms
};
inline void mainFunc(vec4 &v, const vec4 &vMod, vec4 &vp) {
while(depth++<skipTop) {
radiciBicomplex(vMod,vp);
v = vp;
}
preStep(v);
radiciBicomplex(vMod,vp);
}
};
/////////////////////////////////////////////////
class BicomplexJ_IIM : public BicomplexBase
{
public:
BicomplexJ_IIM() { stepFn = (stepPtrFn) &BicomplexJ_IIM::Step; }
protected:
//void Step(vec4 &v, vec4 &vp) { preStep(v); radiciBicomplex(vec4(v, last4D), vp); } //remove
void Step(vec4 &v, vec4 &vp) { mainFunc(v, v, vp); }
};
/////////////////////////////////////////////////
class BicomplexJMod0_IIM : public BicomplexBase
{
public:
BicomplexJMod0_IIM() { stepFn = (stepPtrFn) &BicomplexJMod0_IIM::Step; }
protected:
//void Step(vec4 &v, vec4 &vp) { preStep(v); radiciBicomplex(vec4(v, dim4D), vp); } remove
void Step(vec4 &v, vec4 &vp) { mainFunc(v, vec4((vec3)v, vVal[0].w), vp); }
};
/////////////////////////////////////////////////
class BicomplexJMod1_IIM : public BicomplexBase
{
public:
BicomplexJMod1_IIM() { stepFn = (stepPtrFn) &BicomplexJMod1_IIM::Step; }
protected:
//void Step(vec4 &v, vec4 &vp) { preStep(v); radiciBicomplex(vec4(v.x, v.y, vVal[0].z, last4D), vp); } remove
void Step(vec4 &v, vec4 &vp) { mainFunc(v, vec4(v.x, v.y, vVal[0].z, v.w), vp); }
};
/////////////////////////////////////////////////
class BicomplexJMod2_IIM : public BicomplexBase
{
public:
BicomplexJMod2_IIM() { stepFn = (stepPtrFn) &BicomplexJMod2_IIM::Step; }
protected:
//void Step(vec4 &v, vec4 &vp) { preStep(v,vp); radiciBicomplex(vec4(last4D, v.x, v.z, v.x), vp); }
//void Step(vec4 &v, vec4 &vp) { preStep(v,vp); radiciBicomplex(vec4(v.y, v.z, last4D, v.x), vp); }
//void Step(vec4 &v, vec4 &vp) { preStep(v,vp); radiciBicomplex(vec4(v.x, v.y, v.y, v.y), vp); }
//void Step(vec4 &v, vec4 &vp) { preStep(v); radiciBicomplex(vec4(v.x, v.y, v.z, v.y), vp); } remove
void Step(vec4 &v, vec4 &vp) { mainFunc(v, vec4(v.x, v.y, v.z, v.y), vp); }
};
/////////////////////////////////////////////////
class BicomplexJMod3_IIM : public BicomplexBase
{
public:
BicomplexJMod3_IIM() { stepFn = (stepPtrFn) &BicomplexJMod3_IIM::Step; }
protected:
void Step(vec4 &v, vec4 &vp) { mainFunc(v, vec4(vVal[0].x, v.y, v.z, v.w), vp); }
};
/////////////////////////////////////////////////
class BicomplexJMod4_IIM : public BicomplexBase
{
public:
BicomplexJMod4_IIM() { stepFn = (stepPtrFn) &BicomplexJMod4_IIM::Step; }
protected:
void Step(vec4 &v, vec4 &vp) { mainFunc(v, vec4(v.x, v.y, v.x, v.w), vp); }
};
/////////////////////////////////////////////////
class BicomplexJMod5_IIM : public BicomplexBase
{
public:
BicomplexJMod5_IIM() { stepFn = (stepPtrFn) &BicomplexJMod5_IIM::Step; }
protected:
void Step(vec4 &v, vec4 &vp) { mainFunc(v, vec4( v.y, v.x, v.w, v.z), vp); }
};
/////////////////////////////////////////////////
class BicomplexJMod6_IIM : public BicomplexBase
{
public:
BicomplexJMod6_IIM() { stepFn = (stepPtrFn) &BicomplexJMod6_IIM::Step; }
protected:
void Step(vec4 &v, vec4 &vp) { mainFunc(v, vec4(vVal[0].x, vVal[0].y, v.z, v.w), vp); }
};
/////////////////////////////////////////////////
class BicomplexJMod7_IIM : public BicomplexBase
{
public:
BicomplexJMod7_IIM() { stepFn = (stepPtrFn) &BicomplexJMod7_IIM::Step; }
protected:
//void Step(vec4 &v, vec4 &vp) { radiciBicomplex(vec4( v.x, v.x, v.z, v.x), vp); }
void Step(vec4 &v, vec4 &vp) { mainFunc(v, vec4( v.x, v.x, v.z, vVal[0].w), vp); }
//void Step(vec4 &v, vec4 &vp) { radiciBicomplex(vec4( v.x, v.x, v.z, last4D), vp); }
};
/////////////////////////////////////////////////
class BicomplexJExplorer : public BicomplexBase
{
public:
BicomplexJExplorer() {
stepFn = (stepPtrFn) &BicomplexJExplorer::Step;
}
void saveAdditionalData(Config &cfg);
void loadAdditionalData(Config &cfg);
void additionalDataCtrls();
void initStep() {
//fractalIIMBase::initStep();
resetQueue();
Insert(vVal[0]);
//stabilize(STABILIZE_DIM);
a1[0] = a2[0] = a3[0] = a4[0] = &vVal[0].x;
a1[1] = a2[1] = a3[1] = a4[1] = &vVal[0].y;
a1[2] = a2[2] = a3[2] = a4[2] = &vVal[0].z;
a1[3] = a2[3] = a3[3] = a4[3] = &vVal[0].w;
a1[4] = a2[4] = a3[4] = a4[4] = &vt.x;
a1[5] = a2[5] = a3[5] = a4[5] = &vt.y;
a1[6] = a2[6] = a3[6] = a4[6] = &vt.z;
a1[7] = a2[7] = a3[7] = a4[7] = &vt.w;
}
protected:
void Step(vec4 &v, vec4 &vp) {
while(depth++<skipTop) {
vt = v;
radiciBicomplex(vec4( *a1[idx0], *a2[idx1], *a3[idx2], *a4[idx3]), vp);
v = vp;
}
preStep(v);
vt = v;
radiciBicomplex(vec4( *a1[idx0], *a2[idx1], *a3[idx2], *a4[idx3]), vp);
}
private:
float *a1[8], *a2[8], *a3[8], *a4[8];
int idx0 = 4, idx1 = 5, idx2 = 6, idx3 = 7 ;
const char str[8][4] { "s.X", "s.Y", "s.Z", "s.W", "i.X", "i.Y", "i.Z", "i.W" };
vec4 vt;
};
/////////////////////////////////////////////////
class quatJulia_IIM : public fractalIIM_4D
{
public:
quatJulia_IIM() { stepFn = (stepPtrFn) &quatJulia_IIM::Step; }
protected:
void Step(vec4 &v, vec4 &vp);
void startData();
};
class glynnJB_IIM : public fractalIIMBase
{
public:
glynnJB_IIM() { stepFn = (stepPtrFn) &glynnJB_IIM::Step; }
protected:
void Step(vec4 &v, vec4 &vp);
void startData();
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment