Tuesday, December 5, 2017

Simple Wavefront .OBJ Model Loader in JOGL

Wavefront .OBJ files are the most simplest of models that can be loaded into OpenGL. I have loaded some simple files and it has worked well. Im still working on other files containing negative vertex indexes.

This is an image of an elephant and a college visualized in a model mentioned in this site=> http://netization.blogspot.in/2014/10/loading-obj-files-in-opengl.html

On request I have texture mapped a custom texture to the elephant body(Chess board pattern)





If you are interested in the .OBJ model file format it is a simple text based model. It does not use any compression in storing the vertices or their relations. Hence this file format is human readable to some extent and editable to a fair degree of control. I am reproducing some text describing the format from an E-Book by David J Eck(without permission of course).
Wavefront .OBJ file format:
For complex shapes that are not described by any simple mathematical formula, it’s not feasible to generate the shape using Java code. We need a way to import shape data into our programs from other sources. The data might be generated by physical measurement, for example, or by an interactive 3D modeling program such as Blender (http://www.blender.org). To make this possible, one program must write data in a format that can be read by another program. The two programs need to use the same graphics file format. One of the most common file formats for the exchange of polygonal mesh data is the Wavefront OBJ file format. Although the official file format can store other types of geometric data, such as Bezier curves, it is mostly used for polygons, and that’s the only use that we will consider here.
An OBJ file (with file extension “.obj”) can store the data for an indexed face set, plus normal vectors and texture coordinates for each vertex. The data is stored as plain, human-readable text, using a simple format. Lines that begin with “v”, “vn”, “vt”, or “f”, followed by a space, contain data for one vertex, one normal vector, one set of texture coordinates, or one face, respectively. For our purposes here, other lines can be ignored. A line that specifies a vertex has the form
v x y z
where x, y, and z are numeric constants giving the coordinates of the vertex. For example:
v 0.707 -0.707 1
Four numbers, specifying homogeneous coordinates, are also legal but, I believe, rarely used. All the “v” lines in the file are considered to be part of one big list of vertices, and the vertices are assigned indices based on their position in the list. The indices start at one not zero, so vertex 1 is the vertex specified by the first “v” line in the file, vertex 2 is specified by the second “v” line, and so on. Note that there can be other types of lines interspersed among the “v” lines—those extra lines are not counted when computing the index of a vertex.
Lines starting with “vn” or “vt” work very similarly. Each “vn” line specifies a normal vector, given by three numbers. Normal vectors are not required to be unit vectors. All the “vn” lines in the file are considered to be part of one list of normal vectors, and normal vectors are assigned indices based on their order in the list. A “vt” line defines texture coordinates with one, two, or three numbers. (Two numbers would be used for 2D image textures.) All the “vt” lines in the file create a list of texture coordinates, which can be referenced by their indices in the list.
Faces are more complicated. Each “f” line defines one face, that is, one polygon. The data on the “f” line must give the list of vertices for the face. The data can also assign a normal vector and texture coordinates to each vertex. Vertices, texture coordinates, and normals are referred to by giving their indices in the respective lists. (Remember that the numbering starts from one, not from zero; if you’ve stored the data in Java arrays, you have to subtract 1 from the numbers given in the “f” line to get the correct array indices. There reference numbers can be negative. A negative index in an “f” line means to count backwards from the position of the “f” line in the file. For example, a vertex index of −1 refers to the “v” line that was seen most recently in the file, before encountering the “f” line; a vertex index of −2 refers the “v” line that precedes that one, an so on. If you are reading the file sequentially and storing data in arrays as you go, then −1 simply refers to the last item that is currently in the array, −2 refers to the next-to-last item, and so on.)
In the simple case, where there are no normals or texture coordinates, an “f” line can simply list the vertex indices in order. For example, an OBJ file for the pyramid example from the previous subsection could look like this:
v 1 0 1
v 1 0 -1
v -1 0 -1
v -1 0 1
v 0 1 0
f 5 4 1
f 5 1 2
f 5 2 3
f 5 3 4
f 1 4 3 2
When texture coordinate or normal data is included, a single vertex index such as “5” is replaced by a data element in the format v/t /n, where v is a vertex index, t is a texture coordinates index, and n is a normal coordinate index. The texture coordinates index can be left out, but the two slash characters must still be there. For example, “5/3/7” specifies vertex number 5, with texture coordinates number 3, and normal vector number 7. And “2//1” specifies vertex 2 with normal vector 7. As an example, here is complete OBJ file representing a cube, with its normal vectors, exactly as exported from Blender. Note that it contains additional data lines, which we want to ignore:
# Blender3D v248 OBJ File:
# www.blender3d.org
mtllib stage.mtl
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vn -0.000000 -1.000000 0.000000
vn 0.000000 1.000000 -0.000000
vn 1.000000 0.000000 0.000000
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl Material
s off
f 1//1 2//1 3//1 4//1
f 5//2 8//2 7//2 6//2
f 1//3 5//3 6//3 2//3
f 2//4 6//4 7//4 3//4
f 3//5 7//5 8//5 4//5
f 5//6 1//6 4//6 8//6

Once you have read a geometric object from an OBJ file and stored the data in arrays, it is easy enough to use the arrays to draw the object with OpenGL.

Monday, December 4, 2017

Object Model Loader in OpenGL

The example provided here at this site was the most simplest of all loaders that I could find on the Internet. I am now trying to load Wavefront .obj files created in Blender in C++ OpenGL.

Here are the snaps of the few objects loaded...
In reverse order
Elephant
College
Porsche
Radar
Teddy


You can download the source and obj files from the site mentioned.
Things that you can do with these files is you can group vertices into faces and faces into components which you can transform and animate in 3D. For example you can load the model created in Blender exported as OBJ file into OpenGL and then display them the way you want.

I have implemented some of the tasks mentioned above a post in this next post: >>>>>> Click Here <<<<<< to visit.


Tuesday, November 28, 2017

Mandelbrot and Julia Set in OpenGL

I have ported the C code from an earlier project to OpenGL. This code runs much faster with better compiler than the earlier runtime environment of TurboC++.
You have to click on certain regions of the Mandelbrot Set and get the Julia Set.

Snapshots:


After clicking a point in the above diagram we get this image below:
(Hint: Those regions that are at the boundary of the Mandelbrot set have got richer Julia set patterns, hence clicking on anywhere and everywhere will not get you interesting patterns)


Here is the source.

This e-book is a really good source of reference for the theory behind this....

Chaos
It has the following chapters:

Iteration
Bifurcation
Universality
Strange Attractors
Strange and Complex
Julia Sets
Mandelbrot Sets
About Dimension
Euclidean Dimension
Topological Dimension
Fractal Dimension
Measuring Chaos
Harmonic Oscillator
Logistic Equation
Lyapunov Exponent
Lyapunov Space
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In JOGL the same thing implemented using Modern OpenGL published in the site:
https://blog.nobel-joergensen.com/

Snapshot:

Here is a link to the Source into my Github.

Wednesday, November 22, 2017

Blender Cup

I have followed a tutorial on making a cup in blender to make well, a cup. Here are two views of the final rendered cup.



This is the link to the video I followed and I recommend people to try making this at leisure.
https://www.youtube.com/watch?v=y__uzGKmxt8
The experience is exhilarating!
After yesterday's adventure I set out to repeat the exercise today again. After several blunders and having many re-looks at the video I generated the following cup(remade from a different view and resolution)

Following this I have made cloth simulation and generated the following image at resolution of 2000.


Friday, September 15, 2017

Engineer's Day Special - Baggage carousel

Tributes to Mokshagundam Visveswaraya who was born on 15th Sept. This day is celebrated as Engineer's day here in India. My college student who needed to visualize a conveyor belt for his student project to be displayed to people on engineers day sought my help. I did this project for him and it probably got him some confidence in his idea of RFID based tagging of luggage in airports. Here is the project on Conveyor Belt at airports. The application once complete will include RFID sensor and a mobile app which people can launch and see for themselves where on the belt their baggage is located.

Snapshot:

Here is the source.

Sunday, September 3, 2017

BrainVita - Marbles - A Game

This game was originally written by me in C++ and now ported to JOGL. I messed up the array part and was hunting online for errors such as arrayindexoutofbounds exception etc. A click outside the marble area still selects a region where marbles don't exist. I have left such bugs to be sorted out by someone truly interested in making this game production grade.

Here is the source.

Here is the snap:

Saturday, September 2, 2017

Ping Pong Balls

I have ported the ping pong balls program to Java OpenGL. Here is the program. As usual the program is not working completely.
The ball collides with the walls and the floor but bounces every time. I meant this as a game of fighting with gravity where the ball falls though the ground and only the tile at the bottom makes it bounce. There are so many unfinished projects in this blog that it will take you quite a lot of time setting things in order. You need to complete these games.


Friday, August 11, 2017

Bresenham's Line Drawing and Mid-Point Circle in Java Graphics 2D

Hello,

I am posting two of my programs which create a line and circle using the bresenham's line drawing and Mid-Point Circle.
Snapshots:


The code for:
Brezenham's Algorithm in Java Graphics2D: Here
Mid Point Circle Algorithm in Java Graphics2D: Here

Smiley Face Created Using JFrame and JPanel(Java Graphics)


Friday, August 4, 2017

Animation, Visual Effects, Gaming and Comics(AVGC) Sector in India

Online gaming is a rising sector in India. There are more people interested in game development and with increasing quality of engineers passing out each year, it is just a matter of time before India becomes a major powerhouse of gaming and animation. Everyone I meet talks of making android games.
It is said that majority of the work happening in the country is low end. We still lack in quality of gaming professionals.
There are is a lot of talent esp artistic talent. Numbers that I read are like gaming industry was worth more than 1 billion dollars in 2012. Karnataka itself has about 20 animation and gaming training institutes with more than 60 campuses training about 10,000 students at any time. This sector is a ripe area for collaboration between major engineering colleges and such run of the mill Institutes running on rented premises.
There is lot of scope for joint projects/infrastructure sharing and joint diploma courses. Launching high end game titles require years of experience in algorithms, computer graphics as well as art. Software industry is nearing stagnation and revenue growth has slowed. Young software engineers may not be suitable in AVGC Industry as they may not possess requisite skills.
We cannot foresee an electronic arts(EA),Adobe or Pixar kind of company to germinate in India at the moment but there are ominous signs of such a possibility in the future.

Friday, July 7, 2017

Install NetBeans and configure for run Java OpenGL

This is dead easy.

1)Install NetBeans and in it create a project.
2)Download these Jars(assuming you  are using windows).
3) On the library folder right click and click add Jar/folder in the popup menu.
4) Add gluegen-rt.jar and jogl-all.jar files to the library.

There you go you can run jogl programs in this project. Only thing is you need to do this for every project.

Install eclipse and configure it for Java OpenGL

When I was born, I knew nothing - anonymous

JRE library is required to run Eclipse so install JRE latest version.
·         Download a JogAmp library
If you haven't done so already, download and extract the JogAmp library you want to use.
For example, to download and extract JOGL, see the following instructions
1) Go to the site http://jogamp.org/deployment/jogamp-current/archive/jogamp-all-platforms.7z and download should automatically start. The zipped archive is about 54MB. If you are short of data balance, better to get the library (zipped file) from a friend.
2) Unzip the .7z file which is a zipped(compressed) file.
3) Only two jar files are all that is needed from this archive. They are glugen-rt.jar and jogl-all.jar.
4) If you are only working in windows download only these four jar files from my gdrive
·         Eclipse IDE project
Probably the simplest way to use JOGL in an Eclipse project is to create another Eclipse project to contain the JOGL JARs, then make your project depend on this new JOGL project. In the example below, I include only the 64-bit Windows native JARs, but you can put native JARs for as many platforms as you wish together into the JOGL Eclipse project.

1) Create a JOGL project

Put all the JOGL code JARs, native JARs for all platforms you wish to support, and source ZIP files in a directory called "JOGL" in your workspace directory.
Click "File > New > Java Project". Type "JOGL" as the project name and click "Next".


2) Click next and in the next page go to the tab libraries.
Click on add external jars. Then navigate to the folder where you have extracted the zip file in the previous step. In the jogamp-all-platforms folder go to the jar folder and add the jar files glugen-rt.jar and jogl-all.jar.


 3) Expand the jogl-all and gluegen-rt JARs. For each of them, double-click "Source attachment", click "Workspace...", navigate to the corresponding *-java-src.zip file in the project, select it, click "OK", and click "OK" again to dismiss the "Source Attachment Configuration" dialog. The JARs should look like this when you're done:

4) Click the "Order and Export" tab. Check both JOGL JARs, then click "Finish".

­
5) Create another java project and add dependency on the JOGL project

    Create another project, give a name and select next.  or if you have an existing project then
    Right-click your project and click "Properties".
    Select the "Java Build Path" on the left, then click the "Projects" tab on the right.
    Click the "Add..." button, check "JOGL", and click "OK".
    Your dependent project should look like this. Click "OK" to dismiss the "Properties" dialog.




That's it! Your project can now use the library.

Wednesday, July 5, 2017

Tetris Game

Tetris is a very popular game among children. It is considered one of the arcade/classical games. An aspiring game developer is recommended to develop a game of Tetris. It is the "Hello World of the Gaming Industry". Wiki page of Tetris says It is a tile-matching puzzle video game, originally designed and programmed by Russian game designer Alexey Pajitnov.
Readers and players would not need any instructions to start playing this one. The Goal? It is to play as long as possible. The game is time based. We would have played this game in our mobiles/consoles since childhood is'nt it.
Developing this game is not as easy as playing it and will test the intelligence of an average coder.
I encountered some problems in rotating the tetris and stacking the tetrises over one another. I am giving a link to my GDrive the code that implements the game of Tetris that I developed. You are welcome to modify the code and I would recommend you give out this code to others too. In the game I developed some problems are yet to be sorted out.
>>>>>Click Here<<<<< for the Code.
If you want to modify my code then you need to
1) Detect the end of the game.
2) Display points scored and create a two level game.
3) Draw the boxes in a better manner may be with borders for each box and some pattern filled inside them.(OO code esp a class to draw each Tetris may be useful here)
4) Delete a completed row at the bottom and increment the points which it does not do.
5) If down arrow is pressed the Tetris should fall by two or more steps.

As a developer it gives me immense displeasure to display "Game Over" and most of the time based games I develop do not have any end. I just let players start the game and play and whatever happens in the end is the untested and un-anticipated part.

Tuesday, July 4, 2017

Tetris in Java OpenGL

The tetris C code has now been ported to Java OpenGL. I did the porting in two sittings of two hours each. It involved quite a lot of changes and I emerged victorious. There was one nagging runtime ArrayIndexOutOfBoundsException which caused a lot of testing time to be wasted.

Here is the code.

Snapshot:

Tuesday, April 11, 2017

Fractal Tree-3D in C#

Following snapshots were obtained in visual studio 2013 using c# and OpenGL.




I rotated the scene and got different views of the tree. The same program implemented in C++ is now done at this place.

Here is the source.
------------------------------------
Update(May,2024):

Sunday, March 5, 2017

Fractal Tree in C++ using OpenGL

A 2D fractal tree using code in the site rosettacode.org in openGL. I am intending to modify the program to make it a 3D tree.

Here is the SnapShot:(Actually the tree drawn is upside down)


Here is the code. I have now succeeded in making a 3D tree albeit in c# which is there in the next post here.

Sunday, January 15, 2017

Points in 3D with gaussian Distribution

Snapshot:


In JOGL this is so easy that I was amazed. Im Trying to generate blobby objects. In the hearn and baker text book its mentioned that points in a gaussian distribution with a surface where the density of the points falls below a threshold is rendered. Will keep updated everyone if this does result in a blobby object.
This piece of code does the magic:

                GL2 gl = arg0.getGL().getGL2();
for(int i=0;i<MAX_RAND;i++)
{
x[i]=1-randomno.nextGaussian()*2;
y[i]=1-randomno.nextGaussian()*2;
z[i]=1-randomno.nextGaussian()*2;
}
gl.glBegin(GL2.GL_POINTS);
for(int i=0;i<MAX_RAND;i++)
{

gl.glVertex3d(x[i],y[i],z[i]);

}
gl.glEnd();

Thanks!

Sunday, January 8, 2017

Car Viewer in TurboC++

This project was created  several years back when I was not good at programming. I was a learner then. I knew very little of graphics. Yet I tried to rotate and do coordinate transformations. This project does viewing... For theory behind this refer James D Foley "Computer Graphics"

Snapshot:


It was supposed to be a car but without wheels.
I am pasting the source here itself for online viewing.

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include<math.h>
#include<dos.h>
#include<stdlib.h>

typedef struct
{float x,y,z;
}point;

typedef struct
{float dx,dy,dz;
}vector;

typedef struct
{int v1,v2; //two vertices of an edge (index into vertices)
}edge;

/*typedef struct
{int e1,e2,e3,e4;     //index into edges
}polygon;
*/
point vertices[40];
edge edges[50];
//polygon polymesh[20];

int noofpolygons,noofedges,noofvertices;
float cosx,sinx,cosy,siny,cosz,sinz,d,umin,umax,vmin,vmax;
float shxpar,shypar,sperx,spery,sperz,f,b;
point vrp,prp,cube[8];
vector vpn,vup={0,1,0},dop;

point transform( point p)
{
 float x,y,z;

  p.x=p.x-vrp.x;        //translate by t(-vrp)
  p.y=p.y-vrp.y;
  p.z=p.z-vrp.z;

  x=p.x;                // rotate wrt y
  p.x=p.x*cosy+p.z*siny;
  p.z=-x*siny+p.z*cosy;

  y=p.y;               // rotate wrt x
  p.y=p.y*cosx-p.z*sinx;
  p.z=y*sinx+p.z*cosx;

  x=p.x;              // rotate wrt z
  p.x=p.x*cosz-p.y*sinz;
  p.y=x*sinz+p.y*cosz;

  p.x=p.x-prp.x;         // translate by t(-prp)
  p.y=p.y-prp.y;
  p.z=p.z-prp.z;

/*  p.x=p.x+shxpar*p.z;     //shear such that dop is z axis
  p.y=p.y+shypar*p.z;

  p.x*=sperx;            // scale such that the size of view
  p.y*=spery; // volume is canonical view volume
  p.z*=sperz;           */

  p.x*=(d/p.z);           // project onto proj n plane
  p.y*=(d/p.z);
  p.z=d;

  return(p);
}
void findmcomp()
{float d1,d2,d3,x,y,z;
     // rotate wrt y
 d=prp.z;
 d1=sqrt(vpn.dx*vpn.dx+vpn.dz*vpn.dz);
 cosy=vpn.dz/d1;
 siny=vpn.dx/d1;

 vpn.dx=0;
 vpn.dz=d1;

 x=vup.dx;
 vup.dx=vup.dx*cosy+vup.dz*siny;
 vup.dz=-x*siny+vup.dz*cosy;
 // rotate wrt x
 d2=sqrt(vpn.dx*vpn.dx+vpn.dy*vpn.dy+vpn.dz*vpn.dz);

 cosx=d1/d2;
 sinx=vpn.dy/d2;

 vpn.dy=0;
 vpn.dz=d2;

 y=vup.dy;
 vup.dy=vup.dy*cosx-vup.dz*sinx;
 vup.dz=y*sinx+vup.dz*cosx;   // this will be zero;
   // rotate wrt z
 d3=sqrt(vup.dx*vup.dx+vup.dy*vup.dy);

 cosz=1;//vup.dy/d3;
 sinz=0;//vup.dx/d3;

 vup.dx=0;
 vup.dy=d3;

/* dop.dx=(umax-umin)/2-prp.x;
 dop.dy=(vmax-vmin)/2-prp.y;
 dop.dz=-prp.z;

 shxpar=-dop.dx/dop.dz;
 shypar=-dop.dy/dop.dz;

 sperx=-2*prp.z/((umax-umin)*(-prp.z+b));
 spery=-2*prp.z/((vmax-vmin)*(-prp.z+b));
 sperz=-1/(-prp.z+b);     */
}
void initializevertices()
{
/* car */
vertices[0].x=10;vertices[0].y=0;vertices[0].z=10;    //0
vertices[1].x=50;vertices[1].y=0;vertices[1].z=10;    //1
vertices[2].x=50;vertices[2].y=30;vertices[2].z=15;  //2
vertices[3].x=10;vertices[3].y=30;vertices[3].z=15;  //3
vertices[4].x=10;vertices[4].y=40;vertices[4].z=50;  //4
vertices[5].x=50;vertices[5].y=40;vertices[5].z=50;   //5
vertices[6].x=50;vertices[6].y=70;vertices[6].z=55;       //6
vertices[7].x=10;vertices[7].y=70;vertices[7].z=55;      //7
vertices[8].x=10;vertices[8].y=70;vertices[8].z=95;     //8
vertices[9].x=50;vertices[9].y=70;vertices[9].z=95;     //9
vertices[10].x=50;vertices[10].y=40;vertices[10].z=100;    //10
vertices[11].x=10;vertices[11].y=40;vertices[11].z=100;    //11
vertices[12].x=10;vertices[12].y=30;vertices[12].z=135;    //12
vertices[13].x=50;vertices[13].y=30;vertices[13].z=135;   //13
vertices[14].x=50;vertices[14].y=0;vertices[14].z=140;   //14
vertices[15].x=10;vertices[15].y=0;vertices[15].z=140;   //15
vertices[16].x=10;vertices[16].y=0;vertices[16].z=100;   //16
vertices[17].x=50;vertices[17].y=0;vertices[17].z=100; // 17
vertices[18].x=50;vertices[18].y=0;vertices[18].z=95;  //18
vertices[19].x=10;vertices[19].y=0;vertices[19].z=95;  //19
vertices[20].x=10;vertices[20].y=0;vertices[20].z=55;  //20
vertices[21].x=50;vertices[21].y=0;vertices[21].z=55; //21
vertices[22].x=50;vertices[22].y=0;vertices[22].z=50; //22
vertices[23].x=10;vertices[23].y=0;vertices[23].z=50;  //23
vertices[24].x=50;vertices[24].y=40;vertices[24].z=30;  //24
vertices[25].x=10;vertices[25].y=40;vertices[25].z=30;  //25
vertices[26].x=50;vertices[26].y=40;vertices[26].z=115;  //26
vertices[27].x=10;vertices[27].y=40;vertices[27].z=115;  //27
}
void initializeedges()
{
 /* car */
 edges[0].v1=0;edges[0].v2=1;    //1
 edges[1].v1=1;edges[1].v2=2;   //2
 edges[2].v1=2;edges[2].v2=3;  //3
 edges[3].v1=3;edges[3].v2=0;   //4
 edges[4].v1=3;edges[4].v2=25;  //5
 edges[5].v1=4;edges[5].v2=5;  //6
 edges[6].v1=5;edges[6].v2=6;  //7
 edges[7].v1=6;edges[7].v2=7;  //8
 edges[8].v1=7;edges[8].v2=4;  //9
 edges[9].v1=7;edges[9].v2=8;  //10
 edges[10].v1=8;edges[10].v2=9;  //11
 edges[11].v1=9;edges[11].v2=10;  //12
 edges[12].v1=10;edges[12].v2=11;  //13
 edges[13].v1=11;edges[13].v2=8;  //14
 edges[14].v1=9;edges[14].v2=6;  //15
 edges[15].v1=27;edges[15].v2=11;  //16
 edges[16].v1=12;edges[16].v2=13;  //17
 edges[17].v1=10;edges[17].v2=26;  //18
 edges[18].v1=13;edges[18].v2=14;  //19
 edges[19].v1=14;edges[19].v2=15;  //20
 edges[20].v1=15;edges[20].v2=12;  //21
 edges[21].v1=15;edges[21].v2=16;  //22
 edges[22].v1=16;edges[22].v2=17;  //23
 edges[23].v1=17;edges[23].v2=14;  //24
 edges[24].v1=18;edges[24].v2=19;  //25
 edges[25].v1=19;edges[25].v2=20;  //26
 edges[26].v1=20;edges[26].v2=21;  //27
 edges[27].v1=21;edges[27].v2=18;  //28
 edges[28].v1=22;edges[28].v2=23;  //29
 edges[29].v1=23;edges[29].v2=0;   //30
 edges[30].v1=22;edges[30].v2=1;   //31
 edges[31].v1=24;edges[31].v2=2;  //32
  edges[32].v1=24;edges[32].v2=25;  //33
   edges[33].v1=25;edges[33].v2=4;  //34
    edges[34].v1=24;edges[34].v2=5;  //35
     edges[35].v1=26;edges[35].v2=27;  //36
      edges[36].v1=27;edges[36].v2=12;  //37
       edges[37].v1=26;edges[37].v2=13;  //38
       edges[38].v1=5;edges[38].v2=22;  //38
       edges[39].v1=4;edges[39].v2=23;  //38
       edges[40].v1=10;edges[40].v2=17;  //38
       edges[41].v1=11;edges[41].v2=16;  //38
       edges[42].v1=5;edges[42].v2=10;  //38
       edges[43].v1=4;edges[43].v2=11;  //38
}
void initializepolymesh()
{

}
void initializeobjects()
{
  initializevertices();
  initializeedges();
  initializepolymesh();
}
void display()
{
  for(int i=0;i<44;i++)
  line(vertices[edges[i].v1].x+320,240+vertices[edges[i].v1].y,vertices[edges[i].v2].x+320,240+vertices[edges[i].v2].y);
}
void findvrpprpvpn(float theta)
{ float rtheta1,rtheta2,lvpn;

   rtheta1=theta*3.141/180;
   rtheta2=(theta+180)*3.141/180;
   vrp.x=20*cos(rtheta1)+30;
   vrp.z=20*sin(rtheta1)+75;
   vrp.y=120;

   prp.x=50*cos(rtheta2)+30;
   prp.z=50*sin(rtheta2)+30;
   prp.y=130;

   vpn.dx=vrp.x-prp.x;
   vpn.dy=vrp.y-prp.y;
   vpn.dz=vrp.z-prp.z;

   lvpn=sqrt(vpn.dx*vpn.dx+vpn.dy*vpn.dy+vpn.dz*vpn.dz);
   vpn.dx=vpn.dx/lvpn;
   vpn.dy=vpn.dy/lvpn;
   vpn.dz=vpn.dz/lvpn;
//   putpixel(prp.x+320,240-prp.z,WHITE);
   prp.x=0;
   prp.y=0;
   prp.z=120;
}
void main()
{
 int gd=DETECT,gm;
 float theta;
 char text[10];
 initgraph(&gd,&gm,"c:\\tc\\bgi");
 moveto(0,0);
  theta=0;
  while(!kbhit())
  {findvrpprpvpn(theta);
   findmcomp();
   initializeobjects();
   for(int i=0;i<32;i++)
    vertices[i]=transform(vertices[i]);
   delay(50);
   cleardevice();
   display();
    theta+=0.1;
    if(theta>360) theta=0;
   }
  getch();
  closegraph();
}

Very soon I will modify the code to perform 3D viewing from any arbitrary position. Currently I am assuming many things. Will post the modified code soon. Several bugs in the software... got confused with x,y and z axis.