From 8fa537d2d7d1574a44fb3cf352d13ce4175236da Mon Sep 17 00:00:00 2001 From: mack Date: Wed, 29 Oct 2025 21:24:15 +0000 Subject: [PATCH] Upload files to "/" --- HydraulicErosion.c | 344 +++++++++++++++++++++++++++++++++++++++++++ STLTextWriter.h | 75 ++++++++++ dotAndCrossProduct.h | 10 ++ 3 files changed, 429 insertions(+) create mode 100644 HydraulicErosion.c create mode 100644 STLTextWriter.h create mode 100644 dotAndCrossProduct.h diff --git a/HydraulicErosion.c b/HydraulicErosion.c new file mode 100644 index 0000000..aed753a --- /dev/null +++ b/HydraulicErosion.c @@ -0,0 +1,344 @@ +#include "STLTextWriter.h" +#include "time.h" + +// I did not write this Image-reading library. You can find the original author at the following link. +// https://github.com/nothings/stb/blob/master/stb_image.h +#define STB_IMAGE_IMPLEMENTATION +//#define STBI_MALLOC +//#define STBI_REALLOC +//#define STBI_FREE +#include "stb_image.h" + +// minimum value function for integers +int imin(int num1, int num2){ + if(num1 < num2){ + return num1; + } + else{ + return num2; + } +} + +// minimum value function for doubles +double dmin(double num1, double num2){ + if(num1 <= num2){ + return num1; + } + else{ + return num2; + } +} + +// minimum value function for doubles +double dmax(double num1, double num2){ + if(num1 >= num2){ + return num1; + } + else{ + return num2; + } +} + +// makes an array index wrap to the other end if it does out of bounds +int indmod(int index, int size){ // index modulus + index %= size; + if(index < 0){ + index += size; + } + return index; +} + +// does literally everything else +int main(int argc, char *argv[]){ + double point1[3] = {0,0,0}; + double point2[3] = {0,0,0}; + double point3[3] = {0,0,0}; + double point4[3] = {0,0,0}; + int hmheight = 0; + int hmwidth = 0; + int n = 0; + double const dpi = 1.0/8; + char filepath[300]; + char modelpath[300]; + int extlen = 0; + char newext[] = "stl"; + + srand(time(NULL)); + printf("\n\n"); + + //check for filename + if(argc < 2){ + printf("Enter file path/name: "); + scanf("%300s",&filepath); + } + else{ + strcpy(filepath, argv[1]); + } + + // populate heightmap + unsigned char *data = stbi_load(filepath, &hmwidth, &hmheight, &n, 0); + if(data == NULL){ + printf("data = NULL\n\n"); + exit(1); + } + double* heightmap; + heightmap = (double*)malloc(hmheight * hmwidth * sizeof(double)); + if(heightmap == NULL){ + printf("Memory for heightmap could not be allocated.\n\n"); + exit(1); + } + + for(int i = 0; i < hmwidth; i++){ + for(int j = 0; j < hmheight; j++){ + heightmap[i*hmheight+j] = 0.5f; + } + } + + for(int i = 0; i < hmwidth; i++){ + for(int j = 0; j < hmheight; j++){ + for(int k = 0; k < n; k++){ + heightmap[i*hmheight+j] += *(data+i*hmheight*n+j*n) / (127.0f*n); + } + heightmap[i*hmheight+j] = dmax(heightmap[i*hmheight+j], 0.1f); + } + } + stbi_image_free(data); + printf("STATUS___Read data into heightmap\n"); + + // bustin' out the spreadsheet again + // Uncomment the code below to get a .csv spreadsheet of the heightmap + /* + FILE *dumpfile; + dumpfile = fopen("heightmap.csv", "w"); + for(int i = 0; i < hmheight*hmwidth; i++){ + fprintf(dumpfile, "%f,", heightmap[i]); + if(i % hmwidth == 0){ + fprintf(dumpfile, "\n"); + } + } + fclose(dumpfile); + */ + + // get model file name + for(int i = strlen(filepath)-1; i >= 0; i--){ + if(filepath[i] == '.'){ + extlen = i; + filepath[i+1] = '\0'; + break; + } + if(i == 0){ + printf("Could not recognize file path/name\n\n"); + exit(1); + } + } + strcpy(modelpath, filepath); + strcat(modelpath, newext); + + // writing to file + FILE *modelfile; + modelfile = fopen(modelpath, "w"); + startSTL(modelfile); + + // drawing the top of the mesh + for(int i = 0; i < hmwidth-1; i++){ // i is the distance from the left edge + for(int j = 0; j < hmheight-1; j++){ // j is the distance from the bottom edge + point1[0] = i*dpi; + point1[1] = j*dpi; + point1[2] = heightmap[i+((hmheight-1-j)*hmwidth)]; + + point2[0] = (i+1)*dpi; + point2[1] = j*dpi; + point2[2] = heightmap[(i+1)+((hmheight-1-j)*hmwidth)]; + + point3[0] = i*dpi; + point3[1] = (j+1)*dpi; + point3[2] = heightmap[i+((hmheight-2-j)*hmwidth)]; + + point4[0] = (i+1)*dpi; + point4[1] = (j+1)*dpi; + point4[2] = heightmap[(i+1)+((hmheight-2-j)*hmwidth)]; + + drawTriangle(modelfile, point1, point2, point4); + drawTriangle(modelfile, point1, point4, point3); + } + } + printf("STATUS___Drew top of mesh\n"); + + //drawing the sides of the mesh + for(int i = 0; i < hmwidth-1; i++){ + // Front edge + point1[0] = i*dpi; + point1[1] = 0; + point1[2] = 0; + + point2[0] = i*dpi; + point2[1] = 0; + point2[2] = heightmap[i+(hmwidth*(hmheight-1))]; + + point3[0] = (i+1)*dpi; + point3[1] = 0; + point3[2] = 0; + + point4[0] = (i+1)*dpi; + point4[1] = 0; + point4[2] = heightmap[i+1+(hmwidth*(hmheight-1))]; + + drawTriangle(modelfile, point1, point4, point2); + drawTriangle(modelfile, point1, point3, point4); + + // Back edge + point1[0] = i*dpi; + point1[1] = (hmheight-1)*dpi; + point1[2] = 0; + + point2[0] = i*dpi; + point2[1] = (hmheight-1)*dpi; + point2[2] = heightmap[i]; + + point3[0] = (i+1)*dpi; + point3[1] = (hmheight-1)*dpi; + point3[2] = 0; + + point4[0] = (i+1)*dpi; + point4[1] = (hmheight-1)*dpi; + point4[2] = heightmap[i+1]; + + drawTriangle(modelfile, point1, point2, point4); + drawTriangle(modelfile, point1, point4, point3); + } + printf("STATUS___Drew front and back of mesh\n"); + for(int j = 0; j < hmheight-1; j++){ + // Left edge + point1[0] = 0; + point1[1] = (hmheight-j-1)*dpi; + point1[2] = 0; + + point2[0] = 0; + point2[1] = (hmheight-j-1)*dpi; + point2[2] = heightmap[j*hmwidth]; + + point3[0] = 0; + point3[1] = (hmheight-j-2)*dpi; + point3[2] = 0; + + point4[0] = 0; + point4[1] = (hmheight-j-2)*dpi; + point4[2] = heightmap[(j+1)*hmwidth]; + + drawTriangle(modelfile, point1, point4, point2); + drawTriangle(modelfile, point1, point3, point4); + + // Right edge + point1[0] = (hmwidth-1)*dpi; + point1[1] = (hmheight-j-1)*dpi; + point1[2] = 0; + + point2[0] = (hmwidth-1)*dpi; + point2[1] = (hmheight-j-1)*dpi; + point2[2] = heightmap[(j*hmwidth)+hmwidth-1]; + + point3[0] = (hmwidth-1)*dpi; + point3[1] = (hmheight-j-2)*dpi; + point3[2] = 0; + + point4[0] = (hmwidth-1)*dpi; + point4[1] = (hmheight-j-2)*dpi; + point4[2] = heightmap[((j+1)*hmwidth)+hmwidth-1]; + + drawTriangle(modelfile, point1, point2, point4); + drawTriangle(modelfile, point1, point4, point3); + } + printf("STATUS___Drew left and right sides of mesh\n"); + + //drawing the bottom of the mesh + point1[0] = 0; + point1[1] = 0; + point1[2] = 0; + point2[0] = 0; + point2[1] = dpi; + point2[2] = 0; + point3[0] = dpi; + point3[1] = 0; + point3[2] = 0; + drawTriangle(modelfile, point1, point2, point3); + point4[2] = 0; + for(int i = 1; i < imin(hmheight, hmwidth)-1; i++){ + point1[0] = 0; + point1[1] = i * dpi; + point2[0] = 0; + point2[1] = (i+1) * dpi; + point3[0] = i * dpi; + point3[1] = 0; + point4[0] = (i+1) * dpi; + point4[1] = 0; + drawTriangle(modelfile, point1, point2, point4); + drawTriangle(modelfile, point1, point4, point3); + + point1[0] = (hmwidth - i - 2) * dpi; + point1[1] = (hmheight - 1) * dpi; + point2[0] = (hmwidth - i - 1) * dpi; + point2[1] = (hmheight - 1) * dpi; + point3[0] = (hmwidth - 1) * dpi; + point3[1] = (hmheight - i - 2) * dpi; + point4[0] = (hmwidth - 1) * dpi; + point4[1] = (hmheight - i - 1) * dpi; + drawTriangle(modelfile, point1, point2, point4); + drawTriangle(modelfile, point1, point4, point3); + } + point1[0] = (hmwidth - 2) * dpi; + point1[1] = (hmheight - 1) * dpi; + point2[0] = (hmwidth - 1) * dpi; + point2[1] = (hmheight - 1) * dpi; + point3[0] = (hmwidth - 1) * dpi; + point3[1] = (hmheight - 2) * dpi; + drawTriangle(modelfile, point1, point2, point3); + if(hmheight > hmwidth){ + for(int i = 0; i < abs(hmheight-hmwidth); i++){ + point1[0] = (hmwidth-1) * dpi; + point1[1] = i * dpi; + point2[0] = (hmwidth-1) * dpi; + point2[1] = (i+1) * dpi; + point3[0] = 0; + point3[1] = (hmwidth+i-1) * dpi; + point4[0] = 0; + point4[1] = (hmwidth+i) * dpi; + + drawTriangle(modelfile, point1, point3, point2); + drawTriangle(modelfile, point2, point3, point4); + } + } + else if(hmheight < hmwidth){ + for(int i = 0; i < abs(hmheight-hmwidth); i++){ + point1[1] = (0) * dpi; + point1[0] = (hmheight+i-1) * dpi; + point2[1] = (0) * dpi; + point2[0] = (hmheight+i) * dpi; + point3[1] = (hmheight-1) * dpi; + point3[0] = (i) * dpi; + point4[1] = (hmheight-1) * dpi; + point4[0] = (i+1) * dpi; + + drawTriangle(modelfile, point1, point3, point2); + drawTriangle(modelfile, point2, point3, point4); + } + } +/* + // reference triangle that points at the origin + point1[0] = 0; + point1[1] = 0; + point2[0] = -0.1; + point2[1] = 0.1; + point2[2] = -0.1; + point3[0] = 0.1; + point3[1] = -0.1; + point3[2] = -0.1; + drawTriangle(modelfile, point1, point2, point3); +*/ + printf("STATUS___Drew bottom of mesh\n\n\n"); + + endSTL(modelfile); + fclose(modelfile); + free(heightmap); + + return 0; +} diff --git a/STLTextWriter.h b/STLTextWriter.h new file mode 100644 index 0000000..05146cc --- /dev/null +++ b/STLTextWriter.h @@ -0,0 +1,75 @@ +#include "stdio.h" +#include "stdlib.h" +#include "math.h" +#include "dotAndCrossProduct.h" + +#define X 0 +#define Y 1 +#define Z 2 + +//draws one triangle +int drawTriangle(FILE *outfile, double coords1[], double coords2[], double coords3[]){ + double vectn[] = {0,0,0}; // normal vector + double vectnlenin = 0; // normal vector length inverse + double vect1[] = {0,0,0}; // vector between coordinates 1 & 2 + double vect2[] = {0,0,0}; // vector between coordinates 1 & 3 + + vect1[0] = coords1[0] - coords2[0]; + vect1[1] = coords1[1] - coords2[1]; + vect1[2] = coords1[2] - coords2[2]; + vect2[0] = coords1[0] - coords3[0]; + vect2[1] = coords1[1] - coords3[1]; + vect2[2] = coords1[2] - coords3[2]; + + crossProduct(vectn, vect1, vect2); +/* if((!isnormal(vectn[0]) && vectn[0] != 0) || (!isnormal(vectn[1]) && vectn[1] != 0) || (!isnormal(vectn[2]) && vectn[2] != 0)){ + printf("Troublemaker:\n\n"); + printf("vectn = %f, %f, %f\n\n", vectn[0], vectn[1], vectn[2]); + printf("vect1 = %f, %f, %f\n", vect1[0], vect1[1], vect1[2]); + printf("vect2 = %f, %f, %f\n\n", vect2[0], vect2[1], vect2[2]); + printf("point1 = %f, %f, %f\n", coords1[0], coords1[1], coords1[2]); + printf("point2 = %f, %f, %f\n", coords2[0], coords2[1], coords2[2]); + printf("point3 = %f, %f, %f\n\n\n", coords3[0], coords3[1], coords3[2]); + } +*/ + vectnlenin = 1 / sqrt((vectn[0]*vectn[0]) + (vectn[1]*vectn[1]) + (vectn[2]*vectn[2])); + vectn[0] = vectn[0] * vectnlenin; + vectn[1] = vectn[1] * vectnlenin; + vectn[2] = vectn[2] * vectnlenin; + + fprintf(outfile, " facet normal %g %g %g\n", vectn[X], vectn[Y], vectn[Z]); + fprintf(outfile, " outer loop\n"); + + fprintf(outfile, " vertex %g %g %g\n", coords1[X], coords1[Y], coords1[Z]); + fprintf(outfile, " vertex %g %g %g\n", coords2[X], coords2[Y], coords2[Z]); + fprintf(outfile, " vertex %g %g %g\n", coords3[X], coords3[Y], coords3[Z]); + + fprintf(outfile, " endloop\n"); + fprintf(outfile, " endfacet\n"); + return 0; +} + +//draws one triangle and allows you to precompute the normal vector +int drawTriangleWithNormal(FILE *outfile, double coords1[], double coords2[], double coords3[], double vectn[]){ + fprintf(outfile, " facet normal %g %g %g\n", vectn[X], vectn[Y], vectn[Z]); + fprintf(outfile, " outer loop\n"); + + fprintf(outfile, " vertex %g %g %g\n", coords1[X], coords1[Y], coords1[Z]); + fprintf(outfile, " vertex %g %g %g\n", coords2[X], coords2[Y], coords2[Z]); + fprintf(outfile, " vertex %g %g %g\n", coords3[X], coords3[Y], coords3[Z]); + + fprintf(outfile, " endloop\n"); + fprintf(outfile, " endfacet\n"); + return 0; +} + +//must be printed at the start of the file +int startSTL(FILE *outfile){ + fprintf(outfile, "solid Mesh\n"); + return 0; +} + +//must be printed at the end of the file +int endSTL(FILE *outfile){ + fprintf(outfile, "endsolid Mesh"); +} diff --git a/dotAndCrossProduct.h b/dotAndCrossProduct.h new file mode 100644 index 0000000..376b10a --- /dev/null +++ b/dotAndCrossProduct.h @@ -0,0 +1,10 @@ +int dotProduct(double outvect[], double vect1[], double vect2[]){ + return 0; +} +int crossProduct(double outvect[], double vect1[], double vect2[]){ + outvect[0] = (vect1[1]*vect2[2]) - (vect1[2]*vect2[1]); + outvect[1] = (vect1[2]*vect2[0]) - (vect1[0]*vect2[2]); + outvect[2] = (vect1[0]*vect2[1]) - (vect1[1]*vect2[0]); + + return 0; +}