www.pudn.com > etree_src.zip > Branch.cpp
//****************************************************************************
// Branch.cpp: implementation of the CBranch class.
//
// Copyright (c) Boris J. Wang (e_boris2002@hotmail.com) 2002 - 2003
// From Institute of Computing Technology, Chinese Academy of Sciences
// Beijing 100871, China
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//****************************************************************************
#include "stdafx.h"
#include "opengl.h"
#include "Branch.h"
#include "tree.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/////////////////////////////////////////////////////////////////////
//Implement for CSegment
////////////////////////////////////////////////////
CglMaterial CSegment::BarkMTR;
float CSegment::SegLeafSize = 1.970f;
float CSegment::LeafExpand = 26.4f;
float CSegment::SegExpand = 26.4f;
float CSegment::SegScaleLen = 0.83f;
float CSegment::SegScaleRad = 0.75f;
float CSegment::SegTwistInc = 61.02f;
float CSegment::SegSideExpand = 58.8f;
float CSegment::SegSideScaleDepth = 0.81f;
float CSegment::SegSideScale = 0.93f;
CglTexture CSegment::Tex(_T("bark.bmp"),GL_Tex_BMP,7);
#define SegDefaultLength 8.0f
CSegment::~CSegment()
{
if(SideBranch)
{
delete SideBranch;
SideBranch = NULL;
}
if(Leaves)
{
delete Leaves;
Leaves = NULL;
}
}
CSegment::CSegment()
{
SetExpand(0.0f);
SetLength(SegDefaultLength);
SetRadius(0.8f);
SetTwist(0.0f);
SideBranch = NULL;
Leaves = NULL;
}
void CSegment::Render(CSegment &Father)
{
Tex.Apply();
BarkMTR.Apply();
glColor4f(0,0,0,CTree::BranchShadowDensity);
glBegin(GL_QUAD_STRIP);
DefineOneLine(HalfRadius, TriRadius, Father.HalfRadius, Father.TriRadius, 0.0f ); // 0/6
DefineOneLine(-HalfRadius, TriRadius, -Father.HalfRadius, Father.TriRadius, 0.1666666667f ); // 1/6
DefineOneLine(-Radius, 0.0f, -Father.Radius, 0.0f, 0.3333333333f ); // 2/6 and so on
DefineOneLine(-HalfRadius, -TriRadius, -Father.HalfRadius, -Father.TriRadius, 0.5f );
DefineOneLine(HalfRadius, -TriRadius, Father.HalfRadius, -Father.TriRadius, 0.6666666667f );
DefineOneLine(Radius, 0.0f, Father.Radius, 0.0f, 0.8333333333f );
DefineOneLine(HalfRadius, TriRadius, Father.HalfRadius, Father.TriRadius, 1.0f ); // 6/6
glEnd();
CTree::TotalQuad += 6;
CTree::TotalVertex += 12;
CTree::TotalNode ++;
CTree::TotalMemory += sizeof(CSegment);
}
void CSegment::DefineOneLine(GLfloat x, GLfloat z, GLfloat fx, GLfloat fz, GLfloat Tex)
{
glNormal3f(fx,0.0f,fz);
glTexCoord2f(Tex,0.0f);
glVertex3f(fx, 0.0f, fz);
{GLfloat x3,y3,z3,x2,z2,x1;
x1 = - z*SinTwist + x*CosTwist;
z2 = z*CosTwist + x*SinTwist;
x2 = x1*CosExpand - Length*SinExpand;
z3 = z2*CosTwist - x2*SinTwist;
y3 = x1*SinExpand + Length*CosExpand;
x3 = z2*SinTwist + x2*CosTwist;
/**************************************************************
The codes above is the simulate the following GL calls which will be ignored within glBegin/glEnd
glPushMatrix();
glTranslatef(0.0f,Length,0.0f);
glRotatef(Expand, CosTwist, 0.0f, SinTwist);
glPopMatrix();
***************************************************************/
glNormal3f(fx,0.0f,fz); //glNormal3f(x3,y3,z3);
glTexCoord2f(Tex,1.0f);
glVertex3f(x3,y3,z3);
}
}
void CSegment::BuildChildren(int Count,GLfloat LeafSize)
{
if(Count)
{
ASSERT(!Next);
ASSERT(!SideBranch);
Next = new CSegment;
ASSERT(Next);
if(Next) //step into
{
Next->SetExpand(SegExpand);
Next->SetLength(SegScaleLen*Length);
Next->SetRadius(SegScaleRad*Radius);
Next->SetTwist(SegTwistInc+Twist);
Next->BuildChildren(Count - 1,LeafSize);
}
}
if(Count>2)
{// Build sidebranch
SideBranch = new CBranch;
ASSERT(SideBranch);
if(SideBranch)
{
SideBranch->LeafScale = LeafSize/CSegment::SegSideScale;
SideBranch->Base = this;
SideBranch->Rebuild(max(1.0f,min(Count,Count*SegSideScaleDepth)));
}
}
else
{// Build leaves
Leaves = new CLeaf;
Leaves[0].Expand = LeafExpand;
Leaves[0].Scale = LeafSize;
Leaves[0].Twist = SegTwistInc+Twist + 180;
}
}
//////////////////////////////////////////////////////////////////////
// Implement for CBranch
//////////////////////////////////////////////////////////////////////
CBranch::CBranch()
{
Base = Segments = NULL;
LeafScale = 0.0;
}
CBranch::~CBranch()
{
FreeAll();
}
bool CBranch::Rebuild(int Count)
{
ASSERT(Count>=1);
if(Segments)delete Segments;
Segments = new CSegment;
ASSERT(Segments);
if(Base)
{
Segments->SetLength(CSegment::SegScaleLen*Base->Length);
Segments->SetRadius(CSegment::SegScaleRad*Base->Radius);
if(Base->Next)
{
Segments->SetExpand(fabs(CSegment::SegSideExpand - Base->Next->Expand));
Segments->SetTwist(Base->Next->Twist+180.0f);
}
}
if(Segments)
{
Segments->BuildChildren(Count - 1,LeafScale);
}
else
{
return false;
}
return true;
}
void CBranch::Render()
{
glPushMatrix();
ASSERT(Segments);
CSegment *seg,*ne;
seg = Segments;
if(Base)
{
Segments->Render(*Base);
glRotatef(Segments->Expand, Segments->SinTwist, 0.0f,Segments->CosTwist);
glTranslatef(0.0f,Segments->Length,0.0f);
}
while(ne = seg->GetNext())
{
if(seg->SideBranch)
{
glPushMatrix();
glScalef(CSegment::SegSideScale,CSegment::SegSideScale,CSegment::SegSideScale);
seg->SideBranch->Render();
glPopMatrix();
}
if(seg->Leaves)
{
seg->Leaves[0].Render();
}
ne->Render(*seg);
glRotatef(ne->Expand, ne->SinTwist, 0.0f,ne->CosTwist);
glTranslatef(0.0f,ne->Length,0.0f);
seg = ne;
}
if(seg->Leaves)
{
seg->Leaves[0].Render();
}
glPopMatrix();
CTree::TotalNode ++;
CTree::TotalMemory += sizeof(CBranch);
}
void CBranch::FreeAll()
{
if(Segments)delete Segments;
Segments = NULL;
}