void ShaderRenderer::drawTexturedRect3D(const Math::Vector3d &topLeft, const Math::Vector3d &bottomLeft,
		const Math::Vector3d &topRight, const Math::Vector3d &bottomRight, Texture *texture) {
	OpenGLTexture *glTexture = static_cast<OpenGLTexture *>(texture);

	const float w = glTexture->width / (float)glTexture->internalWidth;
	const float h = glTexture->height / (float)glTexture->internalHeight;

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);
	glDepthMask(GL_FALSE);

	glBindTexture(GL_TEXTURE_2D, glTexture->id);

	const GLfloat vertices[] = {
		// S   T         X                 Y                 Z
		   0,  0,  -topLeft.x(),      topLeft.y(),      topLeft.z(),
		   0,  h,  -bottomLeft.x(),   bottomLeft.y(),   bottomLeft.z(),
		   w,  0,  -topRight.x(),     topRight.y(),     topRight.z(),
		   w,  h,  -bottomRight.x(),  bottomRight.y(),  bottomRight.z(),
	};

	_rect3dShader->use();
	_rect3dShader->setUniform1f("texScale", 1.0f);
	_rect3dShader->setUniform("mvpMatrix", _mvpMatrix);
	glBindBuffer(GL_ARRAY_BUFFER, _rect3dVBO);
	glBufferSubData(GL_ARRAY_BUFFER, 0, 20 * sizeof(float), vertices);

	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

	glDisable(GL_BLEND);
	glDepthMask(GL_TRUE);
}
Example #2
0
void TinyGLRenderer::drawTexturedRect3D(const Math::Vector3d &topLeft, const Math::Vector3d &bottomLeft,
		const Math::Vector3d &topRight, const Math::Vector3d &bottomRight, Texture *texture) {

	TinyGLTexture *glTexture = static_cast<TinyGLTexture *>(texture);

	const float w = glTexture->width / (float)glTexture->internalWidth;
	const float h = glTexture->height / (float)glTexture->internalHeight;

	tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
	tglEnable(TGL_BLEND);
	tglDepthMask(TGL_FALSE);

	tglBindTexture(TGL_TEXTURE_2D, glTexture->id);

	tglBegin(TGL_TRIANGLE_STRIP);
		tglTexCoord2f(0, 0);
		tglVertex3f(-topLeft.x(), topLeft.y(), topLeft.z());

		tglTexCoord2f(0, h);
		tglVertex3f(-bottomLeft.x(), bottomLeft.y(), bottomLeft.z());

		tglTexCoord2f(w, 0);
		tglVertex3f(-topRight.x(), topRight.y(), topRight.z());

		tglTexCoord2f(w, h);
		tglVertex3f(-bottomRight.x(), bottomRight.y(), bottomRight.z());
	tglEnd();

	tglDisable(TGL_BLEND);
	tglDepthMask(TGL_TRUE);
}
Example #3
0
void Lua_V2::WorldToScreen() {
	lua_Object xObj = lua_getparam(1);
	lua_Object yObj = lua_getparam(2);
	lua_Object zObj = lua_getparam(3);
	if (!lua_isnumber(xObj) || !lua_isnumber(yObj) || !lua_isnumber(zObj)) {
		lua_pushnumber(0.0);
		lua_pushnumber(0.0);
		return;
	}

	float x = lua_getnumber(xObj);
	float y = lua_getnumber(yObj);
	float z = lua_getnumber(zObj);
	Math::Vector3d pos = Math::Vector3d(x, y, z);

	const Set::Setup *setup = g_emi->getCurrSet()->getCurrSetup();
	const Math::Vector3d interest = setup->_interest;
	const float roll = setup->_roll;
	const Math::Quaternion quat = Math::Quaternion(interest.x(), interest.y(), interest.z(), roll);
	Math::Matrix4 view = quat.toMatrix();
	view.transpose();

	pos -= setup->_pos;
	pos = view.getRotation() * pos;
	pos.z() = -pos.z();

	Math::Matrix4 proj = GfxBase::makeProjMatrix(setup->_fov, setup->_nclip, setup->_fclip);
	proj.transpose();
	Math::Vector4d screen = proj * Math::Vector4d(pos.x(), pos.y(), pos.z(), 1.0);
	screen /= screen.w();

	lua_pushnumber((screen.x() + 1) * 320);
	lua_pushnumber((1 - screen.y()) * 240);
}
Example #4
0
/**
 * @class Model
 */
Model::Model(const Common::String &filename, const char *data, int len, CMap *cmap, Model *parent) :
		Object(), _parent(parent), _numMaterials(0), _numGeosets(0), _cmap(cmap) {
	_fname = filename;

	if (g_grim->getGameType() == GType_MONKEY4) {
		Common::MemoryReadStream ms((const byte *)data, len);
		loadEMI(ms);
	} else if (len >= 4 && READ_BE_UINT32(data) == MKTAG('L','D','O','M'))
		loadBinary(data, cmap);
	else {
		TextSplitter ts(data, len);
		loadText(&ts, cmap);
	}

	Math::Vector3d max;

	_rootHierNode->update();
	bool first = true;
	for (int i = 0; i < _numHierNodes; ++i) {
		ModelNode &node = _rootHierNode[i];
		if (node._mesh) {
			Mesh &mesh = *node._mesh;
			//NOTE: Setting p to mesh._matrix._pos seems more similar to original
			// but, as in original, it also stops manny quite far away from the
			// bone wagon when approaching it from behind in set sg.
			// Using the node position looks instead more realistic, but, on the
			// other hand, it may not work right in all cases.
			Math::Vector3d p = node._matrix.getPosition();
			float x = p.x();
			float y = p.y();
			float z = p.z();
			for (int k = 0; k < mesh._numVertices * 3; k += 3) {
				if (first || mesh._vertices[k] + x < _bboxPos.x())
					_bboxPos.x() = mesh._vertices[k] + x;
				if (mesh._vertices[k + 1] + y < _bboxPos.y())
					_bboxPos.y() = mesh._vertices[k + 1] + y;
				if (mesh._vertices[k + 2] + z < _bboxPos.z())
					_bboxPos.z() = mesh._vertices[k + 2] + z;

				if (first || mesh._vertices[k] + x > max.x())
					max.x() = mesh._vertices[k] + x;
				if (mesh._vertices[k + 1] + y > max.y())
					max.y() = mesh._vertices[k + 1] + y;
				if (mesh._vertices[k + 2] + z > max.z())
					max.z() = mesh._vertices[k + 2] + z;

				first = false;
			}
		}
	}

	_bboxSize = max - _bboxPos;
}
Example #5
0
/**
 * @class Model
 */
Model::Model(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap, Model *parent) :
		Object(), _parent(parent), _numMaterials(0), _numGeosets(0), _cmap(cmap) {
	_fname = filename;

	if (g_grim->getGameType() == GType_MONKEY4) {
		loadEMI(data);
	} else if (data->readUint32BE() == MKTAG('L','D','O','M'))
		loadBinary(data, cmap);
	else {
		data->seek(0, SEEK_SET);
		TextSplitter ts(data);
		loadText(&ts, cmap);
	}
	delete data;

	Math::Vector3d max;

	_rootHierNode->update();
	bool first = true;
	for (int i = 0; i < _numHierNodes; ++i) {
		ModelNode &node = _rootHierNode[i];
		if (node._mesh) {
			Mesh &mesh = *node._mesh;
			Math::Vector3d p = mesh._matrix.getPosition();
			float x = p.x();
			float y = p.y();
			float z = p.z();
			for (int k = 0; k < mesh._numVertices * 3; k += 3) {
				if (first || mesh._vertices[k] + x < _bboxPos.x())
					_bboxPos.x() = mesh._vertices[k] + x;
				if (first || mesh._vertices[k + 1] + y < _bboxPos.y())
					_bboxPos.y() = mesh._vertices[k + 1] + y;
				if (first || mesh._vertices[k + 2] + z < _bboxPos.z())
					_bboxPos.z() = mesh._vertices[k + 2] + z;

				if (first || mesh._vertices[k] + x > max.x())
					max.x() = mesh._vertices[k] + x;
				if (first || mesh._vertices[k + 1] + y > max.y())
					max.y() = mesh._vertices[k + 1] + y;
				if (first || mesh._vertices[k + 2] + z > max.z())
					max.z() = mesh._vertices[k + 2] + z;

				first = false;
			}
		}
	}

	_bboxSize = max - _bboxPos;
}
void ShaderRenderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) {
  double x, y, z;

  x = screen.x;
  y = kOriginalHeight - screen.y;
  z = 0.9f;

  const Math::Vector2d tl = _viewport.getTopLeft();
  x = 2 * double(x - tl.getX()) / _viewport.getWidth() - 1.0f;
  y = 2 * double(y - tl.getY()) / _viewport.getHeight() - 1.0f;
  z = 2 * z - 1.0f;

  // Screen coords to 3D coords
  Math::Vector4d point = Math::Vector4d(x, y, z, 1.0f);
  point = _mvpMatrix * point;

  // 3D coords to polar coords
  Math::Vector3d v = Math::Vector3d(point.x(), point.y(), point.z());
  v.normalize();

  Math::Vector2d horizontalProjection = Math::Vector2d(v.x(), v.z());
  horizontalProjection.normalize();

  pitch = 90 - Math::Angle::arcCosine(v.y()).getDegrees();
  heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees();

  if (horizontalProjection.getX() > 0.0)
    heading = 360 - heading;
}
Example #7
0
Math::Vector3d Actor::getTangentPos(const Math::Vector3d &pos, const Math::Vector3d &dest) const {
	if (_collisionMode == CollisionOff) {
		return dest;
	}

	Model *model = getCurrentCostume()->getModel();
	Math::Vector3d p = _pos + model->_insertOffset;
	float size = model->_radius * _collisionScale;

	Math::Vector2d p1(pos.x(), pos.y());
	Math::Vector2d p2(dest.x(), dest.y());
	Math::Segment2d segment(p1, p2);

	// TODO: collision with Box
// 	if (_collisionMode == CollisionSphere) {
		Math::Vector2d center(p.x(), p.y());

		Math::Vector2d inter;
		float distance = segment.getLine().getDistanceTo(center, &inter);

		if (distance < size && segment.containsPoint(inter)) {
			Math::Vector2d v(inter - center);
			v.normalize();
			v *= size;
			v += center;

			return Math::Vector3d(v.getX(), v.getY(), dest.z());
		}
// 	} else {

// 	}

	return dest;
}
Example #8
0
/* Given a position and a size this function calculates and pushes
 * the nearest point to that which will be valid if the boxes are
 * shrunk by the amount specified.
 */
void Lua_V1::GetShrinkPos() {
	lua_Object xObj = lua_getparam(1);
	lua_Object yObj = lua_getparam(2);
	lua_Object zObj = lua_getparam(3);
	lua_Object rObj = lua_getparam(4);

	if (!lua_isnumber(xObj) || !lua_isnumber(yObj) || !lua_isnumber(zObj) || !lua_isnumber(rObj))
		return;

	float x = lua_getnumber(xObj);
	float y = lua_getnumber(yObj);
	float z = lua_getnumber(zObj);
	float r = lua_getnumber(rObj);
	Math::Vector3d pos;
	pos.set(x, y, z);

	Sector* sector;
	g_grim->getCurrSet()->shrinkBoxes(r);
	g_grim->getCurrSet()->findClosestSector(pos, &sector, &pos);
	g_grim->getCurrSet()->unshrinkBoxes();

	if (sector) {
		lua_pushnumber(pos.x());
		lua_pushnumber(pos.y());
		lua_pushnumber(pos.z());
	} else {
		lua_pushnil();
	}
}
Example #9
0
bool Sector::isPointInSector(const Math::Vector3d &point) const {
	// Calculate the distance of the point from the plane of the sector.
	// Return false if it isn't within a margin.
	if (_height < 9000.f) { // No need to check when height is 9999.
		// The plane has equation ax + by + cz + d = 0
		float a = _normal.x();
		float b = _normal.y();
		float c = _normal.z();
		float d = -_vertices[0].x() * a - _vertices[0].y() * b - _vertices[0].z() * c;

		float dist = (a * point.x() + b * point.y() + c * point.z() + d) /
					sqrt(a * a + b * b + c * c);
		// dist is positive if it is above the plain, negative if it is
		// below and 0 if it is on the plane.

		if (fabsf(dist) > _height + 0.01) // Add an error margin
			return false;
	}

	// On the plane, so check if it is inside the polygon.
	for (int i = 0; i < _numVertices; i++) {
		Math::Vector3d edge = _vertices[i + 1] - _vertices[i];
		Math::Vector3d delta = point - _vertices[i];
		if (edge.x() * delta.y() < edge.y() * delta.x())
			return false;
	}
	return true;
}
Example #10
0
void Lua_V2::GetActorPuckVector() {
	lua_Object actorObj = lua_getparam(1);
	lua_Object addObj = lua_getparam(2);

	if (!lua_isuserdata(actorObj) || lua_tag(actorObj) != MKTAG('A','C','T','R')) {
		lua_pushnil();
		return;
	}

	Actor *actor = getactor(actorObj);
	// Note: The wear chore of dumbshadow.cos is only started from Lua if
	// GetActorPuckVector returns a non-nil value. The original engine seems
	// to return nil for all actors that have never followed walkboxes.
	if (!actor || !actor->hasFollowedBoxes()) {
		lua_pushnil();
		return;
	}

	Math::Vector3d result = actor->getPuckVector();
	if (!lua_isnil(addObj))
		result += actor->getPos();

	lua_pushnumber(result.x());
	lua_pushnumber(result.y());
	lua_pushnumber(result.z());
}
Example #11
0
Math::Vector3d Sector::getProjectionToPuckVector(const Math::Vector3d &v) const {
	if (_normal.z() == 0)
		error("Trying to walk along vertical plane");

	Math::Vector3d result = v;
	result.z() -= Math::Vector3d::dotProduct(_normal, v) / _normal.z();
	return result;
}
Example #12
0
bool Actor::shouldDrawShadow(int shadowId) {
	Shadow *shadow = &_shadowArray[shadowId];
	if (!shadow->active)
		return false;

	// Don't draw a shadow if the shadow caster and the actor are on different sides
	// of the the shadow plane.
	Sector *sector = shadow->planeList.front().sector;
	Math::Vector3d n = sector->getNormal();
	Math::Vector3d p = sector->getVertices()[0];
	float d = -(n.x() * p.x() + n.y() * p.y() + n.z() * p.z());

	p = getPos();
	// Move the tested point a bit above ground level.
	if (g_grim->getGameType() == GType_MONKEY4)
		p.y() += 0.01;
	else
		p.z() += 0.01;
	bool actorSide = n.x() * p.x() + n.y() * p.y() + n.z() * p.z() + d < 0.f;
	p = shadow->pos;
	bool shadowSide = n.x() * p.x() + n.y() * p.y() + n.z() * p.z() + d < 0.f;

	if (actorSide == shadowSide)
		return true;
	return false;
}
Example #13
0
Math::Vector3d Sector::getProjectionToPlane(const Math::Vector3d &point) const {
	if (_normal.z() == 0)
		error("Trying to walk along vertical plane");

	// Formula: return p - (n . (p - v_0))/(n . k) k
	Math::Vector3d result = point;
	result.z() -= Math::Vector3d::dotProduct(_normal, point - _vertices[0]) / _normal.z();
	return result;
}
Example #14
0
Math::Angle Actor::getYawTo(const Math::Vector3d &p) const {
	Math::Vector3d dpos = p - _pos;

	if (g_grim->getGameType() == GType_MONKEY4) {
		dpos.y() = dpos.z();
	}
	if (dpos.x() == 0 && dpos.y() == 0)
		return 0;
	else
		return Math::Angle::arcTangent2(-dpos.x(), dpos.y());
}
Example #15
0
Math::Angle Actor::getYawTo(Actor *a) const {
	Math::Vector3d forwardVec = getSimplePuckVector();
	Math::Vector3d delta = a->getPos() - _pos;

	if (g_grim->getGameType() == GType_MONKEY4) {
		delta.y() = 0;
	} else {
		delta.z() = 0;
	}

	return Math::Vector3d::angle(forwardVec, delta);
}
Example #16
0
float Sector::distanceToPoint(const Math::Vector3d &point) const {
	// The plane has equation ax + by + cz + d = 0
	float a = _normal.x();
	float b = _normal.y();
	float c = _normal.z();
	float d = -_vertices[0].x() * a - _vertices[0].y() * b - _vertices[0].z() * c;

	// dist is positive if it is above the plain, negative if it is
	// below and 0 if it is on the plane.
	float dist = (a * point.x() + b * point.y() + c * point.z() + d);
	dist /= sqrt(a * a + b * b + c * c);
	return dist;
}
Example #17
0
bool Frustum::isInside(const Math::AABB &aabb) const {
	Math::Vector3d min = aabb.getMin();
	Math::Vector3d max = aabb.getMax();
	
	for (int i = 0; i < 6; ++i) {
		const Plane &plane = _planes[i];
		Math::Vector3d positive = min;

		if (plane._normal.x() >= 0.0f)
			positive.x() = max.x();
		if (plane._normal.y() >= 0.0f)
			positive.y() = max.y();
		if (plane._normal.z() >= 0.0f)
			positive.z() = max.z();

		float dist = _planes[i].getSignedDistance(positive);
		if (dist < 0.0f)
			return false;
	}

	return true;
}
Example #18
0
float Movement::computeAngleBetweenVectorsXYPlane(const Math::Vector3d &v1, const Math::Vector3d &v2) const {
	Math::Vector3d v1XY = v1;
	v1XY.z() = 0.0;

	Math::Vector3d v2XY = v2;
	v2XY.z() = 0.0;

	Math::Angle angle = Math::Vector3d::angle(v1XY, v2XY);
	Math::Vector3d cross = Math::Vector3d::crossProduct(v1XY, v2XY);
	if (cross.z() < 0) {
		angle = -angle;
	}

	return angle.getDegrees();
}
Example #19
0
void Lua_V2::GetActorWorldPos() {
	lua_Object actorObj = lua_getparam(1);

	if (!lua_isuserdata(actorObj) || lua_tag(actorObj) != MKTAG('A','C','T','R'))
		return;

	Actor *actor = getactor(actorObj);
	if (!actor)
		return;

	Math::Vector3d pos = actor->getWorldPos();
	lua_pushnumber(pos.x());
	lua_pushnumber(pos.y());
	lua_pushnumber(pos.z());
}
Example #20
0
void BaseRenderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) {
	// Screen coords to 3D coords
	Math::Vector3d obj;
	Math::gluMathUnProject(Math::Vector3d(screen.x, _system->getHeight() - screen.y, 0.9f), _mvpMatrix, frameViewport(), obj);

	// 3D coords to polar coords
	obj.normalize();

	Math::Vector2d horizontalProjection = Math::Vector2d(obj.x(), obj.z());
	horizontalProjection.normalize();

	pitch = 90 - Math::Angle::arcCosine(obj.y()).getDegrees();
	heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees();

	if (horizontalProjection.getX() > 0.0)
		heading = 360 - heading;
}
Example #21
0
void TinyGLRenderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) {
	// Screen coords to 3D coords
	Math::Vector3d obj;
	Math::gluMathUnProject<float, int>(Math::Vector3d(screen.x, kOriginalHeight - screen.y, 0.9),
		_cubeModelViewMatrix, _cubeProjectionMatrix, _cubeViewport, obj);

	// 3D coords to polar coords
	obj.normalize();

	Math::Vector2d horizontalProjection = Math::Vector2d(obj.x(), obj.z());
	horizontalProjection.normalize();

	pitch = 90 - Math::Angle::arcCosine(obj.y()).getDegrees();
	heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees();

	if (horizontalProjection.getX() > 0.0)
		heading = 360 - heading;
}
Example #22
0
void Renderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) {
	double x, y, z;

	// Screen coords to 3D coords
	gluUnProject(screen.x, kOriginalHeight - screen.y, 0.9, _cubeModelViewMatrix, _cubeProjectionMatrix, (GLint *)_cubeViewport, &x, &y, &z);

	// 3D coords to polar coords
	Math::Vector3d v = Math::Vector3d(x, y, z);
	v.normalize();

	Math::Vector2d horizontalProjection = Math::Vector2d(v.x(), v.z());
	horizontalProjection.normalize();

	pitch = 90 - Math::Angle::arcCosine(v.y()).getDegrees();
	heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees();

	if (horizontalProjection.getX() > 0.0)
		heading = 360 - heading;
}
Example #23
0
void Lua_V1::GetSectorOppositeEdge() {
	lua_Object actorObj = lua_getparam(1);
	lua_Object nameObj = lua_getparam(2);

	if (!lua_isuserdata(actorObj) || lua_tag(actorObj) != MKTAG('A','C','T','R'))
		return;

	if (!lua_isstring(nameObj)) {
		lua_pushnil();
		return;
	}

	Actor *actor = getactor(actorObj);
	const char *name = lua_getstring(nameObj);

	int numSectors = g_grim->getCurrSet()->getSectorCount();
	for (int i = 0; i < numSectors; i++) {
		Sector *sector = g_grim->getCurrSet()->getSectorBase(i);
		if (strmatch(sector->getName(), name)) {
			if (sector->getNumVertices() != 4)
				warning("GetSectorOppositeEdge(): cheat box with %d (!= 4) edges!", sector->getNumVertices());
			Math::Vector3d* vertices = sector->getVertices();
			Sector::ExitInfo e;

			sector->getExitInfo(actor->getPos(), -actor->getPuckVector(), &e);
			float frac = (e.exitPoint - vertices[e.edgeVertex + 1]).getMagnitude() / e.edgeDir.getMagnitude();
			e.edgeVertex -= 2;
			if (e.edgeVertex < 0)
				e.edgeVertex += sector->getNumVertices();
			Math::Vector3d edge = vertices[e.edgeVertex + 1] - vertices[e.edgeVertex];
			Math::Vector3d p = vertices[e.edgeVertex] + edge * frac;
			lua_pushnumber(p.x());
			lua_pushnumber(p.y());
			lua_pushnumber(p.z());

			return;
		}
	}

	lua_pushnil();
}
Example #24
0
static void polarRectTo3dRect(const PolarRect &polarRect,
                              Math::Vector3d &topLeft, Math::Vector3d &topRight,
                              Math::Vector3d &bottomLeft, Math::Vector3d &bottomRight) {
	static const float scale = 50.0;

	Math::Vector3d direction = Scene::directionToVector(polarRect.centerPitch, 90.0 - polarRect.centerHeading) * scale;

	Math::Vector3d u = Math::Vector3d(direction.z(), 0.0, -direction.x());
	u.normalize();

	Math::Vector3d v = Math::Vector3d::crossProduct(direction, u);
	v.normalize();

	Math::Vector3d sizeU = u * polarRect.width  / 90.0 * scale;
	Math::Vector3d sizeV = v * polarRect.height / 90.0 * scale;

	topRight = direction + sizeV + sizeU;
	bottomRight = direction - sizeV + sizeU;
	bottomLeft = direction - sizeV - sizeU;
	topLeft = direction + sizeV - sizeU;
}
Example #25
0
void Lua_V2::GetActorPuckVector() {
	lua_Object actorObj = lua_getparam(1);
	lua_Object addObj = lua_getparam(2);

	if (!lua_isuserdata(actorObj) || lua_tag(actorObj) != MKTAG('A','C','T','R')) {
		lua_pushnil();
		return;
	}

	Actor *actor = getactor(actorObj);
	if (!actor) {
		lua_pushnil();
		return;
	}

	Math::Vector3d result = actor->getPuckVector();
	if (!lua_isnil(addObj))
		result += actor->getPos();

	lua_pushnumber(result.x());
	lua_pushnumber(result.y());
	lua_pushnumber(result.z());
}
Example #26
0
/** 
 * Generates a lookat matrix. For reference, see 
 * http://clb.demon.fi/MathGeoLib/docs/float3x3_LookAt.php 
 */
void Matrix<3, 3>::buildFromTargetDir(const Math::Vector3d &modelForward, const Math::Vector3d &targetDirection, 
						   const Math::Vector3d &modelUp, const Math::Vector3d &worldUp)
{
    Math::Vector3d modelRight = Math::Vector3d::crossProduct(modelUp, modelForward);
	modelRight.normalize();
	Math::Vector3d worldRight = Math::Vector3d::crossProduct(worldUp, targetDirection);
	worldRight.normalize();
	Math::Vector3d perpWorldUp = Math::Vector3d::crossProduct(targetDirection, worldRight);
	perpWorldUp.normalize();
	
	Math::Matrix3 m1;
	m1.getRow(0) << worldRight.x() << worldRight.y() << worldRight.z();
	m1.getRow(1) << perpWorldUp.x() << perpWorldUp.y() << perpWorldUp.z();
	m1.getRow(2) << targetDirection.x() << targetDirection.y() << targetDirection.z();
	m1.transpose();
	
	Math::Matrix3 m2;
	m2.getRow(0) << modelRight.x() << modelRight.y() << modelRight.z();
	m2.getRow(1) << modelUp.x() << modelUp.y() << modelUp.z();
	m2.getRow(2) << modelForward.x() << modelForward.y() << modelForward.z();
	
	this->operator=(m1 * m2);
}
void ResourceSerializer::syncAsVector3d(Math::Vector3d &value) {
	syncAsFloat(value.x());
	syncAsFloat(value.y());
	syncAsFloat(value.z());
}
Example #28
0
void AnimationEmi::animate(Skeleton *skel, float delta) {
	_time += delta;
	if (_time > _duration) {
		_time = _duration;
	}

	for (int bone = 0; bone < _numBones; ++bone) {
		Bone &curBone = _bones[bone];
		if (!curBone._target)
			curBone._target = skel->getJointNamed(curBone._boneName);

		Math::Matrix4 &relFinal = curBone._target->_finalMatrix;
		Math::Quaternion &quatFinal = curBone._target->_finalQuat;

		if (curBone._rotations) {
			int keyfIdx = 0;
			Math::Quaternion quat;
			Math::Vector3d relPos = relFinal.getPosition();

			for (int curKeyFrame = 0; curKeyFrame < curBone._count; curKeyFrame++) {
				if (curBone._rotations[curKeyFrame]._time >= _time) {
					keyfIdx = curKeyFrame;
					break;
				}
			}

			if (keyfIdx == 0) {
				quat = curBone._rotations[keyfIdx]._quat;
			} else if (keyfIdx == curBone._count - 1) {
				quat = curBone._rotations[keyfIdx - 1]._quat;
			} else {
				float timeDelta = curBone._rotations[keyfIdx - 1]._time - curBone._rotations[keyfIdx]._time;
				float interpVal = (_time - curBone._rotations[keyfIdx]._time) / timeDelta;

				// Might be the other way around (keyfIdx - 1 slerped against keyfIdx)
				quat = curBone._rotations[keyfIdx]._quat.slerpQuat(curBone._rotations[keyfIdx - 1]._quat, interpVal);
			}
			quat.toMatrix(relFinal);
			quatFinal = quat;
			relFinal.setPosition(relPos);
		}

		if (curBone._translations) {
			int keyfIdx = 0;
			Math::Vector3d vec;

			for (int curKeyFrame = 0; curKeyFrame < curBone._count; curKeyFrame++) {
				if (curBone._translations[curKeyFrame]._time >= _time) {
					keyfIdx = curKeyFrame;
					break;
				}
			}

			if (keyfIdx == 0) {
				vec = curBone._translations[keyfIdx]._vec;
			} else if (keyfIdx == curBone._count - 1) {
				vec = curBone._translations[keyfIdx - 1]._vec;
			} else {
				float timeDelta = curBone._translations[keyfIdx - 1]._time - curBone._translations[keyfIdx]._time;
				float interpVal = (_time - curBone._translations[keyfIdx]._time) / timeDelta;

				vec.x() = curBone._translations[keyfIdx - 1]._vec.x() +
						  (curBone._translations[keyfIdx]._vec.x() - curBone._translations[keyfIdx - 1]._vec.x()) * interpVal;

				vec.y() = curBone._translations[keyfIdx - 1]._vec.y() +
						  (curBone._translations[keyfIdx]._vec.y() - curBone._translations[keyfIdx - 1]._vec.y()) * interpVal;

				vec.z() = curBone._translations[keyfIdx - 1]._vec.z() +
						  (curBone._translations[keyfIdx]._vec.z() - curBone._translations[keyfIdx - 1]._vec.z()) * interpVal;
			}
			relFinal.setPosition(vec);
		}
	}

}
Example #29
0
void Walk::onGameLoop() {
	if (!_path->hasSteps()) {
		// There is no path to the destination
		stop();
		return;
	}

	Resources::Floor *floor = StarkGlobal->getCurrent()->getFloor();

	// Get the target to walk to
	Math::Vector3d currentPosition = _item3D->getPosition3D();
	Math::Vector3d target = _path->computeWalkTarget(currentPosition);

	// Compute the direction to walk into
	Math::Vector3d direction = target - currentPosition;
	direction.z() = 0;
	direction.normalize();

	// Compute the angle with the current character direction
	Math::Vector3d currentDirection = _item3D->getDirectionVector();
	float directionDeltaAngle = computeAngleBetweenVectorsXYPlane(currentDirection, direction);

	// If the angle between the current direction and the new one is too high,
	// make the character turn on itself until the angle is low enough
	if (ABS(directionDeltaAngle) > getAngularSpeed() + 0.1f) {
		_turnDirection = directionDeltaAngle < 0 ? kTurnLeft : kTurnRight;
	} else {
		_turnDirection = kTurnNone;
	}

	float distancePerGameloop = computeDistancePerGameLoop();

	Math::Vector3d newPosition;
	if (_turnDirection == kTurnNone) {
		// Compute the new position using the distance per gameloop
		if (currentPosition.getDistanceTo(target) > distancePerGameloop) {
			newPosition = currentPosition + direction * distancePerGameloop;
		} else {
			newPosition = target;
		}
	} else {
		// The character does not change position when it is turning
		newPosition = currentPosition;
		direction = currentDirection;

		Math::Matrix3 rot;
		rot.buildAroundZ(_turnDirection == kTurnLeft ? -getAngularSpeed() : getAngularSpeed());
		rot.transformVector(&direction);
	}

	// Some scripts expect the character position to be the exact destination
	if (newPosition == _destination) {
		_reachedDestination = true;
		stop();
	}

	// Update the new position's height according to the floor
	int32 newFloorFaceIndex = floor->findFaceContainingPoint(newPosition);
	if (newFloorFaceIndex >= 0) {
		floor->computePointHeightInFace(newPosition, newFloorFaceIndex);
	} else {
		warning("Item %s is walking off the floor", _item->getName().c_str());
	}

	// Update the item's properties
	_item3D->setPosition3D(newPosition);
	if (direction.getMagnitude() != 0.0) {
		_item3D->setDirection(computeAngleBetweenVectorsXYPlane(direction, Math::Vector3d(1.0, 0.0, 0.0)));
	}
	if (newFloorFaceIndex >= 0) {
		// When unable to find the face containing the new position, keep the previous one
		// to prevent draw order glitches.
		_item3D->setFloorFaceIndex(newFloorFaceIndex);
	}

	changeItemAnim();
}
Example #30
0
void SaveGame::writeVector3d(const Math::Vector3d &vec) {
	writeFloat(vec.x());
	writeFloat(vec.y());
	writeFloat(vec.z());
}