- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已经在这个问题上工作了很长时间,并被这个错误所困扰。
我们在 F# 中为学校项目构建了一个光线追踪器。 (解释光线追踪器的链接:https://blog.frogslayer.com/kd-trees-for-faster-ray-tracing-with-triangles/)
我们为三角形、边界框、处理具有数千个三角形的图形的 KD 树(例如斯坦福兔子和 KD 树的遍历算法)制作了命中函数。
我们已经调试了 KD 树的创建,确保为浮点添加一个 epsilon 值,并检查边界框之间的重复项没有被删除。我们确信我们正确地分割了场景中的形状列表,但是我们在尝试渲染的图形中得到了“洞”。
这是我们的 KD 树实现,我附上了孔的图片:
Stanford Bunny
Helix
module TmKdtree
open Point
open Shapes
type BoundingBox = BasicShape.BoundingBox
type Shape = BasicShape.Shape
type TmKdtree =
| Leaf of BasicShape.Triangle list * BoundingBox
| Node of BasicShape.Triangle list * TmKdtree * TmKdtree * BoundingBox * (string*Point)
let epsilon = 0.001
//Making a boundingbox for the KD-tree, by finding max H point in the boundingboxlist and min l point in the boundingbox list.
let mkKdBbox (shapes : BasicShape.Triangle list) : BoundingBox =
let shapeX = List.map(fun x -> x:> Shape) shapes
let sbbox = List.map (fun (c:Shape) -> c.getBounding().Value) shapeX
let bL = List.map (fun (b:BasicShape.BoundingBox) -> b.getL) sbbox
let bH = List.map (fun (b:BasicShape.BoundingBox) -> b.getH) sbbox
let minX = List.minBy (fun x -> Point.getX x) bL
let minY = List.minBy (fun x -> Point.getY x) bL
let minZ = List.minBy (fun x -> Point.getZ x) bL
let maxX = List.maxBy (fun x -> Point.getX x) bH
let maxY = List.maxBy (fun x -> Point.getY x) bH
let maxZ = List.maxBy (fun x -> Point.getZ x) bH
{p1=(mkPoint (Point.getX minX - epsilon) (Point.getY minY - epsilon) (Point.getZ minZ - epsilon) )
; p2=(mkPoint (Point.getX maxX + epsilon) (Point.getY maxY + epsilon) (Point.getZ maxZ + epsilon) )}
//Splitting existing boundingbox according to left and right list of shapes
let BoundingBoxL (bbox:BoundingBox) axis midp : BoundingBox =
match axis with
| "x" -> {p1 = bbox.getL - epsilon; p2 = Point.mkPoint ((Point.getX midp)) ((Point.getY (bbox.getH))) ((Point.getZ (bbox.getH))) + epsilon}
| "y" -> {p1 = bbox.getL - epsilon; p2 = Point.mkPoint (Point.getX (bbox.getH)) ((Point.getY midp)+epsilon) ((Point.getZ (bbox.getH))) + epsilon }
| "z" -> {p1 = bbox.getL - epsilon; p2 = Point.mkPoint (Point.getX (bbox.getH)) (Point.getY (bbox.getH)) (Point.getZ midp) + epsilon}
let BoundingBoxR (bbox:BoundingBox) axis midp : BoundingBox =
match axis with
| "x" -> {p1 = (Point.mkPoint (Point.getX midp) (Point.getY (bbox.getL)) (Point.getZ (bbox.getL))) - epsilon; p2 = bbox.getH + epsilon}
| "y" -> {p1 = (Point.mkPoint (Point.getX (bbox.getL)) (Point.getY midp) (Point.getZ (bbox.getL))) - epsilon; p2 = bbox.getH + epsilon}
| "z" -> {p1 = (Point.mkPoint (Point.getX (bbox.getL)) (Point.getY (bbox.getL)) (Point.getZ midp)) - epsilon; p2 = bbox.getH + epsilon}
//Get left node
let getLeft s =
match s with
| Node(_,l,_,_,_) -> l
| Leaf(_,_) as leaf -> leaf
let getRight s =
match s with
| Node(_,_,r,_,_) -> r
| Leaf(_,_) as leaf -> leaf
//Get the triangle list
let getShapes s =
match s with
| Node(b,_,_,_,_) -> b
| Leaf(b,_) -> b
let getAxis s =
match s with
| Node(_,_,_,_,a) -> a
| Leaf(_,_) -> failwith "leaf ramt af axis"
//Get bounding box
let getBox s =
match s with
| Node(_,_,_,b,_) -> Some b
| Leaf(_,b) -> Some b
let closestHit (triList : BasicShape.Triangle list) ray =
let sndRects = List.map(fun x -> x:> Shape) triList
let min = List.map(fun (x:Shape) -> x.hit ray) sndRects |> List.choose id
match min with
|[] -> None
|_ -> Some(List.minBy (fun (di, nV, mat) -> di) min)
let searchLeaf leaf ray t' =
match leaf with
| Leaf(s,_) -> let hit = closestHit s ray
match hit with
|Some(f,_,_) -> if (f<t') then Some hit else None
|None -> None
| Node(_,_,_,_,_) -> failwith "Expected leaf"
let order(d, left, right) =
if d > 0.0
then (left, right)
else (right, left)
let rec search node ray t t' =
match node with
|Leaf(_,_) -> searchLeaf node ray t'
|Node(_,_,_,_,a') ->
let direction = Ray.getDirection ray (fst a')
let origin = Ray.getOrigin ray (fst a')
let nodeValue = Point.getFromAxis (snd a') (fst a')
if(direction) = 0.0 then
printfn("%s") "flatsite"
if(origin <= nodeValue) then search (getLeft node) ray t t'
else search (getRight node) ray t t'
else
let tHit = (nodeValue - origin) / direction
let (fst, snd) = order(direction,getLeft node, getRight node)
if tHit <= t || tHit < 0.0 then
search snd ray t t'
else if tHit >= t' then
search fst ray t t'
else
match search fst ray t tHit with
|Some hit -> Some hit
|_ -> search snd ray tHit t'
let traverse tree ray (bawx:BasicShape.BoundingBox) =
match(bawx).hit(ray) with
|Some(t,t') -> search tree ray t t'
|None -> None
//Finding the midpoint in the triangles in Shapes-list - we do this (recursively) to find out what axis to split
let rec mkTmKdtree (shapes : BasicShape.Triangle list) (box:BasicShape.BoundingBox) =
//Finding biggest dimension in the shapes list
let axis = snd (box.getLongestAxis)
let axisMidPoint =
let midPoint = List.fold (fun acc (ele:BasicShape.Triangle) -> (acc + ele.getMidPoint())) (Point.mkPoint 0.0 0.0 0.0) shapes
let avgMid = midPoint / float(shapes.Length)
avgMid
let rec largerThanSplit (xs:BasicShape.Triangle list) =
let results = List.choose(fun (elem:BasicShape.Triangle) ->
match axis with
|"x" -> if (Point.getX (elem.getMidPoint())) >= (Point.getX axisMidPoint) then Some elem else None
|"y" -> if (Point.getY (elem.getMidPoint())) >= (Point.getY axisMidPoint) then Some elem else None
|"z" -> if (Point.getZ (elem.getMidPoint())) >= (Point.getZ axisMidPoint) then Some elem else None) xs
results
let rec lessThanSplit (xs:BasicShape.Triangle list) =
let results = List.choose(fun (elem:BasicShape.Triangle) ->
match axis with
|"x" -> if ((Point.getX (elem.getMidPoint())) <= (Point.getX (axisMidPoint))) then Some elem else None
|"y" -> if ((Point.getY (elem.getMidPoint())) <= (Point.getY (axisMidPoint))) then Some elem else None
|"z" -> if ((Point.getZ (elem.getMidPoint())) <= (Point.getZ (axisMidPoint))) then Some elem else None) xs
results
//Creating the left and right list from the above
let rightTest = largerThanSplit shapes
let leftTest = lessThanSplit shapes
//If one of the trees are empty, we add make left and right equivelant.
let left = if(leftTest.IsEmpty && rightTest.Length > 0) then rightTest else leftTest
let right = if(rightTest.IsEmpty && leftTest.Length > 0) then leftTest else rightTest
//Check for duplicates among the lists.
if(((float(left.Length+right.Length-shapes.Length)/float(shapes.Length)) < 0.4) && left.Length <> shapes.Length && right.Length<>shapes.Length) then
let leftTree = mkTmKdtree left (BoundingBoxL box axis axisMidPoint)
let rightTree = mkTmKdtree right (BoundingBoxR box axis axisMidPoint)
Node(shapes,leftTree, rightTree, (box),(axis,axisMidPoint))
else Leaf(shapes, (box))
最佳答案
感谢您的回复!结果我发现这个bug出在我们对数字的反射(reflect)中,与程序的数据结构无关。
不过还是谢谢你! :-)
关于f# - 光线追踪 F# - 缺少三角形会在图 : Hit properly? 中产生孔洞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37377012/
我有以下代码: interface F { (): string; a(): number; } function f() { return '3'; } f['a'] = f
比如我有一个 vector vector > v={{true,1},{true,2},{false,3},{false,4},{false,5},{true,6},{false,7},{true,8
我需要编写一个要在 GHCi 上运行的模块,并将函数组合为相同的函数。这个(经典的fog(x) = f(g(x)))运行: (.) f g = (\x -> f (g x)). 当我尝试这样写时出现问
动态规划这里有一个问题 大写字母AZ对应于整数[-13,12],因此一个字符串对应于一整列。我们将对应的整列的总和称为字符串的特征值。例如:字符串ACM对应的总体列为{-13,-11,-1},则ACM
我想知道为什么 F-Sharp 不支持无穷大。 这适用于 Ruby(但不适用于 f#): let numbers n = [1 .. 1/0] |> Seq.take(n) -> System.Div
如何从已编译的 F# 程序中的字符串执行 F# 代码? 最佳答案 这是一个小脚本,它使用 FSharp CodeDom 将字符串编译为程序集,并将其动态加载到脚本 session 中。 它使用类型扩展
有什么方法可以在 F# List 和 F# Tuple 之间转换? 例如: [1;2;3] -> (1,2,3) (1,2,3,4) -> [1;2;3;4] 我需要两个函数来做到这一点: le
我想将一个或多个 .fsx 文件加载到 F# 交互中,并将 .fsx 文件中定义的所有函数都包含在作用域中,以便我可以直接使用控制台中的功能。 #load 指令执行指定的 .fsx 文件,但随后我无法
我正在尝试像 this page 中那样编写 F 代数.不同之处在于,不是用元组组合,而是像这样: type FAlgebra[F[_], A] = F[A] => A def algebraZip[
给定一个 F# 记录: type R = { X : string ; Y : string } 和两个对象: let a = { X = null ; Y = "##" } let b = {
所以我们有一组文件名\url,如file、folder/file、folder/file2、folder/file3、folder/folder2/fileN等。我们得到一个字符串,如文件夹/。我们想
假设我有一个字符串“COLIN”。 这个字符串的数值是: 3 + 15 + 12 + 9 + 14 = 53. 所以 A = 1, B = 2, C = 3, and so on. 为此,我什至不知道
在 C# 中,我有以下代码来创建一个对象实例。 var myObject = new MyClass("paramvalue") { Property1 = "value1" Proper
即,标准库中有这样的函数吗? let ret x _ = x 为了保持代码可读性,我想尽量减少自制基本构建功能构建块的数量,并使用现有的东西。 最佳答案 不。你可能想看看 FSharpX。 关于f#
目前,我有一个函数可以将列表中每个列表的第一个元素( float )返回到单独的列表。 let firstElements list = match list with | head:
我刚刚解决了problem23在 Project Euler 中,我需要一个 set 来存储所有丰富的数字。 F# 有一个不可变集合,我可以使用 Set.empty.Add(i) 创建一个包含数字 i
F#语言具有计算自然对数的函数log和计算以10为底的对数的log10。 在F#中以2为底的对数的最佳计算方法是什么? 最佳答案 您可以简单地使用以下事实:“ b的a对数” = ln(b)/ ln(a
动机 我有一个长时间运行的 bool 函数,它应该在数组中执行,如果数组中的元素满足条件,我想立即返回。我想并行搜索并在第一个完整线程返回正确答案时终止其他线程。 问题 在 F# 中实现并行存在函数的
我最近完成了一个生成字符串列表的项目,我想知道执行此操作的最佳方法。 字符串生成是上下文敏感的,以确定它是否可以接受(这是游戏中的一系列游戏,所以你必须知道最后一次游戏是什么) 我这样做的方法是使用一
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是一名优秀的程序员,十分优秀!