Sunday, April 27, 2008

Better Scene Layout

I like this layout more.


(2048 x 2048 -- 256 samples / pixel -- rendering time = real 426m19.944s, 7 hours 30 minutes on a 1800 mhz P4 )

Saturday, April 26, 2008

Transparancy + Reflection

Today I finished the last regular assignment for my ray tracing course - transparancy & reflection! Here are some of the images I generated.


Extremely High Resolution Image (2048 x 2048 -- 128 samples / pixel -- rendering time : real 279m22.153s, a bit over 4 hours)


This is the first image that I generated with spheres of different index of refraction, and ratio of reflectance to transmission. Overall, I think it looks pretty cool. There are a few minor changes I would like to make, but they shouldn't take too long. The sky needs to be changed from my polluted sky brown to a beautiful blue, the small middle sphere looks like it is getting clipped by the camera and the two upper spheres need more reflectance. This was still a ton of work getting here.


I like the color of the balls visible in this one



A box and a sphere



Messing with a transparent sphere and box



Some reflection





One of the passes at multiple spheres - after getting this far scene layout is taking a while


Index of refraction = 1.0, with some phong shading going on


Totally reflective - but still phong shaded

I also found an interesting blog by Pete Shirley, a professor at the University of Utah, about graphics. My professor, Joe Kniss, went to Utah and studied graphics. Check it out here. I also added him to the "friends links" that I support, even though we have never talked (so aren't friends).

Thursday, April 24, 2008

Oleg + Brian Strength Training

For about two months, my friend Oleg Semanov and I have been lifting weights at the gym. We bring his PDA to record the weights that we lift, in order to keep track of our improvement and our goals. We both have been improving, but Oleg has improved on sit-ups extremely fast. He went from completing 3 sets of 25 sit-ups on the ground to 3 sets of 25 on a major incline. Next time we do sit-ups, we are going to move him up another bar. This will bring him to about a 40 degree incline.

Currently, Oleg and I are tied on leg press and calf extensions. This is another area that Oleg improved on very quickly. When we started, I was at 4 weights @ 45 lbs (20.411 kg) each + the bar at 45 lbs. I think the bar weighs 45, so this totals to 5 x 45 = 225 lbs (102 kg) and Oleg was at 3 x 45 = 135 lbs (61 kg). Now, we both are at 6 x 45 + bar = 7 * 45 = 315 lbs (142 kg). That's a 232 % gain for Oleg and a 139% gain for me.



Oleg doing Sit-Ups so fast he is blurry


On the way down...


and the way up

ActionScript Update

Today I have been working on my ActionScript front end for Mark Olah's molecular spiders a ton. In addition to moving the scene around, I completed a bit of some scene resizing code. Check it out below.






For this version, you should be able to move the entire scene around by clicking, holding, and moving your mouse around. This version ALSO supports resizing by using the scroll wheel, but my Blogger stuff seems to be getting in the way of it. You can also check it out directly by clicking here. If you are so inclined to take a look at my code to see how I accomplished this, I packaged it up for everyone here.



If you are interested in how I added mouse listeners to my flash file, check out the com\identityMine\documentClass\DocumentClass.as file. Since I started doing Flash as a programmer, everything is implemented in classes.

Lately, I've been consciously trying to stay positive in a lot of different ways. If I feel discouraged with my ray tracer, or something else, I try and play handball with a friend, go to the gym, or a yoga class, or read something inspirational and then work hard at whatever has been bothering me. Maintaining a positive outlook is something I need to focus on, and improve on, but things like this always help me smile. The University of New Mexico ALWAYS has interesting characters sitting on the border between UNM-land and Central Avenue.


Fashion Conscious Protester




I believe he is equating President Bush with the Anti-Christ. Unfortunately, I did not have time to ask him the specifics of his political platform.

Tuesday, April 22, 2008

Complex Adaptive Systems - Assignment 3 Finished

Today Ratheesh and I finished the remaining section of our complex adaptive systems homework. We knocked out the programming without too much of a hassle. However, some of the programs took hours to run.

Here are a few of the images we were able to generate based on our simple fractal, with different branching rules and different levels of iteration.


Binary Tree - 4 Levels of Iteration


Binary Tree - 8 Levels of Iteration


6-ary Tree - 4 Levels of Iteration


6-ary Tree - 6 Levels of Iteration


The complete code is available here. Please leave me a comment if you use it to generate any fractals for yourself (or for an assignment).

Also, here is a PDF of our write up. The analysis could probably be a bit stronger, and our simulation is still gathering data, but overall I think it's all right.

Sunday, April 20, 2008

Easier L-System to Analyze

After working for a long, long time with Ratheesh on the L-System:


rule(1).before = 'F';
rule(1).after = 'FF';

rule(2).before = 'G';
rule(2).after = 'F[+G][-G]F[+G][-G]FG';

Which generates this tree.




However, I decided to use this simpler L-system:


rule(1).before = 'F';
rule(1).after = 'F[-F][+F]';


I thought it would be much, MUCH easier to analyze. It would be cool to come up with an expansion that makes the trunk grow more, but keeps the binary relation, but I'm probably not going to be up for that... Here are the different trees that it generates depending on the number of repetitions.


0 reps



1 reps



2 reps




3 reps



4 reps



10 reps

Saturday, April 19, 2008

L-System Fractal Growth Assignment

Today I really started on the L-System assignment Melanie Moses handed out. I am still at a very early stage of development, but I have some interesting images already.





And the following Matlab code:
%
%L-system
%2D

clear all
clf

%Rules-- Cell array {1,x} is the xth string to be replaced
% -- {2,x}

rule(1).before = 'F';
rule(1).after = 'FF';
%rule(1).after = 'F[-F]F[+F]F';

rule(2).before = 'G';
rule(2).after = 'F[+G][-G]F[+G][-G]FG';
%rule(2).after = 'F[+G]F[-G]G';

nRules = length(rule);

%angle: +operator means turn left; -operator means turn right
%delta = 27.5; %degrees
delta = 25.0; % This is 'theta' in the project specifications

%length of the line segments corresponding to the symbols F and G
lenF = 1;
lenG = 1;

%starting seed
axiom = 'G';
%axiom = 'F';

%number of repititions -- This is 'N' in the project specification
nReps = 4;

for i=1:nReps

%one character/cell, with indexes the same as orilsys.mginal axiom string
axiomINcells = cellstr(axiom');
%axiom

for j=1:nRules
%the indexes of each 'before' string
hit = strfind(axiom, rule(j).before);
if (length(hit)>=1)
for k=hit
axiomINcells{k} = rule(j).after;
end
end
end
%now convert individual cells back to a string
axiom=[];0
for j=1:length(axiomINcells)
axiom = [axiom, axiomINcells{j}];
end
end

leaf_count = (axiom == 'G');
leaf_count = leaf_count(axiom == 'G');
sprintf('leaf_count = %d',length(leaf_count))

branch_count = (axiom == 'F');
branch_count = branch_count(axiom == 'F');
sprintf('branch_count = %d', length(branch_count))

sprintf('length(axiom) = %d', length(axiom))

axiom

% Now draw the string as turtle graphics
%Upper case (e.g. F or G) causes a line to be drawn in the current direction of the turtle
%Lower case causes a move with no draw
%angle +operator means turn left; -operator means turn right

%Init the turtle
xT = 0;
yT = 0;
aT = 0;
da = deg2rad(delta) ; %convert to radians

%init the turtle stack
stkPtr = 1;

%set(gca,'xlim', [-5 5], 'ylim', [-5 5]);
hold on

% Leaf counter
leafs = 0;

for i=1:length(axiom)
cmdT = axiom(i);
switch cmdT
case 'F' % Branches
newxT = xT + lenF*cos(aT);
newyT = yT + lenF*sin(aT);
%line([xT newxT], [yT newyT]);
line([yT newyT], [xT newxT],'color',[.3 .3 0], 'linewidth',2);
xT = newxT;
yT = newyT;
case 'G' % Leaves
leafs = leafs + 1;
newxT = xT + lenG*cos(aT);
newyT = yT + lenG*sin(aT);
%line([xT newxT], [yT newyT]);
line([yT newyT], [xT newxT],'color','g', 'linewidth',2);
xT = newxT;
yT = newyT;
case '+'
aT = aT + da;
case '-'
aT = aT - da;
case '[' %push the stack
stack(stkPtr).xT = xT ;
stack(stkPtr).yT = yT ;
stack(stkPtr).aT = aT ;
stkPtr = stkPtr +1 ;
case ']' %pop the stack
stkPtr = stkPtr -1 ;
xT = stack(stkPtr).xT ;
yT = stack(stkPtr).yT ;
aT = stack(stkPtr).aT ;
otherwise
disp('error')
return
end
%drawnow
end

sprintf('leafs = %d', leafs);

daspect([1,1,1])






Sunday, April 13, 2008

ActionScript Parsing

I've been helping Mark Olah out on some molecular computer visualizations in ActionScript and we are moving towards getting an actual front end for his simulator. In order to do that, we need to have some mechanism of communicating between his software and the ActionScript I have been working on to draw the pictures.

Mark suggested we have a fairly simple format that looks something like this:

//Hello World! This is Brian J. Stinar reading in a file with Adobe AIR.


Begin Surface
-1, -1, 2, 2
1.0, 1.0, 0, A
1.0, 2.0, 1, A
1.0, 3.0, 2, A
1.0, 4.0, 3, A
2.0, 1.0, 4, B
3.0, 1.0, 5, B
4.0, 1.0, 6, B
5.0, 1.0, 7, B
End Surface

Begin Spider
brian_spider_1, 4, 1
brian_spider_2, 4, 3
brian_spider_3, 4, 1,
End Spider
// Here is another comment

Begin Trace
Body Move brian_spider_1
LegAttach brian_spider_1, 1, 0
Spider Detach brian_spider_1

End Trace


If you would like to test out my parser with this file, the file I am parsing is available here.

Then, I will read in this file and generate graphics accordingly. After working today for a few hours, I think I have parsing down in ActionScript (Adobe AIR, actually?). The regular expression syntax is just like Perl, and well documented by Adobe.

Here is the code I came up with :


package com.identityMine.filereader
{

import flash.filesystem.*;
import flash.display.MovieClip;

// The extention here is to make it so that I can independently test these routines
public class FILEREADER extends MovieClip {


// Constructor - loads in the input file we are reading
public function FILEREADER(){
// Create a file object and let our app know where the file
// exists

// have we seen the "Begin Surface" command yet?
var inSurface : Boolean = false;
var inTrace : Boolean = false;
var inSpider : Boolean = false;
var inMove : Boolean = false;

// This is the file we are reading
var myFile:File = File.applicationDirectory;
myFile = myFile.resolvePath("mySampleFile.txt");

var fileStream : FileStream = new FileStream();
fileStream.open(myFile, FileMode.READ);

// Everything inside our file
var fileContents : String = fileStream.readUTFBytes(fileStream.bytesAvailable);

// Split our entire file based on newlines
var splitString = fileContents.split("\n");

// this prints out everything in my fileContents string
// trace (splitString);

// iterate through each element in the array
// each represents a piece of information necessary to construct our
// visualization

// looping variable
var i : int;
// splitting variable
var split_val : int;

// Regular Expression for matching a string of 1 or more digits
var re1 = new RegExp("[0-9]+");

// Regular Expression for matching a sequence of alph characters
var re2 = new RegExp("[a-z]*[A-Z]*");
var re3 = new RegExp("[//s]*LegAttach");

var SubVals;

for (i = 0; i < split_val = "Begin Surface" insurface =" true;" i =" i" insurface ="="" subvals =" splitString[i].split(',');" split_val = "End Surface" insurface =" false;" split_val = "Begin Trace" intrace =" true;" split_val = "Begin Spider" inspider =" true;" split_val = "End Spider" inspider ="="" inspider =" false;" inspider ="="" subvals =" splitString[i].split(',');" split_val = "Body Move" inmove =" true;" split_val = "Spider Detach" inmove ="="" intrace ="="" inmove =" false;" split_val = "End Trace" intrace ="="" intrace =" false;" split_val = "LegAttach" intrace ="="" inmove ="="" subvals =" splitString[i].split(',');">













Code Available Here



This is a TERRIBLE solution to my problem of not being able to display code well on my blog. As an actual solution, I should make my blog wider (and yes, adjust the images that came with the template.)


As of yet, I still need to check to see how error resilient my code is. I think my regular expressions might accept too much stuff. For the next small increment, I am going to actually print out the corresponding function call I plan on making. For testing purposes, I added a bit of junk into my trace file and my program spit it out.



Axis Aligned Boxes - Stage 1 Complete!

Jon Bradley mentioned that Axis Aligned Boxes would be good to test the dielectric shading with. Since Jon has the best ray tracer I've seen in the class, I thought it would be a good idea to listen to him.




Pass 1 - Axis Aligned Box



Pass 2 - Axis Aligned Box with Correct (matte) Shading



Pass 3 - Axis Aligned Box floating above the plane (rather than bisected)




Jon Bradley, possibly the best living programmer

Kate Walking Her Dog at the UNM Duck Pond

Today my girlfriend Kate decided to take her families dog for a walk at the UNM duck pond. She sent me two photos of the duck pond from here camera phone. I was surprised by how nice the photos turned out.







Other than a massive amount of ray tracing and going to church, my cousin and I created a temporary burrito factory in my apartment to make 20 burritos for the upcoming week. I don't think I'll start selling burritos on the corner of Central & Stanford, but if the whole computer science thing doesn't work out it's always an option. I'll probably hit the UNM gym for about an hour, do some molecular visualization / ActionScript research and then go to sleep. That doesn't sound too bad for a Sunday.

Saturday, April 12, 2008

New Complex Adaptive Systems Assignment

Dr. Moses posted a new assignment for the Complex Adaptive Systems class I am taking. Unfortunately, she didn't actually post the assignment. She handed it out on a piece of paper, which due to some absent minded mistake of mine, I didn't get a copy of. Luckily, my friend Rosh gave me a copy that I scanned.



Click it for a bigger image


Or check out the text I OCR'd from this website (and formatted a tiny bit):

Complex Adaptive Systems, CS 591
Assignment 3: Fractals
Due midnight April 21,2008

For this assignment (worth 50 rather than 100 points) you do not need to prepare a report.

You only need to do the following.

Write a program that draws trees following the West et al 1997 algorithm. To make things
easier, draw your trees in 2 dimensions so that each branch has a width and a length (not a
radius). The length ratio (y) is set so that the branches are area filling (as opposed to volume
filling in West et al). Thus, given a branching ratio (n), y= n1/2 rather than y= n1/3. Similarly,
rather than being area-preserving, the widths of branches should be width-preserving, that
so that ft = n1. In the 2-D version, of West et al predict Nt ~A„et?ft, where JVt = the number of
terminal units andA,et = the area (or footprint) of the network.

Allow the user to specify a depth (N) of the tree, the number of daughter branches (n) per
parent and the branching angle (0). Specify the size of the 'invariant terminal unit1 (the leaf
or capillary) to be length ln= 2 and width wn= 1/2, so that the area of a terminal unit An = 1.

Build your tree from the leaves back to the trunk.

For each tree your program should output:
a) A 2D drawing of your tree.
b) Report the number of leaves (Nt), the Area of the whole tree (Ami), and the ratio of
leaf area to whole network area ((Wt* A)/A„et) given N.
c) Calculate and report the fractal dimension of each tree you generate.

Turn ln
i) Your code
11) Drawings of 2 trees generated by your code (specify JV, n and ff).
iii) A table reporting the items in b) and c) for trees with the following inputs
(12 lines in your table): N = 2,4,8,10; n = 2,4,8
iv) A mathematical description of
a. the relationship between Nt and A„ec
b. how fractal dimension depends on n and N?
Extra credit (10 points if you solve how fractal networks fit ln Euclidean organisms, partial
credit for a good effort). Consider that the networks you generated above are circulatory
networks for 2D circular animals (small networks for circular mice, big networks for
circular cows). If the maximum distance between leaves of the tree equals the diameter of
the animal, how big is the animal, i.e. what is its area? (This makes the most sense visually if
you use n=4 in 2d). Calculate the area of the animal (given the diameter above) as a function
of the area of the network.
You should see that the area of the circle does not equal the area of the network. West et al
propose the following (translated to 2D):
a. The number of capillaries is n" and n" oc AnM2/3
b. To achieve A„eta Adrcie, set Nt °cAcircie2/3. then AMt« Nt3/2 \< x Acireie2''3)2/3o<:Acirde.
Can you draw a tree, and an organism surrounding that tree that shows whether these
conditions cause A„et ~ ACMe? Can you relax the assumption that the animal is circular to
show that this is true under other assumptions? Can you relax the assumption that the
terminal units are invariant to solve this problem? Can you systematically change 8 or n as
you change N to cause Anet ~ AcWe? Show your results with fractal branches that fill the area
of the circular organisms, and explain them mathematically.

General Cleanup on Phong Shading

Today I spent a long time just working on the Phong model stuff that wasn't exactly correct in my ray tracer. I believe I have generally fixed my problems, but touching base with Nate Gaunt might be a good idea.

Coming soon : Dielectrics!



One of the "interesting" images I generated while getting this working...


1024 x 1024 @ 128 samples / pixel (both with a specular power of 25)

Thursday, April 3, 2008

Acceleration Data Structure - Bounding Volume Hierarchy

I finished my bounding volume hierarchy earlier this week and I wanted to post my results and my code. The design is base on a binary tree, with each level splitting the higher level in half. Currently, I simply alternate between splitting along the three planes I have an option of splitting on. My initial structure is simply the bounding box of the .obj file (two points - one constructed from the smallest x, y, and z values and the other from the largest values.)

The basic binary tree stuff is sort of from here, but I wrote my own search routine and modified the code a bit.


The major point that could be improved on this is the splitting. Instead of alternating between the dimensions that I split on, I could write a method that determines the best way to split (based on the equality of the triangles in each subdivision.)

I spent a while getting this page to display in a somewhat aesthetic manner. Copy and paste between Kate and Firefox doesn't always look so great, and my blogger template doesn't lend itself to major widening my posts very well.

For a .tar.gz of this current revision, you can download one here. For the acceleration data structure, check out Object.cpp and Object.h.

1 Box (single bounding box)


real 0m24.015s
user 0m12.120s
sys 0m0.070s


2 Boxes -

real 0m16.169s
user 0m8.080s
sys 0m0.030s


16 Boxes -

real 0m9.564s
user 0m5.310s
sys 0m0.050s



From 1 bounding box to 2 it is very easy to see the running time getting cut in half. From 2 to 16, there is not such an obvious speed up. I believe this is because we have to traverse more levels of our tree (not too much locality) verse iterate through bigger triangle vectors (more locality.) If my model had more triangles, I think we would still see an exponential decrease in running time as we increase the number of leaves in the binary tree.




void Object :: BuildLevels(TreeNode * rootNode, int currentDepth, int splitDimension){

cout << "debugging = " << debugging << "\n";
debugging = debugging + 1;
cout << "currentDepth = " << currentDepth << "\n";

assert (rootNode->item != NULL);6

BoundingBox parentBox = *(rootNode->item);

int maxDepth = 16;

TreeNode * left, * right;

left = new TreeNode();
right = new TreeNode();

rootNode->left = left;
rootNode->right = right;


BoundingBox * leftBox, * rightBox;

Point3D smallPoint = parentBox.getSmallPoint();
Point3D bigPoint = parentBox.getBigPoint();


if (splitDimension == 0){
// split along x
float halfx = (parentBox.getSmallPoint().x + parentBox.getBigPoint().x) / 2;

// Let's start with the smaller box along an x cut
// it is defined by the smallest origional point and
// the x-cutpoint, y-maxPoint and z-maxpoint

leftBox = new BoundingBox(smallPoint, Point3D(halfx, parentBox.getBigPoint().y,parentBox.getBigPoint().z));

// the right box is defined by the x-cutpoint, y-minPoint,
// z-minPoint and the bigPoint from the origional box
rightBox = new BoundingBox(Point3D(halfx, parentBox.getSmallPoint().y, parentBox.getSmallPoint().z), bigPoint);
}

if (splitDimension == 1){
// split along y
float halfy = (parentBox.getSmallPoint().y + parentBox.getBigPoint().y) / 2;

leftBox = new BoundingBox(smallPoint, Point3D(bigPoint.x, halfy, bigPoint.z));
rightBox = new BoundingBox(Point3D(smallPoint.x, halfy, smallPoint.z), bigPoint);
}

if (splitDimension == 2){
// split along z
float halfz = (parentBox.getSmallPoint().z + parentBox.getBigPoint().z) / 2;

leftBox = new BoundingBox(smallPoint, Point3D(bigPoint.x, bigPoint.y, halfz));
rightBox = new BoundingBox(Point3D(smallPoint.x, smallPoint.y, halfz), bigPoint);
}

left->item = leftBox;
right->item = rightBox;

// let's go through all the triangles in the root and
// assign them to the left box, right box or both.

for (int i = 0; i <>triangles.size(); i++){

Triangle * myTriangle =rootNode->triangles[i];


if (triangleInsideBox(myTriangle, *leftBox) == true){
// add the triangle to the left box
left->triangles.push_back(myTriangle);
}

if (triangleInsideBox(myTriangle, *rightBox) == true){
right->triangles.push_back(myTriangle);
}

if ((triangleInsideBox(myTriangle, *rightBox) == false) && (triangleInsideBox(myTriangle, *leftBox) == false)){
cout << "ERROR!!! TRIANGLE IN NEITHER BOX!" << "\n";
}

}


if (currentDepth < maxDepth){
BuildLevels(left, currentDepth + 1,(splitDimension + 1) % 3);

BuildLevels(right, currentDepth + 1,(splitDimension + 1) % 3);

rootNode->triangles.clear();
}

else{
cout << "number of boxes in leaf = " << rootNode->triangles.size() << "\n";

}
}