Ejemplo n.º 1
0
void RenderSprite(float size, Vec3 *eyePos, Mat4 matModelView)
{
	if(size == 0)
		return;

	size /= 2;

	glPushMatrix();
    matModelView.Translate(*eyePos);
	matModelView = matModelView.Inverse();
	glMultMatrixf(matModelView.m);

	glDisable(GL_CULL_FACE);

	glBegin(GL_TRIANGLE_STRIP);
		glTexCoord2f(0.0f, 1.0f);
		glVertex3f( -size,  size, 0);
		glTexCoord2f(1.0f, 1.0f);
		glVertex3f( size,   size, 0);
		glTexCoord2f(0.0f, 0.0f);
		glVertex3f( -size, -size, 0);
		glTexCoord2f(1.0f, 0.0f);
		glVertex3f( size,  -size, 0);
	glEnd();

	glEnable(GL_CULL_FACE);

	glPopMatrix();
}
Ejemplo n.º 2
0
		bool GetShot(Shot* shot, Vec3 poi, Vec3 momentum)
		{
			if(blood_material != NULL)
				for (int i = 0; i < 8; ++i)
				{
					Particle* p = new Particle(corpse->game_state, poi, Random3D::RandomNormalizedVector(Random3D::Rand(5)) + momentum * Random3D::Rand(), NULL, blood_material, Random3D::Rand(0.05f, 0.15f), 0.25f);
					p->gravity = 9.8f;
					p->damp = 0.05f;

					corpse->game_state->Spawn(p);
				}

			Mat4 xform;
			{
				xform = rbi->GetTransformationMatrix();
				float ori_values[] = {xform[0], xform[1], xform[2], xform[4], xform[5], xform[6], xform[8], xform[9], xform[10]};
				Quaternion rigid_body_ori = Quaternion::FromRotationMatrix(Mat3(ori_values).Transpose());
				Vec3 pos = xform.TransformVec3(0, 0, 0, 1);
				xform = Mat4::FromPositionAndOrientation(pos, rigid_body_ori.ToMat3().Transpose());
			}

			Vec3 pos = xform.TransformVec3(0, 0, 0, 1);
			Vec3 x_axis = xform.TransformVec3(1, 0, 0, 0);
			Vec3 y_axis = xform.TransformVec3(0, 1, 0, 0);
			Vec3 z_axis = xform.TransformVec3(0, 0, 1, 0);

			Vec3 local_poi;
			local_poi = poi - pos;
			local_poi = Vec3(Vec3::Dot(local_poi, x_axis), Vec3::Dot(local_poi, y_axis), Vec3::Dot(local_poi, z_axis));
			local_poi = local_poi.x * x_axis + local_poi.y * y_axis + local_poi.z * z_axis;

			rbi->Activate();
			rbi->ApplyImpulse(momentum, local_poi);
			return true;
		}
Ejemplo n.º 3
0
	Mat4Stack(void)
	{
		Mat4<T>		mat;

		mat.setIdentity();
		stack.push(mat);
	}
Ejemplo n.º 4
0
void Geometry::update(u32 delta)
{
	char szPath[MAX_PATH] = {0};
	char szPath2[MAX_PATH];
	while(mAniTime.current > mAniTime.end)
	{
		mAniTime.current -= mAniTime.end;
	}
	if (mSkin && mSkeleton)
	{
		mSkeleton->update(mAniTime, *mSkin);
	}
	if (!mStopAimation)
	{
		mAniTime.current += delta * m_speed;;
	}
	//
	Vec3 speed(0.000, 0.000, 0.0);
	Quaternion q(0, 0, 0, 0.000*mAniTime.current);
	Mat4 tQ(q);
	Mat4 tT = Mat4::IDENTITY;
	Vec3 offsetMatrix(-0.5, -0.5, 0.0);
	tT.setTrans(offsetMatrix);
	mUVMatrix = tT.inverse() * tQ * tT;
	//
	mMaterial->update(delta);
}
Ejemplo n.º 5
0
Mat4 Mat4::scaled(float x, float y, float z) const {
    Mat4 m;
    m.v[0] = x;
    m.v[5] = y;
    m.v[10] = z;
    return m.mul(*this);
}
Ejemplo n.º 6
0
Mat4& BcCamera::GetTransform()
{
    Mat4* Ret = new Mat4();
    Ret->Translate(m_Position);
    Ret->Rotate(m_Rotation);
    return *Ret;
}
Ejemplo n.º 7
0
void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val)
{
  Mat4 O;

  O.loadIdentity();
  O.M[0][0] = 2.0 / (right - left);
  O.M[1][1] = 2.0 / (top - bottom);

  O.M[0][3] = -(right + left) / (right - left);
  O.M[1][3] = -(top + bottom) / (top - bottom);

  if (dxcompat_zrange01){
    O.M[2][2] = 1.0 /(far_val - near_val);
    O.M[2][3] = -near_val / (far_val - near_val);
  }
  else {
    O.M[2][2] = 2.0 / (far_val - near_val);   // -2.0 used in OpenGL documentation but can't be right!
    O.M[2][3] = -(far_val + near_val) / (far_val - near_val);
  }

  if (g_modelview)
    modelmat.mulrightby(O);
  else
    projectionmat.mulrightby(O);
}
Ejemplo n.º 8
0
Mat4 Mat4::translated(const Vec4 &dv) const {
    Mat4 m;
    m.set(3, 0, dv[0]);
    m.set(3, 1, dv[1]);
    m.set(3, 2, dv[2]);
    return m.mul(*this);
}
Ejemplo n.º 9
0
void Mat4::Rotate(const Vec3 &axis, const float angle)
{
	Mat4 tmp;
	
	tmp.BuildRotate(axis, angle);
	(*this) *= tmp;
}
Ejemplo n.º 10
0
void Mat4::RotateZ(const float angle)
{
	Mat4 tmp;
	
	tmp.BuildRotateZ(angle);
	(*this) *= tmp;
}
Ejemplo n.º 11
0
void calc_projective (const std::vector<double>& frame_ts,
                      const std::vector<Vec4>& gyro_quat,
                      const std::vector<Vec3>& acc_trans,
                      const std::vector<double>& gyro_ts,
                      CalibrationParams calib,
                      std::vector<Mat4>& projective)
{
    int index0 = 0;
    int index1 = 0;

    size_t frame_count = frame_ts.size();

    for (int fid = 0; fid < frame_count; fid++) {
        const double ts0 = frame_ts[fid] + calib.gyro_delay;
        Quatern quat0 = interp_gyro_quatern(ts0, gyro_quat, gyro_ts, index0) + Quatern(calib.gyro_drift);

        const double ts1 = frame_ts[fid + 1] + calib.gyro_delay;
        Quatern quat1 = interp_gyro_quatern(ts1, gyro_quat, gyro_ts, index1) + Quatern(calib.gyro_drift);

        Vec3 trans0 = acc_trans[fid];
        Vec3 trans1 = acc_trans[fid + 1];

        Mat4 extr0 = calc_extrinsic(quat0, trans0);
        Mat4 extr1 = calc_extrinsic(quat1, trans1);

        Mat3 intr = calc_intrinsic(calib.fx, calib.fy, calib.cx, calib.cy, calib.skew);

        Mat4 intrinsic = Mat4(Vec4(intr.v0, 0),
                              Vec4(intr.v1, 0),
                              Vec4(intr.v2, 0),
                              Vec4(0, 0, 0, 1));

        projective[fid] = intrinsic * extr0 * extr1.transpose() * intrinsic.inverse();
    }
}
Ejemplo n.º 12
0
Mat4 Entity::getModelMatrix() {
    Mat4 mat;
    mat.scale(scale.x, scale.y, scale.z);
    mat = mat * rotation;
    mat.translate(position);
    return mat;
}
Ejemplo n.º 13
0
Mat4 * get_transformation(Transform *self)
{
	Mat4 *t = NULL;
	Mat4 *r = NULL;
	Mat4 *s = NULL;

	t = mat4_init_translation(self->translation->x,
					        self->translation->y,
					  	    self->translation->z);
	r = mat4_init_rotation(self->rotation->x,
					        self->rotation->y,
					  	    self->rotation->z);
	s = mat4_init_scaling(self->scaling->x,
					        self->scaling->y,
					  	    self->scaling->z);

	if (t && r && s)
	{
		return(s->mul(s, (t->mul(t,r))));
	}
	else
	{
		return(NULL);
	}
}
void ABBTest::update(float dt)
{
    if (_pick)
        return;
    
    _drawAABB->clear();
    
    Vec3 extents = Vec3(60, 30, 60);
    _aabb = AABB(-extents, extents);
    
    static float angle = 0.f;
    if (angle > 360) {
        angle = 0;
    }
    angle+=0.01f;
    
    Mat4 mat = Mat4::IDENTITY;
    mat.rotate(Vec3::UNIT_Y, angle);
    
    _aabb.transform(mat);
    Vec3 corners[8] = {};
    _aabb.getCorners(corners);
    
    _drawAABB->setPosition3D(_aabb.getCenter());
    _drawAABB->drawCube(corners, Color4F(0,0,1,1));
}
Ejemplo n.º 15
0
void Camera::setTransform(const Vec4 &_pos, const Vec4 &_rotation )
{
  m_position = _pos;
  m_rotation = _rotation;

  m_viewMatrix.identity();

//  // Rotation
  m_viewMatrix.rotate(_rotation);

  // Translate
  Mat4 tmp;
  tmp.identity();
  tmp.m_m[3][0] = _pos.m_x;
  tmp.m_m[3][1] = _pos.m_y;
  tmp.m_m[3][2] = _pos.m_z;

//  tmp.m_m[0][3] *= -1;
//  tmp.m_m[3][0] *= -1;

//  tmp.m_m[1][3] *= -1;
//  tmp.m_m[3][1] *= -1;

  tmp *= m_viewMatrix;
  m_viewMatrix = tmp;

  setView();
}
Ejemplo n.º 16
0
bool Ray::intersects(const OBB& obb, float* distance) const
{
    AABB aabb;
    aabb._min = - obb._extents;
    aabb._max = obb._extents;

    Ray ray;
    ray._direction = _direction;
    ray._origin = _origin;

    Mat4 mat = Mat4::IDENTITY;
    mat.m[0] = obb._xAxis.x;
    mat.m[1] = obb._xAxis.y;
    mat.m[2] = obb._xAxis.z;

    mat.m[4] = obb._yAxis.x;
    mat.m[5] = obb._yAxis.y;
    mat.m[6] = obb._yAxis.z;

    mat.m[8] = obb._zAxis.x;
    mat.m[9] = obb._zAxis.y;
    mat.m[10] = obb._zAxis.z;

    mat.m[12] = obb._center.x;
    mat.m[13] = obb._center.y;
    mat.m[14] = obb._center.z;

    mat = mat.getInversed();

    ray.transform(mat);

    return ray.intersects(aabb, distance);

}
Ejemplo n.º 17
0
void ModelStatic::calculateBoundingBox(AABB& box)
{
    zeq_model_proto_t* proto = getModelPrototype();
    
    if (!proto)
        return;
    
    Mat4 matrix = getModelMatrix();
    Vec3 pos;
    
    for (VertexBuffer* vb : proto->getVertexBuffers())
    {
        for (Vertex& vert : *vb)
        {
            matrix.transformVector(pos, vert.pos);
            box.addInternalPoint(pos);
        }
    }
    
    for (VertexBuffer* vb : proto->getVertexBuffersNoCollide())
    {
        for (Vertex& vert : *vb)
        {
            matrix.transformVector(pos, vert.pos);
            box.addInternalPoint(pos);
        }
    }
}
Ejemplo n.º 18
0
Mat4 Quaternion::extractMat4() const {
    Mat4 result;

    result.set(0, 0, 1 - 2 * this->vector[Y] * this->vector[Y] -
                         2 * this->vector[Z] * this->vector[Z]);
    result.set(0, 1, 2 * this->vector[X] * this->vector[Y] -
                     2 * this->vector[Z] * this->vector[W]);
    result.set(0, 2, 2 * this->vector[X] * this->vector[Y] +
                     2 * this->vector[Y] * this->vector[W]);

    result.set(1, 0, 2 * this->vector[X] * this->vector[Y] +
                     2 * this->vector[Z] * this->vector[W]);
    result.set(1, 1, 1 - 2 * this->vector[X] * this->vector[X] -
                         2 * this->vector[Z] * this->vector[Z]);
    result.set(1, 2, 2 * this->vector[Y] * this->vector[Z] -
                     2 * this->vector[X] * this->vector[W]);

    result.set(2, 0, 2 * this->vector[X] * this->vector[Z] -
                     2 * this->vector[Y] * this->vector[W]);
    result.set(2, 1, 2 * this->vector[Y] * this->vector[Z] +
                     2 * this->vector[X] * this->vector[W]);
    result.set(2, 2, 1 - 2 * this->vector[X] * this->vector[X] -
                         2 * this->vector[Y] * this->vector[Y]);

    return result;
}
Ejemplo n.º 19
0
float Camera::getDepthInView(const Mat4& transform) const
{
    Mat4 camWorldMat = getNodeToWorldTransform();
    const Mat4 &viewMat = camWorldMat.getInversed();
    float depth = -(viewMat.m[2] * transform.m[12] + viewMat.m[6] * transform.m[13] + viewMat.m[10] * transform.m[14] + viewMat.m[14]);
    return depth;
}
Ejemplo n.º 20
0
Vec2 Director::convertToUI(const Vec2& glPoint)
{
    Mat4 transform;
    GLToClipTransform(&transform);

    Vec4 clipCoord;
    // Need to calculate the zero depth from the transform.
    Vec4 glCoord(glPoint.x, glPoint.y, 0.0, 1);
    transform.transformVector(glCoord, &clipCoord);

	/*
	BUG-FIX #5506

	a = (Vx, Vy, Vz, 1)
	b = (a×M)T
	Out = 1 ⁄ bw(bx, by, bz)
	*/
	
	clipCoord.x = clipCoord.x / clipCoord.w;
	clipCoord.y = clipCoord.y / clipCoord.w;
	clipCoord.z = clipCoord.z / clipCoord.w;

    Size glSize = _openGLView->getDesignResolutionSize();
    float factor = 1.0/glCoord.w;
    return Vec2(glSize.width*(clipCoord.x*0.5 + 0.5) * factor, glSize.height*(-clipCoord.y*0.5 + 0.5) * factor);
}
Ejemplo n.º 21
0
void WldModel::readObjectPlacements(WLD* wld)
{
    for (Fragment* frag : wld->getFragsByType(0x15))
    {
        Frag15* f15 = (Frag15*)frag;
        
        const char* modelName = wld->getFragName(f15->nameref);
        if (!modelName)
            continue;
        
        ConvModel* obj = getObjectDefinition(modelName);
        if (!obj)
            continue;
        
        float rotY = -(f15->rotX / 512.0f * 360.0f);
        float rotZ =   f15->rotY / 512.0f * 360.0f;
        
        Mat4 mat = Mat4::angleYZ(rotY, rotZ);
        mat.setTranslation(Vec3(f15->x, f15->z, f15->y));
        
        float scale = f15->scaleZ;
        
        if (scale != 0.0f && scale != 1.0f)
            mat = mat * Mat4::scale(scale);
        
        addObjectPlacement(mat, obj);
    }
}
Ejemplo n.º 22
0
void CanvasCairo::pathAltArcTo(float rx, float ry, float angle, bool largeArc, bool sweep, float x, float y) {
	double _x, _y;
	cairo_get_current_point (_context, &_x, &_y);

	rx = fabsf(rx); ry = fabsf(ry);

	Mat4 transform(Mat4::IDENTITY); Mat4::createRotationZ(angle, &transform);
	Mat4 inverse = transform; inverse.transpose();

	Vec2 vDash(cocos2d::PointApplyTransform(Vec2((_x - x) / 2, (_y - y) / 2), inverse));
	float lambda = (vDash.x * vDash.x) / (rx * rx) + (vDash.y * vDash.y) / (ry * ry);
	if (lambda > 1.0f) {
		rx = sqrtf(lambda) * rx; ry = sqrtf(lambda) * ry;
		vDash = Vec2(cocos2d::PointApplyTransform(Vec2((_x - x) / 2, (_y - y) / 2), inverse));
	}

	float rx_y1_ = (rx * rx * vDash.y * vDash.y);
	float ry_x1_ = (ry * ry * vDash.x * vDash.x);
	float cst = sqrtf(((rx * rx * ry * ry) - rx_y1_ - ry_x1_) / (rx_y1_ + ry_x1_));

	Vec2 cDash((largeArc != sweep ? 1.0f : -1.0f) * cst * rx * vDash.y / ry,
			(largeArc != sweep ? 1.0f : -1.0f) * - cst * ry * vDash.x / rx);

	float cx = cDash.x + (_x + x) / 2;
	float cy = cDash.y + (_y + y) / 2;

	float startAngle = Vec2::angle(Vec2(1.0f, 0.0f), Vec2((vDash.x - cDash.x) / rx, (vDash.y - cDash.y) / ry));
	float sweepAngle = Vec2::angle(Vec2((vDash.x - cDash.x) / rx, (vDash.y - cDash.y) / ry),
			Vec2((-vDash.x - cDash.x) / rx, (-vDash.y - cDash.y) / ry));

	pathArcTo(cx, cy, rx, ry, startAngle, sweepAngle, angle);
}
Ejemplo n.º 23
0
void glLoadMatrixf(const GLfloat *m)
{
	if (g_modelview)
		modelmat.set(m);
	else
		projectionmat.set(m);
}
Ejemplo n.º 24
0
Mat4 Mat4::rotated(float angle, const Vec4 &axis) const {
    Mat4 m;
    Vec4 r = axis.normalized();
    float c, s, t;
    s = sinf(angle);
    c = cosf(angle);
    t = 1.0f - c;

    m[0] = t * r[0] * r[0] + c;
    m[1] = t * r[0] * r[1] - s * r[2];
    m[2] = t * r[0] * r[2] + s * r[1];
    m[3] = 0.0f;

    m[4] = t * r[0] * r[1] + s * r[2];
    m[5] = t * r[1] * r[1] + c;
    m[6] = t * r[1] * r[2] - s * r[0];
    m[7] = 0.0f;

    m[8]  = t * r[0] * r[2] - s * r[1];
    m[9]  = t * r[1] * r[2] + s * r[0];
    m[10] = t * r[2] * r[2] + c;
    m[11] = 0.0f;

    m[12] = 0.0f;
    m[13] = 0.0f;
    m[14] = 0.0f;
    m[15] = 1.0f;
    
    return m.mul(*this);
}
Ejemplo n.º 25
0
void Physics3DComponent::syncPhysicsToNode()
{
    if (_physics3DObj->getObjType() == Physics3DObject::PhysicsObjType::RIGID_BODY
     || _physics3DObj->getObjType() == Physics3DObject::PhysicsObjType::COLLIDER)
    {
        Mat4 parentMat;
        if (_owner->getParent())
            parentMat = _owner->getParent()->getNodeToWorldTransform();
        
        auto mat = parentMat.getInversed() * _physics3DObj->getWorldTransform();
        //remove scale, no scale support for physics
        float oneOverLen = 1.f / sqrtf(mat.m[0] * mat.m[0] + mat.m[1] * mat.m[1] + mat.m[2] * mat.m[2]);
        mat.m[0] *= oneOverLen;
        mat.m[1] *= oneOverLen;
        mat.m[2] *= oneOverLen;
        oneOverLen = 1.f / sqrtf(mat.m[4] * mat.m[4] + mat.m[5] * mat.m[5] + mat.m[6] * mat.m[6]);
        mat.m[4] *= oneOverLen;
        mat.m[5] *= oneOverLen;
        mat.m[6] *= oneOverLen;
        oneOverLen = 1.f / sqrtf(mat.m[8] * mat.m[8] + mat.m[9] * mat.m[9] + mat.m[10] * mat.m[10]);
        mat.m[8] *= oneOverLen;
        mat.m[9] *= oneOverLen;
        mat.m[10] *= oneOverLen;
        
        mat *= _transformInPhysics;
        static Vec3 scale, translation;
        static Quaternion quat;
        mat.decompose(&scale, &quat, &translation);
        _owner->setPosition3D(translation);
        quat.normalize();
        _owner->setRotationQuat(quat);
    }
}
Ejemplo n.º 26
0
void GLProgram::setUniformsForBuiltins(const Mat4 &matrixM)
{
	auto& vp = _director->getVPMat();
	
	if (_flags.usesM)
		setUniformLocationWithMatrix4fv(_builtInUniforms[UNIFORM_M_MATRIX], matrixM.m, 1);

	if (_flags.usesV)
		setUniformLocationWithMatrix4fv(_builtInUniforms[UNIFORM_V_MATRIX], vp.view.m, 1);

    if (_flags.usesP)
        setUniformLocationWithMatrix4fv(_builtInUniforms[UNIFORM_P_MATRIX], vp.projection.m, 1);

	if (_flags.usesVP)
		setUniformLocationWithMatrix4fv(_builtInUniforms[UNIFORM_VP_MATRIX], vp.viewProjection.m, 1);

	if (_flags.usesMV) {
		Mat4 matrixMV = vp.view * matrixM;
		setUniformLocationWithMatrix4fv(_builtInUniforms[UNIFORM_MV_MATRIX], matrixMV.m, 1);
	}

	if (_flags.usesEyePosition)
	{
		auto pos = Camera::getVisitingCamera()->getEyePosition();		
		setUniformLocationWith3f(_builtInUniforms[UNIFORM_EYE_POSITION], pos.x, pos.y, pos.z);
	}

    if (_flags.usesMVP) {
        Mat4 matrixMVP = vp.viewProjection * matrixM;
        setUniformLocationWithMatrix4fv(_builtInUniforms[UNIFORM_MVP_MATRIX], matrixMVP.m, 1);
    }

    if (_flags.usesNormal)
    {
        Mat4 mvInverse = matrixM;
        mvInverse.m[12] = mvInverse.m[13] = mvInverse.m[14] = 0.0f;
        mvInverse.inverse();
        mvInverse.transpose();
        GLfloat normalMat[9];
        normalMat[0] = mvInverse.m[0];normalMat[1] = mvInverse.m[1];normalMat[2] = mvInverse.m[2];
        normalMat[3] = mvInverse.m[4];normalMat[4] = mvInverse.m[5];normalMat[5] = mvInverse.m[6];
        normalMat[6] = mvInverse.m[8];normalMat[7] = mvInverse.m[9];normalMat[8] = mvInverse.m[10];
        setUniformLocationWithMatrix3fv(_builtInUniforms[UNIFORM_NORMAL_MATRIX], normalMat, 1);
    }

    if (_flags.usesTime) {
        // This doesn't give the most accurate global time value.
        // Cocos2D doesn't store a high precision time value, so this will have to do.
        // Getting Mach time per frame per shader using time could be extremely expensive.
        float time = _director->getTotalFrames() * _director->getAnimationInterval();
		 
        setUniformLocationWith4f(_builtInUniforms[GLProgram::UNIFORM_TIME], time/10.0, time, time*2, time*4);
        setUniformLocationWith4f(_builtInUniforms[GLProgram::UNIFORM_SIN_TIME], time/8.0, time/4.0, time/2.0, sinf(time));
        setUniformLocationWith4f(_builtInUniforms[GLProgram::UNIFORM_COS_TIME], time/8.0, time/4.0, time/2.0, cosf(time));
    }

    if (_flags.usesRandom)
        setUniformLocationWith4f(_builtInUniforms[GLProgram::UNIFORM_RANDOM01], CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1());
}
Ejemplo n.º 27
0
Vec2 Node::convertToNodeSpace(const Vec2& worldPoint) const
{
    Mat4 tmp = getWorldToNodeTransform();
    Vec3 vec3(worldPoint.x, worldPoint.y, 0);
    Vec3 ret;
    tmp.transformPoint(vec3,&ret);
    return Vec2(ret.x, ret.y);
}
Vec3 BillboardParticleSystem::convertToNodeSpace3D(const Vec3& worldPoint) const
{
    Mat4 tmp = getWorldToNodeTransform();
    Vec3 vec3(worldPoint.x, worldPoint.y, worldPoint.z);
    Vec3 ret;
    tmp.transformPoint(vec3,&ret);
    return Vec3(ret.x, ret.y,ret.z);
}
Ejemplo n.º 29
0
Mat4 Camera::GetTransform()
{
	Mat4 transform;
	transform.MakeHRot(Vec3(1.0f, 0.0f, 0.0f), Pitch);
	transform *= HRot4(Vec3(0.0f, 1.0f, 0.0f), Yaw);
	transform *= HTrans4(Position);
	return transform;
}
Ejemplo n.º 30
0
Mat4 stableBasisFromUpVector(const Vec4 &up) {
    Vec4 fwd = Vec4(0,1,0).orth(up).normalized();
    Vec4 side = fwd.cross(up).normalized();
    Mat4 mat;
    mat.setXVector(side);
    mat.setYVector(up.normalized());
    mat.setZVector(fwd);
    return mat;
}