lightfieldApproximator.hpp 11.1 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1
2
3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg           *
Pierre Kraemer's avatar
Pierre Kraemer committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
20
* Web site: http://cgogn.u-strasbg.fr/                                         *
Pierre Kraemer's avatar
Pierre Kraemer committed
21
22
23
24
25
26
27
28
29
30
31
32
33
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

namespace CGoGN
{

namespace Algo
{

namespace Decimation
{

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/************************************************************************************
 *                      LIGHTFIELD QUADRIC METRIC : frame                           *
 ************************************************************************************/

template <typename PFP>
void Approximator_FrameHalf<PFP>::approximate(Dart d)
{
	this->m_approx[d] = this->m_attrV[d] ;
}

/************************************************************************************
 *                      LIGHTFIELD QUADRIC METRIC : functions                       *
 ************************************************************************************/

template <typename PFP>
bool Approximator_RGBfunctionsHalf<PFP>::init()
{
	// get actual frames and hypothetical approximated frames
52
53
54
	m_frame = this->m_map.template getAttribute<MATRIX33>(VERTEX, "frame") ;
	m_approxFrame = this->m_map.template getAttribute<MATRIX33>(EDGE, "approx_frame") ;
	m_quadricRGBfunctions = this->m_map.template getAttribute<QuadricRGBfunctions<REAL> >(EDGE, "quadricRGBfunctions") ;
55

Pierre Kraemer's avatar
Pierre Kraemer committed
56
	MapBrowserLinked<typename PFP::MAP> mb(this->m_map) ;
57
	this->m_map.foreach_orbit(EDGE, mb) ;
58
59
60
61
62
63
64
65

	// create quadric embedding for computing and set them to 0
	for (Dart d = mb.begin() ; d != mb.end() ; mb.next(d))
		m_quadricRGBfunctions[d].zero() ;

	// Check on embeddings
	if (!m_frame.isValid() || !m_approxFrame.isValid() || !m_quadricRGBfunctions.isValid())
	{
66
		CGoGNerr << "Approximator_RGBfunctions::init() --> No approxPosition or no quadricRGBfunctions specified" << CGoGNendl ;
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
		return false ;
	}

	return true ;
}

template <typename PFP>
void Approximator_RGBfunctionsHalf<PFP>::approximate(Dart d)
{
	MAP& m = this->m_map ;
	Dart dd = m.phi2(d) ;	// get the two vertices

	// Approximation
	this->m_approx[d] = this->m_attrV[d] ;

	// Compute quadrics for error evaluation
	// get hypothetical local frames
	VEC3 i,n ;

	m_approxFrame[d].getSubVectorH(0,0,i) ;
	m_approxFrame[d].getSubVectorH(2,0,n) ;

	// Get previous local frames
	VEC3 n1,n2,i1,i2,j1,j2 ;

	m_frame[d].getSubVectorH(0,0,i1) ;
	m_frame[dd].getSubVectorH(0,0,i2) ;

	m_frame[d].getSubVectorH(1,0,j1) ;
	m_frame[dd].getSubVectorH(1,0,j2) ;

	m_frame[d].getSubVectorH(2,0,n1) ;
	m_frame[dd].getSubVectorH(2,0,n2) ;

	// Compute j1' and j2'
	VEC3 j1pr = n1 ^ i ;
	j1pr.normalize() ;
	VEC3 j2pr = n2 ^ i ;
	j2pr.normalize() ;

	// Rotation dans sens trigo dans le plan tangent autour de n (i1->i)
//	REAL gamma1 = ((j1 * i) > 0 ? 1 : -1) * acos( std::max(std::min(1.0f, i1 * i ), -1.0f)) ; // angle positif ssi
	REAL gamma2 = ((j2 * i) > 0 ? 1 : -1) * acos( std::max(std::min(1.0f, i2 * i ), -1.0f)) ; // -PI/2 < angle(i,j1) < PI/2  ssi i*j1 > 0
	// Rotation dans le sens trigo autour de l'axe i (n1->n)
//	REAL alpha1 = ((n * j1pr) > 0 ? -1 : 1) * acos( std::max(std::min(1.0f, n * n1), -1.0f) ) ; // angle positif ssi
	REAL alpha2 = ((n * j2pr) > 0 ? -1 : 1) * acos( std::max(std::min(1.0f, n * n2), -1.0f) ) ; // PI/2 < angle(j1',n) < -PI/2 ssi j1'*n < 0

//	assert (-0.01 < gamma1 && gamma1 < 0.01) ;
//	assert (-0.01 < alpha1 && alpha1 < 0.01) ;
	REAL gamma1 = REAL(0) ;
	REAL alpha1 = REAL(0) ;

	// Create and sum quadrics
	m_quadricRGBfunctions[d] += QuadricRGBfunctions<REAL>(this->m_attrV[d], gamma1, alpha1) ;
	m_quadricRGBfunctions[d] += QuadricRGBfunctions<REAL>(this->m_attrV[dd], gamma2, alpha2) ;
}

Pierre Kraemer's avatar
Pierre Kraemer committed
124
125
126
127
128
129
130
/************************************************************************************
 *                      LIGHTFIELD QUADRIC METRIC : frame                           *
 ************************************************************************************/

template <typename PFP>
bool Approximator_Frame<PFP>::init()
{
131
132
	m_position = this->m_map.template getAttribute<VEC3>(VERTEX, "position") ;
	m_approxPosition = this->m_map.template getAttribute<VEC3>(EDGE, "approx_position") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
133
134
135

	if (!m_position.isValid() || !m_approxPosition.isValid())
	{
136
		CGoGNerr << "Approximator_Frame::init() --> No approxPosition or no quadricRGBfunctions specified" << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
137
138
139
140
141
142
143
144
145
		return false ;
	}
	return true ;
}

template <typename PFP>
void Approximator_Frame<PFP>::approximate(Dart d)
{
	MAP& m = this->m_map ;
Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
146
	Dart dd = m.phi2(d) ;	// get 2 vertices
Pierre Kraemer's avatar
Pierre Kraemer committed
147

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
148
	// if QEM placed new vertex at one of the previous : place same frame
Pierre Kraemer's avatar
Pierre Kraemer committed
149
150
151
152
153
	if (this->m_approxPosition[d] == this->m_position[d]) // new Position is position of vertex d
		this->m_approx[d] = this->m_attrV[d] ;
	else if (this->m_approxPosition[d] == this->m_position[dd]) // new Position is position of vertex dd
		this->m_approx[d] = this->m_attrV[dd] ;
	else {
Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
154
		// Create two segments : v0-v1 and v0-v
Pierre Kraemer's avatar
Pierre Kraemer committed
155
156
157
158
		VEC3 segment = this->m_position[dd] ;
		segment -= this->m_position[d] ;

		VEC3 segmentNew = m_approxPosition[d] ;
159
		segmentNew -= this->m_position[d] ;
Pierre Kraemer's avatar
Pierre Kraemer committed
160

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
161
		// Orthogonal projection of v0-v onto v0-v1 : get coefficient t
162
		REAL t = (segment * segmentNew) / segment.norm() ;
Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
163
		t = std::max (std::min (t , REAL(1)) , REAL(0) ) ; // clamp it to [0,1]
Pierre Kraemer's avatar
Pierre Kraemer committed
164
165

		VEC3 n1, n2 ;
Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
166
167
		this->m_attrV[d].getSubVectorH(2, 0, n1) ; // get normal n1
		this->m_attrV[dd].getSubVectorH(2, 0, n2) ; // get normal n2
Pierre Kraemer's avatar
Pierre Kraemer committed
168
169
170
171

		VEC3 newN = slerp(n1,n2,t) ; // spherical interpolation
		newN.normalize() ;

172
		VEC3 newI = n2 ^ n1 ; // i is perpendicular to newNormal
Pierre Kraemer's avatar
Pierre Kraemer committed
173
174
		newI.normalize() ;

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
175
		VEC3 newJ = newN ^ newI ; // (i,j,n) is a direct frame
Pierre Kraemer's avatar
Pierre Kraemer committed
176
177
		newJ.normalize() ;

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
178
		// save into m_approx
179
180
181
182
		if (!this->m_approx[d].setSubVectorH(0,0,newI) ||
			!this->m_approx[d].setSubVectorH(1,0,newJ) ||
			!this->m_approx[d].setSubVectorH(2,0,newN) )
			assert(!"Approximator_Frame::approximate") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
183
	}
184

Pierre Kraemer's avatar
Pierre Kraemer committed
185
186
187
188
189
190
191
192
193
}

/************************************************************************************
 *                      LIGHTFIELD QUADRIC METRIC : functions                       *
 ************************************************************************************/

template <typename PFP>
bool Approximator_RGBfunctions<PFP>::init()
{
Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
194
	// get actual frames and hypothetical approximated frames
195
196
197
	m_frame = this->m_map.template getAttribute<MATRIX33>(VERTEX, "frame") ;
	m_approxFrame = this->m_map.template getAttribute<MATRIX33>(EDGE, "approx_frame") ;
	m_quadricRGBfunctions = this->m_map.template getAttribute<QuadricRGBfunctions<REAL> >(EDGE, "quadricRGBfunctions") ;
198

Pierre Kraemer's avatar
Pierre Kraemer committed
199
	MapBrowserLinked<typename PFP::MAP> mb(this->m_map) ;
200
	this->m_map.foreach_orbit(EDGE, mb) ;
201

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
202
	// create quadric embedding for computing and set them to 0
203
	for (Dart d = mb.begin() ; d != mb.end() ; mb.next(d))
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
204
		m_quadricRGBfunctions[d].zero() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
205

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
206
	// Check on embeddings
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
207
	if (!m_frame.isValid() || !m_approxFrame.isValid() || !m_quadricRGBfunctions.isValid())
Pierre Kraemer's avatar
Pierre Kraemer committed
208
	{
209
		CGoGNerr << "Approximator_RGBfunctions::init() --> No approxPosition or no quadricRGBfunctions specified" << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
210
211
212
213
214
215
216
217
218
		return false ;
	}
	return true ;
}

template <typename PFP>
void Approximator_RGBfunctions<PFP>::approximate(Dart d)
{
	MAP& m = this->m_map ;
219
	Dart dd = m.phi1(d) ;	// get the two vertices
Pierre Kraemer's avatar
Pierre Kraemer committed
220

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
221
	// get hypothetical local frames
Pierre Kraemer's avatar
Pierre Kraemer committed
222
	VEC3 i,n ;
Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
223

224
225
	m_approxFrame[d].getSubVectorH(0,0,i) ;
	m_approxFrame[d].getSubVectorH(2,0,n) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
226

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
227
228
229
	// Get previous local frames
	VEC3 n1,n2,i1,i2,j1,j2 ;

230
231
	m_frame[d].getSubVectorH(0,0,i1) ;
	m_frame[dd].getSubVectorH(0,0,i2) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
232

233
234
	m_frame[d].getSubVectorH(1,0,j1) ;
	m_frame[dd].getSubVectorH(1,0,j2) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
235

236
237
	m_frame[d].getSubVectorH(2,0,n1) ;
	m_frame[dd].getSubVectorH(2,0,n2) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
238

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
239
	// Compute j1' and j2'
Pierre Kraemer's avatar
Pierre Kraemer committed
240
	VEC3 j1pr = n1 ^ i ;
241
	j1pr.normalize() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
242
	VEC3 j2pr = n2 ^ i ;
243
244
245
246
247
248
249
250
251
	j2pr.normalize() ;

	// Rotation dans sens trigo dans le plan tangent autour de n (i1->i)
	REAL gamma1 = ((j1 * i) > 0 ? 1 : -1) * acos( std::max(std::min(1.0f, i1 * i ), -1.0f)) ; // angle positif ssi
	REAL gamma2 = ((j2 * i) > 0 ? 1 : -1) * acos( std::max(std::min(1.0f, i2 * i ), -1.0f)) ; // -PI/2 < angle(i,j1) < PI/2  ssi i*j1 > 0
	// Rotation dans le sens trigo autour de l'axe i (n1->n)
	REAL alpha1 = ((n * j1pr) > 0 ? -1 : 1) * acos( std::max(std::min(1.0f, n * n1), -1.0f) ) ; // angle positif ssi
	REAL alpha2 = ((n * j2pr) > 0 ? -1 : 1) * acos( std::max(std::min(1.0f, n * n2), -1.0f) ) ; // PI/2 < angle(j1',n) < -PI/2 ssi j1'*n < 0

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
252
253
254
255
//	assert (-3.15 < gamma1 && gamma1 <= 3.15) ;
//	assert (-3.15 < gamma2 && gamma2 <= 3.15) ;
//	assert (-3.15 < alpha1 && alpha1 <= 3.15) ;
//	assert (-3.15 < alpha2 && alpha2 <= 3.15) ;
256

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
257
258
//	MATRIX36 &f1 = this->m_attrV[d] ;
//	MATRIX36 &f2 = this->m_attrV[dd] ;
259

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
260
	// Create and sum quadrics
261
	m_quadricRGBfunctions[d].zero() ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
262
263
	m_quadricRGBfunctions[d] += QuadricRGBfunctions<REAL>(this->m_attrV[d], gamma1, alpha1) ;
	m_quadricRGBfunctions[d] += QuadricRGBfunctions<REAL>(this->m_attrV[dd], gamma2, alpha2) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
264

Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
265
	// Compute new function
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
266
	if (! m_quadricRGBfunctions[d].findOptimizedRGBfunctions(this->m_approx[d])) {
Kenneth Vanhoey's avatar
LF    
Kenneth Vanhoey committed
267
		this->m_approx[d] = this->m_attrV[d]; // if fail take first one
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
268
	}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
269
//	MATRIX36 &newF = this->m_approx[d] ;
270
271
272
273
274
275
276
277
278
279
280
//	CGoGNout << "Approx of : " <<CGoGNendl ;
//	CGoGNout << "Frame1 : " << m_frame[d] << CGoGNendl ;
//	CGoGNout << "Function1 : "<< this->m_attrV[d] << CGoGNendl ;
//	CGoGNout << "gamma1 : " << gamma1 << CGoGNendl ;
//	CGoGNout << "Frame2 : " << m_frame[dd] << CGoGNendl ;
//	CGoGNout << "Function2 : "<< this->m_attrV[dd] << CGoGNendl ;
//	CGoGNout << "gamma2 : " << gamma2 << CGoGNendl ;
//	CGoGNout << "is " << CGoGNendl ;
//	CGoGNout << "Frame :" << m_approxFrame[d] << CGoGNendl ;
//	CGoGNout << "Function : " << this->m_approx[d] << CGoGNendl ;
//	CGoGNout << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
281
282
283
284
285
286
287
}

} //namespace Decimation

} //namespace Algo

} //namespace CGoGN