• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Martomate / Hexacraft / 4212765122

pending completion
4212765122

push

github

Martin Jakobsson
Moved block specs from json files to code

51 of 51 new or added lines in 9 files covered. (100.0%)

1609 of 4743 relevant lines covered (33.92%)

0.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/scala/com/martomate/hexacraft/world/render/ChunkRenderer.scala
1
package com.martomate.hexacraft.world.render
2

3
import com.martomate.hexacraft.util.CylinderSize
4
import com.martomate.hexacraft.world.{BlocksInWorld, ChunkCache}
5
import com.martomate.hexacraft.world.block.Blocks
6
import com.martomate.hexacraft.world.chunk.{Chunk, EntitiesInChunk}
7
import com.martomate.hexacraft.world.chunk.storage.LocalBlockState
8
import com.martomate.hexacraft.world.coord.CoordUtils
9
import com.martomate.hexacraft.world.coord.fp.CylCoords
10
import com.martomate.hexacraft.world.coord.integer.{BlockRelWorld, ChunkRelWorld}
11

12
import java.nio.ByteBuffer
13
import java.util
14
import org.joml.{Matrix4f, Vector4f}
15
import org.lwjgl.BufferUtils
16
import scala.collection.mutable.ArrayBuffer
17

18
object ChunkRenderer:
×
19
  def getChunkRenderData(
20
      chunkCoords: ChunkRelWorld,
21
      blocks: Array[LocalBlockState],
22
      world: BlocksInWorld
23
  )(using CylinderSize)(using Blocks: Blocks): ChunkRenderData =
×
24
    val chunkCache = new ChunkCache(world)
25

×
26
    val sidesToRender = Array.tabulate[util.BitSet](8)(_ => new util.BitSet(16 * 16 * 16))
×
27
    val sideBrightness = Array.ofDim[Float](8, 16 * 16 * 16)
×
28
    val sidesCount = Array.ofDim[Int](8)
29

×
30
    for s <- 0 until 8 do
×
31
      val shouldRender = sidesToRender(s)
×
32
      val shouldRenderTop = sidesToRender(0)
×
33
      val brightness = sideBrightness(s)
×
34
      val otherSide = oppositeSide(s)
35

36
      var i1 = 0
×
37
      val i1Lim = blocks.length
38
      while i1 < i1Lim do
×
39
        val lbs = blocks(i1)
40
        val c = lbs.coords
41
        val b = lbs.block
42

×
43
        val c2w = c.globalNeighbor(s, chunkCoords)
×
44
        val c2 = c2w.getBlockRelChunk
×
45
        val crw = c2w.getChunkRelWorld
×
46
        val neigh = chunkCache.getChunk(crw)
47

48
        if neigh != null then
×
49
          val bs = neigh.getBlock(c2)
50

×
51
          if bs.blockType.isTransparent(bs.metadata, otherSide) then
×
52
            brightness(c.value) = neigh.lighting.getBrightness(c2)
×
53
            shouldRender.set(c.value)
×
54
            sidesCount(s) += 1
55

56
            // render the top side
×
57
            if s > 1 && b.blockType.isTransparent(b.metadata, s) then
×
58
              shouldRenderTop.set(c.value)
×
59
              sidesCount(0) += 1
60

61
        i1 += 1
62

×
63
    val buffers = for (side <- 0 until 8) yield
×
64
      val shouldRender = sidesToRender(side)
×
65
      val brightness = sideBrightness(side)
×
66
      val buf = BufferUtils.createByteBuffer(sidesCount(side) * ChunkRenderData.blockSideStride(side))
67

×
68
      populateBuffer(chunkCoords, blocks, side, shouldRender, brightness, buf)
×
69
      buf.flip()
70
      buf
71

72
    ChunkRenderData(buffers)
73

×
74
  private def populateBuffer(
75
      chunkCoords: ChunkRelWorld,
76
      blocks: Array[LocalBlockState],
77
      side: Int,
78
      shouldRender: java.util.BitSet,
79
      brightness: Array[Float],
80
      buf: ByteBuffer
81
  )(using Blocks: Blocks): Unit =
×
82
    val verticesPerInstance = if (side < 2) 7 else 4
83

84
    var i1 = 0
×
85
    val i1Lim = blocks.length
86
    while i1 < i1Lim do
×
87
      val lbs = blocks(i1)
88
      val bCoords = lbs.coords
89
      val block = lbs.block
90

×
91
      if shouldRender.get(bCoords.value) then
×
92
        val coords = BlockRelWorld.fromChunk(bCoords, chunkCoords)
×
93
        buf.putInt(coords.x)
×
94
        buf.putInt(coords.y)
×
95
        buf.putInt(coords.z)
96

97
        val blockType = block.blockType
×
98
        buf.putInt(Blocks.textures(blockType.name)(side))
×
99
        buf.putFloat(blockType.blockHeight(block.metadata))
100

101
        var i2 = 0
102
        while i2 < verticesPerInstance do
103
          // TODO: change in the future to make lighting smoother
×
104
          buf.putFloat(brightness(bCoords.value))
105
          i2 += 1
106

107
      i1 += 1
108

×
109
  def getEntityRenderData(entities: EntitiesInChunk, side: Int, world: BlocksInWorld)(using
110
      CylinderSize
111
  ): Iterable[EntityDataForShader] =
×
112
    val chunkCache = new ChunkCache(world)
113

×
114
    val tr = new Matrix4f
115

×
116
    for ent <- entities.allEntities yield
×
117
      val baseT = ent.transform
118
      val model = ent.model
119

×
120
      val parts = for part <- model.parts yield
×
121
        baseT.mul(part.transform, tr)
122

×
123
        val coords4 = tr.transform(new Vector4f(0, 0.5f, 0, 1))
×
124
        val blockCoords = CylCoords(coords4.x, coords4.y, coords4.z).toBlockCoords
×
125
        val coords = CoordUtils.getEnclosingBlock(blockCoords)._1
×
126
        val cCoords = coords.getChunkRelWorld
127

×
128
        val partChunk = chunkCache.getChunk(cCoords)
129

130
        val brightness: Float =
131
          if partChunk != null
×
132
          then partChunk.lighting.getBrightness(coords.getBlockRelChunk)
×
133
          else 0
134

135
        EntityPartDataForShader(
×
136
          modelMatrix = new Matrix4f(tr),
×
137
          texOffset = part.textureOffset(side),
×
138
          texSize = part.textureSize(side),
×
139
          blockTex = part.texture(side),
140
          brightness
141
        )
142

143
      EntityDataForShader(model, parts)
144

×
145
  private def oppositeSide(s: Int): Int =
×
146
    if s < 2 then 1 - s else (s - 2 + 3) % 3 + 2
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc