fix(lab_2): worked

All worked 2-nd lab
This commit is contained in:
Kirill 2025-05-04 16:26:52 +03:00
parent be5701e4de
commit f18d6f1025
6 changed files with 67 additions and 299 deletions

View File

@ -21,18 +21,33 @@ dependencies {
implementation("org.lwjgl:lwjgl")
implementation("org.lwjgl:lwjgl-glfw")
implementation("org.lwjgl:lwjgl-opengl")
implementation("org.lwjgl:lwjgl-stb")
implementation("org.lwjgl:lwjgl-nanovg")
implementation("org.lwjgl:lwjgl-nfd")
implementation("org.lwjgl:lwjgl-openal")
runtimeOnly("org.lwjgl:lwjgl::$lwjglNatives")
runtimeOnly("org.lwjgl:lwjgl-glfw::$lwjglNatives")
runtimeOnly("org.lwjgl:lwjgl-opengl::$lwjglNatives")
runtimeOnly("org.lwjgl:lwjgl-stb::$lwjglNatives")
runtimeOnly("org.lwjgl:lwjgl-nanovg::$lwjglNatives")
runtimeOnly("org.lwjgl:lwjgl-nfd::$lwjglNatives")
runtimeOnly("org.lwjgl:lwjgl-openal::$lwjglNatives")
// JavaFX bindings
implementation("org.openjfx:javafx-controls:17")
implementation("org.openjfx:javafx-fxml:17")
implementation("org.openjfx:javafx-graphics:17")
}
application {
mainClass.set("org.exampl.MainKt")
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(21)
}

View File

@ -7,9 +7,9 @@ import javax.swing.filechooser.FileNameExtensionFilter
class Form1 {
private var loaded = false
private var currentLayer = 0
var currentLayer = 0
private val bin = Bin()
private val view = View()
val view = View()
private var minTF = -3000
private var widthTF = 2000
@ -42,11 +42,14 @@ class Form1 {
openFileDialog()
while (!glfwWindowShouldClose(window)) {
displayFPS()
glfwPollEvents()
if (loaded) {
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
view.drawQuads(currentLayer)
}
glfwSwapBuffers(window)
glfwPollEvents()
}
}
}

View File

@ -1,222 +1,8 @@
package org.exampl
/*import org.lwjgl.opengl.GL
import org.lwjgl.opengl.GL11.*
import org.lwjgl.opengl.GL15.*
import org.lwjgl.opengl.GL20.*
import org.lwjgl.opengl.GL30.*
import org.lwjgl.system.MemoryUtil
import org.lwjgl.glfw.GLFW.*
import java.io.File
import java.nio.ByteBuffer
import java.nio.ByteOrder
import kotlin.math.*
class CTVisualizer {
private var window: Long = 0
private var vao = 0
private var vbo = 0
private var textureID = 0
private var shaderProgram = 0
private var currentLayer = 0
private var minValue = 0
private var maxValue = 40961
private var windowWidth = 1600
private var windowHeight = 1000
private lateinit var volumeData: ShortArray
private var width = 256 // Фиксированный размер для примера
private var height = 256
private var depth = 256
fun run(binFilePath: String) {
initWindow()
initOpenGL()
loadVolumeData(binFilePath)
mainLoop()
cleanup()
}
private fun initWindow() {
if (!glfwInit()) {
throw RuntimeException("Failed to initialize GLFW")
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE)
window = glfwCreateWindow(windowWidth, windowHeight, "КТ Визуализация (OpenTK/Kotlin)", 0, 0)
if (window == 0L) {
glfwTerminate()
throw RuntimeException("Failed to create GLFW window")
}
glfwMakeContextCurrent(window)
glfwSwapInterval(1)
glfwShowWindow(window)
}
private fun initOpenGL() {
GL.createCapabilities()
val vertexShader = """
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 texCoord;
out vec2 TexCoord;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
TexCoord = texCoord;
}
""".trimIndent()
val fragmentShader = """
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D ourTexture;
void main() {
FragColor = texture(ourTexture, TexCoord);
}
""".trimIndent()
shaderProgram = createShaderProgram(vertexShader, fragmentShader)
vao = glGenVertexArrays()
vbo = glGenBuffers()
glBindVertexArray(vao)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
val vertices = floatArrayOf(
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
)
val vertexBuffer = MemoryUtil.memAllocFloat(vertices.size)
vertexBuffer.put(vertices).flip()
glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW)
glVertexAttribPointer(0, 2, GL_FLOAT, false, 4 * 4, 0)
glVertexAttribPointer(1, 2, GL_FLOAT, false, 4 * 4, 2 * 4)
glEnableVertexAttribArray(0)
glEnableVertexAttribArray(1)
MemoryUtil.memFree(vertexBuffer)
textureID = glGenTextures()
glBindTexture(GL_TEXTURE_2D, textureID)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
}
private fun loadVolumeData(binFilePath: String) {
val file = File(binFilePath)
if (!file.exists()) {
throw IllegalArgumentException("File $binFilePath not found")
}
val buffer = ByteBuffer.wrap(file.readBytes())
.order(ByteOrder.LITTLE_ENDIAN)
.asShortBuffer()
volumeData = ShortArray(width * height * depth)
buffer.get(volumeData)
// Автоматическое определение min/max значений
minValue = volumeData.minOrNull()?.toInt() ?: 0
maxValue = volumeData.maxOrNull()?.toInt() ?: 4096
println("Loaded volume data: ${volumeData.size} voxels")
println("Value range: $minValue - $maxValue")
}
private fun updateTexture(layer: Int) {
val layerData = ByteBuffer.allocateDirect(width * height * 4)
for (y in 0 until height) {
for (x in 0 until width) {
val value = volumeData[x + y * width + layer * width * height].toInt()
val normalized = ((value - minValue).toFloat() / (maxValue - minValue).toFloat()).coerceIn(0f, 1f)
val color = (normalized * 255).toInt()
layerData.put(color.toByte())
layerData.put(color.toByte())
layerData.put(color.toByte())
layerData.put(255.toByte()) // Alpha
}
}
layerData.flip()
glBindTexture(GL_TEXTURE_2D, textureID)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, layerData)
}
private fun mainLoop() {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f)
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT)
updateTexture(currentLayer)
glUseProgram(shaderProgram)
glBindVertexArray(vao)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
glfwSwapBuffers(window)
glfwPollEvents()
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
currentLayer = min(currentLayer + 1, depth - 1)
}
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
currentLayer = max(currentLayer - 1, 0)
}
}
}
private fun createShaderProgram(vertexShaderSource: String, fragmentShaderSource: String): Int {
val vertexShader = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(vertexShader, vertexShaderSource)
glCompileShader(vertexShader)
val fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(fragmentShader, fragmentShaderSource)
glCompileShader(fragmentShader)
val program = glCreateProgram()
glAttachShader(program, vertexShader)
glAttachShader(program, fragmentShader)
glLinkProgram(program)
glDeleteShader(vertexShader)
glDeleteShader(fragmentShader)
return program
}
private fun cleanup() {
glDeleteVertexArrays(vao)
glDeleteBuffers(vbo)
glDeleteTextures(textureID)
glDeleteProgram(shaderProgram)
glfwTerminate()
}
}
fun main() {
// Укажите путь к вашему .bin файлу
val binFilePath = "./testdata.bin"
CTVisualizer().run(binFilePath)
}*/
import org.lwjgl.glfw.GLFW.*
import org.lwjgl.opengl.GL
import org.lwjgl.opengl.GL11.glViewport
import org.lwjgl.opengl.GL11.*
import org.lwjgl.system.MemoryUtil.NULL
import kotlin.system.exitProcess
@ -238,21 +24,35 @@ fun main() {
glViewport(0, 0, width, height)
}
val form1 = Form1()
glfwSetKeyCallback(window) { _: Long, key: Int, _: Int, action: Int, _: Int ->
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
when (key) {
GLFW_KEY_LEFT -> {
if (form1.currentLayer > 0) {
form1.currentLayer--
form1.view.needReload = true
}
}
GLFW_KEY_RIGHT -> {
if (form1.currentLayer < Bin.Z - 1) {
form1.currentLayer++
form1.view.needReload = true
}
}
}
}
}
glfwMakeContextCurrent(window)
glfwSwapInterval(1)
glfwShowWindow(window)
GL.createCapabilities()
val form1 = Form1()
form1.run(window)
glfwTerminate()
exitProcess(0)
}

View File

@ -6,6 +6,8 @@ import java.awt.image.BufferedImage
import java.nio.ByteBuffer
class View {
var needReload = false
fun setupView(width: Int, height: Int) {
glShadeModel(GL_SMOOTH)
glMatrixMode(GL_PROJECTION)
@ -15,79 +17,12 @@ class View {
}
fun drawQuads(layerNumber: Int) {
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glBegin(GL_QUADS)
for (x in 0 until Bin.X - 1) {
for (y in 0 until Bin.Y - 1) {
val value1 = Bin.array[x + y * Bin.X + layerNumber * Bin.X * Bin.Y]
val value2 = Bin.array[x + (y + 1) * Bin.X + layerNumber * Bin.X * Bin.Y]
val value3 = Bin.array[x + 1 + (y + 1) * Bin.X + layerNumber * Bin.X * Bin.Y]
val value4 = Bin.array[x + 1 + y * Bin.X + layerNumber * Bin.X * Bin.Y]
val color1 = TransferHelper.transferFunction(value1)
val color2 = TransferHelper.transferFunction(value2)
val color3 = TransferHelper.transferFunction(value3)
val color4 = TransferHelper.transferFunction(value4)
glColor3f(color1.red / 255.0f, color1.green / 255.0f, color1.blue / 255.0f)
glVertex2f(x.toFloat(), y.toFloat())
glColor3f(color2.red / 255.0f, color2.green / 255.0f, color2.blue / 255.0f)
glVertex2f(x.toFloat(), (y + 1).toFloat())
glColor3f(color3.red / 255.0f, color3.green / 255.0f, color3.blue / 255.0f)
glVertex2f((x + 1).toFloat(), (y + 1).toFloat())
glColor3f(color4.red / 255.0f, color4.green / 255.0f, color4.blue / 255.0f)
glVertex2f((x + 1).toFloat(), y.toFloat())
}
if (needReload) {
generateTextureImage(layerNumber)
load2DTexture()
needReload = false
}
glEnd()
}
fun drawQuadStrip(layerNumber: Int) {
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
for (x in 0 until Bin.X - 1) {
glBegin(GL_QUAD_STRIP)
for (y in 0 until Bin.Y) {
val value1 = Bin.array[x + y * Bin.X + layerNumber * Bin.X * Bin.Y]
val value2 = Bin.array[x + 1 + y * Bin.X + layerNumber * Bin.X * Bin.Y]
val color1 = TransferHelper.transferFunction(value1)
val color2 = TransferHelper.transferFunction(value2)
glColor3f(color1.red / 255.0f, color1.green / 255.0f, color1.blue / 255.0f)
glVertex2f(x.toFloat(), y.toFloat())
glColor3f(color2.red / 255.0f, color2.green / 255.0f, color2.blue / 255.0f)
glVertex2f((x + 1).toFloat(), y.toFloat())
}
glEnd()
}
}
private lateinit var textureImage: BufferedImage
private var textureID: Int = 0
fun generateTextureImage(layerNumber: Int) {
textureImage = BufferedImage(Bin.X, Bin.Y, BufferedImage.TYPE_INT_ARGB)
for (x in 0 until Bin.X) {
for (y in 0 until Bin.Y) {
val pixelNumber = x + y * Bin.X + layerNumber * Bin.X * Bin.Y
val color = TransferHelper.transferFunction(Bin.array[pixelNumber])
textureImage.setRGB(x, y, color.rgb)
}
}
}
fun drawTexture() {
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, textureID)
@ -112,6 +47,21 @@ class View {
glDisable(GL_TEXTURE_2D)
}
private lateinit var textureImage: BufferedImage
private var textureID: Int = 0
fun generateTextureImage(layerNumber: Int) {
textureImage = BufferedImage(Bin.X, Bin.Y, BufferedImage.TYPE_INT_ARGB)
for (x in 0 until Bin.X) {
for (y in 0 until Bin.Y) {
val pixelNumber = x + y * Bin.X + layerNumber * Bin.X * Bin.Y
val color = TransferHelper.transferFunction(Bin.array[pixelNumber])
textureImage.setRGB(x, y, color.rgb)
}
}
}
fun load2DTexture() {
textureID = glGenTextures()
glBindTexture(GL_TEXTURE_2D, textureID)