Thursday, October 9, 2014

This is a simple tutorial to load a .obj file (wavefront .obj) using OpenGL. I came up with this loader during my university project, where I had a requirement to load various objects into my OpenGL scene. The aim of the project was to build a 3D environment containing various objects around which one could roam about in first person view as in free roaming games.

I wanted to include objects like cars, air-crafts, boats etc in my OpenGL scene. It was then that I stumbled upon wavefront .obj files. I realized that there were plenty of cool and complex objects available all over the internet in wavefront .obj file format. But I could not put them to use as I did not have a loader that loaded these .obj files into my scene.

Then I thought I must understand the wavefront .obj file format. I spent a few minutes understanding the obj format and a few more minutes to write a code that reads the vertex information from it and renders the object defined in the .obj file using GL_Points. After a few minutes of coding, what I got was a clean loader which was capable of displaying the object in the .obj file.

You can read about wavefront .obj file from here: http://en.wikipedia.org/wiki/Wavefront_.obj_file

A simple wavefront .obj loader in OpenGL using C



//headers
#include<GL/gl.h>
#include<GL/glut.h>
#include<stdio.h>
//globals
GLuint elephant;
float elephantrot;
char ch='1';
//other functions and main
//wavefront .obj loader code begins
void loadObj(char *fname)
{
    FILE *fp;
    int read;
    GLfloat x, y, z;
    char ch;
    elephant=glGenLists(1);
    fp=fopen(fname,"r");
    if (!fp)
    {
        printf("can't open file %s\n", fname);
        exit(1);
    }
    glPointSize(2.0);
    glNewList(elephant, GL_COMPILE);
    {
        glPushMatrix();
        glBegin(GL_POINTS);
        while(!(feof(fp)))
        {
            read=fscanf(fp,"%c %f %f %f",&ch,&x,&y,&z);
            if(read==4&&ch=='v')
            {
                glVertex3f(x,y,z);
            }
        }
        glEnd();
    }
    glPopMatrix();
    glEndList();
    fclose(fp);
}
//wavefront .obj loader code ends here
void reshape(int w,int h)
{
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 0.1, 1000.0);
    //glOrtho(-25,25,-2,2,0.1,100);
    glMatrixMode(GL_MODELVIEW);
}
void drawElephant()
{
    glPushMatrix();
    glTranslatef(0,-40.00,-105);
    glColor3f(1.0,0.23,0.27);
    glScalef(0.1,0.1,0.1);
    glRotatef(elephantrot,0,1,0);
    glCallList(elephant);
    glPopMatrix();
    elephantrot=elephantrot+0.6;
    if(elephantrot>360)elephantrot=elephantrot-360;
}
void display(void)
{
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    drawElephant();
    glutSwapBuffers(); //swap the buffers
}
int main(int argc,char **argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
    glutInitWindowSize(800,450);
    glutInitWindowPosition(20,20);
    glutCreateWindow("ObjLoader");
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutIdleFunc(display);
    loadObj("data/elepham.obj");//replace elepham.obj withp orsche.obj or radar.obj or any other .obj to display it
    glutMainLoop();
    return 0;
}


Screenshots of the .obj loader loading objects into a OpenGL scene

You can also download the complete repository from my github page at https://github.com/nanosmooth/opengl_objloader

Saturday, September 27, 2014

Lets have a look at a simple way to make images scale responsively in a webpage in response to the device on which the webpage is viewed. In the example considered below, the image will scale responsively to the required dimension, stay aligned to the center and will maintain its aspect ratio. If you are viewing this page on a desktop / laptop, try to resize the browser to smaller dimensions and you can see that the image will resize to the browser's width. In fact, all elements including the images on this site is designed to resize (i.e., show a responsive behavior) keeping in mind the responsive web design techniques.

Demo

(Resize your browser window)

This is achieved by wrapping the img element into a div section with style containing the property 'display' with value 'table' and for the property 'margin' we provide a value '20px auto' signifying that we need a margin of 20px on the top and bottom of the div section and let the browser calculate the left and right margins automatically so as the keep the div section centered horizontally. In the img tag make sure the width property is specified with a value set to 100%.

Code


Monday, September 15, 2014

Here is a simple way to generate a web form which has default values loaded into the text fields without actually using a placeholder tag. A placeholder tag is only supported by few browsers. This form uses javascript to achieve the same functionality and works with all browsers having javascript enabled.

This is how the signup form behaves in action.

Demo

New user? Sign up below...

Given below is the code to create the above signup form, without using placeholder tag.

HTML


CSS


JavaScript


Sunday, September 14, 2014

Creating a facebook login for a website involves the following 3 activities on a high-level. Each of these have been explained in detail below.

  • Obtain App ID and App Secret which is required to initialize the Facebook SDK for login.

  • Download and configure(if required) the Facebook PHP SDK for your website.

  • Authenticate, Authorize and Make requests to the Graph API to obtain the required facebook user information.

Obtaining App ID and App Secret


  • Create and configure a Facebook App in the name of your project here http://developers.facebook.com/apps
  • Click on the Add a New App button as shown below
    Add a New App
  • Select the fourth circle - WWW Website
    Add a New App
  • In the next window, click on "Skip Quickstart" as you don't have anything existing to be configured. Type in the name of your application as desired, select an appropriate category below and click on Create App.
    Create a New App
  • Now you have your App ID and App Secret which you will be making use to initialize the Facebook PHP SDK and get the user information.

    App ID and App Secret

Download the Facebook PHP SDK


You can download the facebook php sdk from here https://github.com/facebook/facebook-php-sdk-v4/archive/4.0-dev.zip

Once downloaded, unpack the contents. Rename the folder "facebook-php-sdk-v4-4.0-dev" to "facebook-php-sdk" for the sake of simplicity. Make sure you move this folder to the same directory which contains your website's index.php i.e., your website's root folder.


Authentication , Authorization and Making requests to the Graph API to obtain the required facebook user information


Facebook login in simple terms can be stated as follows:
  • Create a helper object, which will help you in generating 'Login URL' and 'Logout URL'.
  • Login URL will take a new user to facebook login page for authentication and redirect to a page as specified by redirectUrl of getLoginUrl() on successful authentication.
  • Logout URL will take an signed in user to facebook's logout page and redirect to a page as specified by redirectUrl of getLogoutUrl().
  • Do a bit of session management.
  • Retrieve user information from Facebook's Graph API.
Also note that you will be taken to the page as specified by redirectUrl only after you make an entry of the absolute path name of the redirect page in your facebook's app. This can be done as follows:

Go to Dashboard >> Settings >> Advanced >> Valid OAuth redirect URIs
Make the entry and save changes.

In the code shown below I have considered two files:
  • index.php
  • fbhome.php
The code is run on xampp local host and the project is named as 'floginproj'. index.php contains the login link which when pressed takes you to facebook login page, after authentication you are redirected to 'fbhome.php'. In fbhome.php you can retrieve the necessary user information obtained via the graph API and store them in the database or use them further as required in your website.

Here is the code:

index.php fbhome.php

Common Errors:


In this section, I've listed down the most common errors you might come across while performing the above steps. Most of the errors given below might happen if you are using a php version lesser than php 5.4. Facebook documentation already mentions that. But in case you are using a lower version you might come across these errors and I have provided a fix.

Parse error: syntax error, unexpected T_OBJECT_OPERATOR in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookResponse.php on line 137

change this >>>
public function getGraphObject($type = 'Facebook\GraphObject') {
return (new GraphObject($this->responseData))->cast($type);
}
to this >>>
public function getGraphObject($type = 'Facebook\GraphObject') {
$GraphObj1=new GraphObject($this->responseData);
$GraphObj=$GraphObj1->cast($type);
return $GraphObj;
}

Parse error: syntax error, unexpected T_OBJECT_OPERATOR in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookResponse.php on line 154

change this >>>
$out[] = (new GraphObject($data[$i]))->cast($type);
to this >>>
$GraphObjData1=new GraphObject($data[$i]);
$GraphObjData=$GraphObjData1->cast($type);
$out[]=$GraphObjData;

Parse error: syntax error, unexpected T_OBJECT_OPERATOR in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRedirectLoginHelper.php on line 146

change this >>>
$response = (new FacebookRequest(
FacebookSession::newAppSession($this->appId, $this->appSecret),
'GET',
'/oauth/access_token',
$params
))->execute()->getResponse();
to this >>>
$response1= (new FacebookRequest(
FacebookSession::newAppSession($this->appId, $this->appSecret),
'GET',
'/oauth/access_token',
$params
));
$response2 = $response1->execute();
$response = $response2->getResponse();

Parse error: syntax error, unexpected T_OBJECT_OPERATOR in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\GraphObject.php on line 111

change this >>>
return (new GraphObject($value))->cast($type);
to this >>>
$GraphObjProp1 = new GraphObject($value);
$GraphObjProp = $GraphObjProp->cast($type);
return $GraphObjProp;

Parse error: syntax error, unexpected T_OBJECT_OPERATOR in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\GraphObject.php on line 147

change this >>>
$out[$key] = (new GraphObject($value))->cast($type);
to this >>>
$GraphObjProp1 = new GraphObject($value);
$GraphObjProp = $GraphObjProp->cast($type);
$out[$key] = $GraphObjProp;

Fatal error: Call to undefined function Facebook\session_status() in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRedirectLoginHelper.php on line 189

change this >>>
protected function storeState($state)
{
if ($this->checkForSessionStatus === true
&& session_status() !== PHP_SESSION_ACTIVE) {
throw new FacebookSDKException(
'Session not active, could not store state.', 720
);
}
$_SESSION[$this->sessionPrefix . 'state'] = $state;
}
to this >>>
protected function storeState($state)
{ $setting = 'session.use_trans_sid';
$current = ini_get($setting);
if (FALSE === $current)
{
throw new UnexpectedValueException(sprintf('Setting %s does not exists.', $setting));
}
$testate = "mix$current$current";
$old = @ini_set($setting, $testate);
$peek = @ini_set($setting, $current);
$result = $peek === $current || $peek === FALSE;
if ($this->checkForSessionStatus === true
&& $result !== true) {
throw new FacebookSDKException(
'Session not active, could not store state.', 720
);
}
$_SESSION[$this->sessionPrefix . 'state'] = $state;
}

Fatal error: Call to undefined function Facebook\session_status() in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRedirectLoginHelper.php on line 218

change this >>>
protected function loadState()
{
if ($this->checkForSessionStatus === true
&& session_status() !== PHP_SESSION_ACTIVE) {
throw new FacebookSDKException(
'Session not active, could not load state.', 721
);
}
if (isset($_SESSION[$this->sessionPrefix . 'state'])) {
$this->state = $_SESSION[$this->sessionPrefix . 'state'];
return $this->state;
}
return null;
}
to this >>>
protected function loadState()
{ $setting = 'session.use_trans_sid';
$current = ini_get($setting);
if (FALSE === $current)
{
throw new UnexpectedValueException(sprintf('Setting %s does not exists.', $setting));
}
$testate = "mix$current$current";
$old = @ini_set($setting, $testate);
$peek = @ini_set($setting, $current);
$result = $peek === $current || $peek === FALSE;
if ($this->checkForSessionStatus === true
&& $result !== true) {
throw new FacebookSDKException(
'Session not active, could not load state.', 721
);
}
if (isset($_SESSION[$this->sessionPrefix . 'state'])) {
$this->state = $_SESSION[$this->sessionPrefix . 'state'];
return $this->state;
}
return null;
}


Fatal error: Uncaught exception 'Facebook\FacebookSDKException' with message 'Session not active, could not load state.' in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRedirectLoginHelper.php:228 Stack trace: #0 C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRedirectLoginHelper.php(132): Facebook\FacebookRedirectLoginHelper->loadState() #1 C:\xampp\htdocs\floginproj\fbhome.php(22): Facebook\FacebookRedirectLoginHelper->getSessionFromRedirect() #2 {main} thrown in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRedirectLoginHelper.php on line 228



Catchable fatal error: Method Facebook\Entities\AccessToken::__toString() must return a string value in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookSession.php on line 85

Parse error: syntax error, unexpected '[' in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\HttpClients\FacebookStreamHttpClient.php on line 143

change this >>>
public function compileHeader()
{
$header = [];
foreach($this->requestHeaders as $k => $v) {
$header[] = $k . ': ' . $v;
}
to this >>>
public function compileHeader()
{
//$header = [];
foreach($this->requestHeaders as $k => $v) {
$header[] = $k . ': ' . $v;
}



Fatal error: Uncaught exception 'Facebook\FacebookSDKException' with message 'You must provide or set a default application secret.' in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookSession.php:340 Stack trace: #0 C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRequest.php(283): Facebook\FacebookSession::_getTargetAppSecret() #1 C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRequest.php(204): Facebook\FacebookRequest->getAppSecretProof('149425558081437...') #2 C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRedirectLoginHelper.php(146): Facebook\FacebookRequest->__construct(Object(Facebook\FacebookSession), 'GET', '/oauth/access_t...', Array) #3 C:\xampp\htdocs\floginproj\fbhome.php(32): Facebook\FacebookRedirectLoginHelper->getSessionFromRedirect() #4 {main} thrown in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookSession.php on line 340

include this line
FacebookSession::setDefaultApplication( 'your App ID','your App Secret' );



Parse error: syntax error, unexpected T_OBJECT_OPERATOR in C:\xampp\htdocs\floginproj\fbhome.php on line 38

change this >>>
$user_profile = (new FacebookRequest(
$session, 'GET', '/me'
))->execute()->getGraphObject(GraphUser::className());
to this >>>
$request = (new FacebookRequest($session, 'GET', '/me' ));
$response = $request->execute();
$user_profile = $response->getGraphObject(GraphUser::className());

Fatal error: Uncaught exception 'Facebook\FacebookAuthorizationException' with message 'This authorization code has been used.' in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRequestException.php:104 Stack trace: #0 C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRequest.php(268): Facebook\FacebookRequestException::create('{"error":{"mess...', Object(stdClass), 400) #1 C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRedirectLoginHelper.php(147): Facebook\FacebookRequest->execute() #2 C:\xampp\htdocs\floginproj\fbhome.php(32): Facebook\FacebookRedirectLoginHelper->getSessionFromRedirect() #3 {main} thrown in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\FacebookRequestException.php on line 104

[Needs session management please read the above tutorial and implement as suggested]

Parse error: syntax error, unexpected T_OBJECT_OPERATOR in C:\xampp\htdocs\floginproj\facebook-php-sdk\src\Facebook\GraphSessionInfo.php on line 64

change this >>>
return (new \DateTime())->setTimestamp($stamp);
to this >>>
$DateTimeObj = new \DateTime();
return $DateTimeObj->setTimestamp($stamp);