Computer graphics 3 lecture 3 opengl
This presentation is the property of its rightful owner.
Sponsored Links
1 / 60

Computer Graphics 3 Lecture 3: OpenGL PowerPoint PPT Presentation


  • 71 Views
  • Uploaded on
  • Presentation posted in: General

Computer Graphics 3 Lecture 3: OpenGL. Pr. Min Chen Dr. Benjamin Mora. University of Wales Swansea. 1. Benjamin Mora. Content. Introduction to OpenGL-NVidia Dawn Demo. Different “drawable” primitives in OpenGL. OpenGL Pipeline and Matrix Transformations. Lighting. Textures.

Download Presentation

Computer Graphics 3 Lecture 3: OpenGL

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Computer graphics 3 lecture 3 opengl

Computer Graphics 3Lecture 3:OpenGL

Pr. Min Chen

Dr. Benjamin Mora

University of Wales Swansea

1

Benjamin Mora


Content

Content

  • Introduction to OpenGL-NVidia Dawn Demo.

  • Different “drawable” primitives in OpenGL.

  • OpenGL Pipeline and Matrix Transformations.

  • Lighting.

  • Textures.

  • Initialization of the OpenGL machine and OpenGL coding.

  • Advanced Features.

University of Wales Swansea

2

Benjamin Mora


Dawn demo

Dawn Demo

University of Wales Swansea

3

Benjamin Mora


Introduction

Introduction

University of Wales Swansea

4

Benjamin Mora


What is opengl

What Is OpenGL?

  • OpenGL is a C (Graphics) Library allowing rendering (i.e., displaying) 3D objects like triangles.

  • Conceived in such a way that most routines are hardware accelerated.

  • Similar to Direct3D (DirectX, Microsoft) on many points.

  • OpenGL 1.0 has been introduced in 1992 by SGI (Silicon Graphics Incorporation).

  • Current Version 3.0.

  • Available now on every PC equipped with a descent graphics card (NVidia, ATI, also Intel…).

University of Wales Swansea

5

Benjamin Mora


What is opengl1

What Is OpenGL?

  • Pros:

    • Industry Standard (not only used in games)

    • Hardware-accelerated.

      • Specially designed GPUs.

      • Software-based versions are by far slower.

    • Portable (Linux, Windows, Macintosh, etc…).

    • Lot of documentation.

      • www.opengl.org

      • The OpenGL Programming Guide 4th Edition The Official Guide to Learning OpenGL Version 1.4.

      • OpenGL forums.

    • Still evolving: more and more options for more realistic renderings.

University of Wales Swansea

6

Benjamin Mora


What is opengl2

What Is OpenGL?

  • Cons:

    • State Machine: Awful programming, difficult to debug, and difficult for beginners!!!

      • Supposed to get better with the 3.0 release

    • Computer Graphics concepts must be learned.

    • Brute force approach: Hardware-Accelerated, but not optimized.

    • Not very flexible: Some computer graphics algorithms cannot take advantage of OpenGL.

    • Not the only way to display objects: Processing a huge amount of data can be faster in software under some conditions.

University of Wales Swansea

7

Benjamin Mora


What is opengl3

What Is OpenGL?

  • OpenGL does not contain a window manager, so an OpenGL rendering context (i.e., an OpenGL windows) must be created through another library (MFCs (?), GLUT, FLTK, GTK…).

  • To use OpenGL, the code should include the correct libraries and files:

    • #include <gl/gl.h>

    • OpenGL extensions must be included separately.

  • OpenGL is mainly used in a C/C++ context, but extensions of the API to other languages exist (OpenGL for java, delphi,…).

University of Wales Swansea

8

Benjamin Mora


How opengl works

How OpenGL works?

  • Aim: Rendering (i.e. displaying) a 3D scene.

  • Objects are “rendered” (drawn) into an invisible frame-buffer (image).

  • When all the objects have been processed, the frame-buffer becomes the new image appearing in your window (double buffering).

    • Ideally 30 fps or more.

University of Wales Swansea

9

Benjamin Mora


How opengl works1

How OpenGL works?

  • Rendering an image needs two main steps.

    • Setting up the parameters.

      • Telling OpenGL where the camera (viewpoint) is located.

      • Telling OpenGL about the lights.

        • position of the lights.

        • Type of lighting, colors.

      • Many other parameters according to the needs.

    • Telling the system where the primitives (basic forms like triangles that represent the object) are located in space.

      • Previous parameters will be taken into account for rendering.

      • If the object is opaque, primitives can be drawn in any order.

      • Every time a primitive is declared, OpenGL rasterizes (drawn) it on the frame-buffer, and keeps only its visible parts using the z-buffer test.

University of Wales Swansea

10

Benjamin Mora


How opengl works2

Projection

Camera System

Primitive

How OpenGL works?

  • The vertices send to the OpenGL machine follow a projection pipeline, before performing an on-screen rasterization (area filling) using a scan-line algorithm.

University of Wales Swansea

11

Benjamin Mora


How opengl works3

Initial Frame-Buffer

After the second primitive rasterization

After the first primitive rasterization

How OpenGL works?

  • Example:

  • Primitives enter the graphics pipeline when specifying their vertex (points) location.

University of Wales Swansea

12

Benjamin Mora


Different drawable primitives in opengl

Different “drawable” primitives in OpenGL

University of Wales Swansea

13

Benjamin Mora


Opengl primitives

OpenGL primitives

5

5

4

4

1

1

3

3

2

2

GL_POINTS

GL_LINES

GL_LINE_STRIP

GL_LINE_LOOP

GL_POLYGON

1

1

1

2

1

2

3

2

3

2

3

1

2

3

4

4

4

4

4

5

5

5

3

5

6

6

GL_TRIANGLE_STRIP

GL_TRIANGLES

GL_TRIANGLE_FAN

GL_QUADS

GL_QUAD_STRIP

University of Wales Swansea

14

Benjamin Mora


Sending primitives to opengl

Sending primitives to OpenGL

  • A primitive mode must be setup first (e.g., glBegin(GL_TRIANGLES)).

  • Vertex coordinates must then be send to the pipeline

    • glVertex function, see later for code!

  • GL_TRIANGLES case

    • Every time 3 consecutive vertices have been sent to the pipeline, a new triangle rasterization occurs.

University of Wales Swansea

15

Benjamin Mora


Primitive rasterization

Primitive Rasterization

  • Every pixel on the projection is called a “fragment”.

  • For every fragment, many parameters like the colors and transparency (RGBA), depth, and the texture coordinates are linearly interpolated.

Rasterization

Linear Interpolation

University of Wales Swansea

16

Benjamin Mora


Primitive rasterization1

Primitive Rasterization

  • Different types (precisions) of colors can be used with OpenGL: [Black Value..White Value]

    • GL_UNSIGNED_BYTE:[0..255].

    • GL_UNSIGNED_SHORT:[0..65535].

    • GL_FLOAT:[0..1.0].

  • Usually, colors are clamped to [0..1].

University of Wales Swansea

17

Benjamin Mora


Opengl pipeline and matrix transformations

OpenGL Pipeline and Matrix Transformations

University of Wales Swansea

18

Benjamin Mora


Regular opengl pipeline

(Regular) OpenGL Pipeline

  • 4D vertex coordinates are expressed in the camera coordinate system by applying a sequence of (4D) transformations.

    • Pipeline and matrices fixed before processing a flow of vertices.

Eye/Camera coordinates

World coordinates

Modelview Matrix

Projection Matrix

Normalized device coordinates

Clip coordinates

Viewport Transformation

Perspective Division

Window Coordinates

University of Wales Swansea

19

Benjamin Mora


Opengl pipeline

Object as stored in memory

OpenGL Pipeline

z

World coordinate system

x

o

University of Wales Swansea

20

Benjamin Mora


Opengl pipeline1

OpenGL Pipeline

z

x

o

1-Modelview transform: Moving objects in space

2-Projection transform: Take into consideration the camera. Coordinates are now expressed in the camera coordinate system

3-w division followed by the viewport transform then occur to find the vertex projections. Once this done for a sufficient number vertices (e.g., 3 for a triangle), object rasterization can happen

University of Wales Swansea

21

Benjamin Mora


Opengl pipeline2

OpenGL Pipeline

  • OpenGL is a state machine.

    • The matrices must be set before sending the graphic primitives (e.g. triangles) into the pipeline.

    • 2 main matrix stacks actually:

      • GL_MODELVIEW

        • Used to specify the camera position and/or the model position.

      • GL_PROJECTION

        • Used in order to specify the projection type, and clip coordinates.

  • Before applying transformations, the relevant stack must be specified:

    • Setting up the current matrix to modelview:

      • glMatrixMode(GL_MODELVIEW);

    • Use glLoadIdentity() to reset it.

University of Wales Swansea

22

Benjamin Mora


Opengl pipeline3

OpenGL Pipeline

  • The current matrix is the matrix in top of the stack.

    • void glPushMatrix();

      • Make a copy of the matrix in top of the stack and put it on the top.

    • void glPopMatrix();

      • Remove the top matrix from the stack.

  • Loading the identity matrix.

    • glLoadIdentity();

    • Required before doing any rotation translation.

  • Stacks are used because they are useful to specify relative coordinate systems.

University of Wales Swansea

23

Benjamin Mora


Opengl pipeline modelview matrix

OpenGL Pipeline: Modelview matrix

  • The modelview matrix can be used to both set the camera location and to move objects in space.

  • The projection matrix should be used to specify either the orthographic projection or the perspective projection

    • Use of either glOrtho or glFrustum to specify them

    • Used for normalizing coordinates between -1 and 1.

      • Required for the quantization of the z value

Rotation matrix created from an angle and a line in the direction x,y,z that cross the origin

Translation Matrix

University of Wales Swansea

24

Benjamin Mora


Projection matrix glortho

Projection Matrix: glOrtho

  • Need to specify a 6-face box with 6 parameters.

  • Normalized coordinates between -1 and 1 after this stage.

  • void glOrtho(glDouble left, glDouble right, glDouble. bottom,glDouble top, glDouble near, glDouble far);

University of Wales Swansea

25

Benjamin Mora


Projection matrix glfrustum

Projection Matrix: glFrustum

  • void glFrustum(glDouble left, glDouble right, glDouble bottom,glDouble top, glDouble near, glDouble far);

  • Non Linearity:

University of Wales Swansea

26

Benjamin Mora


Perspective division

Perspective Division

  • Once the vertices have been transformed, we need to know their projection into the image space.

  • Image coordinates are still expressed as [-1, 1]

Projection on x [-1..1]

Fragment Depth

University of Wales Swansea

27

Benjamin Mora


Viewport

Viewport

  • Map the normalized x and y coordinates to a portion of the image.

  • void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);

x+width,y+height

image

x,y

0,0

University of Wales Swansea

28

Benjamin Mora


Viewport1

Viewport

  • Map the normalized x and y coordinates to a portion of the image.

  • void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);

x+width,y+height

image

x,y

0,0

University of Wales Swansea

29

Benjamin Mora


Z buffer test

Z-Buffer test

  • Example:

Final image

Final z-buffer

University of Wales Swansea

30

Benjamin Mora


Z buffer test1

Z-Buffer test

  • Once the vertices projected, rasterization occurs.

  • Primitives can be sent to the graphics hardware in any order, thanks to the z-buffer test that will keep the nearest fragments.

  • A z value is stored for every pixel (z-buffer).

  • Algorithm:

    If the rasterized z-value is less than the current z-value

    Then replace the previous color and z-value by the new ones

University of Wales Swansea

31

Benjamin Mora


Stencil test

Stencil test

  • A stencil buffer can be used for implementing complex algorithms (e.g., Shadow volumes).

  • A value is associated with every pixel.

  • The stencil test is performed after the z-test and compare the current stencil value with a reference value.

  • The stencil value can possibly be incremented every time a fragment passes the stencil test.

University of Wales Swansea

32

Benjamin Mora


Stencil test1

Stencil test

http://www.opengl.org/resources/tutorials/advanced/advanced97/notes/node196.html

University of Wales Swansea

33

Benjamin Mora


Lighting

Lighting.

University of Wales Swansea

34

Benjamin Mora


Opengl lighting model

OpenGL Lighting Model

  • In real life, every material has its own reflection properties (called BRDF, i.e. Bidirectional Reflectance Distribution Function).

  • Illumination is computed from the light source position, the surface orientation and the camera position.

  • Illumination is computed at

    the vertices, and then interpolated

    for every fragment.

University of Wales Swansea

35

Benjamin Mora


Opengl lighting model phong

OpenGL Lighting Model (Phong)

  • 3 components:

    • Ambiant.

      • Do not depend of the light

        source.

    • Diffuse.

      • The light is evenly reflected

        in all direction.

    • Specular.

      • The reflection is predominant in a given direction.

      • The specular coefficient can be varied.

  • The light intensity can decrease according the distance (constant, linear or quadratic).

University of Wales Swansea

36

Benjamin Mora


Opengl lighting model1

OpenGL Lighting Model

http://en.wikipedia.org/wiki/Phong_shading

University of Wales Swansea

37

Benjamin Mora


Opengl lighting model2

OpenGL Lighting Model

  • OpenGL formula:

  • A “light” can be created, specifying all the required constants for the light.

  • A “material” can be created in OpenGL, specifying all the constants for the surface.

University of Wales Swansea

38

Benjamin Mora


Model limitations

Model Limitations

  • No native shadows.

    • Shadows can be implemented by using specific algorithms and texture mapping.

  • Phong shading is just an imperfect model.

    • Global (i.e. realistic) illumination can not be done efficiently.

  • Better to interpolate normals first, and then compute shading.

  • Faked Normals.

    • The actual surface derivative do not usually match the specified normal.

University of Wales Swansea

39

Benjamin Mora


Texture mapping

Texture Mapping

  • OpenGL interpolates the texture coordinates for every rasterized fragment and then fetches the pixel from the texture.

  • Textures are stored on the graphics board and are highly optimized.

    • Textures must be loaded first.

    • Texture coordinates must be attributed to vertices at the same time as vertex normals and vertex coordinates.

      • See next slides.

University of Wales Swansea

40

Benjamin Mora


Initialization of the opengl machine and opengl coding

Initialization of the OpenGL Machine and OpenGL Coding.

University of Wales Swansea

41

Benjamin Mora


Opengl coding

OpenGL Coding

  • First, set the parameters.

    • Viewpoint (camera).

    • Lights.

    • Materials.

    • Textures.

    • Etc…

  • Second, tell OpenGL the primitives to render, possibly specifying for every vertex its:

    • Colors.

    • Normals.

    • Texture Coordinates.

University of Wales Swansea

42

Benjamin Mora


Opengl coding1

OpenGL Coding

  • #include <gl/gl.h>

  • Enabling some specific features:

    • void glEnable(GLenum cap);

    • void glDisable(GLenum cap);

    • glEnable(GL_DEPTH_TEST);//Enabling z-buffer

    • glEnable(GL_LIGHTING);//Enabling lighting.

    • glEnable(GL_LIGHT0);//Enabling light 0 (at least 8 lights)

    • glEnable(GL_TEXTURE_2D);//Enabling 2D textures

University of Wales Swansea

43

Benjamin Mora


Opengl coding2

OpenGL Coding

  • Specifying the current matrix:

    • void glMatrixMode (GLenum mode);

      • glMatrixMode(GL_MODELVIEW);

      • glMatrixMode(GL_PROJECTION);

  • Initializing the current matrix:

    • void glLoadIdentity();

  • Handling the matrix stack:

    • void glPushMatrix ( );//New copy on the top of the stack.

    • void glPopMatrix ( ); //Remove the top of the stack.

University of Wales Swansea

44

Benjamin Mora


Opengl coding3

OpenGL Coding

  • Rotations (modifying the current matrix):

    • void glRotated ( GLdouble angle , GLdouble x , GLdouble y , GLdouble z );

    • void glRotatef ( GLfloat angle , GLfloat x , GLfloat y , GLfloat z );

  • Translations (modifying the current matrix):

    • void glTranslated ( GLdouble x, GLdouble y, GLdouble z );

    • void glTranslatef ( GLfloat x , GLfloat y , GLfloat z );

  • Scaling (modifying the current matrix):

    • void glScaled ( GLdouble x , GLdouble y , GLdouble z );

    • void glScalef ( GLfloat x , GLfloat y , GLfloat z );

University of Wales Swansea

45

Benjamin Mora


Opengl coding4

OpenGL Coding

  • Erasing the Frame-Buffer:

    • void glClearColor ( GLclampf red , GLclampf green , GLclampf blue , GLclampf alpha ); //Defines a clear color

    • void glClear ( GLbitfield mask ); //Clear the image

  • Examples:

    • glClear(GL_COLOR_BUFFER_BIT |

      GL_DEPTH_BUFFER_BIT |

      GL_ACCUM_BUFFER_BIT |

      GL_STENCIL_BUFFER_BIT );

University of Wales Swansea

46

Benjamin Mora


Opengl coding5

OpenGL Coding

  • Sending graphics primitives to the OpenGL machine:

    glBegin(GL_LINES); //Specify lines. Could be GL_TRIANGLES, etc…

    //First vertex

    glColor3f(1.0,0.,0.);//3 float colors for the first vertex

    glNormal3f(0.707,0.707,0); //first normal

    glTexcoord2f(0,0); //First texture coordinate

    glVertex3f(500,100,2); //first vertex

    //Second vertex

    glColor4f(1.0,0.,0.,1.);//4 float colors (last value: opacity)

    glNormal3fv(v); //gives a vector of float as parameters

    glTexcoord2f(1,1); //Second texture coordinate

    glVertex3d(500,100,2);//double instead of float

    glEnd(); // End of the vertex flow

University of Wales Swansea

47

Benjamin Mora


Opengl coding6

OpenGL Coding

  • Initializing lighting

    void GLRenderer::InitLighting()

    {

    float ambiant[4]= {0.2,0.2,0.2,1.};

    float diffuse[4]= {0.7,0.7,0.7,1.};

    float specular[4]= {1,1,1,1.};

    float exponent=8;

    //glMatrixMode(GL_MODELVIEW);

    //glLoadIdentity();

    //Be careful here: the lights go through the OpenGL transform pipeline

    float lightDir[4] = {0,0,1,0};

    glEnable(GL_LIGHTING);

    glEnable(GL_LIGHT0);

    glLightfv(GL_LIGHT0,GL_AMBIENT,ambiant);

    glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);

    glLightfv(GL_LIGHT0,GL_SPECULAR,specular);

    glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,exponent);

    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDir);

    }

University of Wales Swansea

48

Benjamin Mora


Opengl coding7

OpenGL Coding

  • Initializing texturing

    unsigned int *textureId=new unsigned int[nbOfTextures];

    glGenTextures(nbOfTextures,textureId);

    for (i=0;i<nbOfTextures;i++)

    {

    glBindTexture(GL_TEXTURE_2D, textureId[i]);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, 3, textureDimensionsX[i], textureDimensionsY[i], 0,GL_RGB,GL_UNSIGNED_BYTE, texture[i]);

    }

University of Wales Swansea

49

Benjamin Mora


Advanced features

Advanced Features.

University of Wales Swansea

50

Benjamin Mora


Advanced features1

Advanced Features

  • Limitations:

    • OpenGL 1.1 was limited to the Phong shading model.

    • Pixel precision may depend on the graphics card manufacturer (usually 8 bits per color).

    • Creating real-time shadows and more complex effects is difficult.

    • Power-of-two textures.

    • Fixed rendering pipeline.

    • Only one possible rendering per frame.

  • Main manufacturers: ATI, NVidia, SGI, XGI.

  • Functionalities and extensions may differ from the different manufacturers => Specific code must often be developed for each platform.

University of Wales Swansea

51

Benjamin Mora


Advanced features vertex arrays

Advanced Features: Vertex Arrays

  • On modern PC platforms, the video card communicate with the CPU through a “slow” AGP or PCI-express bus.

  • Too much communication can kill performance.

    • e.g., processing a lot of small triangles.

  • The fast video memory associated with the GPU can be used to store the vertices and reduce the communication bandwidth.

University of Wales Swansea

52

Benjamin Mora


Advanced features vertex arrays1

Advanced Features: Vertex Arrays

  • Up to six arrays can be specified:

    void VertexPointer ( int size, enum type, sizei stride, void *pointer ) ;

    void ColorPointer ( int size, enum type, sizei stride, void *pointer ) ;

    void TexCoordPointer ( int size, enum type, sizei stride, void *pointer ) ;

    void IndexPointer ( enum type, sizei stride, void *pointer ) ;

    void NormalPointer ( enum type, sizei stride, void *pointer ) ;

    void EdgeFlagPointer ( sizei stride, void *pointer ) ;

www.opengl.org

University of Wales Swansea

53

Benjamin Mora


Advanced features vertex arrays2

Advanced Features: Vertex Arrays

  • Other functions are required to make it work.

    void EnableClientState ( enum array ) ;

    void DisableClientState ( enum array ) ; void ArrayElement ( int i ) ; void DrawArrays ( enum mode, int first, sizei count ) ;

    void DrawElements ( enum mode, sizei count, enum type, void *indices ) ;

University of Wales Swansea

54

Benjamin Mora


Advanced features extensions

Advanced Features: Extensions

  • Since OpenGL 1.2, extensions are supported.

  • Main Extensions:

    • Floating-point extensions to get a better precision at the frame buffer level.

      • ATI: 24 bit precision (now 32). NVidia: 16 or 32 bit precision.

      • High Dynamic Range (HDR) images, Tone Mapping.

    • Non-Power-of-Two textures: Saves memory.

    • Render-to-Texture (Cube Maps).

      • Shadow Maps.

    • Bump-Mapping.

    • Vertex and Fragment programs.

      • Floating-point precision at the program level.

University of Wales Swansea

55

Benjamin Mora


Advanced features extensions1

Advanced Features: Extensions

char* extensionsList = (char*) glGetString(GL_EXTENSIONS);

// All the supported extensions are inside the string

// extensionsList.

//Example for getting the 3D texture functionality.

//First step: Declare a function type

typedef void (APIENTRY * PFNGLTEXIMAGE3DPROC)

(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)

PFNGLTEXIMAGE3DPROC glTexImage3D; // Declare a function pointer

glTexImage3D= (PFNGLTEXIMAGE3DPROC) wglGetProcAddress("glTexImage3D");

//Get the pointer address;

University of Wales Swansea

56

Benjamin Mora


Advanced features render to texture

Advanced Features: Render to texture

  • Allows rendering into an intermediate image that will be re-used in the final image.

    • Useful for (cube or spherical map) environmental mapping.

    • Mirroring effects.

    • Reflections.

    • Refractions.

    • Lighting effects.

    • Bump mapping.

    • Vertex Textures.

University of Wales Swansea

57

Benjamin Mora


Advanced features shadows

Advanced Features: Shadows

  • How to efficiently compute shadows that are compatible with current graphics hardware ?

  • Two possibilities:

    • Shadow Maps.

      • See CS 307

    • Shadow Volumes.

University of Wales Swansea

58

Benjamin Mora


Advanced features shadow volume

Advanced Features: Shadow Volume

Image created by Steve Leach using OpenOffice Draw (v1.9.95), 30 May 2005 for use in the Shadow Volumes article.

http://en.wikipedia.org/wiki/Shadow_volume

University of Wales Swansea

59

Benjamin Mora


Advanced features shadow volume1

Advanced Features: Shadow Volume

  • Encode the surface of regions (volumes) of the scene that are located inside the penumbra.

  • Make use of the stencil test after having rendered the scene.

    • Stencil buffer initialized to 0.

    • Every fragment that passes the z-test adds +1 to the stencil value.

    • If even count at the end => object visible from light source.

  • Exact shadow contours.

  • Shadow volumes are hard to update when the scene is complex and dynamic.

University of Wales Swansea

60

Benjamin Mora


  • Login