1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the AUTHORS
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "engines/stark/visual/actor.h"
24 
25 #include "engines/stark/model/model.h"
26 #include "engines/stark/model/animhandler.h"
27 #include "engines/stark/gfx/driver.h"
28 #include "engines/stark/gfx/texture.h"
29 #include "engines/stark/scene.h"
30 #include "engines/stark/services/services.h"
31 
32 namespace Stark {
33 
VisualActor()34 VisualActor::VisualActor() :
35 		Visual(TYPE),
36 		_animHandler(nullptr),
37 		_model(nullptr),
38 		_textureSet(nullptr),
39 		_textureSetFacial(nullptr),
40 		_time(0),
41 		_modelIsDirty(true),
42 		_faceTextureName(' ') {
43 }
44 
~VisualActor()45 VisualActor::~VisualActor() {
46 }
47 
setModel(Model * model)48 void VisualActor::setModel(Model *model) {
49 	if (_model == model) {
50 		return; // Nothing to do
51 	}
52 
53 	_model = model;
54 	_modelIsDirty = true;
55 }
56 
setAnimHandler(AnimHandler * animHandler)57 void VisualActor::setAnimHandler(AnimHandler *animHandler) {
58 	_animHandler = animHandler;
59 }
60 
setAnim(SkeletonAnim * anim)61 void VisualActor::setAnim(SkeletonAnim *anim) {
62 	_animHandler->setAnim(anim);
63 }
64 
setTexture(Gfx::TextureSet * texture)65 void VisualActor::setTexture(Gfx::TextureSet *texture) {
66 	_textureSet = texture;
67 }
68 
setTextureFacial(Gfx::TextureSet * textureFacial)69 void VisualActor::setTextureFacial(Gfx::TextureSet *textureFacial) {
70 	_textureSetFacial = textureFacial;
71 }
72 
setNewFace(char shape)73 void VisualActor::setNewFace(char shape) {
74 	_faceTextureName = shape;
75 }
76 
resolveTexture(const Material * material) const77 const Gfx::Texture *VisualActor::resolveTexture(const Material *material) const {
78 	const Gfx::Texture *texture = nullptr;
79 	if (_textureSetFacial && material->name == "face") {
80 		texture = _textureSetFacial->getTexture(Common::String::format("%c.bmp", _faceTextureName));
81 
82 		if (!texture) {
83 			// Default face texture in case the requested shape was not found
84 			texture = _textureSetFacial->getTexture("i.bmp");
85 		}
86 	}
87 
88 	if (!texture) {
89 		texture = _textureSet->getTexture(material->texture);
90 	}
91 
92 	return texture;
93 }
94 
setTime(uint32 time)95 void VisualActor::setTime(uint32 time) {
96 	_time = time;
97 }
98 
getModelMatrix(const Math::Vector3d & position,float direction)99 Math::Matrix4 VisualActor::getModelMatrix(const Math::Vector3d &position, float direction) {
100 	Math::Matrix4 modelMatrix;
101 	modelMatrix.setPosition(position);
102 
103 	Math::Angle swayAngle = StarkScene->getSwayAngle();
104 	if (swayAngle != 0) {
105 		Math::Quaternion swayRotation = Math::Quaternion(StarkScene->getSwayDirection(), swayAngle / 2.0);
106 		modelMatrix = modelMatrix * swayRotation.toMatrix();
107 	}
108 
109 	float floatOffset = StarkScene->getFloatOffset();
110 	if (floatOffset != 0) {
111 		Math::Matrix4 floatTranslation;
112 		floatTranslation.setPosition(Math::Vector3d(0, 0, floatOffset));
113 		modelMatrix = modelMatrix * floatTranslation;
114 	}
115 
116 	Math::Matrix4 rot1;
117 	rot1.buildAroundX(90);
118 
119 	Math::Matrix4 rot2;
120 	rot2.buildAroundY(270 - direction);
121 
122 	Math::Matrix4 scale;
123 	scale.setValue(2, 2, -1.0f);
124 
125 	return modelMatrix * rot1 * rot2 * scale;
126 }
127 
intersectRay(const Math::Ray & ray,const Math::Vector3d & position,float direction)128 bool VisualActor::intersectRay(const Math::Ray &ray, const Math::Vector3d &position, float direction) {
129 	Math::Matrix4 inverseModelMatrix = getModelMatrix(position, direction);
130 	inverseModelMatrix.inverse();
131 
132 	// Build an object local ray from the world ray
133 	Math::Ray localRay = ray;
134 	localRay.transform(inverseModelMatrix);
135 
136 	return _model->intersectRay(localRay);
137 }
138 
resetBlending()139 void VisualActor::resetBlending() {
140 	if (_animHandler) {
141 		_animHandler->resetBlending();
142 	}
143 }
144 
145 } // End of namespace Stark
146