void TreeStem::Build(TreeSegment* parentSeg, float offset, TreeGeneralParams generalParams, TreeLevelParams levelParams, LevelContext& context) { static int dbNumStems[4]; dbNumStems[levelParams.level]++; ConsolePrint(L"current numStems: (0-%d),(1-%d),(2-%d),(3-%d)\n", dbNumStems[0], dbNumStems[1], dbNumStems[2], dbNumStems[3]); SAFE_DELETE(mFirstSeg); mParentSeg = parentSeg; mLevelParams = levelParams; float parentLength = 0; float stemOffset = 0; if(parentSeg) { mPos = Vector3(0, offset, 0); // offset: 当stem是parentSeg的一个枝条时, stem在parentSeg上长出的位置 parentLength = mParentSeg->mStem->GetLength(); stemOffset = mParentSeg->mSegIndex * mParentSeg->mStem->GetSegLength() + offset; } else { _Assert(mLevelParams.level == 0); // 只有trunk不存在parentSeg mPos = Vector3::Zero; } mLength = calcStemLength(generalParams, parentLength, stemOffset); mBaseRadius = calcStemBaseRadius(generalParams, parentLength, stemOffset); float baseLength = 0; if(mLevelParams.level == 0) { baseLength = generalParams.baseSize * mLength; } calcStemBranchInterval(parentLength, stemOffset, baseLength, &mNumBranches, &mBranchInterval); float parentBaseLength = 0; if(mLevelParams.level == 1) { parentBaseLength = generalParams.baseSize * parentLength; } float downAngle = 0; float rotateAngle = 0; calcBranchAngle(parentLength, stemOffset, parentBaseLength, context.rotateAngle, &downAngle, &rotateAngle); context.rotateAngle = rotateAngle; mOrient = Quaternion(0, DEGREE_TO_RAD(rotateAngle), DEGREE_TO_RAD(downAngle)); buildSegment(generalParams, NULL, 0, 0, 0, 0, LevelContext()); }
void FMIndexBuilder::build(const std::string& filename) { // Initialization m_str_bytes = 0; m_str_symbols = 0; m_num_large_markers_wrote = 0; m_num_small_markers_wrote = 0; // // Step 1: make a symbol -> count map and use it to build a huffman tree // std::map<char, size_t> count_map; BWTDiskReader* p_reader = new BWTDiskReader(filename); // Discard header for now p_reader->discardHeader(); // Read one symbol from the bwt at a time char b; while((b = p_reader->readChar()) != '\n') { count_map[b]++; } HuffmanTreeCodec<char> encoder(count_map); m_decoder.initialize(encoder); assert(count_map['$'] > 1); m_strings = count_map['$'] - 1; /* for(std::map<char, size_t>::iterator iter = count_map.begin(); iter != count_map.end(); ++iter) { printf("%c %zu\n", iter->first, iter->second); } std::cout << "Bits required for string: " << encoder.getRequiredBits(count_map) << "\n"; */ // // Step 2: use the huffman tree to compress the string // // re-initialize the reader delete p_reader; p_reader = new BWTDiskReader(filename); p_reader->discardHeader(); // We buffer 128 or 256 symbols at a time and huffman-encode each segment std::deque<char> buffer; while((b = p_reader->readChar()) != '\n') { buffer.push_back(b); if(buffer.size() == m_small_sample_rate) { buildSegment(encoder, buffer); buffer.clear(); } } // Build a segment for the remaining symbols if(!buffer.empty()) buildSegment(encoder, buffer); m_eof_pos = p_reader->getEOFPos(); delete p_reader; delete mp_str_tmp; delete mp_sm_tmp; delete mp_lm_tmp; mp_str_tmp = NULL; mp_sm_tmp = NULL; mp_lm_tmp = NULL; }
void TreeStem::buildSegment(TreeGeneralParams generalParams, TreeSegment* prevSeg, int segIndex, float splitAngle, float divergeAngle, float rotateYAngle, LevelContext& context) { _Assert(segIndex < mLevelParams.curveRes); static int dbNumSegs[4]; dbNumSegs[mLevelParams.level]++; ConsolePrint(L"current numSegs: (0-%d),(1-%d),(2-%d),(3-%d)\n", dbNumSegs[0], dbNumSegs[1], dbNumSegs[2], dbNumSegs[3]); int numSegs = mLevelParams.curveRes; float segLength = mLength / numSegs; TreeSegment* seg = New TreeSegment; float curveDelta = 0; if(segIndex != 0) { if(mLevelParams.curveBack == 0) { curveDelta = mLevelParams.curve / mLevelParams.curveRes; } else { if(segIndex < (mLevelParams.curveRes + 1) / 2) curveDelta = 2 * mLevelParams.curve / mLevelParams.curveRes; else curveDelta = -2 * mLevelParams.curveBack / mLevelParams.curveRes; } curveDelta += RandomVariation(0, mLevelParams.curveV) / mLevelParams.curveRes; } Vector3 basePos; if(prevSeg == NULL) basePos = Vector3::Zero; else basePos = Vector3(0, segLength, 0); seg->mPos = basePos; seg->mOrient = Quaternion(0, DEGREE_TO_RAD(divergeAngle), DEGREE_TO_RAD(curveDelta + splitAngle)); seg->mSegIndex = segIndex; seg->mParent = prevSeg; seg->mStem = this; Quaternion parentOrientWorld; if(prevSeg) { prevSeg->mChildren.push_back(seg); parentOrientWorld = prevSeg->mOrientWorld; } else { mFirstSeg = seg; parentOrientWorld = mOrient; } // divergeAngle是绕世界的y轴旋转 seg->mOrientWorld = Quaternion(0, DEGREE_TO_RAD(rotateYAngle), 0) * (parentOrientWorld * seg->mOrient); seg->mOrient = WorldRotationToLocal(parentOrientWorld.Difference(seg->mOrientWorld), parentOrientWorld); // create seg vb ... std::vector<float> segRadius; { float offset = (float)segIndex / numSegs; float offsetDelta = 1.0f / numSegs / mLevelParams.segSegsH; for(int i = 0; i <= mLevelParams.segSegsH; ++i) { segRadius.push_back(GetStemRadius(offset)); offset += offsetDelta; } } bool closeTop = true; bool closeBottom = true; //if(segIndex == 0) // closeBottom = true; //if(segIndex == numSegs - 1) // closeTop = true; seg->mGeo = New TreeSegGeo(segLength, mLevelParams.segSegsW, mLevelParams.segSegsH, segRadius, Quaternion(0, 0, DEGREE_TO_RAD(curveDelta + splitAngle)), closeTop, closeBottom); seg->mGeo->CalculateNormals(); seg->mGeo->BuildGeometry(XYZ_N); // branches if(seg->mStem->GetNumBranches() != 0 && mLevelParams.level < generalParams.levels - 1) { float baseOffset = 0; if(mLevelParams.level == 0) { float baseLength = generalParams.baseSize * mLength; baseOffset = baseLength - segIndex * segLength; } float offset = 0; if(baseOffset <= 0) { offset = mBranchInterval - context.branchDistError; } else if(baseOffset < segLength) { offset = baseOffset + mBranchInterval; } else { offset = segLength + mBranchInterval; } while(offset < segLength - 0.0001f) { TreeStem* branch = New TreeStem(mTree, mLevelParams.level + 1); branch->Build(seg, offset, generalParams, mTree->GetLevelParams(mLevelParams.level + 1), context); seg->mBranches.push_back(branch); offset += mBranchInterval; } context.branchDistError = segLength - (offset - mBranchInterval); } // splits if(segIndex == numSegs - 1) return; int numSplits = 0; if(mLevelParams.level == 0 && segIndex == 0) { numSplits = generalParams.baseSplits; } else { numSplits = (int)(mLevelParams.segSplits + context.splitError); context.splitError = mLevelParams.segSplits + context.splitError - numSplits; } if(numSplits < 1) // no splits { buildSegment(generalParams, seg, segIndex + 1, 0, 0, 0, context); } else { Vector3 vecUp = Vector3(0, 1, 0) * seg->mOrientWorld; float declination = VectorAngle(Vector3(0, 1, 0), vecUp); float splitAngleFactor = 1.0f; // 调整此算法来使splitAngle随枝干的水平角度加成变化 splitAngleFactor = fabs(declination - PI/2) / (PI/2); float childSplitAngle = max(0, splitAngleFactor * RandomVariation(mLevelParams.splitAngle, mLevelParams.splitAngleV)); for(int i = 0; i <= numSplits; ++i) { float childDivergeAngle = 0; float childRotateYAngle = 0; childDivergeAngle = ((float)i / (numSplits + 1)) * 360; if(mLevelParams.level == 0 && segIndex == 0) { childRotateYAngle = 0; } else { float rf = RandomFloat(0, 1.0f); int s = sign(RandomFloat(-1.0f, 1.0f)); childRotateYAngle = s * (20 + 0.75f * (30 + fabs(declination - 90)) * pow(rf, 2)); } buildSegment(generalParams, seg, segIndex + 1, childSplitAngle, childDivergeAngle, childRotateYAngle, context); } } }