void MultiDLA::density(double density, double& denAero, double& porosity) const { if (m_finished) { // calc double volume = 0.0; int32_t sx = m_fld->size().coord(0); int32_t sy = m_fld->size().coord(1); int32_t sz = m_fld->size().coord(2); MCoord::setDefDims(3); MCoord sc; for (size_t i = 0; i < 3; ++i) { sc.setCoord(i, m_fld->size().coord(i)); } CellsField* cf = new CellsField(sc, MCoord(), 2 * m_fld->radius()); for (int32_t ix = 0; ix < sx; ++ix) { for (int32_t iy = 0; iy < sy; ++iy) { for (int32_t iz = 0; iz < sz; ++iz) { if (m_fld->element(MCoord(ix, iy, iz)) == OCUPIED_CELL) { MCoord currCoord(ix, iy, iz); cf->setElement(currCoord); volume += vAdd(cf, currCoord); } } } } delete cf; double aeroVolume = volume / (sx * sy * sz); porosity = 1.0 - aeroVolume; denAero = density * aeroVolume; } }
bool hitTriang(Photon *photon, Triang *triang, const float distance, const Material *materials) { Shader shader = DIFFUSE; // Better idea? if (fDot(triang->direct, photon->direct) > -EPSILON) triang->direct = vNeg(triang->direct); // Update ray's position to the point where the ray hits the sphere photon->origin = fFMA(photon->direct, distance - UM(10), photon->origin); photon->lambda = materials[triang->mID].lambda; if (shader == CRAZY) { photon->direct = vNorm(vSub(newVec(0.99, 0, 0), photon->origin)); return REFLECTED; } else if (shader == SPECULAR) { // Angle between new and old vector is twice the angle between old vector and normal Vec reflect = vDot(photon->direct, triang->direct); photon->direct = vSub(photon->direct, vMul(triang->direct, vAdd(reflect, reflect))); return REFLECTED; } else if (shader == DIFFUSE) { photon->direct = randDir(); if (fDot(photon->direct, triang->direct) < EPSILON) photon->direct = vNeg(photon->direct); return REFLECTED; } else return ABSORBED; }
void IMU::orthonormalize(float inputDCM[3][3]) { // Takes 700 us. // Orthogonalize the i and j unit vectors (DCMDraft2 Eqn. 19). errDCM = vDotP(inputDCM[0], inputDCM[1]); vScale(inputDCM[1], -errDCM/2, dDCM[0]); // i vector correction vScale(inputDCM[0], -errDCM/2, dDCM[1]); // j vector correction vAdd(inputDCM[0], dDCM[0], inputDCM[0]); vAdd(inputDCM[1], dDCM[1], inputDCM[1]); // k = i x j vCrossP(inputDCM[0], inputDCM[1], inputDCM[2]); // Normalize all three vectors. vNorm(inputDCM[0]); vNorm(inputDCM[1]); vNorm(inputDCM[2]); }
Photon triangEmit(const Triang *triang, const Material *materials) { Photon p; float u = drand48(), v = drand48(); Vec point = vAdd(fMul(triang->vectab, u), fMul(triang->vectac, v)); // If point is outside triangle if (!triang->rectan && u + v < EPSILONONE) p.origin = vSub(vAdd(triang->origin, vAdd(triang->vectab, triang->vectac)), point); else p.origin = vAdd(triang->origin, point); p.direct = randDir(); if (fDot(p.direct, triang->direct) > EPSILON) p.direct = vNeg(p.direct); p.lambda = materials[triang->mID].lambda; return p; }
Intersect Triangle::intersect(Ray r) { Intersect::Intersect ret = *new Intersect::Intersect(); float a = v1.getX() - v2.getX(); float b = v1.getY() - v2.getY(); float c = v1.getZ() - v2.getZ(); float d = v1.getX() - v3.getX(); float e = v1.getY() - v3.getY(); float f = v1.getZ() - v3.getZ(); float g = r.getDir().at(0); float h = r.getDir().at(1); float i = r.getDir().at(2); float j = v1.getX() - r.getEye().at(0); float k = v1.getY() - r.getEye().at(1); float l = v1.getZ() - r.getEye().at(2); float eiminushf = e*i - h*f; float gfminusdi = g*f - d*i; float dhminuseg = d*h - e*g; float akminusjb = a*k - j*b; float jcminusal = j*c - a*l; float blminuskc = b*l - k*c; float m = a*(eiminushf) + b*(gfminusdi) + c*(dhminuseg); float beta = (j*(eiminushf) + k*(gfminusdi) + l*(dhminuseg))/m; if (beta < 0) {return ret;} float gamma = (i*(akminusjb) + h*(jcminusal) + g*(blminuskc))/m; if (gamma < 0 || beta+gamma > 1) {return ret;} float t = (-1)*(f*(akminusjb) + e*(jcminusal) + d*(blminuskc))/m; std::vector<float> p; std::vector<float> vec1 = v1.toVec(); std::vector<float> vec2 = v2.toVec(); std::vector<float> vec3 = v3.toVec(); std::vector<float> sub1 = vSub(&vec2, &vec1); std::vector<float> sub2 = vSub(&vec3, &vec1); std::vector<float> scaled1 = vScale(&beta, &sub1); std::vector<float> scaled2 = vScale(&gamma, &sub2); std::vector<float> added1 = vAdd(&vec1, &scaled1); p = vAdd(&added1, &scaled2); ret.setPoint(p); return ret; }
double MultiDLA::surfaceArea(double density, uint32_t steps) const { double result = 0.0; if (m_finished) { #ifndef _WIN32 uint32_t t0 = uint32_t(clock()); #endif // calc double volume = 0.0; double square = 0.0; int32_t sx = m_fld->size().coord(0); int32_t sy = m_fld->size().coord(1); int32_t sz = m_fld->size().coord(2); MCoord::setDefDims(3); MCoord sc; for (size_t i = 0; i < 3; ++i) { sc.setCoord(i, m_fld->size().coord(i)); } CellsField* cf = new CellsField(sc, MCoord(), 2 * m_fld->radius()); double cellRadius = cf->radius(); for (int32_t ix = 0; ix < sx; ++ix) { for (int32_t iy = 0; iy < sy; ++iy) { for (int32_t iz = 0; iz < sz; ++iz) { if (m_fld->element(MCoord(ix, iy, iz)) == OCUPIED_CELL) { MCoord currCoord(ix, iy, iz); cf->setElement(currCoord); volume += vAdd(cf, currCoord) * cube(cf->side()); square += SfromR(cellRadius); } } } } delete cf; // -> Monte-Carlo uint32_t positive = m_fld->monteCarlo(steps); result = 1000000 * square * positive / (steps * density * volume); #ifndef _WIN32 std::cout << "Прошло: " << double(clock() - t0) / CLOCKS_PER_SEC << " сек." << std::endl; #endif } return result; }
double intersectRectan(Rectan *rectan, Photon *photon) { // Clipping double dotProduct = vDotp(photon->direct, rectan->direct); if (dotProduct < EPSILON && dotProduct > -EPSILON) return MISS; // For explanation, see intersectCamera Vec vec = vSub(rectan->origin, photon->origin); double dist = vDotp(rectan->direct, vec) / dotProduct; if (dist < EPSILON) return MISS; /**************/ // Hit point on plane Vec point = vMul(photon->direct, dist); point = vAdd(photon->origin, point); point = vSub(point, rectan->origin); // Compute dot products double dotAA = vDotp(rectan->vectab, rectan->vectab); double dotBB = vDotp(rectan->vectad, rectan->vectad); double dotAB = vDotp(rectan->vectab, rectan->vectad); double dotAP = vDotp(rectan->vectab, point); double dotBP = vDotp(rectan->vectad, point); // Compute barycentric coordinates double denominator = 1 / (dotAA * dotBB - dotAB * dotAB); double u = (dotBB * dotAP - dotAB * dotBP) * denominator; double v = (dotAA * dotBP - dotAB * dotAP) * denominator; // Check if point is in rectangle if (u < EPSILON || v < EPSILON || u > EPSILONONE || v > EPSILONONE) return MISS; return dist; }
void handleInput(GameState* gs, InputState* is) { double te = gs->frameSpan; float moveSpeed = gs->settings.keyScroll * te; // should load from config float rotateSpeed = gs->settings.keyRotate * te; // 20.8 degrees float keyZoom = gs->settings.keyZoom * te; float mouseZoom = gs->settings.mouseZoom * te; if(is->clickButton == 1) { /* flattenArea(gs->map.tb, gs->cursorPos.x - 5, gs->cursorPos.y - 5, gs->cursorPos.x + 5, gs->cursorPos.y + 5 ); setZone(&gs->map, gs->cursorPos.x - 5, gs->cursorPos.y - 5, gs->cursorPos.x + 5, gs->cursorPos.y + 5, gs->activeTool + 1 ); checkMapDirty(&gs->map); */ } if(is->buttonDown == 1) { gs->mouseDownPos.x = gs->cursorPos.x; gs->mouseDownPos.y = gs->cursorPos.y; printf("start dragging at (%d,%d)\n", (int)gs->cursorPos.x, (int)gs->cursorPos.y); } if(is->buttonUp == 1) { //vCopy(&gs->cursorPos, &gs->mouseDownPos); printf("stopped dragging at (%d,%d)\n", (int)gs->cursorPos.x, (int)gs->cursorPos.y); } if(is->clickButton == 2) { gs->activeTool = (gs->activeTool + 1) % 3; } // look direction if(is->keyState[38] & IS_KEYDOWN) { gs->direction += rotateSpeed; } if(is->keyState[39] & IS_KEYDOWN) { gs->direction -= rotateSpeed; } // keep rotation in [0,F_2PI) gs->direction = fmodf(F_2PI + gs->direction, F_2PI); // zoom if(is->keyState[52] & IS_KEYDOWN) { gs->zoom += keyZoom; gs->zoom = fmin(gs->zoom, -10.0); } if(is->keyState[53] & IS_KEYDOWN) { gs->zoom -= keyZoom; } if(is->clickButton == 4) { gs->zoom += mouseZoom; gs->zoom = fmin(gs->zoom, -10.0); } if(is->clickButton == 5) { gs->zoom -= mouseZoom; } // movement Vector move = { .x = moveSpeed * sin(F_PI - gs->direction), .y = moveSpeed * cos(F_PI - gs->direction), .z = 0.0f }; if(is->keyState[111] & IS_KEYDOWN) { vAdd(&gs->lookCenter, &move, &gs->lookCenter); } if(is->keyState[116] & IS_KEYDOWN) { vSub(&gs->lookCenter, &move, &gs->lookCenter); } // flip x and y to get ccw normal, using move.z as the temp move.z = move.x; move.x = -move.y; move.y = move.z; move.z = 0.0f; if(is->keyState[113] & IS_KEYDOWN) { vSub(&gs->lookCenter, &move, &gs->lookCenter); } if(is->keyState[114] & IS_KEYDOWN) { vAdd(&gs->lookCenter, &move, &gs->lookCenter); } if(is->keyState[110] & IS_KEYDOWN) { nearPlane += 50 * te; printf("near: %f, far: %f\n", nearPlane, farPlane); } if(is->keyState[115] & IS_KEYDOWN) { nearPlane -= 50 * te; printf("near: %f, far: %f\n", nearPlane, farPlane); } if(is->keyState[112] & IS_KEYDOWN) { farPlane += 250 * te; printf("near: %f, far: %f\n", nearPlane, farPlane); } if(is->keyState[117] & IS_KEYDOWN) { farPlane -= 250 * te; printf("near: %f, far: %f\n", nearPlane, farPlane); } static lastChange = 0; if(is->keyState[119] & IS_KEYDOWN) { if(gs->frameTime > lastChange + 1) { gs->debugMode = (gs->debugMode + 1) % 5; lastChange = gs->frameTime; } } } void setGameSettings(GameSettings* g, UserConfig* u) { const float rotateFactor = 0.7260f; const float scrollFactor = 300.0f; const float zoomFactor = 600.0f; g->keyRotate = rotateFactor * fclampNorm(u->keyRotateSensitivity); g->keyScroll = scrollFactor * fclampNorm(u->keyScrollSensitivity); g->keyZoom = zoomFactor * fclampNorm(u->keyZoomSensitivity); g->mouseRotate = rotateFactor * fclampNorm(u->mouseRotateSensitivity); g->mouseScroll = scrollFactor * fclampNorm(u->mouseScrollSensitivity); g->mouseZoom = 4 * zoomFactor * fclampNorm(u->mouseZoomSensitivity); printf("keyRotate %.3f\n", g->keyRotate); printf("keyScroll %.3f\n", g->keyScroll); printf("keyZoom %.3f\n", g->keyZoom); printf("mouseRotate %.3f\n", g->mouseRotate); printf("mouseScroll %.3f\n", g->mouseScroll); printf("mouseZoom %.3f\n", g->mouseZoom); } void setUpView(GameState* gs) { } void depthPrepass(XStuff* xs, GameState* gs, InputState* is) { // draw UI renderUIPicking(xs, gs); // draw terrain // TODO: factor all the math into the frame setup function //mScale3f(10, 10, 10, &mModel); //mRot3f(0, 1, 0, gs->direction, &mModel); msPush(&gs->proj); msPerspective(60, gs->screen.aspect, nearPlane, farPlane, &gs->proj); msPush(&gs->view); // order matters! don't mess with this. msTrans3f(0, -1, gs->zoom, &gs->view); msRot3f(1, 0, 0, F_PI / 6, &gs->view); msRot3f(0,1,0, gs->direction, &gs->view); msTrans3f(-gs->lookCenter.x, 0, -gs->lookCenter.y, &gs->view); // y-up to z-up rotation msRot3f(1, 0, 0, F_PI_2, &gs->view); msScale3f(1, 1, -1, &gs->view); // calculate cursor position Vector eyeCoord; Vector worldCoord; Matrix p, invp, invv; // device space (-1:1) Vector devCoord; devCoord.x = 0.50; devCoord.y = 0.50; devCoord.z = -1.0; // eye space mInverse(msGetTop(&gs->proj), &invp); vMatrixMul(&devCoord, &invp, &eyeCoord); vNorm(&eyeCoord, &eyeCoord); // world space mInverse(msGetTop(&gs->view), &invv); vMatrixMul(&eyeCoord, &invv, &worldCoord); vNorm(&worldCoord, &worldCoord); // draw terrain // drawTerrainBlockDepth(&gs->map, msGetTop(&gs->model), msGetTop(&gs->view), msGetTop(&gs->proj)); drawTerrainDepth(&gs->map, msGetTop(&gs->view), msGetTop(&gs->proj), &gs->screen.wh); msPop(&gs->view); msPop(&gs->proj); }
bool hitRectan(Photon *photon, Rectan *rectan, double distance) { // Specular reflection if (true) { // Update ray's position to the point where the ray hits the sphere Vec vec = vMul(photon->direct, distance); photon->origin = vAdd(photon->origin, vec); // Angle between new and old vector is twice the angle between old vector and normal vec = vMul(rectan->direct, vDotp(photon->direct, rectan->direct) * 2.f); vec = vSub(rectan->direct, photon->direct); photon->direct = vNorm(vec); // Might not be necessary... vec = vMul(photon->direct, 1000.f * EPSILON); photon->origin = vAdd(photon->origin, vec); return REFLECTED; } // Diffuse reflection else if (false) { // Necessary for adjusting direction of reflected photon later on bool positiveAngle = NO; if (vDotp(photon->direct, rectan->direct) > EPSILON) positiveAngle = YES; // Update ray's position to the point where the ray hits the sphere Vec vec = vMul(photon->direct, distance); photon->origin = vAdd(photon->origin, vec); #warning DEBUG!!! // Camera origin /*Vec origin; origin.x = 0.99f; origin.y = 0.f; origin.z = 0.f; Vec newDir; newDir = vSub(&origin, &photon->origin); photon->direct = vNorm(&newDir);*/ // Using spherical coordinate system to guarantee // uniform distribution of orientations in space double azimuth = drand48() * M_PI * 2; // "phi" double inclination = acos(2 * drand48() - 1); // "theta" photon->direct.x = sin(inclination) * cos(azimuth); photon->direct.y = sin(inclination) * sin(azimuth); photon->direct.z = cos(inclination); // Adjusting direction of reflected photon // Incoming positive -> negative outgoing // Incomi ng negative -> positive outgoing if (positiveAngle) { if (vDotp(photon->direct, rectan->direct) > EPSILON) photon->direct = vMul(photon->direct, -1.f); } else if (vDotp(photon->direct, rectan->direct) < -EPSILON) photon->direct = vMul(photon->direct, -1.f); photon->direct = vNorm(photon->direct); // Might not be necessary... vec = vMul(photon->direct, 1000.f * EPSILON); photon->origin = vAdd(photon->origin, vec); // Color photon->wavelength = rectan->mID; return REFLECTED; } /* * Absorption */ else return ABSORBED; }
void MultiDLA::cMultiDLA(CellsField* fld, double targetPorosity, uint32_t initN, uint32_t step, uint32_t hitCnt) { fld->clear(); double currVol = 0.0; double needVol = fld->cellsCnt() * (1 - targetPorosity); bool needHit = (hitCnt != 1); size_t dimensions = MCoord::defDims(); MCoordVec* mapNeigh = createNeighborsMap(dimensions); MCoordVec* mapSteps = createStepMap(dimensions, step); uint32_t currCnt = 0; MCoord currCoord; while (currCnt != initN) { currCoord = freeRandomPntInField(fld); fld->setElement(currCoord); currVol += vAdd(fld, currCoord); ++currCnt; } CellsField* hitField; if (needHit) { hitField = new CellsField(fld->size(), MCoord(), fld->radius() * 2); } while (currVol < needVol) { currCoord = freeRandomPntInField(fld); if (needHit) { hitField->clear(); } while (true) { if (!fld->isSet(currCoord) && cntNeighbors(fld, mapNeigh, currCoord) != 0) { FieldElement newHitCnt = 1; if (needHit) { newHitCnt = hitField->elementVal(currCoord) + 1; hitField->setElementVal(currCoord, newHitCnt); } if (newHitCnt >= hitCnt) { fld->setElement(currCoord); currVol += vAdd(fld, currCoord); ++currCnt; break; } } MCoord tmpCoord = makeStep(currCoord, mapSteps); tmpCoord = toroidizeCoords(tmpCoord, fld->size()); while (fld->isSet(tmpCoord)) { tmpCoord = makeStep(currCoord, mapSteps); tmpCoord = toroidizeCoords(tmpCoord, fld->size()); } currCoord = tmpCoord; } } delete mapNeigh; mapNeigh = nullptr; delete mapSteps; mapSteps = nullptr; if (needHit) { delete hitField; hitField = nullptr; } }
/************************************************************************************************ * Bouncher moving * ************************************************************************************************/ void cBouncher::Move(float mx, float my, float mz) { this->Pos = vAdd(this->Pos, vInit(mx, my, mz)); }
/************************************************************************************************ * Move ball forward * ************************************************************************************************/ void cBall::MoveForward() { this->Pos = vAdd(this->Pos, vScale(this->Dir, this->Vel)); }
//=============================================== // Unit Tests //=============================================== int main() { // set for command line argument -t to run unit tests. bool test = true; if (test) { std::cout<<"\n=================\nBegin UNIT TESTS\n=================\n\n"; Light::Light n = *new Light::Light(0, 1, 1, 0, 0.5, 0.5, 0.5); n.print(); Intersect::Intersect i = *new Intersect::Intersect(); if(i.isHit()) { std::cout<<"INCORRECT! hit is true.\n\n"; } else { std::cout<<"CORRECT! hit is false.\n\n"; i.setHit(true); } if(i.isHit()) { std::cout<<"CORRECT! hit is true.\n\n"; } else { std::cout<<"INCORRECT! hit is false.\n\n"; } std::vector<float> ptest(3); ptest[0] = 0; ptest[1] = 1; ptest[2] = 2; i.setPoint(ptest); std::vector<float> p = i.getPoint(); std::cout<< "[" << p[0] << ", " << p[1] << ", " << p[2] << "]\n"; Vertex::Vertex a = *new Vertex::Vertex(0,0,0); Vertex::Vertex b = *new Vertex::Vertex(1,0,0); Vertex::Vertex c = *new Vertex::Vertex(0,1,0); a.print(); a = a.sub(b); a.print(); std::vector<float> d = c.toVec(); std::cout<<"vec ["<< d[0] << ", " << d[1] << ", " << d[2] << "]\n"; Vertex::Vertex e1 = *new Vertex::Vertex(d); e1.print(); Vertex a1 = *new Vertex::Vertex(0,1,0); Vertex b1 = *new Vertex::Vertex(1,-1,0); Vertex c1 = *new Vertex::Vertex(-1,-1,0); Triangle t = *new Triangle::Triangle(a1,b1,c1); p[0] = 0; p[1] = 0; p[2] = 0; std::vector<float> e(3); e[0] = 0; e[1] = 0; e[2] = 3; Ray::Ray r = *new Ray::Ray(e, p); i = t.intersect(r); if (i.isHit()) { std::cout<<"Triangle Intersected - OKAY\n"; } Sphere::Sphere s = *new Sphere::Sphere(1, p); if (s.intersect(r).isHit()) { std::cout<<"Sphere Intersected - OKAY\n"; } e[0] = 0; e[1] = -4; e[2] = -4; p[0] = 1; p[1] = 1; p[2] = -1; r.setEye(e); r.setPoint(p); std::cout<<"projected "; vPrint(r.project(1.5)); PPM* ppm = new PPM(640, 480, 255); int val; for (float h = 0; h<480; h++) { for (float w =0; w<640; w++) { val = h;//std::min(255, (int)((w/639)*255.0f)); ppm->addPixel(*(new Pixel::Pixel(val, val, val))); } } ppm->save("output"); /* for (float h = 0; h < 3; h++) { for (float w = 0; w< ppm->getW(); w++) { std::cout<<w<<" "; ppm->getPixel(w, h).print(); } } */ std::cout<<"End PPM tests\n"; Pixel::Pixel px = *new Pixel::Pixel(255, 255, 255); Pixel::Pixel black = *new Pixel::Pixel(0,0,0); Pixel::Pixel pfloat = *new Pixel::Pixel(1.0f, 0.9f, 0.05f); Pixel::Pixel pmax = *new Pixel::Pixel(2.0f, 1.0f, 0.5f); px.print(); black.print(); black.add(px); black.print(); pfloat.print(); pmax.print(); std::vector<float> test1(3); test1[0] = 1; test1[1] = 0; test1[2] = 0.5; std::vector<float> test2(3); test2[0] = 0; test2[1] = 1; test2[2] = 0.5; std::cout<<vDot(test1, test2)<<"\n"; vPrint(vSub(test1, test2)); vPrint(vAdd(test1, test2)); vPrint(vMult(test1, test2)); vPrint(normalize(test1)); vPrint(normalize(test2)); vPrint(vCross(test1, test2)); vPrint(vScale(-1, test1)); std::cout<<"\n=================\nEnd UNIT TESTS\n=================\n\n"; return 0; } else { return 0; } }