PDA

View Full Version : Extracting cubic beziers from .OBJ files



Daedalus
02-06-2000, 03:44 PM
Hi,
I'm trying to design my own 3d engine with cubic beziers patches being the primary primative (as opposed to dealing directly with triangles) and I'm pretty familiar with techniques like forward dfferencing to render the patches. My problem is importing geometry from standard file formats like .OBJ (.OBJ is one of a number of formats, but it seemed like the easiest and most common to start with). I've read the file format specifications that are posted on www.wotsit.org (http://www.wotsit.org) but most modelling programs store all curves as complex curves rather than nicely defined control points. What I would like to know is how to take that info out of the file and derive the control points from it and, in the case of more complex curved surfaces, how to break the curves up into smaller cubic patches. If anyone knows how to do this, knows of an example/tutorial, or knows of another file format that is easier for this please let me know. Any help would be greatly appreciated.
-Daedalus

Nathan d'Obrenan
02-06-2000, 10:20 PM
Daedalus

The best way to go about implemetning parametric surfaces into your program, would be to actually use the vertex information as the control points. This method would work best if implemented with bezier equations, I am unfamilier with how nurbs operate.

If you want to break up the curved surface into smaller groups, the .obj format breaks up all its triangle information into groups. Just seperate the groups into a smaller chunks.

I am unaware of any programs which export control point data, however their might be some.

joseph
02-06-2000, 10:41 PM
I modified a 3DSMax (2.5 or 3.0) script that my friend wrote for gamasutra.com and made it export NURBs data. You can probably look at the MaxScript language and figure out how to get bezier patch data. The target format is called RTG and it's pretty easy to parse.

-Joseph

here's the MaxScript:

-------------------------------------------------------------------------------------
-- RTGExport.ms
-- This utility exports geometry from Max 2.5 into the Alias text-based RTG v1.8 format.
-- The RTG (RealTimeGames) format is not very well supported, but it is so simple that
-- writing support for it is easy.
--
-- Original script was written by Wyeth Ridgway
-- Modified by Joseph Laurino: added support for NURBS
-------------------------------------------------------------------------------------
utility RTGExport "Alias RTG v1.8 Export"
(
-- Define variables that are visible to all functions in the utility
local ostream, tabs = ""

-- Define the GUI interface
group "Options"
(
checkbox cb_exportSelOnly "Export Selected Only"
checkbox cb_outputVertNorms "Output Vertex Normals" checked:true
checkbox cb_outputVertColors "Output Vertex Colors" checked:true
checkbox cb_outputPolyNorms "Output Polygon Normals" checked:true
checkbox cb_outputTexCoords "Output Texture Coords" checked:true
checkbox cb_outputHierarchy "Output Hierarchy" checked:true
)
button btn_export "Save As..." width:100

-- Now define the functions that the utility uses

-------------------------------------------------------------------------------------
-- This function exports a NURBSCVSurface object to the RTG file.
-- <nurbscvsurface>.uOrder : integer
-- <nurbscvsurface>.vOrder : integer
-- <nurbscvsurface>.numUKnots : integer
-- <nurbscvsurface>.numVKnots : integer
-- <nurbscvsurface>.numCVs : point2

function ExportNURBSCVSurface nurbsObj name =
(
-- Output the nurbs header
Format "\n\nNURBS_START % uOrder% vOrder% numUKnots% numVKnots% numCVsU% numCVsV%\n" name nurbsObj.uOrder nurbsObj.vOrder nurbsObj.numUKnots nurbsObj.numVKnots (nurbsObj.numCVs.x as Integer) (nurbsObj.numCVs.y as Integer) to http://www.opengl.org/discussion_boards/ubb/redface.gifstream

Format "\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
for i = 1 to nurbsObj.numUKnots do
(
Format "UKNOT %\n" (getUKnot nurbsObj i) to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)

Format "\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream

for i = 1 to nurbsObj.numVKnots do
(
Format "VKNOT %\n" (getVKnot nurbsObj i) to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)

Format "\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream

for i = 1 to (nurbsObj.numCVs.x as Integer) do
(
for j = 1 to (nurbsObj.numCVs.y as Integer) do
(
controlVertex = (getCV nurbsObj i j )
Format "CV x % y % z % w %\n" controlVertex.x controlVertex.y controlVertex.z controlVertex.weight to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
)


Format "\n\nNURBS_END %" name to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)

-------------------------------------------------------------------------------------
-- This function exports a geometry object to the RTG file.
function ExportMesh meshObj name =
(
-- Output the object header
Format "\n\nOBJECT_START % v%" name meshObj.numVerts to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
if cb_outputVertNorms.checked then
Format " n%" meshObj.numVerts to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
if cb_outputTexCoords.checked then
Format " t%" meshObj.numtverts to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
Format " p%\n\n" meshObj.numFaces to http://www.opengl.org/discussion_boards/ubb/redface.gifstream

-- Vertex output is in local space
Format "VERTEX local\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
if meshObj.numVerts > 0 then
(
for i = 1 to meshObj.numVerts do
(
vert = ((GetVert meshObj i)-meshObj.pos)
Format "% % % %\n" (i-1) vert.x vert.y vert.z to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
)

-- Vertex normals
if meshObj.numVerts > 0 and cb_outputVertNorms.checked then
(
Format "\nNORMAL\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
for i = 1 to meshObj.numVerts do
(
normal = GetNormal meshObj i
Format "% % % %\n" (i-1) normal.x normal.y normal.z to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
)

-- Texture coords
if meshObj.numTVerts > 0 and cb_outputTexCoords.checked then
(
Format "\nTEXCOORD\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
for i = 1 to meshObj.numTVerts do
(
uvw = GetTVert meshObj i
Format "% % % %\n" (i-1) uvw.x uvw.y uvw.z to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
)

-- Polygon
Format "\nPOLYGON\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
if meshObj.NumFaces > 0 then
(
for i = 1 to meshObj.numFaces do
(
poly = GetFace meshObj i
Format "% 3 v % % %" (i-1) (poly.x as integer -1) (poly.y as integer -1) (poly.z as integer -1) to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
-- Specify vert normals
if cb_outputVertNorms.checked then
Format " n % % %" (poly.x as integer -1) (poly.y as integer -1) (poly.z as integer -1) to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
-- Tex coord
if cb_outputTexCoords.checked and meshObj.numTverts > 0 then
(
tvert = GetTVFace meshObj i
Format " t % % %" (tvert.x as integer -1) (tvert.y as integer -1) (tvert.z as integer -1) to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
-- Face normal
if cb_outputPolyNorms.checked then
(
normal = GetFaceNormal meshObj i
Format " N % % %" normal.x normal.y normal.z to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
-- Texture ref
Format " T 0\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
)

Format "\nOBJECT_END %\n" name to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)

-------------------------------------------------------------------------------------
-- This function is called once per node in the scene.
-- A node in Max may be all sorts of things. We are only interested in geometry.
--
-- jyl: figuring out if a node is a NURBS surface is pretty tricky, I had to resort to an
-- ugly string in string search for "Surface"
-- hopefully in Max 3.0, I can determine the class type better!
--
function ExportNode node =
(
-- Create node and export class specific data

local surfaceString = findString node.name "Surface"

if SuperClassOf node == GeometryClass and surfaceString != undefined then
(
nurbSet = getNurbsSet node

if nurbSet.numObjects > 0 then
(
local nurbsObj = getObject nurbSet 1

if classOf nurbsObj == NURBSCVSurface then
(
ExportNURBSCVSurface nurbsObj node.name
)
)
)
else if SuperClassOf node == GeometryClass and ClassOf node == Editable_mesh then
ExportMesh node node.name
else if SuperClassOf node == GeometryClass then
(
-- Build a mesh out of this object and save it
local temp = copy node
convertToMesh temp
ExportMesh temp node.name
delete temp
)
else -- Not geometry.. could be a camera, light, etc.
return false

return true
)

-------------------------------------------------------------------------------------
-- This function recurses down the node hierarchy calling ExportNode for each node.
function RecursiveExportNode node =
(
if (ExportNode node) == false then
return false

-- Recurse children before writing this node
for child in node.children do
RecursiveExportNode child
)
-------------------------------------------------------------------------------------
-- Output the RTG file header.
function OutputHeader =
(
Format "OUTPUT_VERT_NORMS " to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
if cb_outputVertNorms.checked then ; Format "on\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
else Format "off\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
Format "OUTPUT_VERT_COLORS " to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
if cb_outputVertColors.checked then ; Format "on\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
else Format "off\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
Format "OUTPUT_POLY_NORMS " to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
if cb_outputPolyNorms.checked then ; Format "on\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
else Format "off\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
Format "OUTPUT_TEX_COORDS " to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
if cb_outputTexCoords.checked then ; Format "on\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
else Format "off\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
Format "OUTPUT_HIERARCHY " to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
if cb_outputHierarchy.checked then ; Format "on\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
else Format "off\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream

Format "SHOW_INDEX_COUNTERS on\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
Format "TEXTURE_MODE per_shader\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
-------------------------------------------------------------------------------------
-- A helper function to write indentation to the file.
function doTabs depth =
(
for x = 1 to depth do
(
Format "\t" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
)
-------------------------------------------------------------------------------------
-- A function to output the hierarchical relationship of geometric objects.
function RecursiveWriteHierarchy node depth =
(
-- Write this node
if SuperClassOf node == GeometryClass then
(
-- Geometry info
doTabs (depth as integer -1)
Format "% G %\n" depth node.name to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
doTabs (depth+1)
Format "tran: % % %\n" node.pos.x node.pos.y node.pos.z to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
doTabs (depth+1)
rot = node.rotation as eulerangles
Format "rot: % % %\n" rot.x rot.y rot.z to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
doTabs (depth+1)
Format "scal: % % %\n" node.scale.x node.scale.y node.scale.z to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
doTabs (depth+1)
Format "sPiv: % % %\n" node.pivot.x node.pivot.y node.pivot.z to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
doTabs (depth+1)
Format "rPiv: % % %\n" node.pivot.x node.pivot.y node.pivot.z to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)
-- Pivot info
-- Recurse to children
-- for children in node.children do
-- RecursiveWriteHierarchy children
)
-------------------------------------------------------------------------------------
-- The highest level function called to export an RTG file.
function ExportRTG =
(
-- Write the RTG header
Format "HEADER_TITLE\t\tMax 2.5 Real Time Game Output\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
Format "HEADER_VERSION\t\tv1.8\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
Format ("HEADER_DATE \t\t" + localtime + "\n") to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
Format "\n\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream

if cb_exportSelOnly.checked then
(
Format "NUMBER_OF_OBJECTS = %\n" selection.count to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
OutputHeader()

for node in selection do
ExportNode node
)
else
(
Format "NUMBER_OF_OBJECTS = %\n" rootnode.children.count to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
OutputHeader()

if cb_outputHierarchy.checked then
(
Format "\nHIERARCHY_LIST HXP 1 top_level\n\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream

for node in rootnode.children do
RecursiveWriteHierarchy node 0

Format "END_HIERARCHY_LIST\n\n" to http://www.opengl.org/discussion_boards/ubb/redface.gifstream
)

for node in rootnode.children do
RecursiveExportNode node
)
)
-------------------------------------------------------------------------------------
-- Open an prepare a file handle for writing.
function GetSaveFileStream =
(
fname = GetSaveFileName types:"Alias RTG (*.rtg)|*.rtg|All Files(*.*)|*.*|"
if fname == undefined then
return undefined

ostream = CreateFile fname
if ostream == undefined then
(
MessageBox "Couldn't open file for writing !"
return undefined
)

return ostream
)

-------------------------------------------------------------------------------------
-- This is the function called when the user activates the utility by pressing on
-- the export button. It opens the file and calls the export routine.
on btn_export pressed do
(
ostream = GetSaveFileStream()
if ostream != undefined then
(
ExportRTG()
close ostream
)
)

) -- End RTGExport

joseph
02-06-2000, 10:43 PM
opps, please convert the wierd smiley ; graphics to semi-colons!

-joseph

joseph
02-06-2000, 10:45 PM
make that colons!

: to colons (i'm really sorry about this)

Daedalus
02-07-2000, 10:54 AM
Wow, thanks for the code Joseph. I changed all the faces into ':' and saves the file with a .ms extension. The only problem is that when I load up 3dsmax 3 and try to load the script nothing happens. I don't get any errors, but I also don't get any extra options under "save as" or "export". I have no experience with Max Script, so I have no idea what could be wrong. You wouldn't, by any chance, have any pointer on what I might have done wrong would you?

-Daedalus

Daedalus
02-07-2000, 11:05 AM
well, I think I might have found the problem. It looks as thought the face art erased more than just a ':'

test:

:-o
http://www.opengl.org/discussion_boards/ubb/redface.gif

I'm trying to figure out exactly what set of characters is missing.

-Daedalus

joseph
02-07-2000, 06:44 PM
I made a link to the original script with instructions on how to intall it on my web site.
http://209.181.143.70/docs/NURBs.htm

-joseph

Daedalus
02-08-2000, 02:35 PM
Thanks a lot Joseph. I finally managed to get the script working. You were right about the .RTG file format too. It is easy to understand. I spent a while, before I got the script working, looking for the file format documentation on the net and couldn't find it anywhere. Luckily I didn't need it.

-Daedalus

Hude
02-08-2000, 10:58 PM
This is off topic but you should read this about ubb...
http://www.opengl.org/discussion_boards/ubb/faq.html

http://www.opengl.org/discussion_boards/ubb/smile.gif