Skip to content
Danlight54 edited this page Jun 23, 2025 · 1 revision

#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;

}

Clone this wiki locally