Skip to content

Commit

Permalink
OpenP5Caustics: First version!
Browse files Browse the repository at this point in the history
  • Loading branch information
prisonerjohn committed Nov 13, 2013
1 parent 8c7385a commit 6ce27e9
Show file tree
Hide file tree
Showing 15 changed files with 2,893 additions and 0 deletions.
128 changes: 128 additions & 0 deletions CloudsLibrary/src/VisualSystems/OpenP5Caustics/vs_src/CastManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//
// CastManager.cpp
// OpenP5Caustics
//
// Created by Elie Zananiri on 11/13/2013.
//
//

#include "CastManager.h"

//--------------------------------------------------------------
//--------------------------------------------------------------
CastManager::CastManager(int width, int height)
{
this->width = width;
this->height = height;

cR = new Caster(width, height);
cG = new Caster(width, height);
cB = new Caster(width, height);

bump = 0.5;
noiseScale = 0.008;
boxW = 300;
boxH = 300;
z = 0;
bReset = false;
bReseed = false;
loopCount;
fpsGranularity = 10000;
algo = kCastAlgoSpiral;
}

//--------------------------------------------------------------
//--------------------------------------------------------------
CastManager::~CastManager()
{
delete cR;
delete cG;
delete cB;
}

//--------------------------------------------------------------
//--------------------------------------------------------------
void CastManager::threadedFunction()
{
long timeStart = ofGetElapsedTimeMillis();

float r = 10;
float t = 0;
int rDir = 1;

while (true) {
if (loopCount % fpsGranularity == 0) {
long delta = ofGetElapsedTimeMillis() - timeStart;
if (delta != 0) {
fps = fpsGranularity*1000.f / delta;
}
timeStart = ofGetElapsedTimeMillis();
}

if (bReseed) {
ofSeedRandom(ofGetElapsedTimeMillis());
bReseed = false;
}

if (bReset) {
cR->reset();
cG->reset();
cB->reset();
bReset = false;
}

float x, y;
switch (algo) {
case kCastAlgoRandom:
x = ofRandom(boxW) + width / 2 - boxW / 2;
y = ofRandom(boxH) + height / 2 - boxH / 2;
break;

case kCastAlgoSpiral:
case kCastAlgoSpiralClear:
r = (r + 0.0001f * rDir);
if (ABS(r) > boxW / 2) {
rDir *= -1;
}
t = fmodf(t + 0.001f, TWO_PI);
x = r * cosf(t) + width / 2;
y = r * sinf(t) + height / 2;
break;

default:
x = 0; y = 0;
ofLogError("CastManager::threadedFunction()") << "Unknown algo: " << algo;
}

// Calculation of gradient.
float dzdx = (ofNoise(x * noiseScale + noiseScale, y * noiseScale, z * noiseScale) - ofNoise(x * noiseScale - noiseScale, y * noiseScale, z * noiseScale)) * bump / (noiseScale * 2);
float dzdy = (ofNoise(x * noiseScale, y * noiseScale + noiseScale, z * noiseScale) - ofNoise(x * noiseScale, y * noiseScale - noiseScale, z * noiseScale)) * bump / (noiseScale * 2);

// More accurate calculation of gradient.
//float dzdx = (ofNoise(x * noiseScale - 2 * noiseScale, y * noiseScale, z * noiseScale) * -0.5
// + ofNoise(x * noiseScale - noiseScale, y * noiseScale, z * noiseScale) * -1
// + ofNoise(x * noiseScale + noiseScale, y * noiseScale, z * noiseScale) * 1
// + ofNoise(x * noiseScale + 2 * noiseScale, y * noiseScale, z * noiseScale) * 0.5) * bump / (noiseScale * 2);

//float dzdy = (ofNoise(x * noiseScale, y * noiseScale - 2 * noiseScale, z * noiseScale) * -0.5
// + ofNoise(x * noiseScale, y * noiseScale - noiseScale, z * noiseScale) * -1
// + ofNoise(x * noiseScale, y * noiseScale + noiseScale, z * noiseScale) * 1
// + ofNoise(x * noiseScale, y * noiseScale + 2 * noiseScale, z * noiseScale) * 0.5) * bump / (noiseScale * 2);

float m = ofVec3f(dzdx, dzdy, 1).length();

// Normal to surface.
float nX = dzdx / m;
float nY = dzdy / m;
float nZ = 1 / m;

float thetaI = acosf(nZ);

cR->cast(x, y, nX, nY, nZ, thetaI);
cG->cast(x, y, nX, nY, nZ, thetaI);
cB->cast(x, y, nX, nY, nZ, thetaI);

loopCount++;
// ofSleepMillis(20);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// CastManager.h
// OpenP5Caustics
//
// Created by Elie Zananiri on 11/13/2013.
//
//

#pragma once

#include "ofMain.h"
#include "Caster.h"

const int kCastAlgoRandom = 0;
const int kCastAlgoSpiral = 1;
const int kCastAlgoSpiralClear = 2;
const int kCastAlgoCount = 3;

//--------------------------------------------------------------
//--------------------------------------------------------------
class CastManager : public ofThread
{
public:
CastManager(int width, int height);
~CastManager();

void cycleAlgo() { algo = (algo + 1) % kCastAlgoCount; };
void start() { startThread(false, false); }
void stop() { stopThread(); }
void reset() { bReset = true; }
void reseed() { bReseed = true; }

void threadedFunction();

int algo;

int width, height;
Caster * cR, * cG, * cB;

float bump; // height of bump
float noiseScale;
float boxW;
float boxH;
float z;
bool bReset;
bool bReseed;
long loopCount;
int fpsGranularity;
float fps;
};
105 changes: 105 additions & 0 deletions CloudsLibrary/src/VisualSystems/OpenP5Caustics/vs_src/Caster.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//
// Caster.cpp
// OpenP5Caustics
//
// Created by Elie Zananiri on 11/13/2013.
//
//

#include "Caster.h"

//--------------------------------------------------------------
Caster::Caster(int width, int height)
{
this->width = width;
this->height = height;
count = width * height;

bg = new float[width * height];

n = 1.3f;
d = 100;
intensity = 1;

bReset = false;
}

//--------------------------------------------------------------
Caster::~Caster()
{
delete [] bg;
}

//--------------------------------------------------------------
void Caster::reset()
{
for (int i = 0; i < count; i++) {
bg[i] = 0;
}
}

//--------------------------------------------------------------
void Caster::cast(float x, float y, float nX, float nY, float nZ, float thetaI)
{
// The angle of the refracted ray relative to the incident ray.
float thetaR = asin(n*sin(thetaI));

// Refracted vector.
float rX = -nX;
float rY = -nY;
float rZ;
if (rX == 0 && rY == 0) {
rZ = -1;
}
else {
rZ = -abs(sqrt(rX*rX+rY*rY)/sin(thetaI+PI-thetaR));
}
//float rZ = -sqrt(rX*rX + rY*rY)/sq(sin(thetaI+PI-thetaR));
if (rZ > 0) {
ofLogError("Caster::cast") << "Refracted Z must be always negative, was " << rZ;
return;
}

// How much we need to scale the refracted vector to hit the back wall.
float s = d / rZ;

// Coordinates where the vector hits the back wall.
float hX = x + s * rX;
float hY = y + s * rY;

if (hX > 0 && hX < width && hY > 0 && hY < height) {
// Integer of closest pixel to the point of impact.
int flX = round(hX);
int flY = round(hY);

int index = flY * width + flX;
if (index < count && index >= 0) {
bg[index] += intensity * (1 - ABS(flX - hX)) * (1 - ABS(flY - hY));
}

// Right neighbour.
index++;
if(flX < hX && index < count && index >= 0) {
bg[index] += intensity * (hX-flX) * abs(flY-hY);
}

// Left neighbour.
index -= 2;
if(flX > hX && index < count && index >= 0) {
bg[index] += intensity * (flX-hX) * abs(flY - hY);
}

// Top neighbour.
index++;
index -= width;
if (flY > hY && index < count && index >= 0) {
bg[index] += intensity * (flY-hY) * abs(flX - hX);
}

// Bottom neighbour.
index += 2 * width;
if (flY < hY && index < count && index >= 0) {
bg[index] += intensity * (hY - flY) * abs(flX - hX);
}
}
}
34 changes: 34 additions & 0 deletions CloudsLibrary/src/VisualSystems/OpenP5Caustics/vs_src/Caster.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Caster.h
// OpenP5Caustics
//
// Created by Elie Zananiri on 11/13/2013.
//
//

#pragma once

#include "ofMain.h"

//--------------------------------------------------------------
//--------------------------------------------------------------
class Caster
{
public:
Caster(int width, int height);
~Caster();

void reset();
void cast(float x, float y, float nX, float nY, float nZ, float thetaI);

float * bg;
int count;
int width, height;

float n; // Index of refraction
float d; // Distance to back wall
float intensity;

bool bReset;
long loopCount;
};
Loading

0 comments on commit 6ce27e9

Please sign in to comment.