func NewOctreeNode(vol *TVolume, parent *TOctree, root *TOctree, brickSize, nodeX, nodeY, nodeZ, rootX, rootY, rootZ int) *TOctree { var me = &TOctree{} var boxSize float64 var allSolid = true var lastColor gfx.TColor var i = 0 me.NodeX, me.NodeY, me.NodeZ, me.RootX, me.RootY, me.RootZ = nodeX, nodeY, nodeZ, rootX, rootY, rootZ if parent == nil { root, boxSize, me.Box, me.Total, me.Level, me.MaxLevel = me, vol.Box.Extent, vol.Box, 1, 0, 0 } else { me.Level = parent.Level + 1 boxSize = parent.Box.Extent * 0.5 me.Box = gfx.NewBox(gfx.NilColor, num.Vec3{parent.Box.Pos.X + (boxSize * float64(nodeX)), parent.Box.Pos.Y + (boxSize * float64(nodeY)), parent.Box.Pos.Z + (boxSize * float64(nodeZ))}, num.Vec3{boxSize, boxSize, boxSize}, 0) } if boxSize > float64(brickSize) { me.ChildNodes = make([]*TOctree, 8) root.Total += 8 for x := 0; x < 2; x++ { for y := 0; y < 2; y++ { for z := 0; z < 2; z++ { me.ChildNodes[i] = NewOctreeNode(vol, me, root, brickSize, x, y, z, rootX+(int(boxSize/2)*x), rootY+(int(boxSize/2)*y), rootZ+(int(boxSize/2)*z)) i++ } } } lastColor = me.ChildNodes[0].Col for _, cn := range me.ChildNodes { if (cn.Brick != nil) || !cn.Col.Equals(&lastColor) { allSolid = false } } if allSolid { me.ChildNodes = nil root.TotalSolids++ me.Brick, me.Col = nil, lastColor } else { root.TotalBricks++ me.Brick, me.Col = vol.MakeBrick(brickSize, rootX, rootY, rootZ, int(boxSize)) } } else { root.MaxLevel = me.Level if me.Brick, me.Col = vol.SubVolume(me.Box, rootX, rootY, rootZ, int(boxSize)); me.Brick == nil { root.TotalSolids++ } else { root.TotalBricks++ } } return me }
func NewVolume(filePath string, volSize int) *TVolume { var fsize = float64(volSize) var normVec num.Vec3 var x, y, z int var prev, next uint8 var max = volSize - 1 var raw = LoadVolumeRaw(filePath, volSize) var invSize, inv256 = 1 / float64(volSize), 1.0 / 256.0 var me = &TVolume{} me.InvScale, me.Scale = 1, 1 me.Box = gfx.NewBox(gfx.NilColor, num.Vec3{0, 0, 0}, num.Vec3{fsize, fsize, fsize}, 0) me.Col, me.Normals, me.Size = make([][][]gfx.TColor, volSize), make([][][]num.Vec3, volSize), volSize for x = 0; x < volSize; x++ { me.Col[x], me.Normals[x] = make([][]gfx.TColor, volSize), make([][]num.Vec3, volSize) for y = 0; y < volSize; y++ { // log.Printf("ALLOC %v,%v...", x, y) me.Col[x][y], me.Normals[x][y] = make([]gfx.TColor, volSize), make([]num.Vec3, volSize) } } for x = 0; x < volSize; x++ { for y = 0; y < volSize; y++ { for z = 0; z < volSize; z++ { if raw[x][y][z] > 0 { me.Col[x][y][z].R = float64(x) * invSize me.Col[x][y][z].G = float64(y) * invSize me.Col[x][y][z].B = float64(z) * invSize me.Col[x][y][z].A = float64(raw[x][y][z]) * inv256 // float64(raw[x][y][z].A) / 256 if x > 0 { prev = raw[x-1][y][z] } else { prev = 0 } if x < max { next = raw[x+1][y][z] } else { next = 0 } normVec.X = (float64(next) * inv256) - (float64(prev) * inv256) if y > 0 { prev = raw[x][y-1][z] } else { prev = 0 } if y < max { next = raw[x][y+1][z] } else { next = 0 } normVec.Y = (float64(next) * inv256) - (float64(prev) * inv256) if z > 0 { prev = raw[x][y][z-1] } else { prev = 0 } if z < max { next = raw[x][y][z+1] } else { next = 0 } normVec.Z = (float64(next) * inv256) - (float64(prev) * inv256) normVec.Normalize() me.Normals[x][y][z] = normVec } } } } return me }
func Reinit(w, h int, target *image.RGBA) { var rt *TThread width, height = w, h Width, Height = float64(w), float64(h) WidthHeightRatio = Width / Height planeHeight = planeWidth / WidthHeightRatio planeHeightHalf = planeHeight / 2 planeStepX, planeStepY = 1/Width, 1/Height planeStepWidth, planeStepHeight = planeStepX*planeWidth, planeStepY*planeHeight renderTarget, HeightWidthRatio, tileWidth, tileHeight = target, Height/Width, int(math.Ceil(Width/float64(NumThreads))), int(math.Ceil(Height/float64(NumThreads))) if Scene == nil { log.Printf("Loading scene...") RootOctree = voxels.NewOctree(voxels.NewVolume("/ssd2/ScanModels/dragon512.raw", volSize), 8) RootOctree.Print(0) MaxSteps = int(VolSize * 1.5) Scene = NewScene() Scene.CamPos.X, Scene.CamPos.Y, Scene.CamPos.Z = 21, 39, 35 // VolSize / 2, VolSize / 2, -(VolSize * 2) Scene.ColAmbient = gfx.TColor{0.66, 0.66, 0.66, 1} Scene.Fog = true Scene.Objects = []*gfx.TObject{ gfx.NewSphere(gfx.TColor{0.33, 0.5, 0.33, 1}, num.Vec3{0, -8198, 0}, 8192, 0.33), gfx.NewSphere(gfx.TColor{0.66, 0.66, 0, 1}, num.Vec3{-8, 0, 0}, 2, 0.25), gfx.NewSphere(gfx.TColor{0, 0, 0.66, 1}, num.Vec3{2.5, -5, 0}, 1.5, 0.75), gfx.NewSphere(gfx.TColor{0.44, 0.22, 0, 1}, num.Vec3{0, 0, 16}, 2.5, 1), gfx.NewSphere(gfx.TColor{0, 0, 0.33, 1}, num.Vec3{0, 0, -18}, 2, 0.75), gfx.NewSphere(gfx.TColor{0.33, 0, 0, 1}, num.Vec3{2.5, 5, 0}, 1.5, 0.25), gfx.NewBox(gfx.TColor{0.44, 0.22, 0, 1}, num.Vec3{0, 0, 0}, num.Vec3{4, 4, 4}, 0.5), gfx.NewBox(gfx.TColor{0.05, 0.05, 0.05, 1}, num.Vec3{-256, -4, 4}, num.Vec3{512, 1, 8}, 0.5), } Scene.Lights = []*gfx.TLight{ gfx.NewLight(num.Vec3{-200, 200, 200}, num.Vec3{20.1, 20.1, 20.1}, gfx.TColor{0.8, 0.8, 0.8, 1}, 256), // NewLight(num.Vec3 { 20, 20, 20 }, num.Vec3 { 0.4, 0.4, 0.4 }, gfx.TColor { 0.6, 0.6, 0.6, 1 }, 20), // NewLight(num.Vec3 { 10, 30, -10 }, num.Vec3 { 0.7, 0.7, 0.7 }, gfx.TColor { 0.4, 0.4, 0.4, 1 }, 20), gfx.NewLight(num.Vec3{600, 600, -600}, num.Vec3{81, 81, 81}, gfx.TColor{0.9, 0.9, 0.9, 1}, 512), } Scene.UpdateCamRot() threads = make([]*TThread, NumThreads*NumThreads) for t := 0; t < len(threads); t++ { rt = &TThread{} rt.picker = gfx.NewPicker(Scene.Objects, Scene.Range) rt.cols, rt.srpd, rt.srpr, rt.srd, rt.srld = make([]gfx.TColor, maxRec+2), make([]float64, maxRec+2), make([]float64, maxRec+2), make([]float64, maxRec+2), make([]float64, maxRec+2) rt.srays, rt.prays, rt.lrays = make([]*gfx.TRay, maxRec+2), make([]*gfx.TRay, maxRec+2), make([]*gfx.TRay, maxRec+2) rt.fcols = make([]gfx.TColor, 8) rt.fweights = make([]float64, 8) rt.voxelFilter = voxels.NewVoxelFilter(nil) rt.voxelFilter.SubVolSize = 8 rt.numIndices, rt.numIndices2 = 8, 8 rt.nodeIndices, rt.nodeIndices2 = make([]int, rt.numIndices), make([]int, rt.numIndices) for i := 0; i < rt.numIndices; i++ { rt.nodeIndices[i], rt.nodeIndices2[i] = i, i } if RootOctree != nil { rt.snrMaxLevel = float64(RootOctree.MaxLevel) rt.traverser = voxels.NewOctreeTraverser(RootOctree, Scene.Lights) } for i := 0; i < len(rt.srays); i++ { rt.prays[i], rt.srays[i], rt.lrays[i] = &gfx.TRay{}, &gfx.TRay{}, &gfx.TRay{} } threads[t] = rt } } Scene.FieldOfView = 33.75 * math.Min(2, WidthHeightRatio) // math.Max(1, WidthHeightRatio)) sceneZoom = 1 / math.Tan(num.DegToRad(Scene.FieldOfView)*0.5) planePosZ = planeWidthHalf * sceneZoom planeRange = planeWidth * Scene.Range runtime.GC() }