|
|
@ -0,0 +1,127 @@ |
|
|
|
|
|
|
|
#include "raylib.h" |
|
|
|
#include <stdlib.h> |
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
float x, y, z; |
|
|
|
} Point3D; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
int p, q; |
|
|
|
int n, m; |
|
|
|
float *U, *V; |
|
|
|
float **w; |
|
|
|
Point3D **P; |
|
|
|
} NURBSSurface; |
|
|
|
|
|
|
|
float Nip(int i, int p, float u, float *U) { |
|
|
|
if (p == 0) |
|
|
|
return (u >= U[i] && u < U[i+1]) ? 1.0f : 0.0f; |
|
|
|
|
|
|
|
float denom1 = U[i+p] - U[i]; |
|
|
|
float denom2 = U[i+p+1] - U[i+1]; |
|
|
|
|
|
|
|
float term1 = denom1 != 0.0f ? (u - U[i]) / denom1 * Nip(i, p - 1, u, U) : 0.0f; |
|
|
|
float term2 = denom2 != 0.0f ? (U[i+p+1] - u) / denom2 * Nip(i + 1, p - 1, u, U) : 0.0f; |
|
|
|
|
|
|
|
return term1 + term2; |
|
|
|
} |
|
|
|
|
|
|
|
Point3D surfacePoint(NURBSSurface *surf, float u, float v) { |
|
|
|
Point3D S = {0, 0, 0}; |
|
|
|
float denom = 0.0f; |
|
|
|
|
|
|
|
for (int i = 0; i <= surf->n; i++) { |
|
|
|
float Ni = Nip(i, surf->p, u, surf->U); |
|
|
|
for (int j = 0; j <= surf->m; j++) { |
|
|
|
float Nj = Nip(j, surf->q, v, surf->V); |
|
|
|
float w = surf->w[i][j]; |
|
|
|
float B = Ni * Nj * w; |
|
|
|
|
|
|
|
S.x += B * surf->P[i][j].x; |
|
|
|
S.y += B * surf->P[i][j].y; |
|
|
|
S.z += B * surf->P[i][j].z; |
|
|
|
denom += B; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
S.x /= denom; |
|
|
|
S.y /= denom; |
|
|
|
S.z /= denom; |
|
|
|
|
|
|
|
return S; |
|
|
|
} |
|
|
|
|
|
|
|
void drawSurface(NURBSSurface *surf, int resolution) { |
|
|
|
for (int i = 0; i < resolution; i++) { |
|
|
|
float u = (float)i / (resolution - 1); |
|
|
|
for (int j = 0; j < resolution; j++) { |
|
|
|
float v = (float)j / (resolution - 1); |
|
|
|
Point3D pt = surfacePoint(surf, u, v); |
|
|
|
DrawSphere((Vector3){pt.x, pt.y, pt.z}, 0.03f, RED); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void freeSurface(NURBSSurface *surf) { |
|
|
|
for (int i = 0; i <= surf->n; i++) { |
|
|
|
free(surf->w[i]); |
|
|
|
free(surf->P[i]); |
|
|
|
} |
|
|
|
free(surf->w); |
|
|
|
free(surf->P); |
|
|
|
free(surf->U); |
|
|
|
free(surf->V); |
|
|
|
} |
|
|
|
|
|
|
|
int main(void) { |
|
|
|
const int screenWidth = 800; |
|
|
|
const int screenHeight = 600; |
|
|
|
|
|
|
|
InitWindow(screenWidth, screenHeight, "NURBS Surface with Raylib"); |
|
|
|
Camera3D camera = {0}; |
|
|
|
camera.position = (Vector3){ 4.0f, 4.0f, 10.0f }; |
|
|
|
camera.target = (Vector3){ 2.0f, 2.0f, 0.0f }; |
|
|
|
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; |
|
|
|
camera.fovy = 45.0f; |
|
|
|
camera.projection = CAMERA_PERSPECTIVE; |
|
|
|
|
|
|
|
NURBSSurface surf = {0}; |
|
|
|
surf.p = 2; |
|
|
|
surf.q = 2; |
|
|
|
surf.n = 3; |
|
|
|
surf.m = 3; |
|
|
|
|
|
|
|
surf.U = (float[]){0,0,0,1,2,2,2}; |
|
|
|
surf.V = (float[]){0,0,0,1,2,2,2}; |
|
|
|
|
|
|
|
surf.w = malloc((surf.n+1) * sizeof(float *)); |
|
|
|
surf.P = malloc((surf.n+1) * sizeof(Point3D *)); |
|
|
|
for (int i = 0; i <= surf.n; i++) { |
|
|
|
surf.w[i] = malloc((surf.m+1) * sizeof(float)); |
|
|
|
surf.P[i] = malloc((surf.m+1) * sizeof(Point3D)); |
|
|
|
for (int j = 0; j <= surf.m; j++) { |
|
|
|
surf.w[i][j] = 1.0f; |
|
|
|
surf.P[i][j] = (Point3D){(float)i, (float)j, (float)(i*j%3)}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
SetTargetFPS(60); |
|
|
|
while (!WindowShouldClose()) { |
|
|
|
UpdateCamera(&camera, CAMERA_ORBITAL); |
|
|
|
|
|
|
|
BeginDrawing(); |
|
|
|
ClearBackground(RAYWHITE); |
|
|
|
BeginMode3D(camera); |
|
|
|
drawSurface(&surf, 20); |
|
|
|
EndMode3D(); |
|
|
|
DrawText("NURBS Surface", 10, 10, 20, DARKGRAY); |
|
|
|
EndDrawing(); |
|
|
|
} |
|
|
|
|
|
|
|
freeSurface(&surf); |
|
|
|
CloseWindow(); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |