Dynamic Camera Movement ?

Dynamic Camera Movement ?

Post by Jongwhan Le » Thu, 03 Feb 2000 04:00:00



Hi

Look At SetCamera().
It's my camera .

I want to implement cool camera movement used in "Super Mario 64".
Its camera is like a movie.
Camera man chases Mario, produces the best view.

My camera floats around 5 points above the ground.
If main object's distance is over 10 (an example), camera moves.(but in the
same altitude)

It look good, but I want make this camera like a movie.
(Camera chases the main object with a best view.)

Is there any algorithm for this?

Toom Raider style is good, but we see only the back part of Lara
Croft(Spelling isn't correct)
I prefer Super Mario 64 style, though.

code)
#include "stdafx.h"
#include <windows.h>
/* Copyright (c) Mark J. Kilgard, 1994. */

/* This program is freely distributable without licensing fees
   and is provided without guarantee or warrantee expressed or
   implied. This program is -not- in the public domain. */

#include <windows.h>
#include <fstream> //  file stream
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gl\glut.h>

#include "actdata.h"

#include <list> //  linked list
using namespace std; //  use standard template library

#include "mathobj.h"
typedef CVec<double> VECTOR;
CActor m_Player(VECTOR(-10,0,-10),0 ); // me
CActorList m_BlockList;
VECTOR m_Camera(0,10,0);
double m_dCameraRad=15;

double m_dWidth;
double m_dHeight; //  screen

double m_dAR;
double m_dLeft=-20;
double m_dRight=20;
double m_dBottom= -1;
double m_dTop=1;

#define KEY_NUM 256
int GV_nKey[KEY_NUM];
#define KEY_LEFT 100
#define KEY_RIGHT 101
#define KEY_UP 102
#define KEY_DOWN 103

void MakeMap(void) {
 char buffer[300];

 ifstream in("map.txt");
 int num;
 in>> num;
 cout<< num <<endl;
 int i,j;

 for (i=0;i<num;i++) {
  in>> buffer;

  for (j=0;j<strlen(buffer);j++) {
   if (buffer[j]=='1') m_BlockList.push_back(CActor(VECTOR(j-20,0,i-20),1));
  }

 }

}

void ReadKey(unsigned char key, int x ,int y)
{

}

void
key(unsigned char key, int px, int py)
{
 GV_nKey[key]=1;

}

void
keyup(unsigned char key, int x, int y)
{
 GV_nKey[key]=0;
}

void
special(int key, int x, int y)
{
 if (key==GLUT_KEY_LEFT) GV_nKey[KEY_LEFT]=1;
 if (key==GLUT_KEY_RIGHT) GV_nKey[KEY_RIGHT]=1;
 if (key==GLUT_KEY_UP) GV_nKey[KEY_UP]=1;
 if (key==GLUT_KEY_DOWN) GV_nKey[KEY_DOWN]=1;
}

void
specialup(int key, int x, int y)
{
 if (key==GLUT_KEY_LEFT) GV_nKey[KEY_LEFT]=0;
 if (key==GLUT_KEY_RIGHT) GV_nKey[KEY_RIGHT]=0;
 if (key==GLUT_KEY_UP) GV_nKey[KEY_UP]=0;
 if (key==GLUT_KEY_DOWN) GV_nKey[KEY_DOWN]=0;

}

void
Idle(void)
{
  double move=0.1;
 static int dir=0;

 VECTOR v2;

 VECTOR& v= m_Player.m_vPos;

 //  backup
 v2=v;

 double& deg= m_Player.m_dDegY;

 if (GV_nKey['A']||GV_nKey['a']) m_Camera.y+=0.4;
 if (GV_nKey['Z']||GV_nKey['z']) m_Camera.y-=0.4;

 if (GV_nKey[KEY_LEFT]) {
  deg +=5 ;
  dir=0;
 }
 if (GV_nKey[KEY_RIGHT]) {
  deg -= 5;
  dir=1;
 }
 if (GV_nKey[KEY_UP]) {
  v.x += move*cos(deg/180.0*3.141592);
  v.z -= move*sin(deg/180.0*3.141592);
 }
 if (GV_nKey[KEY_DOWN]) {
  v.x += -move*cos(deg/180.0*3.141592);
  v.z -= -move*sin(deg/180.0*3.141592);
 }
 if (GV_nKey[27]) exit(0);

 if (GV_nKey[' '] && m_Player.m_nMode==0) {
  m_Player.m_nMode=1;
  m_Player.m_nFrame=0;
 }

 // jump
 double jump=0;

 if (m_Player.m_nMode==1) {
  double height=2;

  if (m_Player.m_nFrame++>=60) m_Player.m_nMode=0;
  double frame= ((double)m_Player.m_nFrame)/60.0;
  v.y = -(frame-0.5)*(frame-0.5)*height/0.5/0.5+height;
 }

 //  calculate distance
 double th=90.0;
 m_dCameraRad= fabs(m_Camera.y)/cos(th/2.0/180.0*3.141592);

 VECTOR a=(v-m_Camera);
 double dis=a.Size();
 if (dis>m_dCameraRad) {
  double move=0.01;
  //  follow
  if (m_Camera.x < v.x) m_Camera.x+=move;
  if (m_Camera.x > v.x) m_Camera.x-=move;
  if (m_Camera.z < v.z) m_Camera.z+=move;
  if (m_Camera.z > v.z) m_Camera.z-=move;

 }

 //  collid?

 if (m_BlockList.Collide(m_Player) ) {
  v=v2;
  if (dir) deg-=10;
  else deg+=10;
 }
 else {
  v2=v;

  if (v.y> MATH_ZERO) v.y-=0.1;
  else v.y=0;
  if (m_BlockList.Collide(m_Player))
  v=v2;
 }

 glutPostRedisplay();

}

void SetCamera(void)
{
 //  calcualte near clipping plane
 if (m_dHeight<MATH_ZERO) return;

 //  get window size
 m_dAR=m_dWidth/m_dHeight; //  aspect ratio
 m_dLeft=-20;
 m_dRight=20;
 m_dBottom= -0.5;
 m_dTop=0.5;

 // 3d
 double sizey = m_dTop-m_dBottom;
    double sizex =  sizey*m_dAR; // control width from height
 double cenx=(m_dLeft+ m_dRight) / 2.;
 double ceny=(m_dTop+ m_dBottom) /2.;

 //  calculate lens size
 m_dLeft=cenx - sizex/2.;
 m_dRight=cenx + sizex/2.;
 m_dTop = ceny + sizey/2.;
 m_dBottom= ceny - sizey/2.;

 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glFrustum(m_dLeft, m_dRight, m_dBottom, m_dTop, 5, 1000);

 //  locate the camera and adjust the direction
 VECTOR& p= m_Player.m_vPos;
 gluLookAt(m_Camera.x, m_Camera.y, m_Camera.z,
  p.x, p.y, p.z,
  0, 1, 0);

 glMatrixMode(GL_MODELVIEW);
 glEnable(GL_COLOR_MATERIAL);
 glLoadIdentity();

}

void SetLight()
{
 //  Set the material color to follow the current color
 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
 // glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
 // glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 100);
 glEnable(GL_COLOR_MATERIAL);

 float ambient[] = { 0.0, 0.0, 0.0, 0.0 };
 float diffuse[] = { 1.0, 1.0, 1.0, 0.0 };
    float specular[] = { 1.0, 1.0, 1.0, 0.0 };

    float position[] = { 0, 50, 0,  0 };
    float lmodel_ambient[] = { 0.7f, 0.7f, 0.7f, 0.0f };
    float local_view[] = { 0.0 };

    glEnable(GL_DEPTH_TEST);

    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glLightfv(GL_LIGHT0, GL_POSITION, position);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);

    glEnable(GL_LIGHT0);
 glDisable(GL_LIGHT1);
 glDisable(GL_LIGHT2);
 glDisable(GL_LIGHT3);
 glDisable(GL_LIGHT4);
 glDisable(GL_LIGHT5);
 glDisable(GL_LIGHT6);
 glDisable(GL_LIGHT7);
 glEnable(GL_LIGHTING);

}

// draw basic grids
//  no color material setting here
void DrawNet(double xsize, double zsize, double xstep, double zstep)
{

 // adjust xsize , zsize
 if (xstep<0.0000001 || zstep<0.0000001) return; // avoid too small grid
 int countx= (int)xsize/xstep;
 int countz= (int)zsize/zstep;

 // okay
 xsize= (double)countx * xstep;
 zsize= (double)countz * zstep;

 glPushMatrix();

 double x,z;

   glLineStipple (1, 0x1c47);  /*  dotted  */
   glLineWidth(1); // thin line

   // minor line
 glBegin(GL_LINES);
 for (x=-xsize; x<xsize+xstep; x+=xstep) {
  glVertex3d(x, 0, -zsize);
  glVertex3d(x, 0,  zsize);

 }

 for (z=-zsize; z<zsize+zstep; z+=zstep) {
  glVertex3d(-xsize, 0, z);
  glVertex3d( xsize, 0, z);
 }

 glEnd();

 // main line
 glDisable(GL_LINE_STIPPLE);
 int c=0;
 glBegin(GL_LINES);
 c=0;
 for (x=0; x<=xsize; x+=xstep) {
  if ( c++%5 == 0 ) {
  glVertex3d(x, 0, -zsize);
  glVertex3d(x, 0,  zsize);
  }
 }

 c=0;
 for (x=0; x>=-xsize; x-=xstep) {
  if ( c++%5 == 0 ) {
  glVertex3d(x, 0, -zsize);
  glVertex3d(x, 0,  zsize);
  }
 }

 c=0;
 for (z=0; z<=zsize; z+=zstep) {
  if (c++%5==0) {
   glVertex3d(-xsize, 0, z);
   glVertex3d( xsize, 0, z);
  }
 }

 c=0;
 for (z=0; z>=-zsize; z-=zstep) {
  if (c++%5==0) {
   glVertex3d(-xsize, 0, z);
   glVertex3d( xsize, 0, z);
  }
 }

 glEnd();

 // major line
 glLineWidth(2);
 glBegin(GL_LINES);
 glVertex3d(0, 0, -zsize);
 glVertex3d(0, 0,  zsize);
 glVertex3d(-xsize, 0, 0);
 glVertex3d( xsize, 0, 0);
 glLineWidth(1);

 glEnd();

 glPopMatrix();

}

void
Display(void)
{

 glClearColor(1.0, 1.0, 1.0,0);
 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT |
 GL_STENCIL_BUFFER_BIT);

 //  set camera now
 SetCamera();

 glPushMatrix();

 ::SetLight();
 glEnable(GL_COLOR_MATERIAL);

 m_Player.Show();

 //  draw map
 m_BlockList.Show();

 //  draw grid lines

 glColor3d(0,0,0);
 glPushMatrix();
 glTranslated(0.5, -0.5, 0.5);
 DrawNet(20, 20, 1, 1);
 glPopMatrix();

 //  text..
 // glPolygonMode

 glPopMatrix();
 glutSwapBuffers();

}

void ReSize(int width, int height)
{
 m_dWidth=width;
 m_dHeight=height;

 SetCamera();

 glViewport(0,0,width,height);

}

int
main(int argc, char **argv)
{
 //  reset key
 int i;
 for (i=0;i<KEY_NUM;i++)
  GV_nKey[i]=0;
  glutInit(&argc, argv);
    MakeMap();

  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
  glutInitWindowSize(600, 400);

  // glutGameModeString("640x480:16@60");
  // glutEnterGameMode();
  glutCreateWindow("Game");

  glutDisplayFunc(Display);
  glutIdleFunc(Idle);
  glutReshapeFunc(ReSize);
   glutKeyboardFunc(key);
  glutKeyboardUpFunc(keyup);
  glutSpecialFunc(special);
  glutSpecialUpFunc(specialup);

  glutMainLoop();

  return 0;

}

void DrawAxis(double height);
void DrawSolidBox(VECTOR Min, VECTOR Max);
 
 
 

Dynamic Camera Movement ?

Post by Timo K Suorant » Fri, 04 Feb 2000 04:00:00


Quote:> see code section of http://ferretti.homepage.com
> there is a c++ class to define a camera

Code is there, but it can hardly be called C++ :)
Also it uses OpenGL matrix transformations, which
if of course fine, but I am trying make camera
with my own Matrix class, so that I concatenate
transformations and don't recreate it in every
frame..



 
 
 

Dynamic Camera Movement ?

Post by Sardauka » Tue, 08 Feb 2000 04:00:00


Then you can see the article on www.gamasutra.com. There is an article
that explain the use of the quaternions for the camera movement.

PS :

Quote:>so that I concatenate transformations and don't recreate it in every

frame..
Pay attention the round error in the transformation matrix come very
quick.
--
===============================
fabio

icq: 56249080
http://ferretti.homepage.com
===============================
 
 
 

1. : Circular camera movement in Povray 3.02

Hi,

Using Povray 3.02, I am making an animation where I need the camera to look
at a fixed point, and then orbit around that point, continuing to look at
it. However, I have been unable to get the camera to do what I want. Here
are my camera settings:

camera {  //  Camera Scene_Camera
  location  <0.000, -899.200, 215.971>
  direction <0.0,     0.0,  1.8317>
  sky       <0.0,     0.0,  1.0>  // Use right handed-system!
  up        <0.0,     0.0,  1.0>  // Where Z is up
  right     <1.33333,  0.0,  0.0>
  look_at   <0.000, 0.000, 215.979>
  //translate
  rotate    <0.000, 0.000, 2*pi*clock>

I know that in povray that if you want to get something to rotate in a
circle around the origon, toy translate it first, and then rotate it. When I
had the camera set up like this though:

camera {  //  Camera Scene_Camera
  location  <0.000, 0.000, 0.000>
  direction <0.0,     0.0,  1.8317>
  sky       <0.0,     0.0,  1.0>  // Use right handed-system!
  up        <0.0,     0.0,  1.0>  // Where Z is up
  right     <1.33333,  0.0,  0.0>
  look_at   <0.000, 0.000, 215.979>
  translate <0.000, -899.200, 215.971>
  rotate    <0.000, 0.000, 2*pi*clock>

the camera wasn't in the right place. Can anybody show me what I am doing
wrong, and how to do what I am trying to do?

Thanks,

Equiprawn

NOTE: Remove ".spam" from address when replying by e-mail!

2. Need help with my GIF algorithm

3. Camera movement trouble

4. Delphi & Games

5. Relationship between the angle (camera is moved) and corresponding movement in pixels

6. Very simple questions...

7. HELP! jerky camera movement

8. need docs

9. Library or parser to extract camera movement

10. Camera movement

11. Need help with creating smooth camera movement

12. Multiple movements in camera path

13. Camera movements in 3D Studio r4