// $Header: /cvs/gled-1.2/Geom1/Glasses/WSSeed.cxx,v 1.7 2005/03/11 17:50:14 matevz Exp $
// Copyright (C) 1999-2005, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.
//______________________________________________________________________
// WSSeed
//
// Weaver Symbol Seed. Serves as container for WSPoints that make up
// the actual symbol. Provides triangulation service and stores
// triangulation data.
#include "WSSeed.h"
#include "WSSeed.c7"
#include "WSPoint.h"
#include <Tvor/TubeTvor.h>
#include <Gled/GThread.h>
#include <TSystem.h>
namespace {
double orto_norm(TVectorF& v, const TVectorF& x, int M) {
double dp = 0;
for(Int_t i=0; i<M; ++i) dp += v(i)*x(i);
for(Int_t i=0; i<M; ++i) v(i) -= x(i)*dp;
double ni = 1/TMath::Sqrt(v.Norm2Sqr());
for(Int_t i=0; i<M; ++i) v(i) *= ni;
return dp;
}
}
ClassImp(WSSeed)
/**************************************************************************/
void WSSeed::_init()
{
mTLevel = 16; mPLevel = 16;
mTexUOffset = mTexVOffset = 0;
bRenormLen = false; mLength = 1;
mLineW = 2; bFat = true;
mTexture = 0;
pTuber = 0; bTextured = false;
mTASleepMS = 50; bTexAnimOn = false;
mDtexU = -0.01; mDtexV = 0;
bUseDispList = false;
}
WSSeed::~WSSeed() { delete pTuber; }
/**************************************************************************/
void WSSeed::SetTexUOffset(Float_t texu)
{
mTexUOffset = texu;
mStampReqTex = Stamp(FID());
}
void WSSeed::SetTexVOffset(Float_t texv)
{
mTexVOffset = texv;
mStampReqTex = Stamp(FID());
}
/**************************************************************************/
void WSSeed::Triangulate()
{
// Should be called under ReadLock.
list<WSPoint*> points; CopyByGlass<WSPoint*>(points);
int size = points.size();
if(!bFat || size < 2) {
// !!!!! Could at least call Coffs !!!!!
// Then don't need them in line rnr
// and in TransAtTime
return;
}
bTextured = (mTexture != 0);
if(pTuber == 0) pTuber = new TubeTvor;
pTuber->Init(0, mTLevel*(size - 1) + 1, mPLevel, false, bTextured);
list<WSPoint*>::iterator a, b;
Float_t len_fac = 1;
if(bRenormLen) {
Float_t len = 0;
b = points.begin();
while((a=b++, b) != points.end()) len += (*a)->mStretch;
len_fac = mLength/len;
}
bool first = true;
b = points.begin();
ZTrans* lcfp;
while((a=b++, b) != points.end()) {
(*a)->Coff(*b);
if(first) {
first = false;
lcfp = init_slide(*a);
hTexU = mTexUOffset; hTexV = mTexVOffset;
}
Float_t delta = 1.0/mTLevel, max = 1 - delta/2;
for(Float_t t=0; t<max; t+=delta) {
ring(*lcfp, *a, t);
hTexU += delta * (*a)->mStretch * len_fac;
hTexV += delta * (*a)->mTwist;
}
}
ring(*lcfp, *(--a), 1);
// Store TexOffsets for re-texturing.
hTexU = mTexUOffset; hTexV = mTexVOffset;
delete lcfp;
}
void WSSeed::ReTexturize()
{
// Should be called under ReadLock.
Float_t du = mTexUOffset - hTexU;
Float_t dv = mTexVOffset - hTexV;
if(pTuber != 0 && pTuber->bTexP) {
float* t = pTuber->mT;
for(int i=0; i<pTuber->mNP; ++i, t+=2) {
t[0] += du;
t[1] += dv;
}
}
hTexU = mTexUOffset;
hTexV = mTexVOffset;
mStampTexDone = mTimeStamp;
}
/**************************************************************************/
void WSSeed::TexAnimStart()
{
if(bTexAnimOn) return;
{
GLensWriteHolder wlck(this);
bTexAnimOn = true;
Stamp(FID());
}
while(bTexAnimOn) {
{
GLensWriteHolder wlck(this);
mTexUOffset = mTexUOffset + mDtexU;
mTexVOffset = mTexVOffset + mDtexV;
mStampReqTex = Stamp(FID());
}
GThread::TestCancel();
gSystem->Sleep(mTASleepMS);
GThread::TestCancel();
}
}
void WSSeed::TexAnimStop()
{
if(!bTexAnimOn) return;
bTexAnimOn = false;
Stamp(FID());
}
/**************************************************************************/
void WSSeed::TransAtTime(ZTrans& lcf, Float_t time, bool repeat_p)
{
// Positions lcf to time.
// If repeat_p is true, the time is clamped into the range.
// 'Up' and 'right' axes are Gram-Schmidt orto-normalized wrt 'front'.
static const string _eh("WSSeed::TransAtTime ");
list<WSPoint*> points; CopyByGlass<WSPoint*>(points);
int size = points.size();
if(size < 2) {
throw(_eh + "not enough points.");
}
// Here should call triangulate if mStamReqTex < mTimeStamp
// The triangulation could measure lengths etc, store them in local data.
// Then also don't need Coff call below.
list<WSPoint*>::iterator a, b;
Float_t len_fac = 1;
Float_t len = 0;
b = points.begin();
while((a=b++, b) != points.end()) len += (*a)->mStretch;
if(bRenormLen) {
len_fac = mLength/len;
len = mLength;
}
if(time < 0 || time > len) {
if(repeat_p) {
time -= ((int)(time/len))*len;
if(time < 0) time += len;
} else {
time = (time < 0) ? 0 : len;
}
}
// printf("OK ... came up with time=%fn", time);
Float_t done = 0;
b = points.begin();
while((a=b++, b) != points.end()) {
done += (*a)->mStretch * len_fac;
if(done >= time) break;
}
Float_t t = 1 - (done - time) / ((*a)->mStretch * len_fac);
// printf(" limits '%s', '%s'; rel.time=%fn",
// (*a)->GetName(), (*b)->GetName(), t);
(*a)->Coff(*b);
TMatrixFColumn hPnt(lcf,4), hAxe(lcf,1);
Float_t t2 = t*t;
Float_t t3 = t2*t;
WSPoint* f = *a;
for(Int_t i=1; i<=3; i++) {
hPnt(i) = f->mCoffs(i, 0) + f->mCoffs(i, 1)*t +
f->mCoffs(i, 2)*t2 + f->mCoffs(i, 3)*t3;
hAxe(i) = f->mCoffs(i, 1) + 2*f->mCoffs(i, 2)*t +
3*f->mCoffs(i, 3)*t2;
}
lcf.OrtoNorm3();
}
/**************************************************************************/
// Protected
/**************************************************************************/
WSPoint* WSSeed::get_first_point()
{
GMutexHolder lmh(mListMutex);
WSPoint* p = 0;
lpZGlass_i i = mGlasses.begin();
while(i != mGlasses.end() && (p = dynamic_cast<WSPoint*>(*i)) == 0) ++i;
return p;
}
ZTrans* WSSeed::init_slide(WSPoint* f)
{
if(f == 0) f = get_first_point();
if(f == 0) return 0;
return new ZTrans(f->RefTrans());
}
void WSSeed::ring(ZTrans& lcf, WSPoint* f, Float_t t)
{
TMatrixFColumn hPnt(lcf,4), hAxe(lcf,1), hUp(lcf,2), hAw(lcf,3);
Float_t t2 = t*t;
Float_t t3 = t2*t;
for(Int_t i=1; i<=3; i++) {
hPnt(i) = f->mCoffs(i, 0) + f->mCoffs(i, 1)*t +
f->mCoffs(i, 2)*t2 + f->mCoffs(i, 3)*t3;
hAxe(i) = f->mCoffs(i, 1) + 2*f->mCoffs(i, 2)*t +
3*f->mCoffs(i, 3)*t2;
}
Float_t w = f->mCoffs(4, 0) + f->mCoffs(4, 1)*t +
f->mCoffs(4, 2)*t2 + f->mCoffs(4, 3)*t3;
Float_t dwdt = TMath::ATan(f->mCoffs(4, 1) + 2*f->mCoffs(4, 2)*t +
3*f->mCoffs(4, 3)*t2);
Float_t dwc = TMath::Cos(dwdt);
Float_t dws = TMath::Sin(dwdt);
lcf.OrtoNorm3();
pTuber->NewRing(mPLevel, true);
Float_t phi = 0, step = 2*TMath::Pi()/mPLevel;
Float_t R[3], N[3], T[2];
for(int j=0; j<mPLevel; j++, phi-=step) {
Float_t cp = TMath::Cos(phi), sp = TMath::Sin(phi);
for(Int_t i=1; i<=3; ++i) {
R[i-1] = hPnt(i) + cp*w*hUp(i) + sp*w*hAw(i);
N[i-1] = -dws*hAxe(i) + dwc*(cp*hUp(i) + sp*hAw(i));
}
// perhaps should invert normals for w<0
T[0] = hTexU; T[1] = hTexV - phi/TMath::TwoPi();
pTuber->NewVert(R, N, 0, T);
}
{ // last one
phi = -2*TMath::Pi();
Float_t cp = TMath::Cos(phi), sp = TMath::Sin(phi);
for(Int_t i=1; i<=3; ++i) {
R[i-1] = hPnt(i) + cp*w*hUp(i) + sp*w*hAw(i);
N[i-1] = -dws*hAxe(i) + dwc*(cp*hUp(i) + sp*hAw(i));
}
// perhaps should invert normals for w<0
T[0] = hTexU; T[1] = hTexV + 1;
pTuber->NewVert(R, N, 0, T);
}
}
ROOT page - Home page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.