Example #1
0
void Circle::append(IndexedVertexBatch<XYZ, GLushort> &batch, const Matrix &matrix, float x, float y) const
{
    float aa = fabsf(a2 - a1);
    int n = ceilf(aa * r / segmentLength) + 1;

    batch.addVertex(matrix.transformPoint(x, y));

    for (int i = 0; i < n; i++)
    {
        float dd = a1 + fminf(aa, i * segmentLength / r);
        float xx = +sinf(dd) * r;
        float yy = +cosf(dd) * r;

        batch.addVertex(matrix.transformPoint(x + xx, y + yy));

        if (i < n - 1)
        {
            if (frontFace == CW)
            {
                batch.addIndices(i + 1, 0, i + 2);
            }
            else
            {
                batch.addIndices(0, i + 1, i + 2);
            }
        }
    }

    batch.incrementIndices(n + 1);
}
Example #2
0
//------------------------------------------------------------------------------
void Plane::transform(const Matrix & mat)
{
    Vector p1 = mat.transformPoint(-d_*normal_);
    Vector p2 = mat.transformPoint((-d_ + 1.0f)*normal_);

    normal_ = p2-p1;
    normal_.normalize();
    setPointOnPlane(p1);
}
Example #3
0
static Vec3 evaluateSkin(Vec3& p, Mesh::Skin s, const Matrix* matrices)
{
	Matrix m = matrices[s.indices[0]] * s.weights.x + matrices[s.indices[1]] * s.weights.y +
			   matrices[s.indices[2]] * s.weights.z + matrices[s.indices[3]] * s.weights.w;

	return m.transformPoint(p);
}
Example #4
0
Vector2 Node::convertToNodeSpace(const Vector2& worldPoint) const
{
    Matrix tmp = getWorldToNodeTransform();
    Vector3 vec3(worldPoint.x, worldPoint.y, 0);
    Vector3 ret;
    tmp.transformPoint(vec3,&ret);
    return Vector2(ret.x, ret.y);
}
Example #5
0
Vector2 Node::convertToWorldSpace(const Vector2& nodePoint) const
{
    Matrix tmp = getNodeToWorldTransform();
    Vector3 vec3(nodePoint.x, nodePoint.y, 0);
    Vector3 ret;
    tmp.transformPoint(vec3,&ret);
    return Vector2(ret.x, ret.y);

}
Example #6
0
//------------------------------------------------------------------------------
void Tank::doTerrainWheelCollision(Wheel & wheel, const Matrix & tank_transform, bool bicubic)
{
    terrain_data_->collideRay(wheel.collision_info_,
                              tank_transform.transformPoint(wheel.pos_),
                              tank_transform.getY(),
                              wheel.prev_penetration_,
                              bicubic);    

    wheel.prev_penetration_ = wheel.collision_info_.penetration_;
}
Example #7
0
bool Form::projectPoint(int x, int y, Vector3* point)
{
    Scene* scene = _node->getScene();
    GP_ASSERT(scene);
    Camera* camera = scene->getActiveCamera();

    if (camera)
    {
        // Get info about the form's position.
        Matrix m = _node->getMatrix();
        Vector3 min(0, 0, 0);
        m.transformPoint(&min);

        // Unproject point into world space.
        Ray ray;
        camera->pickRay(Game::getInstance()->getViewport(), x, y, &ray);

        // Find the quad's plane.  We know its normal is the quad's forward vector.
        Vector3 normal = _node->getForwardVectorWorld();

        // To get the plane's distance from the origin, we'll find the distance from the plane defined
        // by the quad's forward vector and one of its points to the plane defined by the same vector and the origin.
        const float& a = normal.x; const float& b = normal.y; const float& c = normal.z;
        const float d = -(a*min.x) - (b*min.y) - (c*min.z);
        const float distance = abs(d) /  sqrt(a*a + b*b + c*c);
        Plane plane(normal, -distance);

        // Check for collision with plane.
        float collisionDistance = ray.intersects(plane);
        if (collisionDistance != Ray::INTERSECTS_NONE)
        {
            // Multiply the ray's direction vector by collision distance and add that to the ray's origin.
            point->set(ray.getOrigin() + collisionDistance*ray.getDirection());

            // Project this point into the plane.
            m.invert();
            m.transformPoint(point);

            return true;
        }
    }
    return false;
}
Example #8
0
void BoundingVolume::transform(const Matrix& m)
{
    // Transform the bounding sphere
    m.transformPoint(center, &center);
    Vector3 translate;
    m.decompose(&translate, NULL, NULL);
    float r = radius * translate.x;
    r = std::max(radius, radius * translate.y);
    r = std::max(radius, radius * translate.z);
    radius = r;

    // Transform the bounding box
    Vector3 corners[8];
    corners[0].set(min.x, max.y, max.z);
    // Left-bottom-front.
    corners[1].set(min.x, min.y, max.z);
    // Right-bottom-front.
    corners[2].set(max.x, min.y, max.z);
    // Right-top-front.
    corners[3].set(max.x, max.y, max.z);
    // Right-top-back.
    corners[4].set(max.x, max.y, min.z);
    // Right-bottom-back.
    corners[5].set(max.x, min.y, min.z);
    // Left-bottom-back.
    corners[6].set(min.x, min.y, min.z);
    // Left-top-back.
    corners[7].set(min.x, max.y, min.z);

    // Transform the corners, recalculating the min and max points along the way.
    m.transformPoint(corners[0], &corners[0]);
    Vector3 newMin = corners[0];
    Vector3 newMax = corners[0];
    for (int i = 1; i < 8; i++)
    {
        m.transformPoint(corners[i], &corners[i]);
        updateMinMax(&corners[i], &newMin, &newMax);
    }
    min = newMin;
    max = newMax;
}
Example #9
0
void Renderer::convertToWorldCoordinates(V3F_C4B_T2F_Quad* quads, ssize_t quantity, const Matrix& modelView)
{
//    kmMat4 matrixP, mvp;
//    kmGLGetMatrix(KM_GL_PROJECTION, &matrixP);
//    kmMat4Multiply(&mvp, &matrixP, &modelView);
    for(ssize_t i=0; i<quantity; ++i)
    {
        V3F_C4B_T2F_Quad *q = &quads[i];
        Vector3 *vec1 = (Vector3*)&q->bl.vertices;
        modelView.transformPoint(vec1);

        Vector3 *vec2 = (Vector3*)&q->br.vertices;
        modelView.transformPoint(vec2);

        Vector3 *vec3 = (Vector3*)&q->tr.vertices;
        modelView.transformPoint(vec3);

        Vector3 *vec4 = (Vector3*)&q->tl.vertices;
        modelView.transformPoint(vec4);
    }
}
Example #10
0
bool Form::projectPoint(int x, int y, Vector3* point)
{
    Scene* scene = _node->getScene();
    Camera* camera;

    if (scene && (camera = scene->getActiveCamera()))
    {
        // Get info about the form's position.
        Matrix m = _node->getWorldMatrix();
        Vector3 pointOnPlane(0, 0, 0);
        m.transformPoint(&pointOnPlane);

        // Unproject point into world space.
        Ray ray;
        camera->pickRay(Game::getInstance()->getViewport(), x, y, &ray);

        // Find the quad's plane.  We know its normal is the quad's forward vector.
        Vector3 normal = _node->getForwardVectorWorld().normalize();

        // To get the plane's distance from the origin, we project a point on the
        // plane onto the plane's normal vector.
        const float distance = fabs(Vector3::dot(pointOnPlane, normal));
        Plane plane(normal, -distance);

        // Check for collision with plane.
        float collisionDistance = ray.intersects(plane);
        if (collisionDistance != Ray::INTERSECTS_NONE)
        {
            // Multiply the ray's direction vector by collision distance and add that to the ray's origin.
            point->set(ray.getOrigin() + collisionDistance*ray.getDirection());

            // Project this point into the plane.
            m.invert();
            m.transformPoint(point);

            return true;
        }
    }
    return false;
}
Example #11
0
void BoundingSphere::transform(const Matrix& matrix)
{
    // Translate the center point.
    matrix.transformPoint(center, &center);

    // Scale the sphere's radius by the scale fo the matrix
    Vector3 scale;
    matrix.decompose(&scale, NULL, NULL);
    float r = radius * scale.x;
    r = max(r, radius * scale.y);
    r = max(r, radius * scale.z);
    radius = r;
}
Example #12
0
void BoundingBox::transform(const Matrix& matrix)
{
    // Calculate the corners.
    Vector3 corners[8];
    getCorners(corners);

    // Transform the corners, recalculating the min and max points along the way.
    matrix.transformPoint(&corners[0]);
    Vector3 newMin = corners[0];
    Vector3 newMax = corners[0];
    for (int i = 1; i < 8; i++)
    {
        matrix.transformPoint(&corners[i]);
        updateMinMax(&corners[i], &newMin, &newMax);
    }
    this->min.x = newMin.x;
    this->min.y = newMin.y;
    this->min.z = newMin.z;
    this->max.x = newMax.x;
    this->max.y = newMax.y;
    this->max.z = newMax.z;
}
void ParticleEmitter::emitOnce(unsigned int particleCount)
{
    GP_ASSERT(_node);
    GP_ASSERT(_particles);

    // Limit particleCount so as not to go over _particleCountMax.
    if (particleCount + _particleCount > _particleCountMax)
    {
        particleCount = _particleCountMax - _particleCount;
    }

    Vector3 translation;
    Matrix world = _node->getWorldMatrix();
    world.getTranslation(&translation);

    // Take translation out of world matrix so it can be used to rotate orbiting properties.
    world.m[12] = 0.0f;
    world.m[13] = 0.0f;
    world.m[14] = 0.0f;

    // Emit the new particles.
    for (unsigned int i = 0; i < particleCount; i++)
    {
        Particle* p = &_particles[_particleCount];
        p->_visible = true;

        generateColor(_colorStart, _colorStartVar, &p->_colorStart);
        generateColor(_colorEnd, _colorEndVar, &p->_colorEnd);
        p->_color.set(p->_colorStart);

        p->_energy = p->_energyStart = generateScalar(_energyMin, _energyMax);
        p->_size = p->_sizeStart = generateScalar(_sizeStartMin, _sizeStartMax);
        p->_sizeEnd = generateScalar(_sizeEndMin, _sizeEndMax);
        p->_rotationPerParticleSpeed = generateScalar(_rotationPerParticleSpeedMin, _rotationPerParticleSpeedMax);
        p->_angle = generateScalar(0.0f, p->_rotationPerParticleSpeed);
        p->_rotationSpeed = generateScalar(_rotationSpeedMin, _rotationSpeedMax);

        // Only initial position can be generated within an ellipsoidal domain.
        generateVector(_position, _positionVar, &p->_position, _ellipsoid);
        generateVector(_velocity, _velocityVar, &p->_velocity, false);
        generateVector(_acceleration, _accelerationVar, &p->_acceleration, false);
        generateVector(_rotationAxis, _rotationAxisVar, &p->_rotationAxis, false);

        // Initial position, velocity and acceleration can all be relative to the emitter's transform.
        // Rotate specified properties by the node's rotation.
        if (_orbitPosition)
        {
            world.transformPoint(p->_position, &p->_position);
        }

        if (_orbitVelocity)
        {
            world.transformPoint(p->_velocity, &p->_velocity);
        }

        if (_orbitAcceleration)
        {
            world.transformPoint(p->_acceleration, &p->_acceleration);
        }

        // The rotation axis always orbits the node.
        if (p->_rotationSpeed != 0.0f && !p->_rotationAxis.isZero())
        {
            world.transformPoint(p->_rotationAxis, &p->_rotationAxis);
        }

        // Translate position relative to the node's world space.
        p->_position.add(translation);

        // Initial sprite frame.
        if (_spriteFrameRandomOffset > 0)
        {
            p->_frame = rand() % _spriteFrameRandomOffset;
        }
        else
        {
            p->_frame = 0;
        }
        p->_timeOnCurrentFrame = 0.0f;

        ++_particleCount;
    }
}
Example #14
0
void TileMap::doDraw(const CurrentTransform& transform, float hsx, float hsy, float hex, float hey)
{
	int sx, sy, ex, ey;
	{
        // inverse transformed hardware start/end x/y
        float x1, y1, x2, y2, x3, y3, x4, y4;
        Matrix inverse = transform.inverse();
        inverse.transformPoint(hsx, hsy, &x1, &y1);
        inverse.transformPoint(hex, hsy, &x2, &y2);
        inverse.transformPoint(hsx, hey, &x3, &y3);
        inverse.transformPoint(hex, hey, &x4, &y4);
        float thsx = std::min(std::min(x1, x2), std::min(x3, x4));
        float thsy = std::min(std::min(y1, y2), std::min(y3, y4));
        float thex = std::max(std::max(x1, x2), std::max(x3, x4));
        float they = std::max(std::max(y1, y2), std::max(y3, y4));

        // cell size width, cell size height
        float csw = std::max(std::max(tilewidth_, tileheight_), displaywidth_);
        float csh = std::max(std::max(tilewidth_, tileheight_), displayheight_);

        sx = floor((thsx - csw) / displaywidth_) + 1;
        sy = floor(thsy / displayheight_);
        ex = floor(thex / displaywidth_) + 1;
        ey = floor((they + csh) / displayheight_);

        // extra 1 block around
        sx--;
        sy--;
        ex++;
        ey++;

        sx = std::max(sx, 0);
        sy = std::max(sy, 0);
        ex = std::min(ex, width_);
        ey = std::min(ey, height_);
	}

	int tileCount = 0;
	for (int y = sy; y < ey; ++y)
		for (int x = sx; x < ex; ++x)
		{
			int index = x + y * width_;

            int tx = tileids_[index].x;
            int ty = tileids_[index].y;

			if (!isEmpty(tx, ty))
				tileCount++;
		}

	if (tileCount == 0)
		return;

	vertices.resize(tileCount * 12);
	texcoords.resize(tileCount * 12);

	int pos = 0;

	for (int y = sy; y < ey; ++y)
		for (int x = sx; x < ex; ++x)
		{
			int index = x + y * width_;

            int tx = tileids_[index].x;
            int ty = tileids_[index].y;
            int flip = tileids_[index].flip;

			if (!isEmpty(tx, ty))
			{
                bool flip_horizontal = (flip & FLIP_HORIZONTAL);
                bool flip_vertical = (flip & FLIP_VERTICAL);
                bool flip_diagonal = (flip & FLIP_DIAGONAL);

                float x0, y0, x1, y1;

                if (!flip_diagonal)
                {
                    x0 = x * displaywidth_;
                    y0 = y * displayheight_ - (tileheight_ - displayheight_);
                    x1 = x0 + tilewidth_;
                    y1 = y0 + tileheight_;
                }
                else
                {
                    x0 = x * displaywidth_;
                    y0 = y * displayheight_ - (tilewidth_ - displayheight_);
                    x1 = x0 + tileheight_;
                    y1 = y0 + tilewidth_;
                }

				vertices[pos + 0]  = x0; vertices[pos + 1]  = y0;
				vertices[pos + 2]  = x1; vertices[pos + 3]  = y0;
				vertices[pos + 4]  = x0; vertices[pos + 5]  = y1;
				vertices[pos + 6]  = x1; vertices[pos + 7]  = y0;
				vertices[pos + 8]  = x1; vertices[pos + 9]  = y1;
				vertices[pos + 10] = x0; vertices[pos + 11] = y1;

				int u0 = marginx_ + tx * (tilewidth_ + spacingx_);
				int v0 = marginy_ + ty * (tileheight_ + spacingy_);
				int u1 = marginx_ + tx * (tilewidth_ + spacingx_) + tilewidth_;
				int v1 = marginy_ + ty * (tileheight_ + spacingy_) + tileheight_;

                float fu0 = (float)u0 / (float)texture_->data->exwidth;
                float fv0 = (float)v0 / (float)texture_->data->exheight;
                float fu1 = (float)u1 / (float)texture_->data->exwidth;
                float fv1 = (float)v1 / (float)texture_->data->exheight;

                fu0 *= texture_->uvscalex;
                fv0 *= texture_->uvscaley;
                fu1 *= texture_->uvscalex;
                fv1 *= texture_->uvscaley;

                if (flip_horizontal)
                    std::swap(fu0, fu1);

                if (flip_vertical)
                    std::swap(fv0, fv1);

                if (flip_diagonal && (flip_vertical != flip_horizontal))
                {
                    std::swap(fu0, fu1);
                    std::swap(fv0, fv1);
                }

                fu0 += 0.0001f;
                fv0 += 0.0001f;
                fu1 -= 0.0001f;
                fv1 -= 0.0001f;

                if (!flip_diagonal)
                {
                    texcoords[pos + 0]  = fu0; texcoords[pos + 1]  = fv0;
                    texcoords[pos + 2]  = fu1; texcoords[pos + 3]  = fv0;
                    texcoords[pos + 4]  = fu0; texcoords[pos + 5]  = fv1;
                    texcoords[pos + 6]  = fu1; texcoords[pos + 7]  = fv0;
                    texcoords[pos + 8]  = fu1; texcoords[pos + 9]  = fv1;
                    texcoords[pos + 10] = fu0; texcoords[pos + 11] = fv1;
                }
                else
                {
                    texcoords[pos + 0]  = fu0; texcoords[pos + 1]  = fv0;
                    texcoords[pos + 2]  = fu0; texcoords[pos + 3]  = fv1;
                    texcoords[pos + 4]  = fu1; texcoords[pos + 5]  = fv0;
                    texcoords[pos + 6]  = fu0; texcoords[pos + 7]  = fv1;
                    texcoords[pos + 8]  = fu1; texcoords[pos + 9]  = fv1;
                    texcoords[pos + 10] = fu1; texcoords[pos + 11] = fv0;
                }

				pos += 12;
			}
		}

	oglEnable(GL_TEXTURE_2D);

    oglBindTexture(GL_TEXTURE_2D, texture_->data->id());

	oglArrayPointer(VertexArray,2, GL_FLOAT, &vertices[0]);
	oglEnableClientState(VertexArray);

	oglArrayPointer(TextureArray,2, GL_FLOAT, &texcoords[0]);
	oglEnableClientState(TextureArray);

	oglDrawArrays(GL_TRIANGLES, 0, tileCount * 6);

	oglDisableClientState(VertexArray);
	oglDisableClientState(TextureArray);
}
Example #15
0
    bool Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
    {
        // Check for a collision with each Form in __forms.
        // Pass the event on.
        std::vector<Form*>::const_iterator it;
        for (it = __forms.begin(); it < __forms.end(); it++)
        {
            Form* form = *it;

            if (form->isEnabled())
            {
                Node* node = form->_node;
                if (node)
                {
                    Scene* scene = node->getScene();
                    Camera* camera = scene->getActiveCamera();

                    if (camera)
                    {
                        // Get info about the form's position.
                        Matrix m = node->getMatrix();
                        Vector3 min(0, 0, 0);
                        m.transformPoint(&min);

                        // Unproject point into world space.
                        Ray ray;
                        camera->pickRay(Game::getInstance()->getViewport(), x, y, &ray);

                        // Find the quad's plane.
                        // We know its normal is the quad's forward vector.
                        Vector3 normal = node->getForwardVectorWorld();

                        // To get the plane's distance from the origin,
                        // we'll find the distance from the plane defined
                        // by the quad's forward vector and one of its points
                        // to the plane defined by the same vector and the origin.
                        const float& a = normal.x; const float& b = normal.y; const float& c = normal.z;
                        const float d = -(a*min.x) - (b*min.y) - (c*min.z);
                        const float distance = abs(d) /  sqrt(a*a + b*b + c*c);
                        Plane plane(normal, -distance);

                        // Check for collision with plane.
                        float collisionDistance = ray.intersects(plane);
                        if (collisionDistance != Ray::INTERSECTS_NONE)
                        {
                            // Multiply the ray's direction vector by collision distance
                            // and add that to the ray's origin.
                            Vector3 point = ray.getOrigin() + collisionDistance*ray.getDirection();

                            // Project this point into the plane.
                            m.invert();
                            m.transformPoint(&point);

                            // Pass the touch event on.
                            const Rectangle& bounds = form->getClipBounds();
                            if (form->getState() == Control::FOCUS ||
                                (evt == Touch::TOUCH_PRESS &&
                                 point.x >= bounds.x &&
                                 point.x <= bounds.x + bounds.width &&
                                 point.y >= bounds.y &&
                                 point.y <= bounds.y + bounds.height))
                            {
                               if (form->touchEvent(evt, point.x - bounds.x, bounds.height - point.y - bounds.y, contactIndex))
                               {
                                   return true;
                               }
                            }
                        }
                    }
                }
                else
                {
                    // Simply compare with the form's bounds.
                    const Rectangle& bounds = form->getClipBounds();
                    if (form->getState() == Control::FOCUS ||
                        (evt == Touch::TOUCH_PRESS &&
                         x >= bounds.x &&
                         x <= bounds.x + bounds.width &&
                         y >= bounds.y &&
                         y <= bounds.y + bounds.height))
                    {
                        // Pass on the event's position relative to the form.
                        if (form->touchEvent(evt, x - bounds.x, y - bounds.y, contactIndex))
                        {
                            return true;
                        }
                    }
                }
            }
        }

        return false;
    }
Example #16
0
RayCastModelHit Model::castRay(const Vec3& origin, const Vec3& dir, const Matrix& model_transform, const Pose* pose)
{
	RayCastModelHit hit;
	hit.m_is_hit = false;
	if (!isReady()) return hit;

	Matrix inv = model_transform;
	inv.inverse();
	Vec3 local_origin = inv.transformPoint(origin);
	Vec3 local_dir = (inv * Vec4(dir.x, dir.y, dir.z, 0)).xyz();

	Matrix matrices[256];
	ASSERT(!pose || pose->count <= lengthOf(matrices));
	bool is_skinned = false;
	for (int mesh_index = m_lods[0].from_mesh; mesh_index <= m_lods[0].to_mesh; ++mesh_index)
	{
		Mesh& mesh = m_meshes[mesh_index];
		is_skinned = pose && !mesh.skin.empty() && pose->count <= lengthOf(matrices);
	}
	if (is_skinned)
	{
		computeSkinMatrices(*pose, *this, matrices);
	}

	for (int mesh_index = m_lods[0].from_mesh; mesh_index <= m_lods[0].to_mesh; ++mesh_index)
	{
		Mesh& mesh = m_meshes[mesh_index];
		bool is_mesh_skinned = !mesh.skin.empty();
		u16* indices16 = (u16*)&mesh.indices[0];
		u32* indices32 = (u32*)&mesh.indices[0];
		bool is16 = mesh.flags.isSet(Mesh::Flags::INDICES_16_BIT);
		int index_size = is16 ? 2 : 4;
		for(int i = 0, c = mesh.indices.size() / index_size; i < c; i += 3)
		{
			Vec3 p0, p1, p2;
			if (is16)
			{
				p0 = mesh.vertices[indices16[i]];
				p1 = mesh.vertices[indices16[i + 1]];
				p2 = mesh.vertices[indices16[i + 2]];
				if (is_mesh_skinned)
				{
					p0 = evaluateSkin(p0, mesh.skin[indices16[i]], matrices);
					p1 = evaluateSkin(p1, mesh.skin[indices16[i + 1]], matrices);
					p2 = evaluateSkin(p2, mesh.skin[indices16[i + 2]], matrices);
				}
			}
			else
			{
				p0 = mesh.vertices[indices32[i]];
				p1 = mesh.vertices[indices32[i + 1]];
				p2 = mesh.vertices[indices32[i + 2]];
				if (is_mesh_skinned)
				{
					p0 = evaluateSkin(p0, mesh.skin[indices32[i]], matrices);
					p1 = evaluateSkin(p1, mesh.skin[indices32[i + 1]], matrices);
					p2 = evaluateSkin(p2, mesh.skin[indices32[i + 2]], matrices);
				}
			}


			Vec3 normal = crossProduct(p1 - p0, p2 - p0);
			float q = dotProduct(normal, local_dir);
			if (q == 0)	continue;

			float d = -dotProduct(normal, p0);
			float t = -(dotProduct(normal, local_origin) + d) / q;
			if (t < 0) continue;

			Vec3 hit_point = local_origin + local_dir * t;

			Vec3 edge0 = p1 - p0;
			Vec3 VP0 = hit_point - p0;
			if (dotProduct(normal, crossProduct(edge0, VP0)) < 0) continue;

			Vec3 edge1 = p2 - p1;
			Vec3 VP1 = hit_point - p1;
			if (dotProduct(normal, crossProduct(edge1, VP1)) < 0) continue;

			Vec3 edge2 = p0 - p2;
			Vec3 VP2 = hit_point - p2;
			if (dotProduct(normal, crossProduct(edge2, VP2)) < 0) continue;

			if (!hit.m_is_hit || hit.m_t > t)
			{
				hit.m_is_hit = true;
				hit.m_t = t;
				hit.m_mesh = &m_meshes[mesh_index];
			}
		}
	}
	hit.m_origin = origin;
	hit.m_dir = dir;
	return hit;
}