Hi there!
I want to load .stl mesh file and custom material with scene setup like that of modelViewer.Is this possible?
If yes can you guide me how?
Thanks
Unfortunately we only support glTF in the ModelViewer utility. Maybe you could convert your STL file to glTF using a tool?
If you want to write some model-loading code in Kotlin, you can look at MeshLoader.kt for inspiration, which is our filamesh loader in sample-textured-object.
I have managed to read .stl file with assimp-kotlin port.
private var scene = Importer().readFile("/storage/emulated/0/Download/wolf.stl")
scene has meshes,materials and textures.
Can you tell me on how to show this scene into filament modelViewer from here?
I want to do something like this in my custom modelViewer
/**
* Loads a stl file and populates the Filament scene.
*/
fun loadModelStl(scene:AiScene) {
destroyModel()
// TODO - Load the asset from scene variable here.
}
Is this possible? Let me know there is simpler way.
I didn't know about the existence of assimp-kotlin, that sounds perfect for your needs!
The next step is to iterate through the AiScene and build up a list of entities with Renderable and Transformable components. Maybe you can look at MeshLoader.kt for inspiration.
Since supporting the stl file format is out of scope for gltfio and Filament, I'll go ahead and close this ticket.
@prideout @romainguy I cannot understand how to iterate over AiScene and build entities is there anything that can show me on how is that done?
I have access to meshes and vertices of each mesh from the stl file.
How to make a filamentAsset out of this?
You can look at the example from MeshLoader.kt. You need to build vertex and index buffers and finally renderables.
I figured mostly everything, One thing i couldn't do was converting MutableList<AiVector3D> into ByteBuffer?
Can you tell me how can this be done?Or if its not need then how to proceed.
P.S.
I need this because in MeshLoader you guys have coded it like this
return vertexBufferBuilder.build(engine).apply { setBufferAt(engine, 0,**data**) }
where data is a ByteBuffer where as i already have a mutableList of vec3d
This is what i have written from what i understood from MeshLoader.kt
private fun readstlHeader(aiScene: AiScene): Header {
val header = Header()
header.totalVertices = aiScene.meshes[0].numVertices.toLong()
header.totalIndices = aiScene.meshes[0].numFaces.toLong() * 3
return header
}
fun loadMeshfromAiScene(
aiScene: AiScene,
materials: Map<String, MaterialInstance>,
engine: Engine
): Mesh {
val header = readstlHeader(aiScene)
val vertexBuffer = createVertexBufferforSTL(engine, header, aiScene.meshes[0].vertices)
val indexBuffer = createIndexBufferforSTL(engine, header, aiScene.meshes[0].faces)
val renderable = createRenderableforSTL(
engine,
aiScene,
indexBuffer,
vertexBuffer,
materials
)
return Mesh(renderable,indexBuffer,vertexBuffer,header.aabb)
}
private fun maxIndex(aiScene: AiScene): Int {
var maxi = -1
for (i in 0 until aiScene.meshes[0].numFaces) {
for (j in 0 until aiScene.meshes[0].faces[i].size) {
if (maxi < aiScene.meshes[0].faces[i][j]) {
maxi = aiScene.meshes[0].faces[i][j]
}
}
}
return maxi
}
private fun createIndexBufferforSTL(engine: Engine, header: Header, data: ByteBuffer): IndexBuffer {
return IndexBuffer.Builder().bufferType(IndexBuffer.Builder.IndexType.UINT)
.indexCount(header.totalIndices.toInt()).build(engine).apply { setBuffer(engine, data) }
}
private fun createVertexBufferforSTL(
engine: Engine,
header: Header,
data: ByteBuffer
): VertexBuffer {
val vertexBufferBuilder =
VertexBuffer.Builder().bufferCount(1).vertexCount(header.totalVertices.toInt())
.normalized(COLOR)
val buffer = ByteBuffer.allocate()
return vertexBufferBuilder.build(engine).apply { setBufferAt(engine, 0, data) }
}
private fun createRenderableforSTL(
engine: Engine,
aiScene: AiScene,
indexBuffer: IndexBuffer,
vertexBuffer: VertexBuffer,
materials: Map<String, MaterialInstance>
): Int {
val builder = RenderableManager.Builder(1)
repeat(1) { i ->
builder.geometry(
i,
RenderableManager.PrimitiveType.TRIANGLES,
vertexBuffer,
indexBuffer,
0L.toInt(),
0,
maxIndex(aiScene),
aiScene.meshes[i].numFaces * 3
)
// Find a material in the supplied material map, otherwise we fall back to
// the default material named "DefaultMaterial"
builder.material(i, materials["DefaultMaterial"] ?: error("Default material not found"))
}
return EntityManager.get().create().apply { builder.build(engine, this) }
}
can you provide link to usage documentation of filament?