Browse Source

bezier example scene

Iver 5 months ago
parent
commit
772f844613

+ 1 - 1
Makefile

@@ -12,4 +12,4 @@ rasteriver.so:
 	$(COMPILER) $(FLAGS_ALL) src/library/rasteriver.c -o compiled_libs/librasteriver.so $(FLAGS_LIB) 
 
 clean:
-	rm build/*
+	-rm build/*

BIN
build/librasteriver.so


BIN
build/main.bin


BIN
compiled_libs/librasteriver.so


+ 5 - 0
src/headers/functions.h

@@ -2,6 +2,7 @@
 #define FUNCTIONS_H
 
 #include "custom_types.h"
+#include "sourparse.h"
 
 RI_mesh* RI_request_meshes(int RI_number_of_requested_objects, char **filenames, int RI_request_just_mesh); // Load object file(s)
 RI_actor* RI_request_actors(int RI_number_of_requested_actors); // Load texture file(s)
@@ -14,5 +15,9 @@ int RI_render(RI_scene *scene, RI_texture *target_texture, int clear_texture); /
 int RI_add_actors_to_scene(int RI_number_of_actors_to_add_to_scene, RI_actor *actors, RI_scene *scene);
 void RI_euler_rotation_to_quaternion(RI_vector_4f* quaternion, RI_vector_3f euler_rotation);
 void RI_tick();
+void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f position, uint32_t color, int bezier_resolution, float size, char *text);
+void RI_draw_line(RI_texture *target_texture, RI_vector_2 point_a, RI_vector_2 point_b, uint32_t color);
+RI_vector_2f v2_to_2f(RI_vector_2 v);
+RI_vector_2 v2f_to_2(RI_vector_2f v);
 
 #endif

+ 90 - 1
src/headers/math.h

@@ -2,6 +2,7 @@
 #define MATH_H
 
 #include "stdint.h"
+#include <math.h>
 
 typedef struct {
     int x; 
@@ -19,6 +20,12 @@ typedef struct {
     double z; 
 } RI_vector_3f;
 
+typedef struct {
+    int x; 
+    int y; 
+    int z; 
+} RI_vector_3;
+
 typedef struct {
     double w; 
     double x; 
@@ -33,6 +40,13 @@ void vector_2f_times(RI_vector_2f *vector, double value){
     vector->y *= value;
 }
 
+// value-wise multiplacation.
+// multiply the whole vector by 1 value
+void vector_2_times(RI_vector_2 *vector, double value){
+    vector->x *= value;
+    vector->y *= value;
+}
+
 // value-wise multiplacation.
 // multiply the whole vector by 1 value
 void vector_3f_times(RI_vector_3f *vector, double value){
@@ -41,6 +55,14 @@ void vector_3f_times(RI_vector_3f *vector, double value){
     vector->z *= value;
 }
 
+// value-wise multiplacation.
+// multiply the whole vector by 1 value
+void vector_3_times(RI_vector_3 *vector, double value){
+    vector->x *= value;
+    vector->y *= value;
+    vector->z *= value;
+}
+
 // hadamard multiplacation.
 // multiply each value of one vector with the matching one on the other vector
 void vector_3f_hadamard(RI_vector_3f *multiplicand, RI_vector_3f multiplicator){
@@ -56,6 +78,13 @@ void vector_2f_element_wise_add(RI_vector_2f *addend_a, RI_vector_2f addend_b){
     addend_a->y += addend_b.y;
 }
 
+// "hadamard" addition.
+// add each value of one vector with the matching one on the other vector
+void vector_2_element_wise_add(RI_vector_2 *addend_a, RI_vector_2 addend_b){
+    addend_a->x += addend_b.x;
+    addend_a->y += addend_b.y;
+}
+
 // "hadamard" addition.
 // add each value of one vector with the matching one on the other vector
 void vector_3f_element_wise_add(RI_vector_3f *addend_a, RI_vector_3f addend_b){
@@ -64,6 +93,14 @@ void vector_3f_element_wise_add(RI_vector_3f *addend_a, RI_vector_3f addend_b){
     addend_a->z += addend_b.z;
 }
 
+// "hadamard" addition.
+// add each value of one vector with the matching one on the other vector
+void vector_3_element_wise_add(RI_vector_3 *addend_a, RI_vector_3 addend_b){
+    addend_a->x += addend_b.x;
+    addend_a->y += addend_b.y;
+    addend_a->z += addend_b.z;
+}
+
 // "hadamard" subtraction.
 // subtraction each value of one vector with the matching one on the other vector
 void vector_3f_element_wise_subtract(RI_vector_3f *minuend, RI_vector_3f subtrahend){
@@ -114,7 +151,22 @@ void vector_2f_lerp(RI_vector_2f vector_a, RI_vector_2f vector_b, RI_vector_2f *
     vector_2f_element_wise_add(result, vector_b);
 }
 
-// beziate between 2 vectors
+// linear interpolate between 2 vectors
+void vector_2_lerp(RI_vector_2 vector_a, RI_vector_2 vector_b, RI_vector_2 *result, double w1){
+    double w0 = 1.0 - w1;
+
+    vector_2_times(result, 0);
+
+    vector_2_times(&vector_a, w0);
+    vector_2_times(&vector_b, w1);
+
+    vector_2_element_wise_add(result, vector_a);
+    vector_2_element_wise_add(result, vector_b);
+}
+
+// beziate between 2 vectors.
+// A & C: end points of the line
+// B: point that determines the curve; off the line
 void vector_2f_bezier_interpolate(RI_vector_2f vector_a, RI_vector_2f vector_b, RI_vector_2f vector_c, RI_vector_2f *result, double w1){
     double w0 = 1.0 - w1;
 
@@ -124,6 +176,18 @@ void vector_2f_bezier_interpolate(RI_vector_2f vector_a, RI_vector_2f vector_b,
     vector_2f_lerp(vector_b, vector_c, result, w1);
 }
 
+// beziate between 2 vectors.
+// A & C: end points of the line
+// B: point that determines the curve; off the line
+void vector_2_bezier_interpolate(RI_vector_2 vector_a, RI_vector_2 vector_b, RI_vector_2 vector_c, RI_vector_2 *result, double w1){
+    double w0 = 1.0 - w1;
+
+    vector_2_lerp(vector_a, vector_b, &vector_b, w1); // this works because the first vector b is a copy and the second is a reference
+    vector_2_lerp(vector_b, vector_c, &vector_c, w1);
+
+    vector_2_lerp(vector_b, vector_c, result, w1);
+}
+
 // linear interpolate between 2 vectors
 void vector_3f_lerp(RI_vector_3f vector_a, RI_vector_3f vector_b, RI_vector_3f *result, double w1){
     double w0 = 1.0 - w1;
@@ -137,5 +201,30 @@ void vector_3f_lerp(RI_vector_3f vector_a, RI_vector_3f vector_b, RI_vector_3f *
     vector_3f_element_wise_add(result, vector_b);
 }
 
+// linear interpolate between 2 vectors
+void vector_3_lerp(RI_vector_3 vector_a, RI_vector_3 vector_b, RI_vector_3 *result, double w1){
+    double w0 = 1.0 - w1;
+
+    vector_3_times(result, 0);
+
+    vector_3_times(&vector_a, w0);
+    vector_3_times(&vector_b, w1);
+
+    vector_3_element_wise_add(result, vector_a);
+    vector_3_element_wise_add(result, vector_b);
+}
+
+// returns the distance between 2 points
+int distance_2(RI_vector_2 a, RI_vector_2 b){
+    return (int)sqrtf((float)((float)(a.x - b.x) * (float)(a.x - b.x)) + (float)((float)(a.y - b.y) * (float)(a.y - b.y)));
+}
+
+RI_vector_2f v2_to_2f(RI_vector_2 v){
+    return (RI_vector_2f){v.x, v.y};
+}
+
+RI_vector_2 v2f_to_2(RI_vector_2f v){
+    return (RI_vector_2){v.x, v.y};
+}
 
 #endif

+ 21 - 45
src/launch_program/main.c

@@ -99,20 +99,29 @@ int main(){
 
     scene->antialiasing_subsample_resolution = 8;
     scene->flags = RI_SCENE_DONT_USE_AA;
-
-    int glyph = 0;
-
-
     
     while (running){
-               
-        if (ri->frame % 1 == 0){
-            glyph++;
-
-                test_object->transform.position = (RI_vector_3f){-10000, -1000,-100000};
-                RI_render(scene, ri->frame_buffer, 1);
+        RI_render(scene, ri->frame_buffer, 1);
+        
+        // RI_render_text(font, ri->frame_buffer, (RI_vector_2f){50, 200}, 0xFFFFFFFF, 10, 300, "A");
+        
+        RI_vector_2f a = {300, 200};
+        RI_vector_2f b = {500, 200};
+        RI_vector_2f c = {400, 500};
+        
+        b.y = sin((double)ri->frame / 100.0) * 700;
+        b.x = cos((double)ri->frame / 100.0) * 700;
+        
+        RI_vector_2f prev = a;
 
+        for (int i = 0; i < ceil(sqrt(ri->frame / 10)); ++i){
+            RI_vector_2f temp; vector_2f_bezier_interpolate(a, b, c, &temp, (double)(i + 1) / (double)(ceil(sqrt(ri->frame / 10))));
+            
+            RI_draw_line(ri->frame_buffer, v2f_to_2(prev), v2f_to_2(temp), 0xFFFFFFFF);
+        
+            prev = temp;
         }
+        printf("%d\n", ri->frame);
 
         // test_object->transform.position = (RI_vector_3f){0, 0, 200};
 
@@ -132,43 +141,10 @@ int main(){
 
         // y_rotation += 0.1;
         
-        float scale = 0.3;
-
-if (font->glyphs[glyph].number_of_contours > 0){
-    for (int i = 0; i < font->glyphs[glyph].number_of_contours; ++i){
-            for (int j = i > 0 ? font->glyphs[glyph].contour_end_indicies[i - 1] : 0; j < font->glyphs[glyph].contour_end_indicies[i]; ++j){
-                // if (!(font->glyphs[glyph].flags[j] & 1)) test_object->material_reference->texture_reference = &ri->error_texture;
-                // test_object->material_reference->texture_reference = test_object_texture;
-                test_object->transform.position = (RI_vector_3f){font->glyphs[glyph].x_coords[j] * scale - 100, font->glyphs[glyph].y_coords[j] * scale - 100, 500};
-            
-                RI_render(scene, ri->frame_buffer, 0);
-            }
-        }
-
-}
-else {
-    for (int k = 0; k < font->glyphs[glyph].number_of_components; k++){
-        int c_glyph = font->glyphs[glyph].components[k].glyph_index;
-
-        if (k == 1) c_glyph = 599;
 
-        int offset_x = (int)font->glyphs[glyph].components[k].arg1;
-        int offset_y = (int)font->glyphs[glyph].components[k].arg2;
-        
-        for (int i = 0; i < font->glyphs[c_glyph].number_of_contours; ++i){
-            for (int j = i > 0 ? font->glyphs[c_glyph].contour_end_indicies[i - 1] : 0; j < font->glyphs[c_glyph].contour_end_indicies[i]; ++j){
-                // if (!(font->glyphs[glyph].flags[j] & 1)) test_object->material_reference->texture_reference = &ri->error_texture;
-                // test_object->material_reference->texture_reference = test_object_texture;
-                test_object->transform.position = (RI_vector_3f){(font->glyphs[c_glyph].x_coords[j] + offset_x) * scale - 100, (font->glyphs[c_glyph].y_coords[j] + offset_y) * scale - 100, 500};
-            
-                RI_render(scene, ri->frame_buffer, 0);
-            }
-        }
-    }
-}
-RI_tick();
-    ++ri->frame;
+        RI_tick();
 
+        ++ri->frame;
     }
 
     SP_free_font(font);

+ 132 - 0
src/library/rasteriver.c

@@ -161,6 +161,138 @@ void written_RI_free(void *__ptr, const char *caller, int line){
     free(__ptr);
 }
 
+void RI_draw_line(RI_texture *target_texture, RI_vector_2 point_a, RI_vector_2 point_b, uint32_t color){
+    int num_pixels = distance_2(point_a, point_b);
+    
+    for (int i = 0; i < num_pixels; ++i){
+        RI_vector_2 point_2_draw; vector_2_lerp(point_a, point_b, &point_2_draw, (double)i / (double)num_pixels);
+
+        if (point_2_draw.x < 0 || point_2_draw.x >= target_texture->resolution.x || point_2_draw.y < 0 || point_2_draw.y >= target_texture->resolution.y) continue;
+
+        target_texture->image_buffer[point_2_draw.y * target_texture->resolution.x + point_2_draw.x] = color;
+    }
+}
+
+int ccw(RI_vector_2f a, RI_vector_2f b, RI_vector_2f c) {
+    return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
+}
+
+int intersects_segments(RI_vector_2f a, RI_vector_2f b, RI_vector_2f c, RI_vector_2f d) {
+    return (ccw(a, c, d) != ccw(b, c, d)) && (ccw(a, b, c) != ccw(a, b, d));
+}
+
+int intersects(RI_vector_2f a, RI_vector_2f b, RI_vector_2f c){
+    RI_vector_2f d = {10000, c.y};
+    return intersects_segments(a, b, c, d);
+}
+
+void render_glyph(RI_texture *target_texture, RI_vector_2f position, float size, uint32_t color, int bezier_resolution, float units_per_em, SP_glyph *glyph){
+    // estimate
+    int new_point_count = 0;
+    int allocated_new_points = glyph->number_of_points * 3;
+    RI_vector_2f *new_points = RI_malloc(sizeof(RI_vector_2f) * allocated_new_points);
+    
+    for (int contour = 0; contour < glyph->number_of_contours; ++contour){
+        // if we are at contour 0, point_start is 0.
+        // if contour is > 0 but != 0, point_start is equal to the previous index
+        int point_start = contour > 0 ? glyph->contour_end_indicies[contour - 1] : 0;
+
+        int point_offset = point_start;
+
+        // find first on-curve point because the first point isn't always on the curves
+        while (!(glyph->flags[point_offset] & 1)){
+            point_offset++;
+        }
+
+        for (int point = 0; point < glyph->contour_end_indicies[contour]; ++point){
+            if (new_point_count == allocated_new_points){
+                allocated_new_points += 20;
+
+                new_points = RI_realloc(new_points, sizeof(RI_vector_2f) * allocated_new_points);
+            }
+            
+            int cur = (point + point_offset) % glyph->contour_end_indicies[contour];
+            int next = (point + point_offset + 1) % glyph->contour_end_indicies[contour];
+            
+            new_points[new_point_count].x = (float)glyph->x_coords[cur] / units_per_em * size;
+            new_points[new_point_count].y = (float)glyph->y_coords[cur] / units_per_em * size;
+
+            target_texture->image_buffer[(int)((new_points[new_point_count].y + position.y) * target_texture->resolution.x + (new_points[new_point_count].x + position.x))] = 0xFF00FF00;
+
+            new_point_count++;
+
+            // if current and next glyph are both on or off the curve, add a point between them-
+            if ((glyph->flags[cur] & 1) == (glyph->flags[next] & 1)){
+                vector_2f_lerp((RI_vector_2f){(float)glyph->x_coords[cur] / units_per_em * size, (float)glyph->y_coords[cur] / units_per_em * size}, (RI_vector_2f){(float)glyph->x_coords[next] / units_per_em * size, (float)glyph->y_coords[next] / units_per_em * size}, &new_points[new_point_count], 0.5);
+
+                target_texture->image_buffer[(int)((new_points[new_point_count].y + position.y) * target_texture->resolution.x + (new_points[new_point_count].x + position.x))] = 0xFF00FF00;
+
+                new_point_count++;
+            }
+        }
+    }
+    
+    allocated_new_points = new_point_count;
+
+    for (int y = (int)((float)glyph->y_min / (float)units_per_em * size) + position.y; y < (int)((float)glyph->y_max / (float)units_per_em * size) + position.y; ++y){
+        for (int x = (int)((float)glyph->x_min / (float)units_per_em * size) + position.x; x < (int)((float)glyph->x_max / (float)units_per_em * size) + position.x; ++x){
+            int intersections = 0;
+            
+            for (int point = 0; point < new_point_count; point += 2){
+                RI_vector_2f point_a = new_points[point % new_point_count];
+                RI_vector_2f point_b = new_points[(point + 1) % new_point_count];
+                RI_vector_2f point_c = new_points[(point + 2) % new_point_count];
+
+                RI_vector_2f prev_point = new_points[point % new_point_count];
+
+                for (int i = 0; i < bezier_resolution; ++i){
+                    float w = (float)(i + 1) / (float)bezier_resolution;
+                    
+                    RI_vector_2f bez_point; vector_2f_bezier_interpolate(point_a, point_b, point_c, &bez_point, w);
+
+                    if (bez_point.y >= 0 && bez_point.x >= 0)
+                    target_texture->image_buffer[(int)((bez_point.y + position.y) * target_texture->resolution.x + (bez_point.x + position.x))] = 0xFFFF5555;
+
+
+                    if(intersects(prev_point, bez_point, (RI_vector_2f){x, y})) intersections++; 
+            
+                    prev_point = bez_point;
+                }
+            }
+
+            if (intersections % 2 != 0) target_texture->image_buffer[y * target_texture->resolution.x + x] = color;
+        }
+    }
+
+    RI_free(new_points);
+}
+
+void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f position, uint32_t color, int bezier_resolution, float size, char *text){
+    int character_count = strlen(text);
+    
+    for (int character_i = 0; character_i < character_count; ++character_i){
+        int glyph = font->unicode_to_glyph_indicies[text[character_i]];
+        
+        SP_glyph *current_glyph = &font->glyphs[glyph];
+        
+        if (current_glyph->number_of_contours > 0){
+            render_glyph(target_texture, position, size, color, bezier_resolution, (int)font->units_per_em, current_glyph);
+        }
+        else {
+            for (int k = 0; k < current_glyph->number_of_components; k++){
+                int c_glyph = current_glyph->components[k].glyph_index;
+                
+                int offset_x = (int)current_glyph->components[k].arg1;
+                int offset_y = (int)current_glyph->components[k].arg2;
+                
+                render_glyph(target_texture, position, size, color, bezier_resolution, (int)font->units_per_em, &font->glyphs[c_glyph]);
+            }
+        }
+        
+        position.x += 50;
+    }
+}
+
 int RI_add_actors_to_scene(int RI_number_of_actors_to_add_to_scene, RI_actor *actors, RI_scene *scene){
     int previous_actor_count = scene->actor_count;