Upload files to "/"
This commit is contained in:
344
HydraulicErosion.c
Normal file
344
HydraulicErosion.c
Normal file
@@ -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;
|
||||
}
|
||||
75
STLTextWriter.h
Normal file
75
STLTextWriter.h
Normal file
@@ -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");
|
||||
}
|
||||
10
dotAndCrossProduct.h
Normal file
10
dotAndCrossProduct.h
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user