Article 5389 of comp.graphics.rendering.renderman: From: "T. Burge" Newsgroups: comp.graphics.rendering.renderman Subject: Re: RiBasis and OpenGL Date: Thu, 01 Jan 1998 12:31:07 +0000 Organization: Apple Computers Lines: 113 Message-ID: <34AB8C83.3D1E@NO_JUNKMAIL.apple.com> References: <34A9B358.8F3FA7FC@cwr.uwa.edu.au> Reply-To: burge@NO_JUNKMAIL.apple.com NNTP-Posting-Host: 17.32.67.142 Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Mailer: Mozilla 3.01 (Macintosh; I; PPC) Path: news.lava.net!coconut-wireless!news.flex.com!www.nntp.primenet.com!globalcenter0!news.primenet.com!nntp.primenet.com!su-news-hub1.bbnplanet.com!su-news-feed4.bbnplanet.com!news.bbnplanet.com!forum.apple.com!news.apple.com!not-for-mail Nicholas Yue wrote: > I am attempting to write a viewer for RIB and stumbled onto some >difficulties. > > Does anyone have ideas as to how I should map the RiBasis capability >to OpenGL. I vaguely remember that in the old Silicon Graphics GL, there >was a way to update some basis matrix (or something similar). > > Am I approaching the problem from a correct angle ? > > From the documentation, the Basis are Bernstien Polynomials in >OpenGL but RenderMan allows a user to write customized basis function. > You'll have to change the basis of the patches using the values given in the last Basis statement in the RIB file. By default the values are RiBezierBasis basis matrices for u and v directions and both ustep and vstep set to 3. I'll include a brief explanation here on changing a basis. Hopefully it answers your questions without too much extra information. To convert from a UBasis by VBasis patch to a Bezier by Bezier basis patch, the control points CP of the UBasis by VBasis patch need to be altered to a new set of points newCP. Let CPx, CPy and CPz be 4x4 arrays of floats storing just the X,Y and Z components of CP respectively. Let newCPx, newCPy and newCPz be 4x4 arrays of floats storing just the X,Y and Z components of newCP respectively. Let Bezier equal the RiBezierBasis basis matrix. Let InvBezier equal the inverse of the RiBezierBasis basis matrix. newCPx = InvBezier * VBasis * CPx * Transpose(InvBezier*UBasis) newCPy = InvBezier * VBasis * CPy * Transpose(InvBezier*UBasis) newCPz = InvBezier * VBasis * CPz * Transpose(InvBezier*UBasis) To derive the above equations and to also convert a bicubic to any form of basis matrices you may desire, consider a point P on the surface of a patch defined by parameter values u and v; basis matrices U and V; and control points CP. Let Px, Py and Pz be the X,Y and Z components of P respectively. A carrot "^" indicates an exponent. Px = [v^3 v^2 v 1]*V*CPx*Transpose(U)*Transpose([u^3 u^2 u 1]) Py = [v^3 v^2 v 1]*V*CPy*Transpose(U)*Transpose([u^3 u^2 u 1]) Pz = [v^3 v^2 v 1]*V*CPz*Transpose(U)*Transpose([u^3 u^2 u 1]) To change a basis of a bicubic patch from U1 by V1 to U2 by V2 note that Px = [v^3 v^2 v 1]*V1*CP1x*Transpose(U1)*Transpose([u^3 u^2 u 1]) = [v^3 v^2 v 1]*V2*CP2x*Transpose(U2)*Transpose([u^3 u^2 u 1]) Py = [v^3 v^2 v 1]*V1*CP1y*Transpose(U1)*Transpose([u^3 u^2 u 1]) = [v^3 v^2 v 1]*V2*CP2y*Transpose(U2)*Transpose([u^3 u^2 u 1]) Pz = [v^3 v^2 v 1]*V1*CP1z*Transpose(U1)*Transpose([u^3 u^2 u 1]) = [v^3 v^2 v 1]*V2*CP2z*Transpose(U2)*Transpose([u^3 u^2 u 1]) The above can be simplified to V1*CP1x*Transpose(U1) = V2*CP2x*Transpose(U2) V1*CP1y*Transpose(U1) = V2*CP2y*Transpose(U2) V1*CP1z*Transpose(U1) = V2*CP2z*Transpose(U2) The new control points CP2 have the following relation to the old control points CP1: CP2x = Inv(V2)*V1 * CP1x * Transpose( Inv(U2) * U1 ) CP2y = Inv(V2)*V1 * CP1y * Transpose( Inv(U2) * U1 ) CP2z = Inv(V2)*V1 * CP1z * Transpose( Inv(U2) * U1 ) The first set of equations at the begining of this note are taken from some code I wrote a couple years back. So barring any typos, they should work. For the rest, hopefully I didn't mix up my 1's and 2's, U's and V's while writing this. I believe there were course notes from SIGGRAPH '92 that provided some material on this. Atleast I think it was 92. When I wrote the code, I included a reference to a memo by Rob Cook which I think came from the '92 course notes. For the section on basis matrices, Cook's memo stated it was based on Ed Catmull's thesis and also work from Tom Duff. To optimize code, you might consider precalculating conversion matrices to interchange the standard basis matrices. With five standard basis matrices used by the RenderMan standard, there would be twenty-five Inv(Basis2)*Basis1 matrices that can be precalculated and stored. Note that when Basis2 equals Basis1, the precalculated value is simply the identity matrix -- which you probably don't need to waste space storing. That makes it only twenty precalculated matrices to store. Only four are needed if you are only going to convert to one of the basis matrices, for example RiBezierBasis. Hope that helps, T. Burge P.S. Refer to www.affine.com for reading and writing RIB files. You might find the RIB Reader useful for what you are doing.