Oculus Rift | Unity 4 Quick Demo
ITP Thesis 2013 | The Myth of Myles and Selym
/*It’s been awhile since I’ve last written in my blog. At the moment, I working on my ITP Thesis which is a series of 3D Animations. I will write more about the inspiration for it when I have more time to play in this space. I’m also brushing up on my Unity 3D, Cinema 4D, Maya, Java, C++, Objective-C, and Javascript skills when I have a moment. As far as this blog, a revamp is long overdue, and I promise to update it more with my little side projects. So, without further ado, below is a progress report for my thesis. More to come at the same bat channel*/
Since February, I’ve been struggling with the story and the interactive elements of my animations. After brief meeting with Marina Zurkow and Georgia Krantz, I had a better sense of direction. Both of them encouraged me to focus on figuring out the story that I wished to tell as well as my intentions for my audience in terms of a response . Focus on the story and not worry so much about the ideal interactive element(s) yet – that would (hopefully) come later.
So, for quite some time, I focused on the moments that stayed with me after the passing of my little brother as well as the formative stops along the journey that shaped me from that moment of loss to the present day. The more and more I thought about this journey – The more and more I felt that this story was one that resonated with me, but I questioned whether or not the story would connect with my intended audience. I felt that I was walking the fine line with a story that was personal but one that my audience would not be able to relate to in the end.
So, after a marathon shower session (some of my best ideas come in the shower), I decided to frame my journey within the context of 3 separate myths. One myth would revolve around loss while the others would follow the themes of being lost and then found. Even now, I debating whether or not the narrative will be either linear or non-linear, but I will figure that out very soon.
After a bit of soul searching and writing, the story of the first animation came to me. At the moment, it is tentatively called – The Myth of Myles & Selym. The myth is one of loss, so I looked to other myths about loss and separation as inspiration such as the Greek myth of Orpheus and Eurydice. I also wanted to tinker with the concepts of the call to the quest, a goddess walking among us in the guise of an old woman, choice, thresholds, and threshold guardians. Here is a synopsis of the 1st animation:
// Beginning of Story
Centuries ago the world below was covered in boundless green but now the world is covered by the infinite blue ocean. Far above in the clouds at the end and the edge of the known world, there exists the floating city of Semele. Since it is believed that no land exists below and many dangers are hidden in the infinite blue, it is forbidden to leave the city. So, no flying crafts of any sort exist. In this city live two brothers, Myles and Selym. The two brothers are a contradiction because they seem so different but they are the same in many subtle ways. The older brother, Myles, is happy and content with his life in Semele for the city represents a safe harbor from the dangers of the world found in the infinite blue – the unknown is seen as a danger. The younger brother, Myles, appreciates all the comforts that Semele provides, but he sees Semele as a silvery city trapped within a golden cage – a city barring him from the thrill of the unknown and the possibilities of new lands beyond the infinite blue.
On a day when the sun reunited with the moon, Myles & Selym stumbled upon an old woman that was looking for a ‘missing one in a golden pair’. The old woman appears to speak in riddles, but Myles & Selym were able to deduce that the old woman was looking for a missing gold earring. In time, the two brothers find the earring.
The old woman is elated with the brother’s discovery and to show her thanks – the old woman gives both Myles & Selym each a gift. She gives Myles an embroidered black book with empty pages (modeled after the black journal I wrote in to cope with the loss of my brother) and Selym a small box with numerous knobs (an object modeled after the sound mixer that my brother owned). When Myles asks the woman the purpose of his gift, the woman smiles and says that the black book is a map and that Myles must fill the pages with his own words to find his way. Myles is confused by the old woman’s response, but he does not question her further. Selym then questions the old woman about the nature of his gift. The old woman smiles and tells Selym that his object is called a mixer once used for sound, and it’s an artifact from a time long ago. She also explains that her gift is a key; but, as far as a lock, Selym would have to find it himself.
After her explanation, the old woman turns around and tells the brothers that she must leave or she will be late. As she walks away, Myles calls out to the woman and asks her where she is from because he has never seen this woman before in his life in Semele. The old woman laughs and says that she is from the Undying Lands beyond the Infinite Blue. Dumbfounded, Selym shouts out to the woman and asks her whether or not she is telling the truth and whether or not more lands exists beyond the infinite blue. The old woman is some distance away from the two brothers at this time, and she stops in her steps after Selym asks his questions – but she does not turn around to look at them. She tells the brothers that the Undying Lands are one among many. She goes on further to say that if you do not believe you will find nothing beyond the infinite blue….but, if you believe, who knows what you may find beyond the blue. Before the woman utters those last words, she continues in her walk forward. Before she turns the corner, Selym calls out and asks the old woman what her name is. As she turns the corner, she tells Selym that her name is Anan (that name is my brother’s nickname in reverse & also means ‘clouds’ in Arabic). Once she turns the corner, she disappears and is never seen again.
As the two brothers stand in the middle of the road, one doubts the words told to him while the other believes. For many days, Selym attempts to unearth the secret of his object due to his belief while Myles sets aside his gift only to gather dust due to his disbelief.
One night full of stars, Selym unearths the secret of his gift. It is indeed a key. The knobs represent a combination. Knowing with Knowing how, Selym discovers the combination and knows where to find the ‘lock’ – an abandoned temple of the old gods found at the edge of the city. So, Selym gathers some provisions and hurries to the forgotten temple because he senses that there is a journey just around the corner.
In this forgotten temple, Selym enters the combination into the mixer, and a flying craft appears before him. Intuition guides Selym and he enters the flying craft. Knowing without knowing how, Selym starts the craft and guides it into the night sky. Once Selym rises, his confidence grows, and he decides to leave the floating city of Semele to follow belief and find the lands beyond the infinite blue. So, Selym leaves Semele and ventures into the unknown of the night sky.
When Myles returns home, he finds a note left behind by Selym. In the note, Myles finds the following words:
“Discovered the Key & the Lock at the forgotten temple.”
Sensing something was amiss, Myles runs into the night with all of his speed. He senses that if he does not get to the temple in time; he would not see his brother again. He does not know why, but he harbors this feeling in the depths of his heart.
By the time that Myles reaches the forgotten temple, it’s too late. In disbelief, Myles sees the flying craft in the sky and knows without knowing how that his brother Selym is leaving Semele, leaving his life here, and leaving his brother, Myles. In desperation, Myles calls out to him, but Selym has already escaped the confines of the borders of Semele.
In despair, Myles waits all night at the far edge of the city for his brother to return, but Selym does not come home that day. Every night after that tragic night, Myles waits at the edge of the city with a blue lantern hoping for his brother to see the light and return home, but Selym never returns.
Today, many believe Selym actually found many lands beyond the Infinite Blue and lived many adventures in one lifetime but was unable to return home to Semele. Others believe Selym found the heavens above instead and lives in the company of the Old Gods.
As far as the fate of Myles, no one knows.
Now, if you look into the night sky in the height of summer, you will see the constellation of Selym in the western sky. The constellation resembles the same ship that Selym used to escape the city of Semele. The constellation is illuminated by reds stars shining liking rubies. Whenever the stars of Selym shine bright in the western sky, the constellation of Myles shines bright in the eastern sky – one solitary blue star in the sky waiting for his brother to return.
// End of Story
After finalizing the story of The Myth of Myles & Selym, I had to make a decision as far as the visual aesthetic of this animation. For a time, I toyed around with the idea of creating a 2D animation solely in After Effects; but, after a few initial sketches, I decided to attempt a 3D animation instead.
Despite my best wishes, my experience with 3D animation software was limited. So, I tracked down a 15 hour tutorial of Cinema 4D R14, and I holed myself in my apartment until I had a solid grasp of the software. In the tutorial, I learned about C4D’s User Interface, Modeling Tools, Materials, Rigging, Particles, Animation, & Rendering. Below are renders of the world of Semele that I built. I also modeled the flying craft that I intended to use in the finals scenes for Selym with help of the tutorial.
Cinema 4D Screenshots
The City of Semele requires a few more tweaks. At the moment, it appears that the city is floating in space when it should appear to be floating in the night sky. So, I will need to add clouds as well as the proper illumination to represent moonlight for the night scene. The first animation needs to reflect the passage of time as the story progresses, so I felt that I needed to create an environment with both a day/night cycle. So, that took a bit of time to build and figure out. Yet, I’m very happy with the results, but I still have a ways to go.
During Spring Break, I really need build the 3 main characters (Selym, Myles, and Anan), rig these characters, and build the scenes. The inspiration for Selym & Myles is a pen sketch that I did some time ago. Here is a scan of that sketch:
If you look closely at the sketch, you will the side profile of two faces conjoined much like the Janus Coin.
The face on the left is a representation of Selym and the one on the right is a representation of Myles. The sketch is bit abstract, but I like it. I think that I will base the characters on this sketch by utilizing both ZBrush and Cinema 4D.
All these tasks have been rather difficult since I’m visiting Austin, TX for the Spring Break to see whether or not I will stay in New York or possibly relocate to Austin (or maybe San Francisco if the right opportunity presents itself) after graduation.
At the rate that I’m going, I’m fearful that I may need to condense the last 2 animations into one, but I cannot worry about that at the moment. If I can pull off one animation of high quality that has interactive elements, that would be a success in itself. So, the worst cast scenario is that I complete on great animation.
Also, I’m reading the Writer’s Journey by Christopher Vogler as a recommendation from Katherine. Actually, Eric Rosenthal brought up the book after my Midterm Presentation. He asked me whether or not I had read the book. Mistaking the book for another that I read, I answered that I did. A day after the presentation, I realized that I had not read this book, so I decided to purchase a copy and read it for the first time.
The Writer’s Journey is a book that explores the structure of mythology and storytelling to assist writers, screenwriters, game designers, etc. Vogler’s work is inspired immensely by the works of mythologist Joseph Campbell & Psychologist Carl Jung. Since I’m also a fan of both of these figures, Vogler’s approach within his book truly resonates with me and will be a true guide for me in this challenging process.
I will be sure to give another update sooner than later.
Until we meet again,
Kojo
Blue Origami Flowers | Cinema 4D R14 + Maxwell Render Test
This is my first go at using the Cinema 4D R14 and Maxwell Render together. So far, I’m liking the results.
Art of Graphics Programming | Final Project | Turn On The Lights
For my final project in the Art of Graphics Programming, I decided to simplify the process. Considering Processing 1.5.1 is no longer functional, I decided to work in C++. I also had certain basic criteria regarding the entire process:
1. Utilize OpenGL via C++ (covered earlier)
2. Gain a better understanding of ambient, diffuse, and specular lights
3. Understand light properties, material properties utilizing OpenGL and GLUT
If I could cover these bases, great. If I could add more bells and whistles, even greater. In the end, I was able to cover the basic criteria. Given more time during the break, I will build up on what I learned into a larger project.
So, why the apparent interest in lights for Computer Graphics. Well, it’s a result of work within this course in addition to works/topics discussed in 2 other course that I took at ITP this past semester: Open Source Animation taught by Nick Fox-Gieg and Embodied Play taught by Phoenix Perry. Throughout the course of the semester, I’ve been exploring 3D Software Applications such as Maya, Cinema 4D, Modo, & Houdini for the purposes of animation in Open Source Animation and asset creation in Unity 3D for Embodied Play. While going even deeper into the graphics rabbit hole, I stumbled across dedicated rendering 3D software such as Maxwell, Indigo and Vray.
For my final project, I wanted to recreate the lights seen in renders such as the ones you would see in the Maxwell Render. So, I aimed to start with a basic sphere (which turned out to be the end result). I would build that towards a larger scene (did not happen in the end). In the following video, I discuss my project in more detail.
Disclaimer: Excuse my excessive use of the phrase ‘Dabbled with..’ and my incorrect use of the term ‘terminal’ (I actually meant console).
AofGP Final Project | Turn On the Lights from Kojo Opuni on Vimeo.
My Final Project for AofGP.
////////
Here is the actual code for my project below.
//
// main.cpp
// AoGPFinalProj
//
// Turn on the Lights (Homage to Teddy Pendergrass)
//
// Created by Kojo Opuni on 12/10/12.
// Copyright (c) 2012 Kojo Opuni. All rights reserved.
//
// Objectives: Utilize OpenGL using C++, Understanding Light Properties & Material Properties unilizing OpenGL & GLUT,
// Gain a better understanding ambient, diffuse, and specular light.
//
//
//
//
//
//
//
#include <iostream>
#include <fstream>
#ifdef __APPLE__
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
using namespace std;
// The Global Variables for the sketch
static int light0On = 1; // White light on?
static int light1On = 1; // Green light on?
static float d = 1.0; // Diffuse and specular white light intensity.
static float m = 0.2; // Global ambient white light intensity.
static int localViewer = 1; // Local viewpoint?
static float p = 1.0; // Positional light?
static float xAngle = 0.0, yAngle = 0.0; // Rotation angles of white light.
//static long font = (long)GLUT_BITMAP_8_BY_13; // Font selection.
static char theStringBuffer[10]; // String buffer.
// Routine to draw a bitmap character string.
void writeBitmapString(void *font, char *string)
{
char *c;
for (c = string; *c != '\0'; c++) glutBitmapCharacter(font, *c);
}
// Routine to convert floating point to char string.
void floatToString(char * destStr, int precision, float val)
{
sprintf(destStr,"%f",val);
destStr[precision] = '\0';
}
// Write data.
void writeData(void)
{
glDisable(GL_LIGHTING); // Disable lighting.
glColor3f(1.0, 1.0, 1.0);
floatToString(theStringBuffer, 4, d);
glRasterPos3f(-1.0, 1.05, -2.0);
// writeBitmapString((void*)font, "Diffuse and specular white light intensity: ");
// writeBitmapString((void*)font, theStringBuffer);
floatToString(theStringBuffer, 4, m);
glRasterPos3f(-1.0, 1.0, -2.0);
// writeBitmapString((void*)font, "Global ambient whitle light intensity: ");
// writeBitmapString((void*)font, theStringBuffer);
glRasterPos3f(-1.0, 0.95, -2.0);
// if (localViewer) writeBitmapString((void*)font, "Local viewpoint.");
// else writeBitmapString((void*)font, "Infinite viewpoint.");
glEnable(GL_LIGHTING); // Re-enable lighting.
}
// You better Initialize Kojo or this program is going to fail AGAIN
void setup(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST); // Enable depth testing.
// Turn on OpenGL lighting.
glEnable(GL_LIGHTING);
// Material property vectors.
float matAmbAndDif[] = {1.0, 0.0, 0.0, 1.0};
float matSpec[] = { 1.0, 1.0, 1,0, 1.0 };
float matShine[] = { 50.0 };
// Material properties of sphere.
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matAmbAndDif);
glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
glMaterialfv(GL_FRONT, GL_SHININESS, matShine);
// Cull back faces.
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
// Learning how to draw
void drawScene()
{
// Light property vectors.
float lightAmb[] = { 0.0, 0.0, 0.0, 1.0 };
float lightDifAndSpec0[] = { d, d, d, 1.0 };
float lightPos0[] = { 0.0, 0.0, 3.0, p };
float lightDifAndSpec1[] = { 0.0, 1.0, 0.0, 1.0 };
float lightPos1[] = { 1.0, 2.0, 0.0, 1.0 };
float globAmb[] = { m, m, m, 1.0 };
// Light0 properties.
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDifAndSpec0);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightDifAndSpec0);
// Light1 properties.
glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmb);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDifAndSpec1);
glLightfv(GL_LIGHT1, GL_SPECULAR, lightDifAndSpec1);
// Infinite vs Local View Point - Don't forget to put the definitions in
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globAmb); // Global ambient light.
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, localViewer); // Enable local viewpoint
// Turn lights off/on.
if (light0On) glEnable(GL_LIGHT0); else glDisable(GL_LIGHT0);
if (light1On) glEnable(GL_LIGHT1); else glDisable(GL_LIGHT1);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
writeData();
gluLookAt(0.0, 3.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// Draw light source spheres (or arrow) after disabling lighting.
glDisable(GL_LIGHTING);
// Light0 positioned and sphere positioned in case of positional light
// and arrow in case of directional light.
glPushMatrix();
glRotatef(xAngle, 1.0, 0.0, 0.0); // Rotation about x-axis.
glRotatef(yAngle, 0.0, 1.0, 0.0); // Rotation about z-axis.
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
glTranslatef(lightPos0[0], lightPos0[1], lightPos0[2]);
glColor3f(d, d, d);
if (light0On)
{
if (p) glutWireSphere(0.05, 8, 8); // Sphere at positional light source.
else // Arrow pointing along incoming directional light.
{
glLineWidth(3.0);
glBegin(GL_LINES);
glVertex3f(0.0, 0.0, 0.25);
glVertex3f(0.0, 0.0, -0.25);
glVertex3f(0.0, 0.0, -0.25);
glVertex3f(0.05, 0.0, -0.2);
glVertex3f(0.0, 0.0, -0.25);
glVertex3f(-0.05, 0.0, -0.2);
glEnd();
glLineWidth(1.0);
}
}
glPopMatrix();
// Light1 and its sphere positioned.
glPushMatrix();
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
glTranslatef(lightPos1[0], lightPos1[1], lightPos1[2]);
// Green Spotlight Color
glColor3f(0.0, 1.0, 0.0);
if (light1On) glutWireSphere(0.05, 8, 8);
glPopMatrix();
glEnable(GL_LIGHTING);
// The Actual Sphere.
glutSolidSphere(1.5, 200, 200);
glutSwapBuffers();
}
// OpenGL window reshape routine.
void resize (int w, int h)
{
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (float)w/(float)h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
}
// The Keyboard Inputs
void keyInput(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
break;
case 'w':
if (light0On) light0On = 0; else light0On = 1;
glutPostRedisplay();
break;
case 'W':
if (light0On) light0On = 0; else light0On = 1;
glutPostRedisplay();
break;
case 'g':
if (light1On) light1On = 0; else light1On = 1;
glutPostRedisplay();
break;
case 'G':
if (light1On) light1On = 0; else light1On = 1;
glutPostRedisplay();
break;
case 'l':
if (localViewer) localViewer = 0; else localViewer = 1;
glutPostRedisplay();
break;
case 'L':
if (localViewer) localViewer = 0; else localViewer = 1;
glutPostRedisplay();
break;
case 'p':
if (p) p = 0.0; else p = 1.0;
glutPostRedisplay();
break;
case 'P':
if (p) p = 0.0; else p = 1.0;
glutPostRedisplay();
break;
case 'd':
if (d > 0.0) d -= 0.05;
glutPostRedisplay();
break;
case 'D':
if (d < 1.0) d += 0.05;
glutPostRedisplay();
break;
case 'm':
if (m > 0.0) m -= 0.05;
glutPostRedisplay();
break;
case 'M':
if (m < 1.0) m += 0.05;
glutPostRedisplay();
break;
default:
break;
}
}
// Callback routine - Go Back to the Documentation if I'm still confused by the key setup
void specialKeyInput(int key, int x, int y)
{
if(key == GLUT_KEY_DOWN)
{
xAngle++;
if (xAngle > 360.0) xAngle -= 360.0;
}
if(key == GLUT_KEY_UP)
{
xAngle--;
if (xAngle < 0.0) xAngle += 360.0;
}
if(key == GLUT_KEY_RIGHT)
{
yAngle++;
if (yAngle > 360.0) yAngle -= 360.0;
}
if(key == GLUT_KEY_LEFT)
{
yAngle--;
if (yAngle < 0.0) yAngle += 360.0;
}
glutPostRedisplay();
}
// Instructions how to use all of the lights. It should appear in the console. If I get anymore errors. I'll jump off a roof
void printInteraction(void)
{
cout << "How to use the different lights" << endl;
cout << "Press 'w' (or 'W') to toggle the white light off/on." << endl
<< "Press 'g' (or 'G') to toggle the green light off/on." << endl
<< "Press 'd/D' to decrease/increase the white light's diffuse and specular intensity." << endl
<< "Press 'm/M' to decrease/increase global ambient white light intensity." << endl
<< "Press 'l' (or 'L') to toggle between infinite and local viewpoint." << endl
<< "Press 'p' (or 'P') to toggle between positional and directional white light." << endl
<< "Press arrow keys to rotate the white light." << endl
<< "Type SLEEP if you hate finals and you want to go to bed" << endl;
}
// Main - Put ALL of the functions above here
int main(int argc, char **argv)
{
printInteraction();
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize (100, 100);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Turn off the Lights. Light a Candle.cpp");
setup();
glutDisplayFunc(drawScene);
glutReshapeFunc(resize);
glutKeyboardFunc(keyInput);
glutSpecialFunc(specialKeyInput);
glutMainLoop();
return 0;
}
I’m going to let Teddy Pendergrass send me off by turning off the lights. Happy Holidays. KO
+

































