Ejemplo n.º 1
0
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());
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
		}
	}
}