Skip to content

Commit 0c9f007

Browse files
committed
- .obj material (tex excluded)
- AiMesh class -> MutableList
1 parent 20cfe9c commit 0c9f007

File tree

11 files changed

+337
-119
lines changed

11 files changed

+337
-119
lines changed

src/main/ScenePreprocessor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class ScenePreprocessor(
6060
// If the information which primitive types are there in the mesh is currently not available, compute it.
6161
if (mPrimitiveTypes == 0) {
6262
mFaces.forEach {
63-
when (it.mNumIndices) {
63+
when (it.size) {
6464
3 -> mPrimitiveTypes = mPrimitiveTypes or AiPrimitiveType.TRIANGLE
6565
2 -> mPrimitiveTypes = mPrimitiveTypes or AiPrimitiveType.LINE
6666
1 -> mPrimitiveTypes = mPrimitiveTypes or AiPrimitiveType.POINT

src/main/defs.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import main.vec._3.Vec3
77
import main.vec._3.Vec3d
88
import main.vec._4.Vec4
99
import main.vec._4.Vec4d
10+
import java.io.File
1011
import kotlin.reflect.KClass
1112

1213
/**
@@ -29,4 +30,7 @@ typealias AiVector2D = Vec2
2930
* This can be adjusted for specific use cases
3031
* It's NOT a total limit, just a limit for individual allocations
3132
*/
32-
fun AI_MAX_ALLOC(size: Int) = (256 * 1024 * 1024) / size
33+
fun AI_MAX_ALLOC(size: Int) = (256 * 1024 * 1024) / size
34+
35+
// TODO file operators overloading, https://youtrack.jetbrains.com/issue/KT-15009
36+
inline operator fun File.plus(another: String) = File(this, another)

src/main/material.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ package main
77
// Name for default materials (2nd is used if meshes have UV coords)
88
const val AI_DEFAULT_MATERIAL_NAME = "DefaultMaterial"
99
// ---------------------------------------------------------------------------
10-
/** @brief Defines how the Nth texture of a specific type is combined with the result of all previous layers.
10+
/** @brief Defines how the Nth texture of a specific Type is combined with the result of all previous layers.
1111
*
1212
* Example (left: key, right: value): <br>
1313
* @code

src/main/mesh.kt

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,14 @@ const val AI_MAX_NUMBER_OF_TEXTURECOORDS = 0x8
5353
* Together with the #aiProcess_Triangulate flag you can then be sure that #aiFace::mNumIndices is always 3.
5454
* @note Take a look at the @link data Data Structures page @endlink for more information on the layout and winding
5555
* order of a face. */
56-
data class AiFace(
57-
//! Number of indices defining this face.
58-
//! The maximum value for this member is #AI_MAX_FACE_INDICES.
59-
var mNumIndices: Int = 0,
60-
61-
//! Pointer to the indices array. Size of the array is given in numIndices.
62-
var mIndices: MutableList<Int> = mutableListOf())
56+
//data class AiFace(
57+
// //! Number of indices defining this face.
58+
// //! The maximum value for this member is #AI_MAX_FACE_INDICES.
59+
// var mNumIndices: Int = 0,
60+
//
61+
// //! Pointer to the indices array. Size of the array is given in numIndices.
62+
// var mIndices: MutableList<Int> = mutableListOf())
63+
typealias AiFace = MutableList<Int>
6364

6465
// ---------------------------------------------------------------------------
6566
/** @brief A single influence of a bone on a vertex.
@@ -206,7 +207,7 @@ data class AiMesh(
206207

207208
/** Bitwise combination of the members of the #aiPrimitiveType enum.
208209
* This specifies which types of primitives are present in the mesh.
209-
* The "SortByPrimitiveType"-Step can be used to make sure the output meshes consist of one primitive type each. */
210+
* The "SortByPrimitiveType"-Step can be used to make sure the output meshes consist of one primitive Type each. */
210211
var mPrimitiveTypes: Int = 0,
211212

212213
/** The number of vertices in this mesh.
@@ -258,7 +259,7 @@ data class AiMesh(
258259
/** Vertex color sets.
259260
* A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex colors per vertex. NULL if not present. Each
260261
* array is mNumVertices in size if present. */
261-
var mColors: Array<Array<AiColor4D>?> = Array(AI_MAX_NUMBER_OF_COLOR_SETS, { null }),
262+
var mColors: Array<MutableList<AiColor4D>?> = Array(AI_MAX_NUMBER_OF_COLOR_SETS, { null }),
262263

263264
/** Vertex texture coords, also known as UV channels.
264265
* A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per vertex. NULL if not present. The array is

src/main/obj/ObjFileData.kt

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import main.mat.Mat4
1616
// ------------------------------------------------------------------------------------------------
1717
data class Face(
1818

19-
//! Primitive type
19+
//! Primitive Type
2020
var m_PrimitiveType: AiPrimitiveType = AiPrimitiveType.POLYGON,
2121
//! Vertex indices
2222
var m_vertices: MutableList<Int> = mutableListOf(),
@@ -55,19 +55,8 @@ data class Material(
5555
//! Name of material description
5656
var materialName: String,
5757

58-
//! Texture names
59-
var texture: String = "",
60-
var textureSpecular: String = "",
61-
var textureAmbient: String = "",
62-
var textureEmissive: String = "",
63-
var textureBump: String = "",
64-
var textureNormal: String = "",
65-
var textureReflection: Array<String> = arrayOf(),
66-
var textureSpecularity: String = "",
67-
var textureOpacity: String = "",
68-
var textureDisp: String = "",
69-
70-
var clamp: BooleanArray = BooleanArray(Material.textureType.values().size, { false }),
58+
//! Textures
59+
var textures: MutableList<Texture> = mutableListOf(),
7160

7261
//! Ambient color
7362
var ambient: AiColor3D = AiColor3D(),
@@ -86,23 +75,29 @@ data class Material(
8675
//! Index of refraction
8776
var ior: Float = 1.0f
8877
) {
89-
enum class textureType {
90-
diffuse,
91-
specular,
92-
ambient,
93-
emissive,
94-
bump,
95-
normal,
96-
reflectionSphere,
97-
reflectionCubeTop,
98-
reflectionCubeBottom,
99-
reflectionCubeFront,
100-
reflectionCubeBack,
101-
reflectionCubeLeft,
102-
reflectionCubeRight,
103-
specularity,
104-
opacity,
105-
disp
78+
class Texture(
79+
val name: String,
80+
val type: Type,
81+
val clamp: Boolean = false
82+
) {
83+
enum class Type {
84+
diffuse,
85+
specular,
86+
ambient,
87+
emissive,
88+
bump,
89+
normal,
90+
reflectionSphere,
91+
reflectionCubeTop,
92+
reflectionCubeBottom,
93+
reflectionCubeFront,
94+
reflectionCubeBack,
95+
reflectionCubeLeft,
96+
reflectionCubeRight,
97+
specularity,
98+
opacity,
99+
disp
100+
}
106101
}
107102
}
108103

src/main/obj/ObjFileImporter.kt

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
package main.obj
22

3-
import com.sun.org.apache.xpath.internal.operations.Mod
43
import main.*
5-
import main.AiVector3D
64
import java.io.File
7-
import java.io.RandomAccessFile
8-
import java.nio.ByteOrder
9-
import java.nio.channels.FileChannel
105
import java.nio.file.FileSystemException
116
import java.util.*
7+
import kotlin.collections.ArrayList
128

139
/**
1410
* Created by elect on 21/11/2016.
@@ -51,14 +47,8 @@ class ObjFileImporter : BaseImporter() {
5147

5248
if (fileSize < ObjMinSize) throw Error("OBJ-file is too small.")
5349

54-
// Allocate buffer and read file into it
55-
val streamedBuffer = file.readLines()
56-
57-
// Get the model name
58-
val modelName = file.name
59-
6050
// parse the file into a temporary representation
61-
val parser = ObjFileParser(streamedBuffer, modelName)
51+
val parser = ObjFileParser(file)
6252

6353
// And create the proper return structures out of it
6454
createDataFromImport(parser.m_pModel, pScene)
@@ -188,26 +178,22 @@ class ObjFileImporter : BaseImporter() {
188178

189179
// Copy all data from all stored meshes
190180
pObjMesh.m_Faces.forEach {
191-
val face = AiFace()
181+
val face = ArrayList<Int>()
192182
when (it.m_PrimitiveType) {
193183
AiPrimitiveType.LINE -> for (i in 0 until it.m_vertices.size - 1) {
194-
face.mNumIndices = 2
195-
uiIdxCount += face.mNumIndices
196-
face.mIndices = IntArray(2).toMutableList()
197-
continue
184+
val mNumIndices = 2
185+
uiIdxCount += mNumIndices
186+
repeat(mNumIndices, { face.add(0) })
198187
}
199188
AiPrimitiveType.POINT -> for (i in 0 until it.m_vertices.size) {
200-
face.mNumIndices = 1
201-
uiIdxCount += face.mNumIndices
202-
face.mIndices = IntArray(1).toMutableList()
203-
continue
189+
val mNumIndices = 1
190+
uiIdxCount += mNumIndices
191+
repeat(mNumIndices, { face.add(0) })
204192
}
205193
else -> {
206194
val uiNumIndices = it.m_vertices.size
207-
face.mNumIndices = uiNumIndices
208195
uiIdxCount += uiNumIndices
209-
if (face.mNumIndices > 0)
210-
face.mIndices = IntArray(uiNumIndices).toMutableList()
196+
repeat(uiNumIndices, { face.add(0) })
211197
}
212198
}
213199
faces.add(face)
@@ -239,15 +225,15 @@ class ObjFileImporter : BaseImporter() {
239225
else if (pMesh.mNumVertices > AI_MAX_ALLOC(main.AiVector3D.SIZE))
240226
throw Error("OBJ: Too many vertices, would run out of memory")
241227

242-
pMesh.mVertices = Array<AiVector3D>(pMesh.mNumVertices, { AiVector3D() }).toMutableList()
228+
pMesh.mVertices = Array(pMesh.mNumVertices, { AiVector3D() }).toMutableList()
243229

244230
// Allocate buffer for normal vectors
245231
if (pModel.m_Normals.isNotEmpty() && pObjMesh.m_hasNormals)
246-
pMesh.mNormals = ArrayList(pMesh.mNumVertices)
232+
pMesh.mNormals = Array(pMesh.mNumVertices, { AiVector3D() }).toMutableList()
247233

248234
// Allocate buffer for vertex-color vectors
249235
if (pModel.m_VertexColors.isNotEmpty())
250-
pMesh.mColors[0] = Array(pMesh.mNumVertices, { AiColor4D() })
236+
pMesh.mColors[0] = Array(pMesh.mNumVertices, { AiColor4D() }).toMutableList()
251237

252238
// Allocate buffer for texture coordinates
253239
if (pModel.m_TextureCoord.isNotEmpty() && pObjMesh.m_uiUVCoordinates[0] != 0) {
@@ -270,7 +256,7 @@ class ObjFileImporter : BaseImporter() {
270256
pMesh.mVertices[newIndex] = pModel.m_Vertices[vertex]
271257

272258
// Copy all normals
273-
if (pModel.m_Normals.isNotEmpty() && vertexIndex in it.m_normals) {
259+
if (pModel.m_Normals.isNotEmpty() && vertexIndex in it.m_normals.indices) {
274260
val normal = it.m_normals[vertexIndex]
275261
if (normal >= pModel.m_Normals.size)
276262
throw Error("OBJ: vertex normal index out of range")
@@ -298,7 +284,7 @@ class ObjFileImporter : BaseImporter() {
298284

299285
val last = (vertexIndex == it.m_vertices.size - 1)
300286
if (it.m_PrimitiveType != AiPrimitiveType.LINE || !last) {
301-
pDestFace.mIndices[outVertexIndex] = newIndex
287+
pDestFace[outVertexIndex] = newIndex
302288
outVertexIndex++
303289
}
304290

@@ -384,10 +370,11 @@ class ObjFileImporter : BaseImporter() {
384370
mat.refracti = pCurrentMaterial.ior
385371

386372
// Adding textures
387-
if (pCurrentMaterial.texture.isNotEmpty()) {
373+
pCurrentMaterial.textures.firstOrNull { it.type == Material.Texture.Type.diffuse }?.let {
388374

389-
mat.textures!!.add(AiMaterialTexture(path = pCurrentMaterial.texture))
375+
mat.textures!!.add(AiMaterialTexture(type = AiTextureType.diffuse))
390376
}
377+
391378
// TODO
392379

393380
// Store material property info in material array in scene

src/main/obj/ObjFileMtlImporter.kt

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package main.obj
2+
3+
import main.AiMaterial
4+
import main.f
5+
import main.i
6+
import javax.sql.rowset.serial.SerialRef
7+
8+
/**
9+
* Created by elect on 27/11/2016.
10+
*/
11+
12+
/**
13+
* @class ObjFileMtlImporter
14+
* @brief Loads the material description from a mtl file.
15+
*/
16+
17+
class ObjFileMtlImporter(buffer: List<String>, private val m_pModel: Model) {
18+
19+
init {
20+
if (m_pModel.m_pDefaultMaterial == null)
21+
m_pModel.m_pDefaultMaterial = Material("default")
22+
load(buffer)
23+
}
24+
25+
fun load(buffer: List<String>) {
26+
27+
for (line in buffer) {
28+
29+
val words = line.trim().split("\\s+".toRegex())
30+
31+
when (words[0][0]) {
32+
'k', 'K' -> when (words[0][1]) {
33+
// Ambient color
34+
'a' -> m_pModel.m_pCurrentMaterial!!.ambient.to(words[1].f, words[2].f, words[3].f)
35+
// Diffuse color
36+
'd' -> m_pModel.m_pCurrentMaterial!!.diffuse.to(words[1].f, words[2].f, words[3].f)
37+
's' -> m_pModel.m_pCurrentMaterial!!.specular.to(words[1].f, words[2].f, words[3].f)
38+
'e' -> m_pModel.m_pCurrentMaterial!!.emissive.to(words[1].f, words[2].f, words[3].f)
39+
}
40+
'd' ->
41+
if (words[0] == "disp") // A displacement map
42+
getTexture(line)
43+
else
44+
m_pModel.m_pCurrentMaterial!!.alpha = words[1].f // Alpha value
45+
'n', 'N' ->
46+
when (words[0][1]) {
47+
// Specular exponent
48+
's' -> m_pModel.m_pCurrentMaterial!!.shineness = words[1].f
49+
// Index Of refraction
50+
'i' -> m_pModel.m_pCurrentMaterial!!.ior = words[1].f
51+
// New material
52+
'e' -> createMaterial(words[1])
53+
}
54+
'm', 'b', 'r' -> getTexture(line)
55+
'i' -> m_pModel.m_pCurrentMaterial!!.illumination_model = words[1].i
56+
}
57+
}
58+
}
59+
60+
// -------------------------------------------------------------------
61+
// Gets a texture name from data.
62+
fun getTexture(line: String) {
63+
64+
val words = line.substringBefore('#').split("\\s+".toRegex()) // get rid of comment
65+
var type: Material.Texture.Type? = null
66+
var clamped = false
67+
68+
if (words[0] == "refl" && TypeOption in words)
69+
type = reflMap[words[words.indexOf(TypeOption) + 1]]
70+
else
71+
type = tokenMap[words[0]]
72+
73+
if (type == null)
74+
throw Error("OBJ/MTL: Encountered unknown texture type")
75+
76+
if (ClampOption in words)
77+
clamped = words[words.indexOf(ClampOption) + 1] == "on"
78+
79+
m_pModel.m_pCurrentMaterial!!.textures.add(Material.Texture(words.last(), type, clamped))
80+
}
81+
82+
// -------------------------------------------------------------------
83+
// Creates a material from loaded data.
84+
fun createMaterial(matName: String) {
85+
86+
val mat = m_pModel.m_MaterialMap[matName]
87+
88+
if (mat == null) {
89+
// New Material created
90+
m_pModel.m_pCurrentMaterial = Material(matName)
91+
m_pModel.m_MaterialLib.add(matName)
92+
m_pModel.m_MaterialMap.put(matName, m_pModel.m_pCurrentMaterial!!)
93+
}
94+
// Use older material
95+
else m_pModel.m_pCurrentMaterial = mat
96+
}
97+
}
98+
99+
// Material specific token map
100+
val tokenMap = mapOf(
101+
"map_Kd" to Material.Texture.Type.diffuse,
102+
"map_Ka" to Material.Texture.Type.ambient,
103+
"map_Ks" to Material.Texture.Type.specular,
104+
"map_d" to Material.Texture.Type.opacity,
105+
"map_emissive" to Material.Texture.Type.emissive, "map_Ke" to Material.Texture.Type.emissive,
106+
"map_bump" to Material.Texture.Type.bump, "map_Bump" to Material.Texture.Type.bump, "bump" to Material.Texture.Type.bump,
107+
"map_Kn" to Material.Texture.Type.normal,
108+
"disp" to Material.Texture.Type.disp,
109+
"map_ns" to Material.Texture.Type.specularity)
110+
111+
val reflMap = mapOf(
112+
"sphere" to Material.Texture.Type.reflectionSphere,
113+
"cube_top" to Material.Texture.Type.reflectionCubeTop,
114+
"cube_bottom" to Material.Texture.Type.reflectionCubeBottom,
115+
"cube_front" to Material.Texture.Type.reflectionCubeFront,
116+
"cube_back" to Material.Texture.Type.reflectionCubeBack,
117+
"cube_left" to Material.Texture.Type.reflectionCubeLeft,
118+
"cube_right" to Material.Texture.Type.reflectionCubeRight)
119+
120+
// texture option specific token
121+
const val ClampOption = "-clamp"
122+
const val TypeOption = "-Type"

0 commit comments

Comments
 (0)