Sunday, April 27, 2008
Saturday, April 26, 2008
Transparancy + Reflection
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
Thursday, April 24, 2008
Oleg + Brian Strength Training
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.
ActionScript Update
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.
Tuesday, April 22, 2008
Complex Adaptive Systems - Assignment 3 Finished
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 - 8 Levels of Iteration
6-ary Tree - 4 Levels of Iteration
6-ary Tree - 6 Levels of Iteration
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
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.
Saturday, April 19, 2008
L-System Fractal Growth Assignment
%
%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
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!
Pass 3 - Axis Aligned Box floating above the plane (rather than bisected)
Kate Walking Her Dog at the UNM Duck Pond
Saturday, April 12, 2008
New Complex Adaptive Systems Assignment
Click it for a bigger image
Or check out the text I OCR'd from this website (and formatted a tiny bit):
Due midnight April 21,2008
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
Coming soon : Dielectrics!
Thursday, April 3, 2008
Acceleration Data Structure - Bounding Volume Hierarchy
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";
}
}