aboutsummaryrefslogtreecommitdiff
path: root/scene.c
blob: a0fa46c53b391f10560b4e264b34d4e70ba8c513 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "scene.h"

#include <stdlib.h>
#include <string.h>

static inline void link_object(space_t *s, object_t *o)
{
	if (s) {
		o->next = s->objects;
		s->objects = o;
	} else {
		o->next = 0;
	}
}

container_t *container_init(container_t *c, unsigned objs, unsigned mats, unsigned ligs) 
{
	c->obj_index = c->mat_index = c->lig_index = 0;

	c->obj_cap = objs;
	c->mat_cap = mats;
	c->lig_cap = ligs;

	return c;
}

space_t *container_prepare_space(container_t *c)
{
	memset(&c->space, 0, sizeof(space_t));
	return &c->space;
}

// Finds the next empty object_t space
// Return NULL if full
static inline object_t *container_obj_space(container_t *cont) 
{
	if (cont->obj_index >= cont->obj_cap) {
		fprintf(stderr, "Could not create object, because container is full\n");
		return NULL;
	}

	// Find a nice spot in the content blob
	return &((object_t *) cont->content)[cont->obj_index++];
}

static inline material_t *container_mat_space(container_t *cont) 
{
	if (cont->mat_index >= cont->mat_cap) {
		fprintf(stderr, "Could not create material, because container is full\n");
		return NULL;
	}

	// Find a nice spot in the content blob.
	// Remember to jump over objects
	return &((material_t *) (
				cont->content + 
				sizeof(object_t) * cont->obj_cap
				))[cont->mat_index++];
}

static inline light_t *container_lig_space(container_t *cont) 
{
	if (cont->lig_index >= cont->lig_cap) {
		fprintf(stderr, "Could not create light, because container is full\n");
		return NULL;
	}

	// Find a nice spot in the content blob.
	// Remember to jump over objects and materials
	return &((light_t *) (
				cont->content + 
				sizeof(object_t) * cont->obj_cap + 
				sizeof(material_t) * cont->mat_cap
				))[cont->lig_index++];
}

object_t *add_object(container_t *cont, unsigned type)
{

	object_t *o = container_obj_space(cont);
	if (!o) {
		return NULL;
	}

	// Fill out the data
	o->type = type;

	// Link to the linked list
	link_object(&cont->space, o);

	return o;
}

light_t *add_light(container_t *cont, unsigned type)
{
	light_t *o = container_lig_space(cont);
	if (!o) {
		return NULL;
	}

	o->type = type;

	space_t *s = &cont->space;
	if (s) {
		o->next = s->lights;
		s->lights = o;
	} else {
		o->next = NULL;
	}

	return o;
}

// It's alot easier to set the stuff outside of this function
material_t *add_material(container_t *cont)
{
	material_t *m = container_mat_space(cont);
	memset(m, 0, sizeof(material_t));

	return m;
}

void obj_norm_at(object_t *o, vector_t *dest, vector_t *point, vector_t *direction)
{
	switch(o->type) {
		case TYPE_SPHERE:
			vector_sub(dest, point, &o->sph.center);
			vector_scale_inv(dest, dest, vector_len(dest));
			break;
		case TYPE_PLANE:
			// Calculate if the point is in front
			vector_scale(dest, &o->pl.norm, (vector_dot(direction, &o->pl.norm) > 0) ? -1 : 1);
			break;
	}

	return;
}