Ejemplo n.º 1
0
void ParticleEmitter3D::PrepareEmitterParameters(Particle * particle, float32 velocity, int32 emitIndex)
{
	Vector3 tempPosition = Vector3();
	Matrix4 * worldTransformPtr = GetWorldTransformPtr();
	Matrix3 rotationMatrix;
	rotationMatrix.Identity();

	if(worldTransformPtr)
	{
		tempPosition = worldTransformPtr->GetTranslationVector();
		rotationMatrix = Matrix3(*worldTransformPtr);;
	}

	//Vector3 tempPosition = particlesFollow ? Vector3() : position;
    if (emitterType == EMITTER_POINT)
    {
        particle->position = tempPosition;
    }
    else if (emitterType == EMITTER_RECT)
    {        
        float32 rand05_x = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        float32 rand05_y = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        float32 rand05_z = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        Vector3 lineDirection(0, 0, 0);
        if(size)
            lineDirection = Vector3(size->GetValue(time).x * rand05_x, size->GetValue(time).y * rand05_y, size->GetValue(time).z * rand05_z);		
		//particle->position = tempPosition + lineDirection;
        particle->position = tempPosition + TransformPerserveLength(lineDirection, rotationMatrix);
    }
	else if ((emitterType == EMITTER_ONCIRCLE_VOLUME) ||
			 (emitterType == EMITTER_ONCIRCLE_EDGES))
	{
		CalculateParticlePositionForCircle(particle, tempPosition, rotationMatrix);
	}

    if (emitterType == EMITTER_SHOCKWAVE)
    {
		// For "Shockwave" emitters the calculation is different.
		PrepareEmitterParametersShockwave(particle, velocity, emitIndex, tempPosition, rotationMatrix);
	}
	else
	{
		PrepareEmitterParametersGeneric(particle, velocity, emitIndex, tempPosition, rotationMatrix);
	}

	if(worldTransformPtr)
	{
		Matrix4 newTransform = *worldTransformPtr;
		newTransform._30 = newTransform._31 = newTransform._32 = 0;		
		float32 speedLength = particle->speed.Length();
		
		particle->speed = particle->speed*newTransform;
		float32 speedLengthAfter = particle->speed.Length();
		if (speedLengthAfter)
			particle->speed*=speedLength/speedLengthAfter;
		
	}	
}
Ejemplo n.º 2
0
void ParticleEmitter::PrepareEmitterParameters(Particle * particle, float32 velocity, int32 emitIndex)
{
    // Yuri Coder, 2013/01/30. ParticleEmitter class can be now only 2D.
    Vector3 tempPosition = particlesFollow ? Vector3() : position;
    if (emitterType == EMITTER_POINT)
    {
        particle->position = tempPosition;
    }
    else if (emitterType == EMITTER_RECT)
    {
        // TODO: add emitter angle support
        float32 rand05_x = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        float32 rand05_y = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        float32 rand05_z = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        Vector3 lineDirection(0, 0, 0);
        if(size)
            lineDirection = Vector3(size->GetValue(time).x * rand05_x, size->GetValue(time).y * rand05_y, size->GetValue(time).z * rand05_z);
        particle->position = tempPosition + lineDirection;
    }
    else if ((emitterType == EMITTER_ONCIRCLE) || (emitterType == EMITTER_SHOCKWAVE))
    {
        // here just set particle position
        // Yuri Coder, 2013/04/18. Shockwave particle isn't implemented for 2D mode -
        // currently draw them in the same way as "onCircle" ones.
        particle->position = tempPosition;
    }

    Vector3 vel;
    //vel.x = (float32)((rand() & 255) - 128);
    //vel.y = (float32)((rand() & 255) - 128);
    //vel.Normalize();

    float32 rand05 = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]

    float32 particleAngle = 0;
    if(emissionAngle)
        particleAngle = DegToRad(emissionAngle->GetValue(time) + angle);

    float32 range = 0.0f;
    if(emissionRange)
        range = DegToRad(emissionRange->GetValue(time));

    if (emitPointsCount == -1)
    {
        // if emitAtPoints property is not set just emit randomly in range
        particleAngle += range * rand05;
    }
    else
    {
        particleAngle += range * (float32)emitIndex / (float32)emitPointsCount;
    }


    vel.x = cosf(particleAngle);
    vel.y = sinf(particleAngle);
    vel.z = 0;

    // reuse particle velocity we've calculated
    // Yuri Coder, 2013/04/18. Shockwave particle isn't implemented for 2D mode -
    // currently draw them in the same way as "onCircle" ones.
    if ((emitterType == EMITTER_ONCIRCLE) || (emitterType == EMITTER_SHOCKWAVE))
    {
        if(radius)
            particle->position += vel * radius->GetValue(time);
    }

    particle->direction.x = vel.x;
    particle->direction.y = vel.y;
    particle->speed = velocity;
    particle->angle = particleAngle;
}
void ParticleEmitter3D::PrepareEmitterParameters(Particle * particle, float32 velocity, int32 emitIndex)
{
	Vector3 tempPosition = Vector3();
	Matrix4 * worldTransformPtr = GetWorldTransformPtr();
	if(worldTransformPtr)
	{
		tempPosition = worldTransformPtr->GetTranslationVector();
	}

	//Vector3 tempPosition = particlesFollow ? Vector3() : position;
    if (emitterType == EMITTER_POINT)
    {
        particle->position = tempPosition;
    }
    else if (emitterType == EMITTER_LINE)
    {
        // TODO: add emitter angle support
        float32 rand05 = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        Vector3 lineDirection(0, 0, 0);
        if(size)
            lineDirection = size->GetValue(time)*rand05;
        particle->position = tempPosition + lineDirection;
    }
    else if (emitterType == EMITTER_RECT)
    {
        // TODO: add emitter angle support
        float32 rand05_x = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        float32 rand05_y = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        float32 rand05_z = (float32)Random::Instance()->RandFloat() - 0.5f; // [-0.5f, 0.5f]
        Vector3 lineDirection(0, 0, 0);
        if(size)
            lineDirection = Vector3(size->GetValue(time).x * rand05_x, size->GetValue(time).y * rand05_y, size->GetValue(time).z * rand05_z);
        particle->position = tempPosition + lineDirection;
    }
    else if (emitterType == EMITTER_ONCIRCLE)
    {
        // here just set particle position
        particle->position = tempPosition;
    }
	
    Vector3 vel = Vector3(1.0f, 0.0f, 0.0f);
    if(emissionVector)
	{
        vel = emissionVector->GetValue(0);
		vel = vel*rotationMatrix;
	}
	
    Vector3 rotVect(0, 0, 1);
    float32 phi = PI*2*(float32)Random::Instance()->RandFloat();
    if(vel.x != 0)
    {
        rotVect.y = sinf(phi);
        rotVect.z = cosf(phi);
        rotVect.x = - rotVect.y*vel.y/vel.x - rotVect.z*vel.z/vel.x;
    }
    else if(vel.y != 0)
    {
        rotVect.x = cosf(phi);
        rotVect.z = sinf(phi);
        rotVect.y = - rotVect.z*vel.z/vel.y;
    }
    else if(vel.z != 0)
    {
        rotVect.x = cosf(phi);
        rotVect.y = sinf(phi);
        rotVect.z = 0;
    }
    rotVect.Normalize();
	
    float32 range = 0;
    if(emissionRange)
        range = DegToRad(emissionRange->GetValue(time) + angle);
    float32 rand05 = (float32)Random::Instance()->RandFloat() - 0.5f;
	
    Vector3 q_v(rotVect*sinf(range*rand05/2));
    float32 q_w = cosf(range*rand05/2);
	
    Vector3 q1_v(q_v);
    float32 q1_w = -q_w;
    q1_v /= (q_v.SquareLength() + q_w*q_w);
    q1_w /= (q_v.SquareLength() + q_w*q_w);
	
    Vector3 v_v(vel);
	
    Vector3 qv_v = q_v.CrossProduct(v_v) + q_w*v_v;
    float32 qv_w = - q_v.DotProduct(v_v);
	
    Vector3 qvq1_v = qv_v.CrossProduct(q1_v) + qv_w*q1_v + q1_w*qv_v;
	
	Vector3 speed = qvq1_v * velocity;
	particle->speed = speed.Length();
    particle->direction = speed/particle->speed;
	if (particle->direction.x <= EPSILON && particle->direction.x >= -EPSILON)
		particle->direction.x = 0.f;
	if (particle->direction.y <= EPSILON && particle->direction.y >= -EPSILON)
		particle->direction.y = 0.f;
	if (particle->direction.z <= EPSILON && particle->direction.z >= -EPSILON)
		particle->direction.z = 0.f;
	
    if (emitterType == EMITTER_ONCIRCLE)
    {
        qvq1_v.Normalize();
        if(radius)
            particle->position += qvq1_v * radius->GetValue(time);
    }
	
    particle->angle = atanf(particle->direction.z/particle->direction.x);

	if(worldTransformPtr)
	{
		Matrix4 newTransform = *worldTransformPtr;
		newTransform._30 = newTransform._31 = newTransform._32 = 0;
		particle->direction = particle->direction*newTransform;
	}
}
Ejemplo n.º 4
0
bool ContourModel::update(vector<vector<Point> > contours,vector<Point2d>& originalPoints, int image_w_half)
{
    
    //step 1: find the larger contours to filter out some noise (area > thresh)
    vector<vector<Point> > largeContours;
    
    int areaThreshold = 130;
    for(int i = 0;i < (int)contours.size();i++)
    {
        vector<Point> currCont = contours.at(i);
        double area = contourArea(contours.at(i));
        if(area > areaThreshold)
        {
            largeContours.push_back(currCont);
        }
    }

    
    //step 2: for each larger contour: find the center of mass and the lane direction to group them
    vector<Point2d> mass_centers;
    vector<Point2d> line_directions;
    for(int i = 0;i < (int)largeContours.size();i++)
    {
        //calculate the line direction for each contour
        Vec4f lineParams;
        fitLine(largeContours.at(i), lineParams, CV_DIST_L2, 0, 0.01, 0.01);
        Point2d lineDirection(lineParams[0],lineParams[1]);
        line_directions.push_back(lineDirection);
        
        //calculate the mass center for each contour
        vector<Moments> contourMoments;
        Moments currMoments = moments(largeContours.at(i));
        double x_cent = currMoments.m10 / currMoments.m00;
        double y_cent = currMoments.m01 / currMoments.m00;
        Point2d mass_cent(x_cent,y_cent);
        mass_centers.push_back(mass_cent);    
    }

    //assert these vectors have same length:
    if(largeContours.size() != mass_centers.size())cout << "ERROR in ContourModel: massCenters.size != largeContours.size()" << endl;
    if(largeContours.size() != line_directions.size())cout << "ERROR in ContourModel: massCenters.size != largeContours.size()" << endl;

    //step 3: create the "mergeList": store for each contour weather it wants to merge with another one
    vector<vector<int> > mergelist;
    //merge contours based on center of mass and line direction
    for(int i = 0;i < (int)largeContours.size();i++)
    {
        vector<int> mergeWishes;
        
        Point2d currCenter = mass_centers.at(i);
        Point2d currDirection = line_directions.at(i);
        
        for(int j = i+1;j < (int)largeContours.size();j++)
        {
            Point2d compCenter = mass_centers.at(j);
            Point2d compDirection = line_directions.at(j);
            
            bool wantMerge = mergeContours(currCenter, currDirection, compCenter, compDirection);
            
            if(wantMerge)mergeWishes.push_back(j);
        }
        
        mergelist.push_back(mergeWishes);
    }

    //step 4: use the mergeList to create the final_mergelist which looks as follows:
    //[ [0,2,5] [3] [1] [4,6]] telling which contours should be merged together
    
    vector<vector<int> > final_mergelist;
    for(int i = 0;i < (int)largeContours.size();i++)
    {
        vector<int> temp;
        temp.push_back(i);
        final_mergelist.push_back(temp);
    }
    
    for(int i = 0;i < (int)largeContours.size();i++)
    {
        vector<int>* containerToPushTo = NULL;
        
        //step 1: find the container the contour i is in - note that this will always succeed so containerToPushTo wont stay NULL
        for(int j = 0;j < (int)final_mergelist.size();j++)
        {
            vector<int>* currContainer;
            currContainer = &final_mergelist.at(j);
            for(int k = 0;k < (int)final_mergelist.at(j).size();k++)
            {
                if(final_mergelist.at(j).at(k) == i)
                {
                    containerToPushTo = currContainer;
                }
            }
        }
        
        //step2: for each element to push: make sure it appears in the container
        for(int j = 0;j < (int)mergelist.at(i).size();j++)
        {
            int elemToMerge = mergelist.at(i).at(j);
            
            //if elemToMerge already appears in containerToPushTo => do nothing
            bool alreadyInContainer = false;
            for(int k = 0;k < (int)containerToPushTo->size();k++)
            {
                if(containerToPushTo->at(k) == elemToMerge)
                    alreadyInContainer = true;
            }
            
            //not inside: push the element and delete it from the old vector it was in
            if(!alreadyInContainer)
            {
                
                //delete it from the old container!!
                for(int k = 0;k < (int)final_mergelist.size();k++)
                {
                    for(int l = 0;l < (int)final_mergelist.at(k).size();l++)
                    {
                        //DEBUG IFS - ERASE LATER
                        if(k < 0 || k >= (int)final_mergelist.size())cout << "OVERFLOW IN 159::ContourModel" << endl;
                        if(l < 0 || l >= (int)final_mergelist.at(k).size())cout << "OVERFLOW IN 160::ContourModel" << endl;

                        if(final_mergelist.at(k).at(l) == elemToMerge)
                        {
                            //DEBUG IF- ERASE LATER
                            if(l < 0 || l >= (int)final_mergelist.at(k).size()) cout << "ERROR ContourModel 162" << endl;
                            final_mergelist.at(k).erase(final_mergelist.at(k).begin()+l);
                        }
                    }
                }
                
                //add it in the new container
                containerToPushTo->push_back(elemToMerge);
            }
            
        }
        
    }
    
    
    //step 5: merge the contours together
    vector< vector<vector<Point> > > mergedContours;
    
    for(int i = 0;i < (int)final_mergelist.size();i++)
    {
        vector<vector<Point> > currGrouping;
        for(int j = 0;j < (int)final_mergelist.at(i).size();j++)
        {
            vector<Point> currContour = largeContours.at(final_mergelist.at(i).at(j));
            currGrouping.push_back(currContour);
        }
        if(currGrouping.size() > 0)mergedContours.push_back(currGrouping);
        
    }


    //TRY TO FIND THE MIDDLE LANE

    vector<vector<Point> >          singleContours;
    vector<vector<vector<Point> > > multipleContours;

    for(int i = 0;i < (int)mergedContours.size();i++)
    {        
        vector<vector<Point> > currContGroup = mergedContours.at(i);
        if(currContGroup.size() == 1) singleContours.push_back(currContGroup.at(0));
        else if(currContGroup.size() > 1) multipleContours.push_back(currContGroup);                
    }

    //in this situation there is actually a chance to apply the middle lane extraction, otherwise the old procedure is applied
    if(multipleContours.size() == 1 && singleContours.size() <= 2 && singleContours.size() > 0)
    {

        //sort single contours by area
        std::sort(singleContours.begin(),singleContours.end(),acompareCont);
        vector<Point> largestSingleContour = singleContours.at(singleContours.size()-1);
        double areaLargestSingle = contourArea(largestSingleContour);

        vector<vector<Point> > middleContour = multipleContours.at(0);
        double areaMiddle = 0;
        bool validMid = true;
        for(int i = 0;i < (int)middleContour.size();i++)
        {
            double areaCurr = contourArea(middleContour.at(i));
            if(areaCurr > areaLargestSingle/2.0){
                validMid = false;
            }
            areaMiddle += contourArea(middleContour.at(i));
        }


        //if both contours have a certain size
        if(areaLargestSingle > 120 && areaMiddle > 120)
        {
            //MIDDLE LANE AND OTHER LANE FOUND => RETURN THE ESTIMATE

            //first argument will be the middle lane
            //second argument will be the other larger lane
            vector<vector<Point2d> > nicelyGroupedPoints;

            //1) --- MIDDLE LANE ---
            vector<Point2d> temp_result;
            for(int i = 0;i < (int)middleContour.size();i++)
            {
                vector<Point> currCont = middleContour.at(i);
                Rect bound = boundingRect(currCont);

                //visit every point in the bounding rect
                for(int y = bound.y;y < bound.y+bound.height;y++)
                {
                    for(int x = bound.x;x < bound.x+bound.width;x++)
                    {
                        if(pointPolygonTest(currCont, Point(x,y), false) >= 0)
                        {
                            temp_result.push_back(Point2d(x-image_w_half,y));
                        }
                    }
                }

            }

            nicelyGroupedPoints.push_back(temp_result);

            //2) --- OTHER LANE ---

            vector<Point2d> temp_result2;

            Rect bound = boundingRect(largestSingleContour);

            //visit every point in the bounding rect
            for(int y = bound.y;y < bound.y+bound.height;y++)
            {
                for(int x = bound.x;x < bound.x+bound.width;x++)
                {
                    if(pointPolygonTest(largestSingleContour, Point(x,y), false) >= 0)
                    {
                        temp_result2.push_back(Point2d(x-image_w_half,y));
                    }
                }
            }


            if(validMid)
            {
                nicelyGroupedPoints.push_back(temp_result2);
                points = nicelyGroupedPoints;
                return true; //middle lane estimate provided
            }
        }
    }

    //MIDDLE LANE WAS NOT FOUND



    //step 6: get the final result: the grouped points matching the contours
    //need to perform a inside contour check within the bounding rectangle of the contour for
    //each point in the bounding rectangle
    vector<vector<Point2d> > nicelyGroupedPoints;

    for(int i = 0;i < (int)mergedContours.size();i++)
    {
        vector<Point2d> temp_result;
        for(int j = 0;j < (int)mergedContours.at(i).size();j++)
        {
            vector<Point> currContour = mergedContours.at(i).at(j);
            Rect bound = boundingRect(currContour);

            //visit every point in the bounding rect
            for(int y = bound.y;y < bound.y+bound.height;y++)
            {
                for(int x = bound.x;x < bound.x+bound.width;x++)
                {
                    if(pointPolygonTest(currContour, Point(x,y), false) >= 0)
                    {
                        temp_result.push_back(Point2d(x-image_w_half,y));
                    }
                }
            }
        }

        if(temp_result.size() > 0)
        {
            nicelyGroupedPoints.push_back(temp_result);
        }
    }


    /*
    //step 6 (alternative): get the final result: the grouped points matching the contours
    //need to perform a inside contour check for the input points if in boundary rectangle of the contour
    vector<vector<Point2d> > nicelyGroupedPoints;

    for(int i = 0;i < mergedContours.size();i++)
    {

        vector<Point2d> temp_result;
        for(int j = 0;j < mergedContours.at(i).size();j++)
        {
            vector<Point> currContour = mergedContours.at(i).at(j);
            Rect bound = boundingRect(currContour);

            for(int k = 0;k < originalPoints.size();k++)
            {
                //check if within the contour:
                if(pointPolygonTest(currContour, originalPoints.at(k), false) >= 0)
                {
                    temp_result.push_back(Point2d(originalPoints.at(k).x-image_w_half, originalPoints.at(k).y));
                }
            }
        }

        if(temp_result.size() > 0)
        {
            nicelyGroupedPoints.push_back(temp_result);
        }
    }

    */


    points = nicelyGroupedPoints;
    return false; //everything as usual, no further information
}