| @ -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; | |||
| } | |||