Help!
I'm drawing a sketch with randomized letters that fill the screen. The code issue is with my
for (int i = 0; i < I1; i++) {
targets = tX + i * ts;
targets2 = tY;
} else {
runTowards = false;
for (int i = 0; i < I1; i++) {
targets = random(ts, width - ts);
targets2 = random(ts, height - ts);`
** I need to update i within the for loop to denote the array letters' locations. The error returns a type mismatch, "float" does not match with int[]
How do I update the i within the for loop?/ (the targets= and targets2=)
Here is the code**
String message = "a,b,c,d,e,f";
int []positions = new int [0];
int[]positions2= new int[1];
int []targets = new int [0] ;
int [] targets2= new int[1];
int I1= message.length();
boolean runTowards = true;
float runSpeed = 100;
float restSpeed = 1;
float currentSpeed = restSpeed;
float ts = 64;
boolean thisHasReached;
float bk;
float elapsedTime;
boolean allHaveReached;
float pauseTime = 1000;
float distX;
float distY;
float changeX;
float changeY;
float tX;
float tY;
float reachedTargetAt = 0;
boolean hasReachedTarget = true;
void setup() {
size (600,600);
background(255);
if ((I1 > targets.length) && (I1 > positions.length)){
pickNewTarget();
}
}
void draw() {
elapsedTime = millis() - reachedTargetAt;
if (elapsedTime > pauseTime) {
pickNewTarget();
}
drawChars();
updatePositions();
updateCurrentSpeed();
}
void drawChars() {
for (int i = 0; i < I1; i++) {
text(message.charAt(i),positions[i], positions[i]);
}
}
void updatePositions() {
allHaveReached = true;
thisHasReached = false;
for (int i = 0; i < I1; i++) {
distX = abs(positions[i] - targets[i]);
distY = abs(positions2[i] - targets2[i]);
changeX = random(currentSpeed);
changeY = random(currentSpeed);
thisHasReached = changeX > distX && changeY > distY;
if (positions[i] > targets[i]) {
changeX = -changeX;
}
if (positions2[i] > targets2[i]) {
changeY = -changeY;
}
positions[i] += changeX;
positions2[i] += changeY;
allHaveReached = allHaveReached && thisHasReached;
}
if ((!hasReachedTarget) && (allHaveReached)) {
hasReachedTarget = true;
reachedTargetAt = millis();
}
}
void updateCurrentSpeed() {
if (hasReachedTarget) {
if (currentSpeed >= restSpeed) {
currentSpeed -= (currentSpeed - restSpeed) * 9;
} else {
currentSpeed += 1;
}
} else {
if (currentSpeed <= runSpeed) {
currentSpeed += (runSpeed - currentSpeed) * 0.25;
} else {
currentSpeed -= 1;
}
}
}
void pickNewTarget() {
if (!runTowards && random(1) > 0.75) {
runTowards = true;
tX = random(ts, width - 3 * ts);
tY = random(ts, height - ts);
for (int i = 0; i < I1; i++) {
targets = tX + i * ts;
targets2 = tY;
}
} else {
runTowards = false;
for (int i = 0; i < I1; i++) {
targets = random(ts, width - ts);
targets2 = random(ts, height - ts);
}
}
hasReachedTarget = false;
}
Please look at this reference for random(): https://processing.org/reference/random_.html. Note that it states "If two parameters are specified, the function will return a float with a value between the two values." You got the error message because you tried to mix ints and floats. You can correct it by changing the array types from int to float, eg.
float[] targets = new float[80] ;
float[] targets2= new float[80];
You'll also need to make those arrays large enough to handle the size of your data or you'll wind up with another error that the array length has been overrun. Then change the loop to reflect that you are adding data to the arrays ([i]):
void pickNewTarget() {
if (!runTowards && random(1) > 0.75) {
runTowards = true;
tX = random(ts, width - 3 * ts);
tY = random(ts, height - ts);
for (int i = 0; i < I1; i++) {
targets[i] = tX + i * ts;
targets2[i] = tY;
}
} else {
runTowards = false;
for (int i = 0; i < I1; i++) {
targets[i] = random(ts, width - ts);
targets2[i] = random(ts, height - ts);
}
}
hasReachedTarget = false;
}
Also need to add a fill() for the text characters or you will see a blank screen.
I'm writing a mosaic ffmpeg filter.
copy code from vf_vflip.c, I register a callback function get_video_buffer
and implement it as follows:
static AVFrame *get_video_buffer(AVFilterLink *link, int w, int h)
{
MosaicContext *s = link->dst->priv;
AVFrame *frame;
int i;
int j,k;
frame = ff_get_video_buffer(link->dst->outputs[0], w, h);
if (!frame)
return NULL;
if (s->w == 0 || s->h == 0)
return frame;
for (i = 0; i < 3; i ++) {
// some trick code
}
return frame;
}
static const AVFilterPad avfilter_vf_mosaic_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
//.get_video_buffer = get_video_buffer,
.filter_frame = filter_frame,
.config_props = config_input,
},
{ NULL }
};
But after read some filter dev guide, I found that only a few filter implement get_video_buffer funcition.The default function is f_default_get_video_buffer()
I make some log find that ffmpeg call function like
get_video_buffer
filter_frame
get_video_buffer
filter_frame
get_video_buffer
filter_frame
...
I'm confused about get_video_buffer do what job.
Only know that some filter will hold frame cache.
Can I juse comment out the get_video_buffer hook?
I see flip job both in get_video_buffer() and filter_frame() in vf_vflip.c
Is it a waste of time?
static AVFrame *get_video_buffer(AVFilterLink *link, int w, int h)
{
FlipContext *flip = link->dst->priv;
AVFrame *frame;
int i;
frame = ff_get_video_buffer(link->dst->outputs[0], w, h);
if (!frame)
return NULL;
for (i = 0; i < 4; i ++) {
int vsub = i == 1 || i == 2 ? flip->vsub : 0;
int height = AV_CEIL_RSHIFT(h, vsub);
if (frame->data[i]) {
frame->data[i] += (height - 1) * frame->linesize[i];
frame->linesize[i] = -frame->linesize[i];
}
}
return frame;
}
static int filter_frame(AVFilterLink *link, AVFrame *frame)
{
FlipContext *flip = link->dst->priv;
int i;
for (i = 0; i < 4; i ++) {
int vsub = i == 1 || i == 2 ? flip->vsub : 0;
int height = AV_CEIL_RSHIFT(link->h, vsub);
if (frame->data[i]) {
frame->data[i] += (height - 1) * frame->linesize[i];
frame->linesize[i] = -frame->linesize[i];
}
}
return ff_filter_frame(link->dst->outputs[0], frame);
}
I've added a background image to my processing file which works fine when I run it in Processing locally, however, I'm receiving this error in console when I host the file:
Uncaught Error using image in background(): PImage not loaded.
I can't find anywhere why this may be happening. Please see my code below:
Particle p = new Particle();
final int LIGHT_FORCE_RATIO = 70; final int LIGHT_DISTANCE= 70 * 50; final int BORDER = 100; float baseRed, baseGreen, baseBlue; float baseRedAdd, baseGreenAdd, baseBlueAdd; final float RED_ADD =
3.2; final float GREEN_ADD = 1.7; final float BLUE_ADD = 4.3; float boxX, boxY; float widthSize = width;
int rectWidth = 915; int rectHeight = 197;
PImage img;
void setup() { img = loadImage("https://s3.amazonaws.com/zcom-media/sites/a0iE000000QK9yZIAT/media/mediamanager/bannerbg.jpg");
background(img); size(1840, 400); // surface.setResizable(true); noCursor(); //img = loadImage("flowtoy.jpg"); baseRed = 0; baseRedAdd = RED_ADD;
baseGreen = 0; baseGreenAdd = GREEN_ADD;
baseBlue = 0; baseBlueAdd = BLUE_ADD;
boxX = width/2; boxY = height/2;
img.loadPixels(); for (int i = 0; i < img.pixels.length; i++) { img.pixels[i] = color(0, 90, 102); } img.updatePixels(); }
void draw() { //image(img, 400, 100, img.width/2, img.height/2); if (mouseX>boxX-rectWidth && mouseX<boxX+rectWidth &&
mouseY>boxY-rectHeight && mouseY<boxY+rectHeight) {
//saveFrame("output/LightDrawing_####.png");
baseRed += baseRedAdd;
baseGreen += baseGreenAdd;
baseBlue += baseBlueAdd;
colorOutCheck();
p.move(mouseX, mouseY);
int tRed = (int)baseRed;
int tGreen = (int)baseGreen;
int tBlue = (int)baseBlue;
tRed *= tRed;
tGreen *= tGreen;
tBlue *= tBlue;
loadPixels();
int left = max(0, p.x - BORDER);
int right = min(width, p.x + BORDER);
int top = max(0, p.y - BORDER);
int bottom = min(height, p.y + BORDER);
for (int y = top; y < bottom; y++) {
for (int x = left; x < right; x++) {
int pixelIndex = x + y * width;
int r = pixels[pixelIndex] >>16 & 0xFF;
int g = pixels[pixelIndex] >> 8 & 0xFF;
int b = pixels[pixelIndex] & 0xFF;
int dx = x - p.x;
int dy = y - p.y;
int distance = (dx *dx ) + (dy* dy);
if (distance < LIGHT_DISTANCE) {
int fixFistance = distance * LIGHT_FORCE_RATIO;
if (fixFistance == 0) {
fixFistance = 1;
}
r = r + tRed / fixFistance;
g = g + tGreen / fixFistance;
b = b + tBlue / fixFistance;
}
pixels[x + y * width] = color(r, g, b);
}
}
updatePixels(); } else {
setup(); }
//updatePixels(); }
void colorOutCheck() { if (baseRed < 10) {
baseRed = 10;
baseRedAdd *= -1; } else if (baseRed > 255) {
baseRed = 255;
baseRedAdd *= -1; }
if (baseGreen < 10) {
baseGreen = 10;
baseGreenAdd *= -1; } else if (baseGreen > 255) {
baseGreen = 255;
baseGreenAdd *= -1; }
if (baseBlue < 10) {
baseBlue = 10;
baseBlueAdd *= -1; } else if (baseBlue > 255) {
baseBlue = 255;
baseBlueAdd *= -1; } }
void mousePressed() { setup(); }
class Particle { int x, y; float vx, vy; //float slowLevel;
Particle() {
x = (int)3;
y = (int)2; // slowLevel = random(100) + 1; }
void move(float targetX, float targetY) {
vx = (targetX - x) ;
vy = (targetY - y) ;
x = (int)(x + vx);
y = (int)(y + vy); } }
Can anybody explain why this may be happening? It's much appreciated, thank you.
I assume by 'hosting the file' you mean running the sketch at www.openprocessing.org.
There are two problem with your code:
Using background() inside setup. This will not work, you will get the error you mentioned. You can try moving that to draw().
Using an image which is hosted in another server. You should host your own images.
A workaround to problem 2 is to store the image as a base64 encoded string.
String uriBase64 = "data:image/jpeg;base64,/9j/4AAQSkZJRgA";
img = loadImage(uriBase64);
Full example here: https://www.openprocessing.org/sketch/511424
Hope everyone is well.I am having a bit of an issue implementing the kd tree from pbrt v2.It's fast but all the normals on the model are wrong after rendering.The funny thing is if I change the values of pMin and pMax in the Bounding Box constructor,I get the correct model with the correct normals but the render takes substantially longer.I dont know what could be causing this.By the way pbrt v2 uses a left-handed coordinate system while I am using a right-handed coordinate system.I have tried changing my coordinate to left-handed and also importing models from a left-handed system instead of a right-handed system but the issue still remains.At one point it worked but the models positions were reversed.Its best to show you my code so u can better understand my dilemma.
*BOUNDING BOX CODE *
class BBox
{
public:
Point pMin,pMax;
BBox(){
pMin = Point(INFINITY,INFINITY,INFINITY);
pMax = Point(-INFINITY,-INFINITY,-INFINITY);
}
BBox(const Point& p) : pMin(p),pMax(p) { }
BBox(const Point& p1,const Point& p2) {
pMin = Point(min(p1.x,p2.x),min(p1.y,p2.y),min(p1.z,p2.z));
pMax = Point(max(p1.x,p2.x),max(p1.y,p2.y),max(p1.z,p2.z));
}
Point boxCentroid() const {
float x = (pMin.x+pMax.x)/2;
float y = (pMin.y+pMax.y)/2;
float z = (pMin.z+pMax.z)/2;
return Point(x,y,z);
}
BBox Union(const BBox &b,const Point& p) {
BBox ret = b;
ret.pMin.x = min(b.pMin.x,p.x);
ret.pMin.y = min(b.pMin.y,p.y);
ret.pMin.z = min(b.pMin.z,p.z);
ret.pMax.x = max(b.pMax.x,p.x);
ret.pMax.y = max(b.pMax.y,p.y);
ret.pMax.z = max(b.pMax.z,p.z);
return ret;
}
friend BBox Union(const BBox& b,const BBox& b2){
BBox ret;
ret.pMin.x = min(b.pMin.x, b2.pMin.x);
ret.pMin.y = min(b.pMin.y, b2.pMin.y);
ret.pMin.z = min(b.pMin.z, b2.pMin.z);
ret.pMax.x = max(b.pMax.x, b2.pMax.x);
ret.pMax.y = max(b.pMax.y, b2.pMax.y);
ret.pMax.z = max(b.pMax.z, b2.pMax.z);
return ret;
}
bool Overlaps(const BBox &b) const {
bool x = (pMax.x >= b.pMin.x) && (pMin.x <= b.pMax.x);
bool y = (pMax.y >= b.pMin.y) && (pMin.y <= b.pMax.y);
bool z = (pMax.z >= b.pMin.z) && (pMin.z <= b.pMax.z);
return (x && y && z);
}
bool Inside(const Point& pt) const {
return (pt.x >= pMin.x && pt.x <= pMax.x &&
pt.y >= pMin.y && pt.y <= pMax.y &&
pt.z >= pMin.z && pt.z <= pMax.z);
}
void Expand(float delta) {
pMin -= Vector(delta,delta,delta);
pMax += Vector(delta,delta,delta);
}
float SurfaceArea() const {
Vector d = pMax - pMin;
return 2.f * (d.x*d.y + d.x*d.z + d.y*d.z);
}
float Volume() const {
Vector d = pMax - pMin;
return d.x*d.y*d.z;
}
int MaximumExtent() const {
Vector diag = pMax - pMin;
if (diag.x > diag.y && diag.x > diag.z)
return 0;
else if (diag.y > diag.z)
return 1;
else
return 2;
}
const Point &operator[](int i) const {
//Assert(i == 0 || i == 1);
return (&pMin)[i];
}
Point &operator[](int i) {
//Assert(i == 0 || i == 1);
return (&pMin)[i];
}
Point Lerp(float tx, float ty, float tz) const {
return Point(::Lerp(tx, pMin.x, pMax.x), ::Lerp(ty, pMin.y, pMax.y),
::Lerp(tz, pMin.z, pMax.z));
}
Vector Offset(const Point &p) const {
return Vector((p.x - pMin.x) / (pMax.x - pMin.x),
(p.y - pMin.y) / (pMax.y - pMin.y),
(p.z - pMin.z) / (pMax.z - pMin.z));
}
void BBox::BoundingSphere(Point *c, float *rad) const {
*c = pMin * 0.5f + pMax * 0.5f;
*rad = Inside(*c) ? Distance(*c, pMax) : 0.f;
}
bool IntersectP(const Ray &ray,float *hitt0,float *hitt1) const {
float t0 = 0.00001f, t1 = INFINITY;
for (int i = 0; i < 3; ++i) {
// Update interval for _i_th bounding box slab
float invRayDir = 1.f / ray.d[i];
float tNear = (pMin[i] - ray.o[i]) * invRayDir;
float tFar = (pMax[i] - ray.o[i]) * invRayDir;
// Update parametric interval from slab intersection $t$s
if (tNear > tFar) swap(tNear, tFar);
t0 = tNear > t0 ? tNear : t0;
t1 = tFar < t1 ? tFar : t1;
if (t0 > t1) return false;
}
if (hitt0) *hitt0 = t0;
if (hitt1) *hitt1 = t1;
return true;
}
};
If I use the current default BBox constructor with the above pMin and pMax values.I get this
But if I change it to
pMin = Point(-INFINITY,-INFINITY,-INFINITY);
pMax = Point(INFINITY,INFINITY,INFINITY);
I get the right model.This...
But it takes substantially longer.(7secs to 51 minutes) You see the issue ??? Anyways I need help.Any help is appreciated.Thanks
Here is the rest of the necessary code (KD-TREE) and (CAMERA)
*KD TREE CODE *
struct BoundEdge
{
//BoundEdge Methods
BoundEdge() { }
BoundEdge(float tt,int pn,bool starting){
t = tt;
primNum = pn;
type = starting ? START : END;
}
bool operator<(const BoundEdge &e) const {
if (t == e.t)
return (int)type < (int)e.type;
else return t < e.t;
}
float t;
int primNum;
enum { START,END } type;
};
struct KdAccelNode
{
void initLeaf(uint32_t *primNums,int np,MemoryArena &arena);
void initInterior(uint32_t axis,uint32_t ac,float s)
{
split = s;
flags = axis;
aboveChild |= (ac<<2);
}
float SplitPos() const { return split; }
uint32_t nPrimitives() const { return nPrims >> 2; }
uint32_t SplitAxis() const { return flags & 3; }
bool isLeaf() const { return (flags & 3)==3; }
uint32_t AboveChild() const { return aboveChild >> 2; }
union{
float split;
uint32_t onePrimitive;
uint32_t *primitives;
};
private:
union{
uint32_t flags;
uint32_t nPrims;
uint32_t aboveChild;
};
};
struct KdToDo{
const KdAccelNode *node;
float tMIN,tMAX;
};
class KdTreeAccel : public Primitive
{
public:
KdTreeAccel(const vector<Primitive*> &p,int icost,int tcost,float ebonus,int maxp,int md)
:primitives(p),isectCost(icost),traversalCost(tcost),emptyBonus(ebonus),maxPrims(maxp),maxDepth(md)
{
//Build Kd-Tree
nextFreeNode = nAllocedNodes = 0;
if(maxDepth <= 0)
maxDepth = Round2Int(8+1.3f * Log2Int(float(primitives.size())));
//<Compute Bounds>
vector<BBox> primBounds;
primBounds.reserve(primitives.size());
for(uint32_t i=0;i<primitives.size();++i)
{
BBox b = primitives[i]->BoxBound();
bounds = Union(bounds,b);
primBounds.push_back(b);
}
//<Allocate Working Memory>
BoundEdge *edges[3];
for(int i=0;i<3;++i)
edges[i] = new BoundEdge[2*primitives.size()];
uint32_t *prims0 = new uint32_t[primitives.size()];
uint32_t *prims1 = new uint32_t[(maxDepth+1) * primitives.size()];
//<Initialize primNums
uint32_t *primNums = new uint32_t[primitives.size()];
for(uint32_t i=0;i<primitives.size();++i)
primNums[i] = i;
//<Start Recursive Construction
buildTree(0,bounds,primBounds,primNums,primitives.size(),maxDepth,edges,prims0,prims1);
//<Free Memory
delete[] primNums;
for (int i = 0; i < 3; ++i)
delete[] edges[i];
delete[] prims0;
delete[] prims1;
}
virtual bool intersect(const Ray& r,float t_min,float t_max,primitive_record &rec) const;
virtual bool intersect_p(const Ray& r,float t_min,float t_max) const;
virtual float area() const;
virtual Vector _normal(const Point& in_point) const;
virtual Point randomSamplePoint() const;
virtual BBox BoxBound() const ;
virtual Point centroid() const ;
private:
void buildTree(int nodeNum,const BBox &nodeBounds,const vector<BBox> &allPrimBounds,uint32_t *primNums,
int nPrimitives,int depth,BoundEdge *edges[3],uint32_t *prims0,uint32_t *prims1,
int badRefines=0);
int isectCost,traversalCost,maxPrims,maxDepth;
float emptyBonus;
vector<Primitive*> primitives;
KdAccelNode *nodes;
int nAllocedNodes,nextFreeNode;
BBox bounds;
MemoryArena arena;
};
void KdAccelNode::initLeaf(uint32_t *primNums,int np,MemoryArena &arena)
{
flags = 3;
nPrims |= (np<<2);
//Store primitive id for leaf node
if(np == 0)
onePrimitive = 0;
else if(np == 1)
onePrimitive = primNums[0];
else{
primitives = arena.Alloc<uint32_t>(np);
for(int i=0;i<np;++i)
primitives[i] = primNums[i];
}
}
void KdTreeAccel::buildTree(int nodeNum,const BBox &nodeBounds,const vector<BBox> &allPrimBounds,uint32_t *primNums,
int nPrimitives,int depth,BoundEdge *edges[3],uint32_t *prims0,uint32_t *prims1,
int badRefines)
{
//Get Next Free Node
assert(nodeNum == nextFreeNode);
if(nextFreeNode == nAllocedNodes){
int nAlloc = max(2*nAllocedNodes,512);
KdAccelNode *n = AllocAligned<KdAccelNode>(nAlloc);
if(nAllocedNodes > 0){
memcpy(n,nodes,nAllocedNodes*sizeof(KdAccelNode));
FreeAligned(nodes);
}
nodes = n;
nAllocedNodes = nAlloc;
}
++nextFreeNode;
//Initialize leaf Node
if(nPrimitives <= maxPrims || depth == 0){
nodes[nodeNum].initLeaf(primNums,nPrimitives,arena);
return;
}
//Initialize Interior Node
//--Choose split axis
int bestAxis = -1, bestOffset = -1;
float bestCost = INFINITY;
float oldCost = isectCost * float(nPrimitives);
float totalSA = nodeBounds.SurfaceArea();
float invTotalSA = 1.f / totalSA;
Vector d = nodeBounds.pMax - nodeBounds.pMin;
uint32_t axis = nodeBounds.MaximumExtent();
int retries = 0;
retrySplit:
for (int i = 0; i < nPrimitives; ++i) {
int pn = primNums[i];
const BBox &bbox = allPrimBounds[pn];
edges[axis][2*i] = BoundEdge(bbox.pMin[axis], pn, true);
edges[axis][2*i+1] = BoundEdge(bbox.pMax[axis], pn, false);
}
sort(&edges[axis][0], &edges[axis][2*nPrimitives]);
int nBelow = 0, nAbove = nPrimitives;
for (int i = 0; i < 2*nPrimitives; ++i) {
if (edges[axis][i].type == BoundEdge::END) --nAbove;
float edget = edges[axis][i].t;
if (edget > nodeBounds.pMin[axis] &&
edget < nodeBounds.pMax[axis]) {
//Compute cost for split at ith edge
uint32_t otherAxis0 = (axis + 1) % 3, otherAxis1 = (axis + 2) % 3;
float belowSA = 2 * (d[otherAxis0] * d[otherAxis1] +
(edget - nodeBounds.pMin[axis]) *
(d[otherAxis0] + d[otherAxis1]));
float aboveSA = 2 * (d[otherAxis0] * d[otherAxis1] +
(nodeBounds.pMax[axis] - edget) *
(d[otherAxis0] + d[otherAxis1]));
float pBelow = belowSA * invTotalSA;
float pAbove = aboveSA * invTotalSA;
float eb = (nAbove == 0 || nBelow == 0) ? emptyBonus : 0.f;
float cost = traversalCost +
isectCost * (1.f - eb) * (pBelow * nBelow + pAbove * nAbove);
if (cost < bestCost) {
bestCost = cost;
bestAxis = axis;
bestOffset = i;
}
}
if (edges[axis][i].type == BoundEdge::START) ++nBelow;
}
assert(nBelow == nPrimitives && nAbove == 0);
//--Create leaf if np good splits found
if (bestAxis == -1 && retries < 2) {
++retries;
axis = (axis+1) % 3;
goto retrySplit;
}
if (bestCost > oldCost) ++badRefines;
if ((bestCost > 4.f * oldCost && nPrimitives < 16) ||
bestAxis == -1 || badRefines == 3) {
nodes[nodeNum].initLeaf(primNums, nPrimitives, arena);
return;
}
//--Classify primitives with respect to split
int n0 = 0, n1 = 0;
for (int i = 0; i < bestOffset; ++i)
if (edges[bestAxis][i].type == BoundEdge::START)
prims0[n0++] = edges[bestAxis][i].primNum;
for (int i = bestOffset+1; i < 2*nPrimitives; ++i)
if (edges[bestAxis][i].type == BoundEdge::END)
prims1[n1++] = edges[bestAxis][i].primNum;
//--Recursively initialize children nodes
float tsplit = edges[bestAxis][bestOffset].t;
BBox bounds0 = nodeBounds, bounds1 = nodeBounds;
bounds0.pMax[bestAxis] = bounds1.pMin[bestAxis] = tsplit;
buildTree(nodeNum+1, bounds0,
allPrimBounds, prims0, n0, depth-1, edges,
prims0, prims1 + nPrimitives, badRefines);
uint32_t aboveChild = nextFreeNode;
nodes[nodeNum].initInterior(bestAxis, aboveChild, tsplit);
buildTree(aboveChild, bounds1, allPrimBounds, prims1, n1,
depth-1, edges, prims0, prims1 + nPrimitives, badRefines);
}
bool KdTreeAccel::intersect(const Ray& r,float t_min,float t_max,primitive_record &rec) const {
//Compute initial Parametric range of ray inside kd-tree extent
float tMIN,tMAX;
if(!bounds.IntersectP(r,&tMIN,&tMAX))
return false;
//Prepare to traverse kd-tree for ray
Vector invDir(1.f/r.d.x,1.f/r.d.y,1.f/r.d.z);
#define MAX_TODO 64
KdToDo todo[MAX_TODO];
int todoPos = 0;
//Traverse kd-tree nodes in order for ray
bool hit = false;
const KdAccelNode *node = &nodes[0];
while (node != NULL) {
if(t_max < tMIN) break;
if(!node->isLeaf())
{
//Process kd-tree interior node
int axis = node->SplitAxis();
float tplane = (node->SplitPos() - r.o[axis]) * invDir[axis];
const KdAccelNode *firstChild, *secondChild;
int belowFirst = (r.o[axis] < node->SplitPos()) ||
(r.o[axis] == node->SplitPos() && r.d[axis] <= 0);
if (belowFirst) {
firstChild = node + 1;
secondChild = &nodes[node->AboveChild()];
}
else {
firstChild = &nodes[node->AboveChild()];
secondChild = node + 1;
}
if (tplane > tMAX || tplane <= 0)
node = firstChild;
else if (tplane < tMIN)
node = secondChild;
else {
todo[todoPos].node = secondChild;
todo[todoPos].tMIN = tplane;
todo[todoPos].tMAX = tMAX;
++todoPos;
node = firstChild;
tMAX = tplane;
}
}
else
{
//Check for intersections inside leaf node
uint32_t nPrimitives = node->nPrimitives();
if (nPrimitives == 1) {
primitive_record tempRec;
Primitive* prim = primitives[node->onePrimitive];
//Check one prim inside leaf node
if(prim->intersect(r,t_min,t_max,tempRec))
{
rec = tempRec;
hit = true;
}
}
else {
primitive_record tempRec;
float closest_so_far = t_max;
uint32_t *prims = node->primitives;
for (uint32_t i = 0; i < nPrimitives; ++i)
{
//Check one prim inside leaf node
if(primitives[prims[i]]->intersect(r,t_min,closest_so_far,tempRec))
{
hit = true;
closest_so_far = tempRec.t;
rec = tempRec;
}
}
}
//Grab next node to process from todo list
if (todoPos > 0) {
--todoPos;
node = todo[todoPos].node;
tMIN = todo[todoPos].tMIN;
tMAX = todo[todoPos].tMAX;
}
else
break;
}
}
return hit;
}
*CAMERA CODE *
Vector random_in_unit_disk() {
Vector p;
do{
p = 2.f*Vector(drand48(),drand48(),0)-Vector(1.f,1.f,0.f);
}while(Dot(p,p) >= 1.f);
return p;
}
class Camera {
public:
Vector lower_left_corner;
Vector horizontal;
Vector vertical;
Point origin;
Vector u,v,w;
float lens_radius; //Focus
float time0,time1;
Camera(Point lookfrom,Point lookat,Vector vup,
float vfov,float aspect,float aperture,float focus_dist,float t0,float t1){
time0 = t0;
time1 = t1;
lens_radius = aperture/2;
float theta = vfov*M_PI/180.f;
float half_height = tanf(theta/2.f);
float half_width = aspect*half_height;
origin = lookfrom;
w = Normalize(lookfrom - lookat);
u = Normalize(Cross(vup,w));
v = Cross(w,u);
lower_left_corner = toVector(origin) - half_width*focus_dist*u - half_height*focus_dist*v - focus_dist*w;
horizontal = 2*half_width*focus_dist*u;
vertical = 2*half_height*focus_dist*v;
}
Ray get_ray(float s,float t) {
Vector rd = lens_radius*random_in_unit_disk();
Vector offset = u * rd.x + v * rd.y;
float time = time0 + drand48()*(time1-time0);
return Ray(origin + offset,lower_left_corner + s*horizontal + t*vertical - toVector(origin) - offset,time);
}
};