Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- .obj to roblox V1.2.2 by magnalite for PUBLIC release
- credits to stravant for triangle making function
- Options
- loadspeed = How fast you want the mesh to load (Higher the greater but more laggy)
- scale = How big you want the mesh to be
- wrongAngleFixer = Should only be true if your model is at an odd angle
- loadColor = If you want the mesh to have colors or not
- offset = translate the model by this Vector
- --]]
- loadspeed = 100
- scale = 10
- wrongAngleFixer = false
- loadColors = true
- offset = Vector3.new()
- shouldrenderVertexes = false
- shouldrenderWireFrame = false
- shouldrenderFaces = true
- --[[
- Changelog-
- V 1.2.2
- --Improved accuracy
- --Stravant's triangle code
- V 1.2.1
- --fixed bug reported by SlingshotJunkie
- V 1.2.0
- --Oysi's triangle code
- --Minor code cleanup
- --PUBLIC RELEASE
- V 1.1.0
- --Added support for more obj file structures
- V 1.0.0
- --Added support for colors (.mtl parsing)
- ]]--
- -------------------------------------------------------------------------------------------------------------------
- print("\n")
- _G.Mesh = nil
- _G.Materials = nil
- print("Waiting for Mesh and Materials Data\n")
- repeat wait() until _G.Mesh and _G.Materials
- objFile = _G.Mesh
- mtlFile = _G.Materials
- PolyDraw = {}
- function parseMaterials()
- materials = {}
- filePos = 0
- local endfile = false
- while endfile == false do
- endFile = true
- materialPos = string.find(mtlFile, "newmtl" ,filePos)
- if materialPos then
- materialNameStartPos = string.find(mtlFile, "%s", materialPos+1)
- materialNameEndPos = string.find(mtlFile, "%s", materialNameStartPos+1)
- materialName = string.sub(mtlFile,materialNameStartPos+1,materialNameEndPos-1)
- colorPos = string.find(mtlFile, "Kd", materialNameEndPos)
- colorStartPos = string.find(mtlFile, "%s", colorPos)
- colorEndPos = string.find(mtlFile, "Ks", colorStartPos)
- color = string.sub(mtlFile, colorStartPos+1,colorEndPos-2)
- color1EndPos = string.find(color, " ")
- color1 = string.sub(color,0,color1EndPos-1)
- color2EndPos = string.find(color, " ", color1EndPos+1)
- color2 = string.sub(color,color1EndPos+1,color2EndPos-1)
- color3 = string.sub(color,color2EndPos+1)
- endColor = Color3.new(tonumber(color1),tonumber(color2),tonumber(color3))
- materials[materialName] = endColor
- filePos = colorEndPos
- else
- endFile = true
- break
- end
- end
- end
- function parseVertexes()
- vertexes = {}
- filePos = 0
- local endfile = false
- while not endfile do
- vertexPos = string.find(objFile, "v ",filePos)
- if vertexPos then
- startPos = string.find(objFile, "%S", vertexPos+1)
- firstCordPos = string.find(objFile, " ", startPos)
- firstCord = string.sub(objFile,vertexPos+1,firstCordPos-1)
- secondCordPos = string.find(objFile, " ", firstCordPos+1)
- secondCord = string.sub(objFile,firstCordPos+1,secondCordPos-1)
- thirdCordPos = string.find(objFile, "%s", secondCordPos+1)
- thirdCord = string.sub(objFile,secondCordPos+1,thirdCordPos-1)
- filePos = thirdCordPos
- if wrongAngleFixer then
- vertex = Vector3.new(tonumber(firstCord)*scale,tonumber(thirdCord)*scale,tonumber(secondCord)*scale) + offset * scale
- else
- vertex = Vector3.new(tonumber(firstCord)*scale,tonumber(secondCord)*scale,tonumber(thirdCord)*scale) + offset * scale
- end
- table.insert(vertexes,vertex)
- else
- print("Number of vertices : " .. #vertexes)
- endfile = true
- end
- end
- end
- function parseFaces()
- faces = {}
- filePos = 0
- local endfile = false
- while not endfile do
- faceStringPos = string.find(objFile, "f ",filePos)
- if loadColors then
- useMaterial = string.find(objFile, "usemtl",filePos)
- if useMaterial and useMaterial < faceStringPos then
- materialNameStartPos = string.find(objFile, "%s", useMaterial)
- materialNameEndPos = string.find(objFile, "%s", materialNameStartPos+1)
- materialName = string.sub(objFile,materialNameStartPos+1,materialNameEndPos-1)
- useColor = materials[materialName]
- end
- end
- if faceStringPos then
- face2startPos = string.find(objFile," ",faceStringPos+2)
- face3startPos = string.find(objFile," ",face2startPos+1)
- facePos1String = objFile:match("%d+",faceStringPos)
- facePos2String = objFile:match("%d+",face2startPos)
- facePos3String = objFile:match("%d+",face3startPos)
- face1Pos = vertexes[tonumber(facePos1String)]
- face2Pos = vertexes[tonumber(facePos2String)]
- face3Pos = vertexes[tonumber(facePos3String)]
- table.insert(faces,{face1Pos,face2Pos,face3Pos,useColor})
- filePos = face3startPos+1
- else
- print("Number of faces : " .. #faces)
- endfile = true
- end
- end
- end
- function renderVertexes()
- speedLoad = 0
- for key, value in pairs(vertexes) do
- if speedLoad > loadspeed then
- wait()
- speedLoad = 0
- end
- speedLoad = speedLoad + 1
- vertexPart = Instance.new("Part",Workspace)
- vertexPart.Size = Vector3.new(1,1,1)
- vertexPart.CFrame = CFrame.new(value.X,value.Y,value.Z)
- vertexPart.Name = key
- vertexPart.Anchored = true
- vertexPart.BrickColor = BrickColor.new("Really red")
- end
- end
- function renderVertexesOfFace(face)
- for key, value in pairs(face) do
- vertexPart = Instance.new("Part",Workspace)
- vertexPart.Size = Vector3.new(1,1,1)
- vertexPart.CFrame = CFrame.new(value.X,value.Y,value.Z)
- vertexPart.Anchored = true
- vertexPart.BrickColor = BrickColor.new("Really red")
- end
- end
- function renderFace(face)
- facesRendered = facesRendered + 1
- PolyDraw.Tri.new(face[1],face[2],face[3],face[4])
- end
- function createFaceInfoHint()
- coroutine.wrap(function()
- local hint = Instance.new("Hint", Workspace)
- local startTime = tick()
- while wait() do
- hint.Text = "Faces rendered : "
- .. facesRendered
- .. " Percent done : "
- .. math.floor((facesRendered/#faces)*10000)/100
- .. "%"
- .. " Approx time left : "
- .. math.floor((((tick() - startTime) / facesRendered) * (#faces-facesRendered))*10)/10
- .. " seconds"
- end
- end)()
- end
- function renderFaces()
- speedLoad = 0
- facesRendered = 0
- createFaceInfoHint()
- for key,value in pairs(faces) do
- if speedLoad > loadspeed then
- wait()
- speedLoad = 0
- end
- speedLoad = speedLoad + 1
- renderFace(value)
- end
- print("Done rendering!")
- end
- function renderWireFrame()
- speedLoad = 0
- for key,value in pairs(faces) do
- if speedLoad > loadspeed then
- wait()
- speedLoad = 0
- end
- speedLoad = speedLoad + 1
- renderWiresForFace(value)
- end
- end
- wire = Instance.new("Part")
- wire.Anchored = true
- wire.formFactor = Enum.FormFactor.Custom
- wire.BrickColor = BrickColor.new("New Yeller")
- function renderWiresForFace(face)
- renderWire(face[1],face[2])
- renderWire(face[2],face[3])
- renderWire(face[3],face[1])
- end
- function renderWire(pos1,pos2)
- local distance = (pos1 - pos2).magnitude
- local wire = wire:Clone()
- wire.Parent = Workspace
- wire.Size = Vector3.new(0.2,0.2,distance)
- wire.CFrame = CFrame.new( pos1, pos2) * CFrame.new(0, 0, -distance/2)
- end
- mesh = Instance.new("Model", Workspace)
- mesh.Name = "Mesh"
- PolyDraw.BrickColor = BrickColor.new(21)
- PolyDraw.CanCollide = false
- local function setupPart(part)
- part.Anchored = true
- part.FormFactor = 'Custom'
- part.CanCollide = PolyDraw.CanCollide
- part.BrickColor = PolyDraw.BrickColor
- part.TopSurface = 'Smooth'
- part.BottomSurface = 'Smooth'
- local mesh = Instance.new("SpecialMesh", part)
- mesh.MeshType = "Wedge"
- mesh.Scale = Vector3.new(0,1,1)
- end
- local Point = {}
- PolyDraw.Point = Point
- function Point.new(parent, at)
- local this = {}
- local mPart = Instance.new('Part')
- setupPart(mPart)
- mPart.Size = Vector3.new(1, 1, 1)
- mPart.Parent = parent
- function this:Set(at)
- mPart.CFrame = CFrame.new(at)
- end
- function this:Destroy()
- mPart:Destroy()
- end
- function this:SetProperty(prop, value)
- mPart[prop] = value
- end
- this:Set(at)
- return this
- end
- local Edge = {}
- PolyDraw.Edge = Edge
- function Edge.new(parent, a, b)
- local this = {}
- local mPart = Instance.new('Part')
- setupPart(mPart)
- mPart.Parent = parent
- function this:Set(a, b)
- local sep = (a-b).magnitude
- mPart.Size = Vector3.new(0.5, 0.5, sep)
- mPart.CFrame = CFrame.new(a, b) * CFrame.new(0, 0, -0.5*sep)
- end
- function this:Destroy()
- mPart:Destroy()
- end
- function this:SetProperty(prop, value)
- mPart[prop] = value
- end
- this:Set(a, b)
- return this
- end
- Tri = {}
- PolyDraw.Tri = Tri
- local function CFrameFromTopBack(at, top, back)
- local right = top:Cross(back)
- return CFrame.new(at.x, at.y, at.z,
- right.x, top.x, back.x,
- right.y, top.y, back.y,
- right.z, top.z, back.z)
- end
- function Tri.new(a, b, c, color)
- local this = {}
- local mPart1 = Instance.new('WedgePart')
- setupPart(mPart1)
- local mPart2 = Instance.new('WedgePart')
- setupPart(mPart2)
- function this:Set(a, b, c)
- --[[ edg1
- A ------|------>B --.
- '\ | / \
- \part1|part2/ |
- \ cut / / Direction edges point in:
- edg3 \ / edg2 / (clockwise)
- \ / |/
- \<- / `
- \ /
- C
- --]]
- local ab, bc, ca = b-a, c-b, a-c
- local abm, bcm, cam = ab.magnitude, bc.magnitude, ca.magnitude
- local edg1 = math.abs(0.5 + ca:Dot(ab)/(abm*abm))
- local edg2 = math.abs(0.5 + ab:Dot(bc)/(bcm*bcm))
- local edg3 = math.abs(0.5 + bc:Dot(ca)/(cam*cam))
- -- Idea: Find the edge onto which the vertex opposite that
- -- edge has the projection closest to 1/2 of the way along that
- -- edge. That is the edge thatwe want to split on in order to
- -- avoid ending up with small "sliver" triangles with one very
- -- small dimension relative to the other one.
- if edg1 < edg2 then
- if edg1 < edg3 then
- -- min is edg1: less than both
- -- nothing to change
- else
- -- min is edg3: edg3 < edg1 < edg2
- -- "rotate" verts twice counterclockwise
- a, b, c = c, a, b
- ab, bc, ca = ca, ab, bc
- abm = cam
- end
- else
- if edg2 < edg3 then
- -- min is edg2: less than both
- -- "rotate" verts once counterclockwise
- a, b, c = b, c, a
- ab, bc, ca = bc, ca, ab
- abm = bcm
- else
- -- min is edg3: edg3 < edg2 < edg1
- -- "rotate" verts twice counterclockwise
- a, b, c = c, a, b
- ab, bc, ca = ca, ab, bc
- abm = cam
- end
- end
- --calculate lengths
- local len1 = -ca:Dot(ab)/abm
- local len2 = abm - len1
- local width = (ca + ab.unit*len1).magnitude
- --calculate "base" CFrame to pasition parts by
- local maincf = CFrameFromTopBack(a, ab:Cross(bc).unit, -ab.unit)
- --make parts
- mPart1.Parent = mesh
- mPart1.Size = Vector3.new(0.2, 0.2, 0.2)
- mPart1.Mesh.Scale = Vector3.new(0.00001, width, len1)/0.2
- mPart1.CFrame = maincf*CFrame.Angles(math.pi,0,math.pi/2)*CFrame.new(0,width/2,len1/2)
- mPart1.Color = color or Color3.new(0, 0, 0.7)
- mPart2.Parent = mesh
- mPart2.Size = Vector3.new(0.2, 0.2, 0.2)
- mPart2.Mesh.Scale = Vector3.new(0.00001, width, len2)/0.2
- mPart2.CFrame = maincf*CFrame.Angles(math.pi,math.pi,-math.pi/2)*CFrame.new(0,width/2,-len1 - len2/2)
- mPart2.Color = color or Color3.new(0, 0, 0.7)
- end
- function this:SetProperty(prop, value)
- mPart1[prop] = value
- mPart2[prop] = value
- end
- this:Set(a, b, c)
- function this:Destroy()
- mPart1:Destroy()
- mPart2:Destroy()
- end
- return this
- end
- -------------------------------------------------------------------------------------------------------------------------------------
- if loadColors then
- parseMaterials()
- end
- parseVertexes()
- parseFaces()
- if shouldrenderVertexes then
- renderVertexes()
- end
- if shouldrenderWireFrame then
- renderWireFrame()
- end
- if shouldrenderFaces then
- renderFaces()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement