POV-Ray : Newsgroups : povray.text.scene-files : Source code for the "NURBS surface" image Server Time
22 Dec 2024 22:26:27 EST (-0500)
  Source code for the "NURBS surface" image (Message 1 to 3 of 3)  
From: Tor Olav Kristensen
Subject: Source code for the "NURBS surface" image
Date: 7 Apr 2002 06:19:49
Message: <3CB019B8.7364047F@online.no>
-that I posted 18. March to the povray.binaries.images group:

http://news.povray.org/povray.binaries.images/23091/


I have inserted some comments into this code in order to try
and explain a little bit more about how to use the macros I've
posted so far.


Prior to rendering:

Copy all the macros that I posted in this message:
"Code for NURBS surfaces as mesh2{} objects" (25. March)
and paste them into a file named "NURBS.inc"

Here's that message:

http://news.povray.org/povray.text.scene-files/23250/161948/


Tor Olav

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Copyright 2002 by Tor Olav Kristensen
// Email: tor### [at] hotmailcom
// http://www.crosswinds.net/~tok
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

#version 3.5;

#include "colors.inc"

#include "NURBS.inc"

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

// Number of control points in the U and V "directions"
#declare NrU = 5;
#declare NrV = 5;


/*
// These control points and their weights will make the surface
// a flat square.

#declare CtrlPoints =
  array[NrU][NrV] {
    { <0,0,  0>, <1,0,  0>, <2,0,  0>, <3,0,  0>, <4,0,  0> },
    { <0,1,  0>, <1,1,  0>, <2,1,  0>, <3,1,  0>, <4,1,  0> },
    { <0,2,  0>, <1,2,  0>, <2,2,  0>, <3,2,  0>, <4,2,  0> },
    { <0,3,  0>, <1,3,  0>, <2,3,  0>, <3,3,  0>, <4,3,  0> },
    { <0,4,  0>, <1,4,  0>, <2,4,  0>, <3,4,  0>, <4,4,  0> }
  }

#declare Weights =
  array[NrU][NrV] {
    {     1,         1,         1,         1,         1      },
    {     1,         1,         1,         1,         1      },
    {     1,         1,         1,         1,         1      },
    {     1,         1,         1,         1,         1      },
    {     1,         1,         1,         1,         1      }
  }
*/


// This is more interesting. Some points have been displaced along
// the z-axis. Each of them are "pulling" a region of the surface
// towards them.

#declare CtrlPoints =
  array[NrU][NrV] {
    { <0,0,  0>, <0,1, -2>, <0,2,  3>, <0,3, -2>, <0,4,  0> },
    { <1,0,  0>, <1,1,  0>, <1,2,  0>, <1,3,  0>, <1,4,  0> },
    { <2,0,  0>, <2,1, -2>, <2,2,  0>, <2,3,  4>, <2,4,  0> },
    { <3,0,  0>, <3,1,  0>, <3,2,  0>, <3,3,  0>, <3,4,  0> },
    { <4,0, -3>, <4,1,  0>, <4,2,  0>, <4,3,  0>, <4,4,  4> }
  }


// These weights can be thought of as a measure for how strong the
// pull or "tension" from their corresponding points will be.
#declare Weights =
  array[NrU][NrV] {
    {    1,         1,         1,         1,         1      },
    {    1,         1,         1,         1,         1      },
    {    1,        10,         1,         1,         1      },
    {    1,         1,         1,         1,         1      },
    {    1,         1,         1,         1,         1      }
  }
// IIRC negative values aren't really "allowed" in NURBS weights.
// (But the results are interesting.)

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

/*
// Uncomment this if you want to see the grid of control points

object {
  ShowControlPoints(CtrlPoints, 0.04)
  pigment { color Yellow }
}

object {
  ShowControlGrid(CtrlPoints, 0.02)
  pigment { color Cyan }
}
*/


// Order must be greater than or equal to 2 and less than or
// equal to the lesser of NrU and NrV. I.e. the number of control
// points above will allow you to try Order values from 2 to 5.
#declare Order = 4;
// For lower Order values, each point will "control" a smaller
// region of the surface. And higher values will make each of
// them "control" a larger region of it.


// It doesn't really matter much what you set these to here.
#declare MinUV = <0, 0>;
#declare MaxUV = <1, 1>;


// Now let a macro calculate the knots.
#declare KnotsU = OpenUniformKnotVector(Order, NrU, MinUV.u, MaxUV.u)
#declare KnotsV = OpenUniformKnotVector(Order, NrV, MinUV.v, MaxUV.v)
// Read about b-splines if you want to select the knots yourself.
// (I may make other knot macros later.)


// Anyway: Have a look at the knot "vectors".
#debug "\nU knot vector: "
printM(KnotsU)
#debug "\nV knot vector: "
printM(KnotsV)
#debug "\n"


// Assemble the 3 parametric functions needed for
// the ParametricMesh() and CylinderMesh() macros.
#declare xFn =
  NURBS_SurfFunction(Order, KnotsU, KnotsV, CtrlPoints, Weights, x)
#declare yFn =
  NURBS_SurfFunction(Order, KnotsU, KnotsV, CtrlPoints, Weights, y)
#declare zFn =
  NURBS_SurfFunction(Order, KnotsU, KnotsV, CtrlPoints, Weights, z)


/*
// If you now limit the ranges that these variables defines,
// then only a part of the surface will be "meshyfied".
// (If you expand these ranges, you'll get an error.)
#declare MinUV = <0.2, 0.0>;
#declare MaxUV = <0.8, 0.9>;
// U will wary from 0.2 to 0.8
// V will wary from 0.0 to 0.9
*/


// This will result in 50*50 squares with 2 triangles each.
#declare Resolution = <50, 50>; // Use <10, 10> if you have a slow PC.
// So there will be 50 squares in the U "direction" and 50 in
// the V "direction". I.e. you'll get 50*50*2 = 5000 triangles.

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

// Then you can calculate the mess and use it directly
#declare MessyMesh =
  ParametricMesh(
    function(u, v) { xFn(u, v) },
    function(u, v) { yFn(u, v) },
    function(u, v) { zFn(u, v) },
    MinUV,
    MaxUV,
    Resolution
  )


/*
// Or you may calculate it and save it for later use
WriteParamMesh(
  function(u, v) { xFn(u, v) },
  function(u, v) { yFn(u, v) },
  function(u, v) { zFn(u, v) },
  MinUV,
  MaxUV,
  Resolution,
  "NURBSmesh.txt"
)

// And then read it back
#declare MessyMesh = #include "NURBSmesh.txt"
*/


// Now show this mesh2 object and let its colour vary along with
// its "depth" in the z-direction. +z is away from the camera.
object {
  MessyMesh
  texture {
    pigment {
      gradient -z
      color_map {
        [ 0.4 color Blue ]
        [ 1.0 color Green*2 ]
      }
    }
    scale <1, 1, 7> // "Depth" diff. between points (in z-direction)
    translate -3*z // "Depth" of the farthest point (in z-direction)
  }
}


/*
// Alternatively you can map an image onto it. (One of the Beta
// releases of POV-Ray had problems with this IIRC).
object {
  MessyMesh
  texture {
    uv_mapping
    pigment {
      image_map {
        png "test"
        map_type 0
        interpolate 2
      }
//      rotate 180*y
    }
  }
}
*/


// Uncomment the pigment statements in the CylinderMesh() macro
// to get different colouring for the 2 cylinder "types".
object {
  CylinderMesh(
    function(u, v) { xFn(u, v) },
    function(u, v) { yFn(u, v) },
    function(u, v) { zFn(u, v) },
    MinUV,
    MaxUV,
    Resolution
    0.01 // Cylinder radius
  )
// Or just uncomment the line below if you
// want them to have the same colour.
//  pigment { color (Magenta + White)/4 + Red/2 }
//  pigment { color (Red + Orange)*0.8 }
}
  
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

// Add a light source
light_source { <2, 1, -5>*10 color White shadowless }


// And a plain camera looking at the mess from the left behind it
camera {
  location <-2.0, 1.1, -4.0>*1.1
  look_at <3.0, 2.2, 0.0>
}


/*
// Also try this camera
camera {
  orthographic
  location <2, 2, -4.5>
  look_at <2, 2, 0>
}
// And then set all weights to 1 and try this camera again.

// U increases towards the right and V increases upwards
// (The x and y components of the control points in the array
// are chosen so that the x components will increase along with
// the U values and the y components will increase along with
// the V values.)
*/


// And then finally add a tuch of blue to the backdrop
background { color Blue/8 }

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7


Post a reply to this message

From: Hugo
Subject: Re: Source code for the "NURBS surface" image
Date: 8 Apr 2002 08:31:16
Message: <3cb18d94@news.povray.org>
Thank you Tor! This looks really promising. Your comments will help me a
lot. I already played with your first nurbs-code, and I see the control
points have to be in a grid. So, it's not possible to insert an extra point
in a row, without modifying all other rows.. I suppose it's very hard to get
beyond this limitation?

But I see your new code allows me to easily adjust weights .. that's a
progress. :o)  I will try nurbs to make interesting transitions between
ordinary primitives.. For example fancy edges of a box.. Next, I will try
some organic shapes.. Well, it seems many shapes could also be done with
isosurfaces (and they are not limited to a grid) but nurbs could be more
precise. I mean, the exact location of a point in a blobbed isosurface seems
very unpredictable to me.. POV-nurbs could very well develop into a useful
modelling tool!  But first I'll have to learn more.

Thanks for your work.

Best regards,
Hugo


Post a reply to this message

From: Tor Olav Kristensen
Subject: Re: Source code for the "NURBS surface" image
Date: 8 Apr 2002 20:36:06
Message: <3CB233EE.7550369E@online.no>
Thank you for your comments Hugo.


Hugo wrote:
> 
> Thank you Tor! This looks really promising. Your comments will help me a
> lot. I already played with your first nurbs-code, and I see the control
> points have to be in a grid. So, it's not possible to insert an extra point
> in a row, without modifying all other rows.. I suppose it's very hard to get
> beyond this limitation?

Yes, I think this is one of the arguments against
NURBS surfaces when compared to subdivision of
surfaces techniques.

Here are some subdivision posts:

http://news.povray.org/search/?s=Subdivision+Surface


> But I see your new code allows me to easily adjust weights .. that's a
> progress. :o)

Unfortunately the code I posted here doesn't
contain any new macros.

I have just tried to show how to call some of the
NURBS macros "manually", instead of calling them
via the NURBS_SurfaceMesh() macro, which makes a
lot of decisions for the users. One of them is
to set all weights to 1. (I made that macro just
so that people could get started easily.)


> I will try nurbs to make interesting transitions between
> ordinary primitives.. For example fancy edges of a box.. Next, I will try
> some organic shapes..

I'm very interested in seeing your achievements.


> Well, it seems many shapes could also be done with
> isosurfaces (and they are not limited to a grid) but nurbs could be more
> precise. I mean, the exact location of a point in a blobbed isosurface seems
> very unpredictable to me.. POV-nurbs could very well develop into a useful
> modelling tool!

Yes, I hope so.


> But first I'll have to learn more.
> Thanks for your work.

You're welcome.


Tor Olav


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.