4 #include <string.h> // for memset
6 struct terrain
* terrain_create(int size
)
8 struct terrain
*t
= malloc(sizeof(struct terrain
));
10 t
->height
= malloc(sizeof(float)*size
*size
);
11 t
->normal
= malloc(sizeof(struct point
)*size
*size
);
13 t
->drawlist
= glGenLists(1);
19 void terrain_destroy(struct terrain
* t
)
23 glDeleteLists(t
->drawlist
, 1);
27 inline static void calculate_normal(int ai
, int aj
, int bi
, int bj
, int ci
, int cj
,
28 float *height
, struct point
*normal
, int size
)
30 struct point a
= {ai
, height
[ai
*size
+aj
], aj
, 0.0};
31 struct point b
= {bi
, height
[bi
*size
+bj
], bj
, 0.0};
32 struct point c
= {ci
, height
[ci
*size
+cj
], cj
, 0.0};
42 struct point
*n
= &normal
[ai
*size
+aj
];
44 point_cross(n
, &b
, &c
);
48 void terrain_bake(struct terrain
*t
)
51 float *height
= t
->height
;
52 struct point
*normal
= t
->normal
;
53 struct point tmp
, *ptr
;
57 // calculate the inside
59 for (i
=1; i
<size
-1; i
++)
61 for (j
=1; j
<size
-1; j
++)
63 ptr
= &normal
[i
*size
+j
];
64 calculate_normal(i
,j
, i
,j
+1, i
+1,j
, height
, normal
, size
);
68 calculate_normal(i
,j
, i
+1,j
, i
,j
-1, height
, normal
, size
);
72 calculate_normal(i
,j
, i
,j
-1, i
-1,j
, height
, normal
, size
);
76 calculate_normal(i
,j
, i
-1,j
, i
,j
+1, height
, normal
, size
);
90 // calculate the outer ridge
92 for (j
=0; j
<size
-1; j
++)
94 calculate_normal(0,j
, 0,j
+1, 1,j
, height
, normal
, size
);
95 calculate_normal(i
,j
, i
-1,j
, i
,j
+1, height
, normal
, size
);
96 calculate_normal(j
,0, j
,1, j
+1,0, height
, normal
, size
);
97 calculate_normal(j
,i
, j
+1,i
, j
,i
-1, height
, normal
, size
);
101 void build_execute(struct terrain
*t
)
103 glNewList(t
->drawlist
, GL_COMPILE_AND_EXECUTE
);
106 float *height
= t
->height
;
107 struct point
*normal
= t
->normal
;
112 float div
= t
->max_height
- t
->min_height
;
113 if (div
== 0) div
= 0.000001;
114 float scale
= 1.0/div
;
117 for (i
=0; i
<size
-1; i
++)
119 glBegin(GL_TRIANGLE_STRIP
);
120 for (j
=0; j
<size
; j
++)
122 z
= height
[i
*size
+j
];
123 zcol
= (z
- t
->min_height
)*scale
;
125 if (t
->drawmode
== FLAT
)
126 glColor3f(0.0, zcol
, 1.0 - zcol
);
128 if (t
->drawmode
== NORMAL
|| t
->drawmode
== NORMAL_DEBUG
)
130 n
= &normal
[i
*size
+j
];
131 glNormal3f(n
->x
, n
->y
, n
->z
);
136 z
= height
[(i
+1)*size
+j
];
137 zcol
= (z
- t
->min_height
)*scale
;
139 if (t
->drawmode
== FLAT
)
140 glColor3f(0.0, zcol
, 1.0 - zcol
);
142 if (t
->drawmode
== NORMAL
|| t
->drawmode
== NORMAL_DEBUG
)
144 n
= &normal
[(i
+1)*size
+j
];
145 glNormal3f(n
->x
, n
->y
, n
->z
);
148 glVertex3f(i
+1, z
, j
);
153 if (t
->drawmode
== NORMAL_DEBUG
)
155 glDisable(GL_LIGHTING
);
156 glColor3f(1.0, 0.0, 0.0);
158 for (i
=0; i
<size
; i
++)
160 for (j
=0; j
<size
; j
++)
162 struct point p
= {i
, height
[i
*size
+j
], j
, 0.0};
163 glVertex3f(p
.x
, p
.y
, p
.z
);
164 point_add(&p
, &normal
[i
*size
+j
]);
165 glVertex3f(p
.x
, p
.y
, p
.z
);
169 glEnable(GL_LIGHTING
);
175 void terrain_draw(struct terrain
*t
)
180 glTranslatef(-0.5*size
, 0.0, -0.5*size
);
182 if (t
->drawmode
== FLAT
)
183 glDisable(GL_LIGHTING
);
192 glCallList(t
->drawlist
);
195 glEnable(GL_LIGHTING
);
200 void terrain_smooth(struct terrain
*t
, float k
)
203 float *height
= t
->height
;
209 for (i
=1; i
<size
; i
++)
211 for (j
=0; j
<size
; j
++)
214 height
[idx
] = height
[(i
-1)*size
+j
] * (1.0-k
) + height
[idx
] * k
;
218 for (i
=size
-2; i
>-1; i
--)
220 for (j
=0; j
<size
; j
++)
223 height
[idx
] = height
[(i
+1)*size
+j
] * (1.0-k
) + height
[idx
] * k
;
227 for (i
=0; i
<size
; i
++)
229 for (j
=1; j
<size
; j
++)
232 height
[idx
] = height
[i
*size
+j
-1] * (1.0-k
) + height
[idx
] * k
;
236 for (i
=0; i
<size
; i
++)
238 for (j
=size
-2; j
>-1; j
--)
241 height
[idx
] = height
[i
*size
+j
+1] * (1.0-k
) + height
[idx
] * k
;
246 void terrain_clear(struct terrain
*t
)
250 memset(t
->height
, 0, sizeof(float)*t
->size
*t
->size
);