@@ 88,19 88,6 @@ typedef struct ClipPlanes {
Plane z_pos;
} ClipPlanes;
-typedef struct Renderer {
- Pixel *pixels;
- DepthVal *depthBuffer;
- int width;
- int height;
- Transform projectionTransform;
- Transform deviceTransform;
- Vertex *vertex_pool;
- int *polygon_pool;
- int *alt_polygon_pool;
- ClipPlanes clip_planes;
-} Renderer;
-
typedef struct Model {
Vector position;
Transform transform;
@@ 132,13 119,38 @@ typedef struct Particle {
Vector acceleration;
} Particle;
+typedef struct Camera {
+ Model *model;
+ Physics *physics;
+ Transform transform;
+ double fov;
+ double aspect;
+ double x_cotan;
+ double y_cotan;
+ double near;
+ double far;
+} Camera;
+
+typedef struct Renderer {
+ Pixel *pixels;
+ DepthVal *depthBuffer;
+ int width;
+ int height;
+ Camera *camera;
+ Transform deviceTransform;
+ Vertex *vertex_pool;
+ int *polygon_pool;
+ int *alt_polygon_pool;
+ ClipPlanes clip_planes;
+} Renderer;
+
typedef struct Scene {
+ Camera *camera;
SceneObject *objects;
Renderable *renderable_pool;
Physics *physics_pool;
Model *model_pool;
Particle *particles;
- Renderer *renderer;
} Scene;
Scene *MoonWorld(void);
@@ 155,7 167,7 @@ SceneObject *NewSceneObject(SceneObject *pool, Model *model, Renderable *rendera
void InitParticleSystem(Scene *scene);
Particle *NewParticlePool(void);
Particle *AddParticle(Particle *pool, Vertex v);
-Renderer *NewRenderer(Pixel *pixels, int width, int height);
+Renderer *NewRenderer(Pixel *pixels, int width, int height, Camera *camera);
void ClearScreen(Renderer *renderer);
DepthVal *NewDepthBuffer(int width, int height);
Transform PerspectiveTransform(double fov, double aspect, double near, double far);
@@ 197,3 209,6 @@ void PlaceObject(SceneObject *obj, Vector p);
Model *NewModel(Model *pool);
void DumpMesh(Mesh *mesh);
void SpinObject(SceneObject *obj, double rx, double ry, double rz);
+Camera *NewCamera(double fov, double aspect, double near, double far, Model *model, Physics *physics);
+void SetCamera(Camera *camera, double fov, double aspect, double near, double far);
+void ZoomIn(Camera *camera, double amt);
@@ 39,7 39,7 @@ int main(void)
SDL_bool done = SDL_FALSE;
Scene *scene = MoonWorld();
- Renderer *gameRenderer = NewRenderer(pixels, SCREEN_WIDTH, SCREEN_HEIGHT);
+ Renderer *gameRenderer = NewRenderer(pixels, SCREEN_WIDTH, SCREEN_HEIGHT, scene->camera);
long frames = 0;
long start = SDL_GetTicks();
@@ 85,6 85,7 @@ int main(void)
Scene *MoonWorld(void)
{
Scene *scene = NewScene();
+ Translate(&(scene->camera->transform), V(0, 0, -5));
SceneObject *cube = CreateSceneObject(scene, "assets/cube.obj", BLACK);
// ScaleObject(cube, 10, 10, 10);
SpinObject(cube, 0, 0.1, 0);
@@ 113,6 114,10 @@ Scene *NewScene(void)
scene->physics_pool = NewPool(Physics, MAX_SCENE_OBJECTS);
scene->model_pool = NewPool(Model, MAX_SCENE_OBJECTS);
scene->particles = NULL;
+ Model *cameraModel = NewModel(scene->model_pool);
+ Physics *cameraPhysics = NewPhysics(scene->physics_pool, cameraModel,
+ V(0, 0, 0), V(0, 0, 0), V(0, 0, 0));
+ scene->camera = NewCamera(20, 1, 1, 100, cameraModel, cameraPhysics);
return scene;
}
@@ 276,17 281,18 @@ Particle *AddParticle(Particle *pool, Vertex v)
return p;
}
-Renderer *NewRenderer(Pixel *pixels, int width, int height)
+Renderer *NewRenderer(Pixel *pixels, int width, int height, Camera *camera)
{
Renderer *r = malloc(sizeof(Renderer));
r->pixels = pixels;
r->depthBuffer = NewDepthBuffer(width, height);
r->width = width;
r->height = height;
-
- r->projectionTransform = PerspectiveTransform(20, (double)width/(double)height, 1, 100);
+ r->camera = camera;
+ /* update aspect ratio */
+ SetCamera(camera, camera->fov, (float)width/(float)height, camera->near, camera->far);
r->deviceTransform = Translation(V(1, 1, 0));
- // Scale to viewport size
+ /* scale to viewport size */
Scale(&(r->deviceTransform), 0.5*(width-1), 0.5*(height-1), 1);
r->vertex_pool = NewPool(Vertex, MAX_RENDER_VERTICES);
@@ 326,15 332,44 @@ DepthVal *NewDepthBuffer(int width, int height)
return values;
}
+Camera *NewCamera(double fov, double aspect, double near, double far, Model *model, Physics *physics)
+{
+ Camera *camera = malloc(sizeof(Camera));
+ camera->model = model;
+ camera->physics = physics;
+ camera->transform = Identity();
+ camera->fov = fov;
+ camera->aspect = aspect;
+ camera->x_cotan = 1/(aspect * tan(fov/2));
+ camera->y_cotan = 1/tan(fov/2);
+ camera->near = near;
+ camera->far = far;
+ return camera;
+}
+
+void SetCamera(Camera *camera, double fov, double aspect, double near, double far)
+{
+ camera->fov = fov;
+ camera->aspect = aspect;
+ camera->x_cotan = 1/(aspect * tan(fov/2));
+ camera->y_cotan = 1/tan(fov/2);
+ camera->near = near;
+ camera->far = far;
+}
+
+void ZoomIn(Camera *camera, double amt)
+{
+ camera->fov *= 1/(amt/100000 + 1);
+ camera->x_cotan = 1/(camera->aspect * tan(camera->fov/2));
+ camera->y_cotan = 1/tan(camera->fov/2);
+}
+
Transform PerspectiveTransform(double fov, double aspect, double near, double far)
{
Transform op, t;
t = Identity();
- // manual camera placement
- Translate(&t, V(0, 0, -5));
-
// perspective transform into canonical view volume
op = Identity();
op.m[0][0] = 1/(aspect * tan(fov/2));
@@ 348,6 383,25 @@ Transform PerspectiveTransform(double fov, double aspect, double near, double fa
return t;
}
+Transform CameraTransform(Camera *camera)
+{
+ Transform op, t;
+
+ t = FromTransform(camera->transform);
+
+ /* perspective transform into canonical view volume */
+ op = Identity();
+ op.m[0][0] = camera->x_cotan;
+ op.m[1][1] = camera->y_cotan;
+ op.m[2][2] = (camera->far + camera->near) / (camera->far - camera->near);
+ op.m[3][3] = 0;
+ op.m[2][3] = (2*camera->far*camera->near) / (camera->far - camera->near);
+ op.m[3][2] = -1;
+ AddTransform(op, &t);
+
+ return t;
+}
+
Vertex *NewVertex(Vertex *pool)
{
assert(PoolTotal(pool) < MAX_RENDER_VERTICES);
@@ 451,9 505,7 @@ void ModelVertex(Vertex *vertex, Model *model)
void ProjectVertex(Vertex *vertex, Renderer *renderer)
{
- // Transform camera_transform = CameraTransform(camera);
- // AddTransform(renderer->projectionTransform, &camera_transform);
- CommitTransform(renderer->projectionTransform, vertex);
+ CommitTransform(CameraTransform(renderer->camera), vertex);
}
int *NewPolygon(int *pool)