// get/update camera from values in node GvBool GvViewpoint::getCamera(GCamera &camera, BBox &bbox, float visibilityLimitNear,float visibilityLimit, Matrix *cameraTransform) { Matrix m; float viewAngle = 0.785398; float aspectRatio = 1.0f; orientation.get(m); camera.position=position; viewAngle = (float) fieldOfView; Point dir(0,0,-1.0); Point up(0,1.0,0); // apply orientation to standard dir and up vectors dir *= m; up *= m; up.Normalize(); if (cameraTransform) { camera.position *= *cameraTransform; dir = RotateOnly(*cameraTransform,dir); up = RotateOnly(*cameraTransform,up); // near far focalDistance ?????????? } dir.Normalize(); up.Normalize(); Point size = bbox.Size(); // computed bounding box float field = max(max(fabs(size.x),fabs(size.y)),fabs(size.z)); int positionInBox = bbox.Inside(camera.position); if (bbox.IsEmpty() || (field<=1E-20f)) field = 2.0f; // no bounding box yet, bad // compute distance to target point //xx float targetDistance = field*2.0f; float targetDistance = field*1.0f; // viewpoint inside scene if (positionInBox) targetDistance = 0.2 * field; camera.targetDistanceIsDefault=1; camera.zrangeIsDefault=1; // compute a reasonable z-range if (visibilityLimit >0.0f) { camera.zfar = visibilityLimit; camera.zrangeIsDefault=0; } else { if (positionInBox) camera.zfar = field*1.5; else camera.zfar = field*3.0f; Point center = bbox.Center(); Point d = camera.position - center; float dist = d.Length(); // make shure object is visible from viewpoint if ((dist+field) > camera.zfar) camera.zfar = dist + field; } if (visibilityLimitNear > 0.0f) camera.znear = visibilityLimitNear; else camera.znear = camera.zfar * camera.znearFactor; // compute target camera.target = camera.position + targetDistance*dir; camera.up = up; // field of view camera.height = 2.0 * tan(viewAngle * 0.5)*targetDistance; camera.width = camera.height * aspectRatio; if (!bbox.IsEmpty()) camera.SetWorldReference(bbox); camera.ComputeWorldUpFromUp(); camera.OnChanged(); return gtrue; }
void DBVH::FindSplit(int nNode, int first, int count, int sdepth) { BBox bbox = nodes[nNode].bbox; if(count <= 1) { LEAF_NODE: depth = Max(depth, sdepth); nodes[nNode].first = first | 0x80000000; nodes[nNode].count = count; } else { int minAxis = MaxAxis(bbox.Size()); const float traverseCost = 0.0; const float intersectCost = 1.0; struct Bin { Bin() :count(0) { box.min = Vec3f(constant::inf, constant::inf, constant::inf); box.max = Vec3f(-constant::inf, -constant::inf, -constant::inf); } BBox box; int count; }; int nBins = count < 8? 8 : 16; Bin bins[nBins]; float mul = nBins * (1.0f - constant::epsilon) / ((&bbox.max.x)[minAxis] - (&bbox.min.x)[minAxis]); float sub = (&bbox.min.x)[minAxis]; for(int n = 0; n < count; n++) { const BBox &box = elements[first + n].GetBBox(); float c = ((&box.max.x)[minAxis] + (&box.min.x)[minAxis]) * 0.5f; int nBin = int( (c - sub) * mul ); bins[nBin].count++; bins[nBin].box += box; } BBox leftBoxes[nBins], rightBoxes[nBins]; int leftCounts[nBins], rightCounts[nBins]; rightBoxes[nBins - 1] = bins[nBins - 1].box; rightCounts[nBins - 1] = bins[nBins - 1].count; leftBoxes[0] = bins[0].box; leftCounts[0] = bins[0].count; for(size_t n = 1; n < nBins; n++) { leftBoxes[n] = leftBoxes[n - 1] + bins[n].box; leftCounts[n] = leftCounts[n - 1] + bins[n].count; } for(int n = nBins - 2; n >= 0; n--) { rightBoxes[n] = rightBoxes[n + 1] + bins[n].box; rightCounts[n] = rightCounts[n + 1] + bins[n].count; } float minCost = constant::inf; float noSplitCost = intersectCost * count * BoxSA(bbox); int minIdx = 1; for(size_t n = 1; n < nBins; n++) { float cost = (leftCounts[n - 1]? BoxSA(leftBoxes[n - 1]) * leftCounts[n - 1] : 0) + (rightCounts[n]? BoxSA(rightBoxes[n]) * rightCounts[n] : 0); if(cost < minCost) { minCost = cost; minIdx = n; } } minCost = traverseCost + intersectCost * minCost; if(noSplitCost < minCost) goto LEAF_NODE; ObjectInstance *it = std::partition(&elements[first], &elements[first + count], TestBoxes(minAxis, minIdx, sub, mul)); BBox leftBox = leftBoxes[minIdx - 1]; BBox rightBox = rightBoxes[minIdx]; int leftCount = leftCounts[minIdx - 1]; int rightCount = rightCounts[minIdx]; if(leftCount == 0 || rightCount == 0) { minIdx = count / 2; leftBox = elements[first].GetBBox(); rightBox = elements[first + count - 1].GetBBox(); for(size_t n = 1; n < minIdx; n++) leftBox += elements[first + n].GetBBox(); for(size_t n = minIdx; n < count; n++) rightBox += elements[first + n].GetBBox(); leftCount = minIdx; rightCount = count - leftCount; } int subNode = nodes.size(); nodes[nNode].subNode = subNode; nodes[nNode].axis = minAxis; nodes[nNode].firstNode = leftBox.min[minAxis] > rightBox.min[minAxis]? 1 : 0; nodes[nNode].firstNode = leftBox.min[minAxis] == rightBox.min[minAxis]? leftBox.max[minAxis] < rightBox.max[minAxis]? 0 :1 : 0; nodes.push_back(Node(leftBox)); nodes.push_back(Node(rightBox)); FindSplit(subNode + 0, first, leftCount, sdepth + 1); FindSplit(subNode + 1, first + leftCount, rightCount, sdepth + 1); } }