Exemplo n.º 1
0
void rotateMesh( Polyhedron & poly, char axis, double radius )
{
    switch ( axis ) {
      case 'x':
	  {
	      Transformation3 map( 1.0,		0.0,		0.0,
				   0.0,		cos(radius),	-sin(radius),
				   0.0,		sin(radius),	cos(radius) );
	      transformMesh( poly, map );
	  }
	  break;
      case 'y':
	  {
	      Transformation3 map( cos(radius),	0.0,		sin(radius),
				   0.0,		1.0,		0.0,
				   -sin(radius),	0.0,		cos(radius) );
	      transformMesh( poly, map );
	  }
	  break;
      case 'z':
	  {
	      Transformation3 map( cos(radius),	-sin(radius),	0.0,
				   sin(radius),	cos(radius),	0.0,
				   0.0,		0.0,		1.0 );
	      transformMesh( poly, map );
	  }
	  break;
      default:
	  cerr << "Illegal axis : " << axis << endl;
	  break;
    }
}
CrystalEditorFrame::CrystalEditorFrame(const RayPathDescriptor &rtd, wxWindow* parent,wxWindowID id):
    rayPathDescriptor(rtd),
    right(1, 0, 0),
    upward(0, 1, 0),
    backward(0, 0, 1),
    target(0, 0, 0),
    distance(10),
    crystalMeshes(0),
    dragging(false),
    prevMousePos(0, 0, 0),
    rayPos(-10, 0, 0),
    rayDir(1, 0, 0)
{
    initialize(parent, id);

    addCrystalToDisplayItem->Enable(false);
    castRayMenuItem->Enable(false);

    crystalMesh = *rtd.mesh;
    transformMesh(crystalMesh, rtd.orientation);
    rayPos = rtd.rayPos;
    rayDir = rtd.rayDir;

    updateRayPaths();

    minimumIntensity = 0.5;
}
Exemplo n.º 3
0
void alignMesh( Polyhedron & poly )
{
    int num = poly.size_of_vertices();

    // initialization here is very important!!
    Point3 ave( 0.0, 0.0, 0.0 );
    for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) {
	ave = ave + ( vi->point() - CGAL::ORIGIN );
    }
    ave = CGAL::ORIGIN + ( ave - CGAL::ORIGIN )/( double )num;

    unsigned int dim	= 3;
    double * data	= new double [ num*dim ];

    int nPoints = 0;
    for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) {
	data[ nPoints * dim + 0 ] = vi->point().x() - ave.x();
	data[ nPoints * dim + 1 ] = vi->point().y() - ave.y();
	data[ nPoints * dim + 2 ] = vi->point().z() - ave.z();
	nPoints++;
    }

    assert( nPoints == ( int )num );

    /*****************************************
      analyze the engenstructure of X^T X
     *****************************************/
    /* define the matrix X */
    gsl_matrix_view X = gsl_matrix_view_array( data, num, dim );

    /* memory reallocation */
    // proj = ( double * )realloc( proj, sizeof( double ) * PDIM * num );

    /* calculate the covariance matrix B */
    gsl_matrix * B              = gsl_matrix_alloc( dim, dim );
    gsl_blas_dgemm( CblasTrans, CblasNoTrans, 1.0,
                    &(X.matrix),
                    &(X.matrix), 0.0,
                    B );
       
    /* divided by the number of samples */
    gsl_matrix_scale( B, 1.0/(double)num );

    gsl_vector * eVal       = gsl_vector_alloc( dim );
    gsl_matrix * eVec       = gsl_matrix_alloc( dim, dim );
    gsl_eigen_symmv_workspace * w
                                = gsl_eigen_symmv_alloc( dim );

    // eigenanalysis of the matrix B
    gsl_eigen_symmv( B, eVal, eVec, w );
    // release the memory of w
    gsl_eigen_symmv_free( w );
    // sort eigenvalues in a descending order
    gsl_eigen_symmv_sort( eVal, eVec, GSL_EIGEN_SORT_VAL_DESC );

    // #ifdef MYDEBUG
    for ( unsigned int i = 0; i < dim; ++i ) {
	cerr << "Eigenvalue No. " << i << " = " << gsl_vector_get( eVal, i ) << endl;
	cerr << "Eigenvector No. " << i << endl;
	double length = 0.0;
	for ( unsigned int j = 0; j < dim; ++j ) {
	    cerr << gsl_matrix_get( eVec, i, j ) << " ";
	    length += gsl_matrix_get( eVec, i, j )*gsl_matrix_get( eVec, i, j );
	}
	cerr << " length = " << length << endl;
    }
    // #endif	// MYDEBUG

    // 0 1 2, 0 2 1, 
    

    Transformation3 map;
    map = 
	Transformation3( gsl_matrix_get(eVec,1,0), gsl_matrix_get(eVec,0,0), gsl_matrix_get(eVec,2,0),
			 gsl_matrix_get(eVec,1,1), gsl_matrix_get(eVec,0,1), gsl_matrix_get(eVec,2,1),
			 gsl_matrix_get(eVec,1,2), gsl_matrix_get(eVec,0,2), gsl_matrix_get(eVec,2,2) );
    if ( map.is_odd() ) {
	cerr << " Transformation matrix reflected" << endl;
	map = 
	    Transformation3( gsl_matrix_get(eVec,1,0), gsl_matrix_get(eVec,0,0), -gsl_matrix_get(eVec,2,0),
			     gsl_matrix_get(eVec,1,1), gsl_matrix_get(eVec,0,1), -gsl_matrix_get(eVec,2,1),
			     gsl_matrix_get(eVec,1,2), gsl_matrix_get(eVec,0,2), -gsl_matrix_get(eVec,2,2) );
    }

    for ( unsigned int i = 0; i < dim; ++i ) {
	cerr << "| ";
	for ( unsigned int j = 0; j < dim; ++j ) {
	    cerr << map.cartesian( i, j ) << " ";
	}
	cerr << "|" << endl;
    }

    transformMesh( poly, map );

    return;
}
wxThread::ExitCode  HaloRenderingThread::Entry()
{
    wxCommandEvent evt(wxEVT_HALO_RENDERING_THREAD_NOTIFY, wxID_ANY);

    setupStruct.resultValid = false;
    setupStruct.imageBuffer = 0;
    setupStruct.rayPaths = new map<RayPathId, RayPathDescriptor>;

    if (setupStruct.crystals.size() == 0)
    {
        evt.SetString(wxT("No crystal population set up."));
        evt.SetInt(1);
        setupStruct.notifee->AddPendingEvent(evt);
        return 0;
    }

    // Cast rays on crystals and refracted rays will form a pixel.

    int crystalTypeIndex = 0;
    CrystalDescriptor *currentDescriptor = &setupStruct.crystals[0];
    const int N_CRYSTAL_TYPES = setupStruct.crystals.size();
    int crystalsRemaining = currentDescriptor->populationWeight;
    Mesh currentMesh;
    size_t percentStep = setupStruct.crystalCount / 100;
    if (percentStep < 1) percentStep = 1;
    Vector3 sunPos(0, 0, -100000);
    rotate2d(sunPos.y, sunPos.z, setupStruct.solarAltitude * 3.14159265636 / 180.0);
    // Two prependicular vector
    Vector3 prepX = sunPos % Vector3(0, 1, 0); // FIXME: Sun on the zenith
    Vector3 prepY = sunPos % prepX;
    prepX /= ~prepX;
    prepY /= ~prepY;
    setupStruct.deleteBuffer = freeBuffer;
    setupStruct.deleteMap = freeMap;
    size_t size = setupStruct.imageSize;
    setupStruct.imageBuffer = new uint32_t[size * size * 6];
    memset(setupStruct.imageBuffer, 0, size * size * 6 * sizeof(uint32_t));
    uint32_t *leftPlane = setupStruct.imageBuffer; // 0th plane
    uint32_t *rightPlane = setupStruct.imageBuffer + size * size; // 1st plane
    uint32_t *topPlane = setupStruct.imageBuffer + 2 * size * size; // 2nd plane
    uint32_t *bottomPlane = setupStruct.imageBuffer + 3 * size * size; // 3rd plane
    uint32_t *backPlane = setupStruct.imageBuffer + 4 * size * size; // 4th plane
    uint32_t *frontPlane = setupStruct.imageBuffer + 5 * size * size; // 5th plane
    double halfImageSize = size * 0.5;
    int maxRays = (setupStruct.maxRayCastInfoSize * 1000000) / (sizeof(RayPathDescriptor) + sizeof(RayPathId));
    if (maxRays == 0) maxRays = 1;
    int recordRayModulus = setupStruct.crystalCount / maxRays;
    if (!recordRayModulus) recordRayModulus = 1;

    struct RefractionColor
    {
        int rgb;
        double refractionIndex;
    };

    RefractionColor colors[] =
    {
        { 0x0000FF, 1.3072 },
        { 0x0080FF, 1.3094 },
        { 0x00FFFF, 1.31 },
        { 0x00FF80, 1.3107 },
        { 0x00FF00, 1.3114 },
        { 0x80FF00, 1.3125 },
        { 0xFFFF00, 1.3136 },
        { 0xFF8000, 1.3147 },
        { 0xFF0000, 1.3158 },
        { 0xFF0040, 1.3172 },
        { 0xFF0080, 1.32 },
    };

    const int N_COLORS = sizeof(colors) / sizeof(colors[0]);

    // Cast many rays.
    for (size_t i = 0; i < setupStruct.crystalCount; i++)
    {
        if (setupStruct.cancelled)
        {
            // If the user shut the rendering down...
            delete[] setupStruct.imageBuffer;
            setupStruct.imageBuffer = 0;
            return 0;
        }
        if (!crystalsRemaining)
        {
            // We iterate through the crystals based on their population weights.
            crystalTypeIndex++;
            if (crystalTypeIndex >= N_CRYSTAL_TYPES) crystalTypeIndex = 0;
            currentDescriptor = &setupStruct.crystals[crystalTypeIndex];
            crystalsRemaining = currentDescriptor->populationWeight;
        }
        // Get the raw mesh
        currentMesh = currentDescriptor->mesh;
        // Rotate it according to the orientation.
        Matrix orientationMatrix = getOrientationMatrix(currentDescriptor->orientation);
        // Apply wobbliness
        Vector3 wobbleRotationAxis(1, 0, 0);
        rotate2d(wobbleRotationAxis.x, wobbleRotationAxis.z, randFloat(0, 3.1415));
        double wobblinessLimit = currentDescriptor->wobbliness * 3.1415 / 180.0;
        Matrix wobbleMatrix = createRotationMatrix(
            wobbleRotationAxis,
            randFloatNormal(
                0,
                wobblinessLimit
            )
        );
        Matrix transformation = orientationMatrix % wobbleMatrix;
        transformMesh(currentMesh, transformation);

        // Crystal created, now cast a ray on it.
        Vector3 offset = prepX * randFloat(-1, 1) + prepY * randFloat(-1, 1);
        vector<RayPath> rayPaths;
        // Compute color here
        double colorCode = randFloat(0, N_COLORS - 1);
        RefractionColor prev = colors[(int)(floor(colorCode))];
        RefractionColor next = colors[(int)(ceil(colorCode))];
        double kColor = colorCode - floor(colorCode);
        RefractionColor currentColor;
        currentColor.rgb = prev.rgb;
        currentColor.refractionIndex = (1 - kColor) * prev.refractionIndex + kColor * next.refractionIndex;
        // Compute real poisition of the ray (Sun is a disk)
        Vector3 realSunPos = sunPos;
        Vector3 rayRotVector;
        double rayRotVectorLength;
        do
        {
            rayRotVector = realSunPos % getRandomVector();
            rayRotVectorLength = ~rayRotVector;
        }
        while (rayRotVectorLength == 0);
        rayRotVector /= rayRotVectorLength;
        realSunPos = transformVector(
            createRotationMatrix(
                rayRotVector,
                randFloat(
                    0,
                    setupStruct.solarDiskRadius * 3.1415926536 / 180.0
                )
            ),
            realSunPos
        );
        computeRayPathInGlassMesh(currentMesh, currentColor.refractionIndex, realSunPos + offset, -realSunPos, 0.01, rayPaths);
        /* Project rays on the six planes. */
        for (size_t j = 0; j < rayPaths.size(); j++)
        {
            RayPath &current = rayPaths[j];
            size_t pathLength = current.size();

            Vector3 exitDir = current[pathLength - 1].first - current[pathLength - 2].first;
            Vector3 projectionDir = -exitDir;

            double xPos, yPos;
            // select the plane to project on.
            uint32_t *plane;
            double xm = 1, ym = 1;
            int planeId;
            if ((fabs(projectionDir.x) > fabs(projectionDir.y)) && (fabs(projectionDir.x) > fabs(projectionDir.z)))
            {
                if (projectionDir.x < 0)
                {
                    plane = leftPlane;
                    planeId = 0;
                    xm = -1;
                }
                else
                {
                    plane = rightPlane;
                    planeId = 1;
                }
                xPos = xm * projectionDir.z / fabs(projectionDir.x) * halfImageSize + halfImageSize;
                yPos = -ym * projectionDir.y / fabs(projectionDir.x) * halfImageSize + halfImageSize;
            }
            if ((fabs(projectionDir.y) > fabs(projectionDir.x)) && (fabs(projectionDir.y) > fabs(projectionDir.z)))
            {
                if (projectionDir.y < 0)
                {
                    plane = bottomPlane;
                    planeId = 3;
                    ym = -1;
                }
                else
                {
                    plane = topPlane;
                    planeId = 2;
                }
                xPos = xm * projectionDir.x / fabs(projectionDir.y) * halfImageSize + halfImageSize;
                yPos = -ym * projectionDir.z / fabs(projectionDir.y) * halfImageSize + halfImageSize;
            }
            if ((fabs(projectionDir.z) > fabs(projectionDir.x)) && (fabs(projectionDir.z) > fabs(projectionDir.y)))
            {
                if (projectionDir.z < 0)
                {
                    plane = frontPlane;
                    planeId = 5;
                }
                else
                {
                    plane = backPlane;
                    planeId = 4;
                    xm = -1;
                }
                xPos = xm * projectionDir.x / fabs(projectionDir.z) * halfImageSize + halfImageSize;
                yPos = -ym * projectionDir.y / fabs(projectionDir.z) * halfImageSize + halfImageSize;
            }
            // Calculate the new intensity of the pixel.
            xPos = clampInInt(xPos, 0, size - 1);
            yPos = clampInInt(yPos, 0, size - 1);
            int prevPixel = plane[(int)(yPos) * size + (int)(xPos)];
            int nextPixel = 0;
            double intensity = current[pathLength - 2].second * 20;
            for (int j = 0; j < 3; j++)
            {
                int currentSaturation = (prevPixel >> (8 * j)) & 0xFF;
                int toAdd = (int)(((currentColor.rgb >> (8 * j)) & 0xFF) * intensity) >> 8;
                int nextSaturation;
                if (currentSaturation + toAdd > 255) nextSaturation = 255;
                else nextSaturation = currentSaturation + toAdd;
                nextPixel += (1 << (8 * j)) * nextSaturation * setupStruct.pixelIntensity;
            }
            plane[(int)(yPos) * size + (int)(xPos)] = nextPixel;
            // Record the ray if needed
            if (!(i % recordRayModulus))
            {
                RayPathId pixelId(planeId, (int)xPos, (int)yPos);
                RayPathDescriptor theDescriptor(
                    &currentDescriptor->mesh,
                    transformation,
                    realSunPos + offset,
                    -realSunPos,
                    intensity
                );
                map<RayPathId, RayPathDescriptor>::iterator it = setupStruct.rayPaths->find(pixelId);
                if (it == setupStruct.rayPaths->end())
                {
                    // If not found, insert it as new
                    setupStruct.rayPaths->insert(
                        make_pair(
                            pixelId,
                            theDescriptor
                        )
                    );
                }
                else if (it->second.intensity < intensity)
                {
                    // If found, update it if the current ray is more intense
                    it->second = theDescriptor;
                }
            }
        }

        if (i % percentStep == 0)
        {
            sendNotifyString(wxString::Format(wxT("Casting rays: %d%%"), i / percentStep));
        }

        crystalsRemaining--;
    }


    evt.SetString(wxT("Completed."));
    evt.SetInt(1); //< 1 means the operation is finished.
    setupStruct.resultValid = true;
    setupStruct.notifee->AddPendingEvent(evt);
    return 0;
}