bool P3DGLWindowContext::Create (unsigned int Width, unsigned int Height) { bool Result; PIXELFORMATDESCRIPTOR PixelFormatDesc; int PixelFormat; HDC DeviceContext; DeviceContext = NULL; Result = GLWindowClassRegister(); if (Result) { Result = GLWindowCreate(&WindowHandle,Width,Height); } if (Result) { DeviceContext = GetDC(WindowHandle); if (DeviceContext == NULL) { Result = false; } } if (Result) { memset(&PixelFormatDesc,0,sizeof(PixelFormatDesc)); PixelFormatDesc.nSize = sizeof(PixelFormatDesc); PixelFormatDesc.nVersion = 1; PixelFormatDesc.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; PixelFormatDesc.iPixelType = PFD_TYPE_RGBA; PixelFormatDesc.cColorBits = 24; PixelFormat = ChoosePixelFormat(DeviceContext,&PixelFormatDesc); if (PixelFormat == 0) { Result = false; } } if (Result) { if (!SetPixelFormat(DeviceContext,PixelFormat,&PixelFormatDesc)) { Result = false; } } if (Result) { GLContext = wglCreateContext(DeviceContext); if (GLContext == NULL) { Result = false; } } if (wglMakeCurrent(DeviceContext,GLContext)) { Result = P3DGLExtInit(); } else { Result = false; } if (DeviceContext != NULL) { ReleaseDC(WindowHandle,DeviceContext); } return(Result); }
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int) { // константы // максимальное число сфер - для выделения буффера памяти long MAX_NUM_SPHERES = 100000000; // реальное число - определяется при считывании из файла или используется в рандомной генерации. long REAL_NUM_SPHERES = 10000000; // количество миров сфер, когда мы убираем сферы лежащие в других сферах - нужно разделять все сферы по разным мирам - там добавления новых сфер происходит быстрее. int SPHERE_WORLD_NUMBER = 128; // количество сфер которое мы обрабатываем полностью, то есть убираем все сферы содержащиеся в других сферах. Так мы бъем все сферы на такие группы и обрабатываем полностью. // после этого мы просто склеиваем все такие группы. Это сделано для того что, обрабатывать все 100M долго по времени (>1h), из за этого нам придется отрисовывать на 30% // cфер больше. long SPHERES_PROCESSING_STEP = 10000000; // имена файлов std::string inputFileName = "input2.txt"; std::string outputTxtFileName = "balabok2.txt"; std::string outputBmpFileName = "balabok2.bmp"; std::string fullOutputTxtFileName = "tmp_balabok/spheres_fullOutput.txt"; CreateDirectory (L"tmp_balabok", NULL); LoggerCreate("tmp_balabok/spheres.log"); // установим зерно генератора случайных чисел srand((unsigned int)time(NULL)); /// create window, start main loop, etc. int windowWidht = 1024; int windowHeight = 1024; if (!GLWindowCreate(L"Spheres", windowWidht, windowHeight)) return 1; /// SphereKoords *allSpheres = new SphereKoords[MAX_NUM_SPHERES]; /// считывание сфер из файла REAL_NUM_SPHERES = readSpheresDataFromFile(inputFileName, allSpheres, MAX_NUM_SPHERES); //generateRandomSpheres(allSpheres, REAL_NUM_SPHERES); SphereWorld * sphereWorlds = new SphereWorld[SPHERE_WORLD_NUMBER]; SphereWorld finalWorld; LOG_DEBUG ("Please, be patient. There is a quite long data preprocessing before rendering.\n"); LOG_DEBUG ("It can take up to 20 minutes for 100M spheres.\n"); LOG_DEBUG ("Take into account, that time for preprocessing wasn't limited.\n"); LOG_DEBUG ("By the way, you can see the progress in this file\n"); auto beginTime = GetTickCount(); /// вычисление сфер внутри других сфер в несколько потоков по блокам (мирам) for (int spheresInitialNumber = 0; spheresInitialNumber < REAL_NUM_SPHERES; spheresInitialNumber += SPHERES_PROCESSING_STEP) { long spheresToProcess = spheresInitialNumber + SPHERES_PROCESSING_STEP >= REAL_NUM_SPHERES ? REAL_NUM_SPHERES - spheresInitialNumber : SPHERES_PROCESSING_STEP; LOG_DEBUG ("processing spheres from %i to %i, time: %i\n", spheresInitialNumber, spheresInitialNumber + spheresToProcess , GetTickCount() - beginTime); int worldsPerThread = SPHERE_WORLD_NUMBER/THREADS_COUNT; SphereWorldWorkerData workersData[THREADS_COUNT]; HANDLE hHandles[THREADS_COUNT]; for (int threadNumber = 0; threadNumber < THREADS_COUNT; ++threadNumber) { long spheresPerThread = spheresToProcess/THREADS_COUNT; workersData[threadNumber] = SphereWorldWorkerData(worldsPerThread, sphereWorlds + threadNumber * worldsPerThread, threadNumber == THREADS_COUNT - 1 ? spheresToProcess - spheresPerThread * (THREADS_COUNT - 1) : spheresPerThread, allSpheres + spheresInitialNumber + spheresPerThread * threadNumber); DWORD ThreadId; hHandles[threadNumber] = CreateThread(NULL, 0, SphereWorldWorker, workersData + threadNumber, 0, &ThreadId); } for (int i = 0; i < THREADS_COUNT; i++) { WaitForSingleObject(hHandles[i],INFINITE); } /// склейка миров из разных потоков for (int degree = (int)(log((double)worldsPerThread) / log(2.0)); degree < log((double)SPHERE_WORLD_NUMBER) / log(2.0); ++degree) { int step = (int) pow(2.0f, (int)degree); for (int worldNumber = 0; worldNumber < SPHERE_WORLD_NUMBER; worldNumber += step * 2) { sphereWorlds[worldNumber].AddSphereWorldInSeveralThreads(sphereWorlds[worldNumber + step], THREADS_COUNT); } } /// простое (без вычислений) добавление сфер из разных миров к финальному миру - сделано для увеличение скорости предобработки. finalWorld.SimpleAddSphereWorld(sphereWorlds[0]); clearWorlds(sphereWorlds, SPHERE_WORLD_NUMBER); } LOG_DEBUG("sphere amount after removing the spheres located insides others: %i, time %i\n", finalWorld.GetCurrentSize(), GetTickCount() - beginTime); LOG_DEBUG("started checking how spheres cover cube (0,0,0 - 1,1,1)\n"); /// проверка насколько сферы покрывают все стороны каждой ячейки finalWorld.GenerateCover(coverBuilder); LOG_DEBUG("covering finished, time %i\n", GetTickCount() - beginTime); LOG_DEBUG("creating the main window, etc, and started rendering\n"); /// generate matrix in cells; REDUCED_NUM_SPHERES = finalWorld.GetCurrentSize(); spheres = new mat4[REDUCED_NUM_SPHERES]; finalWorld.GenerateMatrixInCells(matrixInCells, spheres); /// вектор со временами отрисовки фремов std::vector<double> msecsPerFrameList; int nSize = windowWidht * windowHeight * 3; GLubyte *pixels = new GLubyte [nSize]; /// старт петли сообщений int result = GLWindowMainLoop(msecsPerFrameList, pixels); /// сохранение всех данных в файлы if (pixels) { SaveBMP(pixels, windowWidht, windowHeight, nSize, outputBmpFileName.c_str()); } double performance = 0; double medianeMsecsPerFrame = 0; std::ofstream fullResultStream(fullOutputTxtFileName); std::ofstream resultStream(outputTxtFileName); fullResultStream << "msecs per frame: "; for (auto msecsValue = msecsPerFrameList.begin(); msecsValue != msecsPerFrameList.end(); ++msecsValue) { medianeMsecsPerFrame += *msecsValue; fullResultStream << *msecsValue << " "; } medianeMsecsPerFrame /= 10.0f; fullResultStream << std::endl << "average msecs per frame: " << medianeMsecsPerFrame ; performance = REAL_NUM_SPHERES / (1000 * medianeMsecsPerFrame); fullResultStream << std::endl << "Mspheres per second: " << performance; resultStream << performance << std::endl; GLWindowDestroy(); LoggerDestroy(); /// TODO: kill all windows handlers and free all the memory. return result; }