framework2

Форк
0
678 строк · 18.5 Кб
1

2
#include "ofNode.h"
3
#include "of3dGraphics.h"
4

5
//----------------------------------------
6
ofNode::ofNode()
7
:parent(nullptr)
8
,localTransformMatrix(1)
9
,legacyCustomDrawOverrided(true){
10
	setPosition({0.f, 0.f, 0.f});
11
	setOrientation({0.f, 0.f, 0.f});
12
	setScale(1.f);
13
	position.disableEvents();
14
	scale.disableEvents();
15
	orientation.disableEvents();
16
}
17

18
//----------------------------------------
19
ofNode::~ofNode(){
20
	if(parent){
21
		parent->removeListener(*this);
22
	}
23

24
	// clearParent() will remove children of this element as a side-effect.
25
	// This changes the "children", and so we can't use a normal foreach
26
	// loop, but must use the following construction to deal with newly
27
	// invalidated iterators:
28
	while (!children.empty()){
29
		(*children.begin())->clearParent();
30
	}
31
}
32

33
//----------------------------------------
34
ofNode::ofNode(const ofNode & node)
35
:parent(node.parent)
36
,axis(node.axis)
37
,localTransformMatrix(node.localTransformMatrix)
38
,legacyCustomDrawOverrided(true){
39
	if(parent){
40
		parent->addListener(*this);
41
	}
42
	position = node.position;
43
	orientation = node.orientation;
44
	scale = node.scale;
45
	position.disableEvents();
46
	scale.disableEvents();
47
	orientation.disableEvents();
48
}
49

50
//----------------------------------------
51
ofNode::ofNode(ofNode && node)
52
:parent(node.parent)
53
,position(std::move(node.position))
54
,orientation(std::move(node.orientation))
55
,scale(std::move(node.scale))
56
,axis(std::move(node.axis))
57
,localTransformMatrix(std::move(node.localTransformMatrix))
58
,legacyCustomDrawOverrided(std::move(node.legacyCustomDrawOverrided))
59
,children(std::move(node.children)){
60
	if(parent){
61
		parent->addListener(*this);
62
	}
63
}
64

65
//----------------------------------------
66
ofNode & ofNode::operator=(const ofNode & node){
67
	if(this == &node) return *this;
68
	parent = node.parent;
69
	position = node.position;
70
	orientation = node.orientation;
71
	scale = node.scale;
72
	axis = node.axis;
73
	position.disableEvents();
74
	scale.disableEvents();
75
	orientation.disableEvents();
76
	localTransformMatrix = node.localTransformMatrix;
77
	legacyCustomDrawOverrided = true;
78
	if(parent){
79
		parent->addListener(*this);
80
	}
81
	return *this;
82
}
83

84
//----------------------------------------
85
ofNode & ofNode::operator=(ofNode && node){
86
	if(this == &node) return *this;
87
	parent = node.parent;
88
	position = std::move(node.position);
89
	orientation = std::move(node.orientation);
90
	scale = std::move(node.scale);
91
	axis = std::move(node.axis);
92
	localTransformMatrix = std::move(node.localTransformMatrix);
93
	legacyCustomDrawOverrided = std::move(node.legacyCustomDrawOverrided);
94
	children = std::move(node.children);
95
	if(parent){
96
		parent->addListener(*this);
97
	}
98
	return *this;
99
}
100

101
//----------------------------------------
102
void ofNode::addListener(ofNode & node){
103
	position.addListener(&node, &ofNode::onParentPositionChanged);
104
	orientation.addListener(&node, &ofNode::onParentOrientationChanged);
105
	scale.addListener(&node, &ofNode::onParentScaleChanged);
106
	position.enableEvents();
107
	orientation.enableEvents();
108
	scale.enableEvents();
109
	children.insert(&node);
110
}
111

112
//----------------------------------------
113
void ofNode::removeListener(ofNode & node){
114
	position.removeListener(&node, &ofNode::onParentPositionChanged);
115
	orientation.removeListener(&node, &ofNode::onParentOrientationChanged);
116
	scale.removeListener(&node, &ofNode::onParentScaleChanged);
117
	if(position.getNumListeners()==0){
118
		position.disableEvents();
119
		scale.disableEvents();
120
		orientation.disableEvents();
121
	}
122
	children.erase(&node);
123
}
124

125
//----------------------------------------
126
void ofNode::setParent(ofNode& parent, bool bMaintainGlobalTransform) {
127
	if (this->parent)
128
	{
129
		// we need to make sure to clear before
130
		// re-assigning parenthood.
131
		clearParent(bMaintainGlobalTransform);
132
	}
133
	if(bMaintainGlobalTransform) {
134
		auto postParentPosition = position - parent.getGlobalPosition();
135
		auto postParentOrientation = orientation.get() * glm::inverse(parent.getGlobalOrientation());
136
		auto postParentScale = scale / parent.getGlobalScale();
137
		parent.addListener(*this);
138
		setOrientation(postParentOrientation);
139
		setPosition(postParentPosition);
140
		setScale(postParentScale);
141
	} else {
142
		parent.addListener(*this);
143
	}
144
	this->parent = &parent;
145
}
146

147
//----------------------------------------
148
void ofNode::clearParent(bool bMaintainGlobalTransform) {
149
	if(parent){
150
		parent->removeListener(*this);
151
	}
152
	if(bMaintainGlobalTransform && parent) {
153
		auto orientation = getGlobalOrientation();
154
		auto position = getGlobalPosition();
155
		auto scale = getGlobalScale();
156
		this->parent = nullptr;
157
		setOrientation(orientation);
158
		setPosition(position);
159
		setScale(scale);
160
	}else{
161
		this->parent = nullptr;
162
	}
163

164
}
165

166
//----------------------------------------
167
ofNode* ofNode::getParent() const {
168
	return parent;
169
}
170

171
//----------------------------------------
172
void ofNode::setPosition(float px, float py, float pz) {
173
	setPosition({px, py, pz});
174
}
175

176
//----------------------------------------
177
void ofNode::setPosition(const glm::vec3& p) {
178
	position = p;
179
	createMatrix();
180
	onPositionChanged();
181
}
182

183
//----------------------------------------
184
void ofNode::setGlobalPosition(float px, float py, float pz) {
185
	setGlobalPosition({px, py, pz});
186
}
187

188
//----------------------------------------
189
void ofNode::setGlobalPosition(const glm::vec3& p) {
190
	if(parent == nullptr) {
191
		setPosition(p);
192
	} else {
193
		auto newP = glm::inverse(parent->getGlobalTransformMatrix()) * glm::vec4(p, 1.0);
194
		setPosition(glm::vec3(newP) / newP.w);
195
	}
196
}
197

198
//----------------------------------------
199
glm::vec3 ofNode::getPosition() const {
200
	return position;
201
}
202

203
//----------------------------------------
204
float ofNode::getX() const {
205
	return position->x;
206
}
207

208
//----------------------------------------
209
float ofNode::getY() const {
210
	return position->y;
211
}
212

213
//----------------------------------------
214
float ofNode::getZ() const {
215
	return position->z;
216
}
217

218
//----------------------------------------
219
void ofNode::setOrientation(const glm::quat& q) {
220
	orientation = q;
221
	createMatrix();
222
	onOrientationChanged();
223
}
224

225
//----------------------------------------
226
void ofNode::setOrientation(const glm::vec3& eulerAngles) {
227
    glm::quat q(glm::radians(eulerAngles));
228
    setOrientation(q);
229
}
230

231
//----------------------------------------
232
void ofNode::setGlobalOrientation(const glm::quat& q) {
233
	if(parent == nullptr) {
234
		setOrientation(q);
235
	} else {
236
		auto invParent = glm::inverse(parent->getGlobalOrientation());
237
		auto m44 = invParent * q;
238
		setOrientation(m44);
239
	}
240
}
241

242
//----------------------------------------
243
glm::quat ofNode::getOrientationQuat() const {
244
	return orientation;
245
}
246

247
//----------------------------------------
248
glm::vec3 ofNode::getOrientationEuler() const {
249
	return getOrientationEulerDeg();
250
}
251

252
//----------------------------------------
253
glm::vec3 ofNode::getOrientationEulerDeg() const {
254
	auto euler = glm::eulerAngles(orientation.get());
255
	return {ofRadToDeg(euler.x), ofRadToDeg(euler.y), ofRadToDeg(euler.z)};
256
}
257

258
//----------------------------------------
259
glm::vec3 ofNode::getOrientationEulerRad() const {
260
	return glm::eulerAngles(orientation.get());
261
}
262

263
//----------------------------------------
264
void ofNode::setScale(float s) {
265
	setScale(s, s, s);
266
}
267

268
//----------------------------------------
269
void ofNode::setScale(float sx, float sy, float sz) {
270
	setScale({sx, sy, sz});
271
}
272

273
//----------------------------------------
274
void ofNode::setScale(const glm::vec3& s) {
275
	this->scale = s;
276
	createMatrix();
277
	onScaleChanged();
278
}
279

280
//----------------------------------------
281
glm::vec3 ofNode::getScale() const {
282
	return scale;
283
}
284

285
//----------------------------------------
286
void ofNode::move(float x, float y, float z) {
287
	move({x, y, z});
288
}
289

290
//----------------------------------------
291
void ofNode::move(const glm::vec3& offset) {
292
	position += offset;
293
	createMatrix();
294
	onPositionChanged();
295
}
296

297
//----------------------------------------
298
void ofNode::truck(float amount) {
299
	move(getXAxis() * amount);
300
}
301

302
//----------------------------------------
303
void ofNode::boom(float amount) {
304
	move(getYAxis() * amount);
305
}
306

307
//----------------------------------------
308
void ofNode::dolly(float amount) {
309
	move(getZAxis() * amount);
310
}
311

312
//----------------------------------------
313
void ofNode::tilt(float degrees) {
314
	rotateDeg(degrees, getXAxis());
315
}
316

317
//----------------------------------------
318
void ofNode::pan(float degrees) {
319
	rotateDeg(degrees, getYAxis());
320
}
321

322
//----------------------------------------
323
void ofNode::roll(float degrees) {
324
	rotateDeg(degrees, getZAxis());
325
}
326

327
//----------------------------------------
328
void ofNode::tiltDeg(float degrees) {
329
	rotateDeg(degrees, getXAxis());
330
}
331

332
//----------------------------------------
333
void ofNode::panDeg(float degrees) {
334
	rotateDeg(degrees, getYAxis());
335
}
336

337
//----------------------------------------
338
void ofNode::rollDeg(float degrees) {
339
	rotateDeg(degrees, getZAxis());
340
}
341

342
//----------------------------------------
343
void ofNode::tiltRad(float radians) {
344
	rotateRad(radians, getXAxis());
345
}
346

347
//----------------------------------------
348
void ofNode::panRad(float radians) {
349
	rotateRad(radians, getYAxis());
350
}
351

352
//----------------------------------------
353
void ofNode::rollRad(float radians) {
354
	rotateRad(radians, getZAxis());
355
}
356

357
//----------------------------------------
358
void ofNode::rotate(const glm::quat& q) {
359
	orientation = q * (const glm::quat&)orientation;
360
	createMatrix();
361
	onOrientationChanged();
362
}
363

364
//----------------------------------------
365
void ofNode::rotate(float degrees, const glm::vec3& v) {
366
	rotateDeg(degrees, v);
367
}
368

369
//----------------------------------------
370
void ofNode::rotateDeg(float degrees, const glm::vec3& v) {
371
	rotate(glm::angleAxis(ofDegToRad(degrees), v));
372
}
373

374
//----------------------------------------
375
void ofNode::rotateRad(float radians, const glm::vec3& v) {
376
	rotate(glm::angleAxis(radians, v));
377
}
378

379
//----------------------------------------
380
void ofNode::rotate(float degrees, float vx, float vy, float vz) {
381
	rotateDeg(degrees, vx, vy, vz);
382
}
383

384
//----------------------------------------
385
void ofNode::rotateDeg(float degrees, float vx, float vy, float vz) {
386
	rotate(glm::angleAxis(ofDegToRad(degrees), glm::vec3(vx, vy, vz)));
387
}
388

389
//----------------------------------------
390
void ofNode::rotateRad(float radians, float vx, float vy, float vz) {
391
	rotate(glm::angleAxis(radians, glm::vec3(vx, vy, vz)));
392
}
393

394
//----------------------------------------
395
void ofNode::rotateAround(const glm::quat& q, const glm::vec3& point) {
396
	//	ofLogVerbose("ofNode") << "rotateAround(const glm::quat& q, const glm::vec3& point) not implemented yet";
397
	//	glm::mat4 m = getLocalTransformMatrix();
398
	//	m.setTranslation(point);
399
	//	m.rotate(q);
400
	
401
	setGlobalPosition(q * (getGlobalPosition() - point) + point);
402
	
403
	onOrientationChanged();
404
	onPositionChanged();
405
}
406

407
//----------------------------------------
408
void ofNode::rotateAround(float degrees, const glm::vec3& axis, const glm::vec3& point) {
409
	rotateAroundDeg(degrees, axis, point);
410
}
411

412
//----------------------------------------
413
void ofNode::rotateAroundDeg(float degrees, const glm::vec3& axis, const glm::vec3& point) {
414
	rotateAround(glm::angleAxis(ofDegToRad(degrees), axis), point);
415
}
416

417
//----------------------------------------
418
void ofNode::rotateAroundRad(float radians, const glm::vec3& axis, const glm::vec3& point) {
419
	rotateAround(glm::angleAxis(radians, axis), point);
420
}
421

422
//----------------------------------------
423
void ofNode::lookAt(const glm::vec3& lookAtPosition){
424
    auto relPosition = (getGlobalPosition() - lookAtPosition);
425
	auto radius = glm::length(relPosition);
426
    if(radius>0){
427
		float latitude = acos(relPosition.y / radius) - glm::half_pi<float>();
428
		float longitude = atan2(relPosition.x , relPosition.z);
429
		glm::quat q = glm::angleAxis(0.f, glm::vec3(0,0,1)) * glm::angleAxis(longitude, glm::vec3(0,1,0)) * glm::angleAxis(latitude, glm::vec3(1,0,0));
430
        setGlobalOrientation(q);
431
    }
432
}
433

434
//----------------------------------------
435
void ofNode::lookAt(const glm::vec3& lookAtPosition, glm::vec3 upVector) {
436
	if(parent){
437
		auto upVector4 = glm::inverse(parent->getGlobalTransformMatrix()) * glm::vec4(upVector, 1.0);
438
		upVector = glm::vec3(upVector4) / upVector4.w;
439
	}
440
	auto zaxis = glm::normalize(getGlobalPosition() - lookAtPosition);
441
	if (glm::length(zaxis) > 0) {
442
		auto xaxis = glm::normalize(glm::cross(upVector, zaxis));
443
		auto yaxis = glm::cross(zaxis, xaxis);
444
		glm::mat3 m;
445
		m[0] = xaxis;
446
		m[1] = yaxis;
447
		m[2] = zaxis;
448

449
		setGlobalOrientation(glm::toQuat(m));
450
	}
451
}
452

453
//----------------------------------------
454
void ofNode::lookAt(const ofNode& lookAtNode){
455
    lookAt(lookAtNode.getGlobalPosition());
456
}
457

458
//----------------------------------------
459
void ofNode::lookAt(const ofNode& lookAtNode, const glm::vec3& upVector) {
460
	lookAt(lookAtNode.getGlobalPosition(), upVector);
461
}
462

463
//----------------------------------------
464
void ofNode::updateAxis() {
465
	if(scale->x>0) axis[0] = glm::vec3(getLocalTransformMatrix()[0]/scale->x);
466
	if(scale->y>0) axis[1] = glm::vec3(getLocalTransformMatrix()[1]/scale->y);
467
	if(scale->z>0) axis[2] = glm::vec3(getLocalTransformMatrix()[2]/scale->z);
468
}
469

470
//----------------------------------------
471
glm::vec3 ofNode::getXAxis() const {
472
	return axis[0];
473
}
474

475
//----------------------------------------
476
glm::vec3 ofNode::getYAxis() const {
477
	return axis[1];
478
}
479

480
//----------------------------------------
481
glm::vec3 ofNode::getZAxis() const {
482
	return axis[2];
483
}
484

485
//----------------------------------------
486
glm::vec3 ofNode::getSideDir() const {
487
	return getXAxis();
488
}
489

490
//----------------------------------------
491
glm::vec3 ofNode::getLookAtDir() const {
492
	return -getZAxis();
493
}
494

495
//----------------------------------------
496
glm::vec3 ofNode::getUpDir() const {
497
	return getYAxis();
498
}
499

500
//----------------------------------------
501
float ofNode::getPitch() const {
502
	return getPitchDeg();
503
}
504

505
//----------------------------------------
506
float ofNode::getHeading() const {
507
	return getHeadingDeg();
508
}
509

510
//----------------------------------------
511
float ofNode::getRoll() const {
512
	return getRollDeg();
513
}
514

515
//----------------------------------------
516
float ofNode::getPitchDeg() const {
517
	return getOrientationEulerDeg().x;
518
}
519

520
//----------------------------------------
521
float ofNode::getHeadingDeg() const {
522
	return getOrientationEulerDeg().y;
523
}
524

525
//----------------------------------------
526
float ofNode::getRollDeg() const {
527
	return getOrientationEulerDeg().z;
528
}
529

530
//----------------------------------------
531
float ofNode::getPitchRad() const {
532
	return getOrientationEulerRad().x;
533
}
534

535
//----------------------------------------
536
float ofNode::getHeadingRad() const {
537
	return getOrientationEulerRad().y;
538
}
539

540
//----------------------------------------
541
float ofNode::getRollRad() const {
542
	return getOrientationEulerRad().z;
543
}
544

545
//----------------------------------------
546
const glm::mat4& ofNode::getLocalTransformMatrix() const {
547
	return localTransformMatrix;
548
}
549

550
//----------------------------------------
551
glm::mat4 ofNode::getGlobalTransformMatrix() const {
552
	if(parent) return parent->getGlobalTransformMatrix() * getLocalTransformMatrix();
553
	else return getLocalTransformMatrix();
554
}
555

556
//----------------------------------------
557
glm::vec3 ofNode::getGlobalPosition() const {
558
	return glm::vec3(getGlobalTransformMatrix()[3]);
559
}
560

561
//----------------------------------------
562
glm::quat ofNode::getGlobalOrientation() const {
563
	if (parent) return parent->getGlobalOrientation() * getOrientationQuat();
564
	return getOrientationQuat();
565
}
566

567
//----------------------------------------
568
glm::vec3 ofNode::getGlobalScale() const {
569
	if(parent) return getScale()*parent->getGlobalScale();
570
	else return getScale();
571
}
572

573
//----------------------------------------
574
void ofNode::orbit(float longitude, float latitude, float radius, const glm::vec3& centerPoint) {
575
	orbitDeg(longitude, latitude, radius, centerPoint);
576
}
577

578
//----------------------------------------
579
void ofNode::orbit(float longitude, float latitude, float radius, ofNode& centerNode) {
580
	orbitDeg(longitude, latitude, radius, centerNode);
581
}
582

583
//----------------------------------------
584
void ofNode::orbitDeg(float longitude, float latitude, float radius, ofNode& centerNode) {
585
	orbitDeg(longitude, latitude, radius, centerNode.getGlobalPosition());
586
}
587

588
//----------------------------------------
589
void ofNode::orbitDeg(float longitude, float latitude, float radius, const glm::vec3& centerPoint) {
590
	glm::quat q = 
591
	          glm::angleAxis(ofDegToRad(longitude), glm::vec3(0, 1, 0)) 
592
	        * glm::angleAxis(ofDegToRad(latitude),  glm::vec3(1, 0, 0));
593

594
	glm::vec4 p { 0.f, 0.f, 1.f, 0.f };	   // p is a direction, not a position, so .w == 0
595
	
596
	p = q * p;							   // rotate p on unit sphere based on quaternion
597
	p = p * radius;						   // scale p by radius from its position on unit sphere
598

599
	setGlobalPosition(centerPoint + p);
600
	setOrientation(q);
601

602
	onOrientationChanged();
603
	onPositionChanged();
604
}
605

606
//----------------------------------------
607
void ofNode::orbitRad(float longitude, float latitude, float radius, ofNode& centerNode) {
608
	orbitRad(longitude, latitude, radius, centerNode.getGlobalPosition());
609
}
610

611
//----------------------------------------
612
void ofNode::orbitRad(float longitude, float latitude, float radius, const glm::vec3& centerPoint) {
613
	glm::quat q = 
614
	          glm::angleAxis(longitude, glm::vec3(0, 1, 0)) 
615
	        * glm::angleAxis(latitude,  glm::vec3(1, 0, 0));
616

617
	glm::vec4 p { 0.f, 0.f, 1.f, 0.f };	   // p is a direction, not a position, so .w == 0
618
	
619
	p = q * p;							   // rotate p on unit sphere based on quaternion
620
	p = p * radius;						   // scale p by radius from its position on unit sphere
621

622
	setGlobalPosition(centerPoint + p);
623
	setOrientation(q);
624

625
	onOrientationChanged();
626
	onPositionChanged();
627
}
628

629
//----------------------------------------
630
void ofNode::resetTransform() {
631
	setPosition({0.f,0.f,0.f});
632
	setOrientation({0.f,0.f,0.f});
633
    setScale({1.f,1.f,1.f});
634
}
635

636
//----------------------------------------
637
void ofNode::draw()  const{
638
	ofGetCurrentRenderer()->draw(*this);
639
}
640

641
//----------------------------------------
642
void ofNode::customDraw(const ofBaseRenderer * renderer) const{
643
	const_cast<ofNode*>(this)->customDraw();
644
	if(!legacyCustomDrawOverrided){
645
		renderer->drawBox(10);
646
		renderer->draw(ofMesh::axis(20),OF_MESH_FILL);
647
	}
648
}
649

650
//----------------------------------------
651
void ofNode::customDraw(){
652
	legacyCustomDrawOverrided = false;
653
}
654

655
//----------------------------------------
656
void ofNode::transformGL(ofBaseRenderer * renderer) const {
657
	if( renderer == nullptr ) {
658
		renderer = ofGetCurrentRenderer().get();
659
	}
660
	renderer->pushMatrix();
661
	renderer->multMatrix( getGlobalTransformMatrix() );
662
}
663

664
//----------------------------------------
665
void ofNode::restoreTransformGL(ofBaseRenderer * renderer) const {
666
	if( renderer == nullptr ) {
667
		renderer = ofGetCurrentRenderer().get();
668
	}
669
	renderer->popMatrix();
670
}
671

672
//----------------------------------------
673
void ofNode::createMatrix() {
674
	localTransformMatrix = glm::translate(glm::mat4(1.0), toGlm(position));
675
	localTransformMatrix = localTransformMatrix * glm::toMat4((const glm::quat&)orientation);
676
	localTransformMatrix = glm::scale(localTransformMatrix, toGlm(scale));
677

678
	updateAxis();
679
}
680

681

682

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.