Team Spartan Cookies & Milk Forums
  • Donations
  • Search
  • Member List
  • Help

Register

Team Spartan Cookies & Milk Forums Garry's Mod Starfall v
1 2 3 4 5 ... 16 Next »
Release Wavefront OBJ to IMesh
Post Reply 
 
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Threaded Mode | Linear Mode
[Release] Wavefront OBJ to IMesh
13-01-2021, 12:16 AM
Post: #1
frdhog Online
Hasn't finished a ship in 2 years
****
Posts: 67
Joined: Feb 2016
Wavefront OBJ to IMesh
Wavefront OBJ to IMesh
I have created a pure Starfall OBJ parser that will take in OBJ strings and can convert it to an IMesh, ready for hologram or HUD use. As I am pretty unimaginative, I named it Wavefront OBJ to IMesh. This forum post will serve as a reference or tutorial to use this library (you can view the source at Shared/frdhog/libs/wavefront_obj.txt)
The advantage this has over external programs is that it allows you to load files that are larger than 1MiB (through io.read & starfallscriptdata), through the HTTP library or pretty much any other means you can think of. Due to quota limits, you can process over multiple ticks and use a callback once completed, use ProcessObjMesh for this

Including the library
To include the library, you'll need to do the following
--@dependency STEAM_0:0:104916709 libs/wavefront_obj.txt cl
require("libs/wavefront_obj.txt")
Note the dependency uses cl as it's easiest to process the meshes on the client rather than network everything
As this was originally created for my own purposes, this 'library' is just public functions.

ParseObjToMesh
If you need a new mesh instantly, you can use ParseObjToMesh. It takes one string and returns the IMesh once complete.
Unlike ProcessObjMesh, you can use this inline but it will error if the file is too large and such the time quota is exceeded while processing it.

ProcessObjMesh
The best way to use my library is to use the ProcessObjMesh function.
ProcessObjMesh(objstr, onComplete, onlyMeshVerts, updateStatus, invertNormals)
Not all of these parameters are needed unless you want to have more control. See the ProcessObjMesh example
  • objstr - the OBJ inputted as a string
  • onComplete - can be one of the following:
    function - your callback will be passed the mesh (or table of MeshVertex)
    imesh - given a mesh reference, this will buildFromTriangles onto this Mesh. Use with the updateStatus callback to detect completion
    table - onlyMeshVerts needs to be true, is a table of MeshVertex structs ready to be pumped into buildFromTriangles
  • onlyMeshVerts - optional boolean that allows onComplete to be a table or to be passed the table of MeshVertex
  • updateStatus - optional callback function - it is passed a number from 1-5, marking the different stages of processing. The processing is complete at 5, it will be safe to use your mesh here
  • invertNormals - optional boolean that will invert the normals for you (the outside is now inwards, or the opposite if your normals are already inverted)

Examples
These are examples of how to use the library, not how to use IMeshes in holograms. For those I recommend checking out other implementations or the files in Shared/frdhog/mesh/
ProcessObjMesh
To simply load in a mesh with one callback you can do something like the following
--Load in our OBJ as a string, this can be done by simply having an included file with return [[ OBJ ]]
objStr = require(objPath)
--Setup our two variables - our mesh used for rendering and a boolean that we use to detect when we can start rendering with our mesh
globalMesh = nil
loaded = false
ProcessObjMesh(objStr, function(outMesh)
globalMesh = outMesh
loaded = true
end)
--Render globalMesh if loaded == true

ProcessObjToVerts
You can use ProcessObjToVerts for a shorter version of ProcessObjMesh with onlyMeshVerts enabled. This may be useful if you want to join multiple OBJs into one IMesh.
objStr = require(objPath)
objStr2 = require(objPath2)
existingVerts = {}
meshCount = 0
local function processVerts(verts) --We are given a table of MeshVertex structs, ready for buildFromTriangles
table.Add(existingVerts, verts) --We add the values of verts onto the end of the existingVerts (GLua function)
meshCount = meshCount + 1
end
ProcessObjToVerts(objStr, processVerts)
ProcessObjToVerts(objStr2, processVerts)
Within a timer or a render hook, Probably in a timer, create mesh if meshCount == 2
if meshCount == 2 and newMesh == nil then
newMesh = Mesh()
newMesh:buildFromTriangles(mesh)
end
--Render our two-in-one mesh here
Note, the processing will not be run in any logical order.

ParseObjToMesh
If your mesh is small and your quota is kickin', you can use the inline ParseObjToMesh. This example also includes how to draw using a HUD in 3D space
local outMesh = ParseObjToMesh(require(objPath))
local mat = Material("models/wireframe")
hook.add("render", "renderMesh", function()
render.start3D()
local trix = ents.self():getWorldTransformMatrix() --Gets a matrix using the chip's pos + ang
render.pushMatrix(trix) --Push the matrix, makes coordinates now relative to the chip
hudMesh:draw() --Draw the mesh
render.popMatrix()
render.end3D()
end)

Other notes
This takes into account normals and UVs, so if materials are facing the wrong direction then double check your 3D model
If processing is running out of time quota, then reduce the global _wavefront_cpuLimit to below 0.6 (meaning 60%) before processing
Please tell me if you get any errors or unexpected behaviour. I will likely ignore errors that include time quota and ParseObjToMesh
Visit this user's website Find all posts by this user
Quote this message in a reply
« Next Oldest | Next Newest »
Post Reply 


  • View a Printable Version
  • Send this Thread to a Friend
  • Subscribe to this thread
Forum Jump:


User(s) browsing this thread: 1 Guest(s)
Contact UsTeam Spartan Cookies & MilkReturn to TopReturn to ContentLite (Archive) ModeRSS Syndication

Powered By MyBB, © 2002-2021 MyBB Group.