void Branch::createRoot() { m_radius = (s_settings->m_startRadius) + (s_settings->m_startRadiusVariation * floatRandom()); m_position = curvePos(); generateSection(m_strips, m_position, Vector3(0.0f, 0.01f, 0.0f)); m_position.y += 0.1f; makeNewDirection(); }
void Branch::createRoot(const Vector3& orgin, const Vector3& direction) { m_radius = (s_settings->m_startRadius) + (s_settings->m_startRadiusVariation * floatRandom()); m_position = orgin; generateSection(m_strips, m_position, direction); m_position.y += 0.1f; if (m_curve) makeNewDirection(); else m_direction = direction; }
bool Branch::makeNewDirection(float angleMul, bool hasReatchedTarget) { if (m_curve) { if (m_curveTarget == m_curveCount) return false; Vector3 pos = curvePos(); Vector3 direction = pos - m_position; // rand... float x = (s_settings->m_angle + s_settings->m_angleVariation * floatRandom()) * angleMul * 0.005f; float y = (s_settings->m_angle + s_settings->m_angleVariation * floatRandom()) * angleMul * 0.005f; float z = (s_settings->m_angle + s_settings->m_angleVariation * floatRandom()) * angleMul * 0.005f; direction = direction.normalize(); direction.x += x; direction.y += y; direction.z += z; m_direction = direction.normalize(); // Set next target if we reatched our target point in the curve if (hasReatchedTarget) ++m_curveTarget; return true; } Matrix4 matrix; float angle = (s_settings->m_angle + s_settings->m_angleVariation * floatRandom()) * angleMul; if (random() & 1) angle = -angle; switch (random() %3 ) { case 0 : { matrix.makeXrotation(angle * (3.1415f / 180.0f)); //m_direction.y = 1.0f; break; } case 1 : { matrix.makeYrotation(angle * (3.1415f / 180.0f)); //m_direction.z = 1.0f; break; } case 2 : { matrix.makeZrotation(angle * (3.1415f / 180.0f)); //m_direction.x = 1.0f; break; } default : ZENIC_ASSERT(false); } m_direction = matrix.apply(m_direction); m_direction.y += -s_settings->m_gravity; m_direction = m_direction.normalize(); return true; }
void Branch::generateSection(Vector3* coords, const Vector3& start, const Vector3& end) { ZENIC_ASSERT(coords); Vector3 up(0.0f, 1.0f, 0.0f); Vector3 rel = end - start; Vector3 n = rel.normalize(); Vector3 right = up.cross(n); float rightLength = right.length(); if (rightLength) right *= 1.0f / rightLength; else right = Vector3(1.0f, 0, 0); up = n.cross(right); for (uint i = 0; i < s_settings->m_sides; ++i) { Vector3 temp = up * (s_cosTable[i] * m_radius) + right * (s_sinTable[i] * m_radius); coords[i] = start + temp; } m_radius = m_radius * (s_settings->m_contact * 0.01f) + (s_settings->m_contactVariation * 0.01f * floatRandom()); }
void DistanceToAtom::compute(const QVector<QVector3D> &pointsOriginal, float cutoff) { if(pointsOriginal.size() == 0) { qDebug() << "DistanceToAtom::compute WARNING: input vector is empty."; return; } QElapsedTimer timer; timer.start(); float min = 1e90; float max = -1e90; for(const QVector3D &point : pointsOriginal) { min = std::min(min, point[0]); min = std::min(min, point[1]); min = std::min(min, point[2]); max = std::max(max, point[0]); max = std::max(max, point[1]); max = std::max(max, point[2]); } max += 1e-5; const float systemSize = max - min; // Now translate all points QVector<QVector3D> points = pointsOriginal; for(QVector3D &point : points) { point[0] -= min; point[1] -= min; point[2] -= min; } float cellSize; CellList cellList = buildCellList(points, systemSize, cutoff, cellSize); const int numCells = cellList.size(); // Each index should be identical m_values.clear(); m_values.resize(m_numberOfRandomVectors); m_randomNumbers.resize(3*m_numberOfRandomVectors); for(int i=0; i<3*m_numberOfRandomVectors; i++) { m_randomNumbers[i] = floatRandom(0, systemSize); } const float oneOverCellSize = 1.0/cellSize; #pragma omp parallel for num_threads(8) for(int i=0; i<m_numberOfRandomVectors; i++) { const float x = m_randomNumbers[3*i+0]; const float y = m_randomNumbers[3*i+1]; const float z = m_randomNumbers[3*i+2]; const int cx = x * oneOverCellSize; const int cy = y * oneOverCellSize; const int cz = z * oneOverCellSize; float minimumDistanceSquared = 1e10; const float minimumDistanceSquared0 = minimumDistanceSquared; // Loop through all 27 cells with size=cutoff for(int dx=-1; dx<=1; dx++) { for(int dy=-1; dy<=1; dy++) { for(int dz=-1; dz<=1; dz++) { const vector<QVector3D> &pointsInCell = cellList[periodic(cx+dx, numCells)][periodic(cy+dy, numCells)][periodic(cz+dz, numCells)]; const int numberOfPointsInCell = pointsInCell.size(); for(int j=0; j<numberOfPointsInCell; j++) { // const QVector3D &point = points[pointIndex]; const QVector3D &point = pointsInCell[j]; float dx = x - point[0]; float dy = y - point[1]; float dz = z - point[2]; if(dx < -0.5*systemSize) dx += systemSize; else if(dx > 0.5*systemSize) dx -= systemSize; if(dy < -0.5*systemSize) dy += systemSize; else if(dy > 0.5*systemSize) dy -= systemSize; if(dz < -0.5*systemSize) dz += systemSize; else if(dz > 0.5*systemSize) dz -= systemSize; const float distanceSquared = dx*dx + dy*dy + dz*dz; if(distanceSquared < minimumDistanceSquared) minimumDistanceSquared = distanceSquared; } } } } if(minimumDistanceSquared == minimumDistanceSquared0) { minimumDistanceSquared = -1; } m_values[i] = float(minimumDistanceSquared); } m_randomNumbers.clear(); points.clear(); // qDebug() << "DTO finished after " << timer.elapsed() << " ms."; m_isValid = true; // if(pointsOriginal.size() == 0) { // qDebug() << "DistanceToAtom::compute WARNING: input vector is empty."; // return; // } // float min = 1e90; // float max = -1e90; // for(const QVector3D &point : pointsOriginal) { // min = std::min(min, point[0]); // min = std::min(min, point[1]); // min = std::min(min, point[2]); // max = std::max(max, point[0]); // max = std::max(max, point[1]); // max = std::max(max, point[2]); // } // max += 1e-5; // const float systemSize = max - min; // // Now translate all points // QVector<QVector3D> points = pointsOriginal; // for(QVector3D &point : points) { // point[0] -= min; // point[1] -= min; // point[2] -= min; // } // float cellSize; // CellList cellList = buildCellList(points, systemSize, cutoff, cellSize); // const int numCells = cellList.size(); // Each index should be identical // const float voxelSize = systemSize / m_size; // for(int i=0; i<m_size; i++) { // for(int j=0; j<m_size; j++) { // for(int k=0; k<m_size; k++) { // const QVector3D voxelCenter((i+0.5)*voxelSize, (j+0.5)*voxelSize, (k+0.5)*voxelSize); // float minimumDistanceSquared0 = 1e10; // float minimumDistanceSquared = 1e10; // // Find the cell list where this position belongs and loop through all cells around // const int cx = voxelCenter[0] / cellSize; // const int cy = voxelCenter[1] / cellSize; // const int cz = voxelCenter[2] / cellSize; // // Loop through all 27 cells with size=cutoff // for(int dx=-1; dx<=1; dx++) { // for(int dy=-1; dy<=1; dy++) { // for(int dz=-1; dz<=1; dz++) { // const vector<int> &pointsInCell = cellList[periodic(cx+dx, numCells)][periodic(cy+dy, numCells)][periodic(cz+dz, numCells)]; // for(const int &pointIndex : pointsInCell) { // const QVector3D &point = points[pointIndex]; // const float distanceSquared = periodicDistanceSquared(point, voxelCenter, systemSize); // minimumDistanceSquared = std::min(minimumDistanceSquared, distanceSquared); // } // } // } // } // if(minimumDistanceSquared == minimumDistanceSquared0) { // minimumDistanceSquared = -1; // } // setValue(i,j,k,float(minimumDistanceSquared)); // } // } // } // m_isValid = true; }