#include #include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #include #pragma comment(lib, "ws2_32.lib") #else #include #include #include #include #endif #define M_PI 3.14159265358979323846 #define M_PHI 1.61803398874989484820458683436563811772030917980576286213544862270526046281890 #define M_TAU 6.2831853071795864769252867665590057683943387987502116419498891846156328125724179972560696506842341359 class Vec3 { public: double x, y, z; Vec3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {} inline double norm() const { return std::sqrt(x*x + y*y + z*z); } inline Vec3 normalize() const { double n = norm(); return Vec3(x/n, y/n, z/n); } inline Vec3 cross(const Vec3& other) const { return Vec3( y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x ); } inline double dot(const Vec3& other) const { return x * other.x + y * other.y + z * other.z; } inline Vec3 operator+(const Vec3& other) const { return Vec3(x + other.x, y + other.y, z + other.z); } inline Vec3 operator-(const Vec3& other) const { return Vec3(x - other.x, y - other.y, z - other.z); } inline Vec3 operator*(double scalar) const { return Vec3(x * scalar, y * scalar, z * scalar); } inline Vec3 operator/(double scalar) const { return Vec3(x / scalar, y / scalar, z / scalar); } bool operator==(const Vec3& other) const { return x == other.x && y == other.y && z == other.z; } bool operator<(const Vec3& other) const { if (x != other.x) return x < other.x; if (y != other.y) return y < other.y; return z < other.z; } struct Hash { size_t operator()(const Vec3& v) const { size_t h1 = std::hash()(std::round(v.x * 1000.0)); size_t h2 = std::hash()(std::round(v.y * 1000.0)); size_t h3 = std::hash()(std::round(v.z * 1000.0)); return h1 ^ (h2 << 1) ^ (h3 << 2); } }; }; class Triangle { public: Vec3 v0, v1, v2; Triangle(const Vec3& v0, const Vec3& v1, const Vec3& v2) : v0(v0), v1(v1), v2(v2) {} Vec3 normal() const { Vec3 edge1 = v1 - v0; Vec3 edge2 = v2 - v0; return edge1.cross(edge2).normalize(); } }; std::vector fibsphere(int numPoints, float radius) { std::vector points; points.reserve(numPoints); for (int i = 0; i < numPoints; ++i) { double y = 1.0 - (i / (double)(numPoints - 1)) * 2.0; double radius_at_y = std::sqrt(1.0 - y * y); double theta = 2.0 * M_PI * i / M_PHI; double x = std::cos(theta) * radius_at_y; double z = std::sin(theta) * radius_at_y; points.emplace_back(x * radius, y * radius, z * radius); } return points; } // Create proper triangulation for Fibonacci sphere std::vector createFibonacciSphereMesh(const std::vector& points) { std::vector triangles; int n = points.size(); // Create a map to quickly find points by their spherical coordinates std::map, int> pointMap; for (int i = 0; i < n; i++) { double phi = std::acos(points[i].y / 3.0); // theta = acos(y/R) double theta = std::atan2(points[i].z, points[i].x); if (theta < 0) theta += 2.0 * M_PI; pointMap[{phi, theta}] = i; } // Create triangles by connecting neighboring points for (int i = 0; i < n - 1; i++) { // For each point, connect it to its neighbors if (i > 0) { triangles.emplace_back(points[i-1], points[i], points[(i+1) % n]); } } // Add cap triangles for (int i = 1; i < n/2 - 1; i++) { triangles.emplace_back(points[0], points[i], points[i+1]); triangles.emplace_back(points[n-1], points[n-1-i], points[n-2-i]); } return triangles; } // Alternative: Use Delaunay triangulation on the sphere (simplified) std::vector createSphereMeshDelaunay(const std::vector& points) { std::vector triangles; int n = points.size(); // Simple approach: connect each point to its nearest neighbors // This is a simplified version - for production use a proper Delaunay triangulation for (int i = 0; i < n; i++) { // Find nearest neighbors (simplified) std::vector> distances; for (int j = 0; j < n; j++) { if (i != j) { double dist = (points[i] - points[j]).norm(); distances.emplace_back(dist, j); } } // Sort by distance and take 6 nearest neighbors std::sort(distances.begin(), distances.end()); int numNeighbors = min(6, (int)distances.size()); // Create triangles with nearest neighbors for (int k = 0; k < numNeighbors - 1; k++) { triangles.emplace_back(points[i], points[distances[k].second], points[distances[k+1].second]); } } return triangles; } Vec3 rotate(const Vec3& point, double angleX, double angleY, double angleZ) { // Rotate around X axis double y1 = point.y * cos(angleX) - point.z * sin(angleX); double z1 = point.y * sin(angleX) + point.z * cos(angleX); // Rotate around Y axis double x2 = point.x * cos(angleY) + z1 * sin(angleY); double z2 = -point.x * sin(angleY) + z1 * cos(angleY); // Rotate around Z axis double x3 = x2 * cos(angleZ) - y1 * sin(angleZ); double y3 = x2 * sin(angleZ) + y1 * cos(angleZ); return Vec3(x3, y3, z2); } std::string generateSVG(const std::vector& points, const std::vector& mesh, double angleX, double angleY, double angleZ) { std::stringstream svg; int width = 800; int height = 600; svg << "\n"; svg << "\n"; svg << "\n"; // Project 3D to 2D auto project = [&](const Vec3& point) -> std::pair { Vec3 rotated = rotate(point, angleX, angleY, angleZ); // Perspective projection double scale = 300.0 / (5.0 + rotated.z); double x = width / 2 + rotated.x * scale; double y = height / 2 + rotated.y * scale; return {x, y}; }; // Draw triangles with shading for (const auto& triangle : mesh) { Vec3 normal = triangle.normal(); Vec3 lightDir = Vec3(0.5, 0.7, 1.0).normalize(); double intensity = max(0.0, normal.dot(lightDir)); // Calculate color based on intensity int r = static_cast(50 + intensity * 200); int g = static_cast(100 + intensity * 150); int b = static_cast(200 + intensity * 55); auto [x0, y0] = project(triangle.v0); auto [x1, y1] = project(triangle.v1); auto [x2, y2] = project(triangle.v2); // Only draw triangles facing the camera Vec3 viewDir(0, 0, 1); if (normal.dot(viewDir) > 0.1) { svg << "\n"; } } // Draw points for debugging for (const auto& point : points) { auto [x, y] = project(point); svg << "\n"; } svg << ""; return svg.str(); } // HTTP server class (keep your existing server implementation) class SimpleHTTPServer { private: int serverSocket; int port; public: SimpleHTTPServer(int port) : port(port), serverSocket(-1) {} ~SimpleHTTPServer() { stop(); } bool start() { #ifdef _WIN32 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed" << std::endl; return false; } #endif serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket < 0) { std::cerr << "Socket creation failed" << std::endl; return false; } int opt = 1; #ifdef _WIN32 if (setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) < 0) { #else if (setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { #endif std::cerr << "Setsockopt failed" << std::endl; return false; } sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(port); if (bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { std::cerr << "Bind failed" << std::endl; return false; } if (listen(serverSocket, 10) < 0) { std::cerr << "Listen failed" << std::endl; return false; } std::cout << "Server started on port " << port << std::endl; return true; } void stop() { if (serverSocket >= 0) { #ifdef _WIN32 closesocket(serverSocket); WSACleanup(); #else close(serverSocket); #endif serverSocket = -1; } } void handleRequests() { // Generate proper Fibonacci sphere std::vector spherePoints = fibsphere(200, 3.0); // Reduced for performance std::vector sphereMesh = createSphereMeshDelaunay(spherePoints); while (true) { sockaddr_in clientAddr; #ifdef _WIN32 int clientAddrLen = sizeof(clientAddr); #else socklen_t clientAddrLen = sizeof(clientAddr); #endif int clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientAddrLen); if (clientSocket < 0) { std::cerr << "Accept failed" << std::endl; continue; } char buffer[4096] = {0}; recv(clientSocket, buffer, sizeof(buffer), 0); std::string request(buffer); std::string response; if (request.find("GET / ") != std::string::npos || request.find("GET /index.html") != std::string::npos) { response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" + getHTML(); } else if (request.find("GET /mesh.svg") != std::string::npos) { static double angle = 0.0; angle += 0.02; std::string svg = generateSVG(sphereMesh, angle, angle * 0.7, angle * 0.3); response = "HTTP/1.1 200 OK\r\nContent-Type: image/svg+xml\r\n\r\n" + svg; } else { response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\n404 Not Found"; } send(clientSocket, response.c_str(), response.length(), 0); #ifdef _WIN32 closesocket(clientSocket); #else close(clientSocket); #endif std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } std::string getHTML() { return R"( 3D Sphere Mesh Renderer

3D Sphere Mesh Renderer

3D Sphere
<--- DO NOT EDIT --->
)"; } }; int main() { SimpleHTTPServer server(5101); if (!server.start()) { std::cerr << "Failed to start server" << std::endl; return 1; } std::cout << "Open your browser and navigate to http://localhost:5101" << std::endl; std::cout << "Press Ctrl+C to stop the server" << std::endl; server.handleRequests(); return 0; }