Solar的Model、Filter示例

本文介绍了Solar框架中Model和Filter的使用方法,强调了Model中的全局过滤器和Action中的局部过滤器,提供了代码示例,如验证用户名、邮箱的唯一性和格式。在Action中,展示了如何处理注册表单的密码匹配、手机号验证等。

Solar的Model、Filter示例

Model、Filter

模型为公有,Action为私有

在Model中添加的是全局的filter,通常是该模型的字段,而与该模型无关的的字段若要验证则放在Action中,比如模型Users 添加的过滤器为:

actionRegister 中添加了如下filter:

源码:模型Users

源码: actionRegister()

源码:register.php

注意 在这里

value = '注册' ,在action中用这条语句if($this->_isProcess('register')) 判断是否用了, Solar会查找本地字符串,将PROCESS_加到register之前(即:PROCESS_REGISTER)查找本地字符串,看是否和value="注册"的"注册"相同,若不相同返回false。

所以,为了使用两者相同,我在/Admin/Controller/Page/Locale/en_US.php中添加了PROCESS_REGISTER => '注册' 的转换。

为什么这个函数只能打印出map result1,后面的都打印不出来了?但是也没有报错。 export const getOnlinePagingDevices = (params: PagingDeviceParams) : ToolsPagingDeviceList => { // 根据 PagingDeviceQuery 接口的定义进行筛选 const newList = mapDeviceToDeviceContent(deviceList); console.log('map result1') const filteredDevices = newList.filter(device => { const query = params.query || {}; // 根据 onlineStatuses 筛选,默认all的话不会发送这个字段,这是一个数组,比如 onlineStatuses: ["OFFLINE"] // todo: 现在设备列表没有和status有关的字段和逻辑,需要补充 if (query?.onlineStatuses && query?.onlineStatuses.length > 0 && !query?.onlineStatuses.includes(device.onlineStatus)) { return false; } // 根据 deviceModels 筛选 if (query?.deviceModels && query?.deviceModels.length > 0 && !query?.deviceModels.includes(device.deviceModel)) { return false; } // 根据 searchValue (模糊搜索 deviceName) 筛选 if (query.searchValue && !device.deviceName.includes(query.searchValue)) { return false; } // 根据 siteId 筛选 // todo: 不知道siteId是什么筛选项,别的筛选项的逻辑还需要补充吗? // if (query.siteId !== undefined && query.siteId !== null && device.siteId !== query.siteId) { // return false; // } return true; // 如果所有条件都匹配,则保留该设备 }); console.log('map result2', filteredDevices) // 数据排序 if (params.sort && params.sort.length > 0) { const sortField = params.sort[0].name; // todo: 选第一列为筛选项时,数组传了deviceName和channelName const sortDirection = params.sort[0].sortDirection.toLowerCase(); filteredDevices.sort((a, b) => { // 检查字段是否存在 if (a[sortField] === undefined || b[sortField] === undefined) { return 0; } const valA = a[sortField]; const valB = b[sortField]; if (valA < valB) { return sortDirection === 'asc' ? -1 : 1; } if (valA > valB) { return sortDirection === 'asc' ? 1 : -1; } return 0; }); } // 数据分页 const page = params.page || { number: 0, size: 10 }; const pageNumber = page.number || 0; const pageSize = page.size || 10; const totalElements = filteredDevices.length; const totalPages = Math.ceil(totalElements / pageSize); const start = pageNumber * pageSize; const end = start + pageSize; const paginatedContent = filteredDevices.slice(start, end); console.log(3) // 数据统计 const deviceStats = { ipcCount: filteredDevices.filter(d => d.deviceType === 'IPC').length, nvrCount: filteredDevices.filter(d => d.deviceType === 'NVR').length, solarCount: filteredDevices.filter(d => d.deviceType === 'SOLAR').length, otherCount: filteredDevices.filter(d => d.deviceType === 'OTHER').length, discoveredDeviceCount: newList.length, // ... 更多统计数据 }; console.log(4) // 构建返回值 const response = { content: paginatedContent, page: { first: pageNumber === 0, last: pageNumber >= totalPages - 1, number: pageNumber, numberOfElements: paginatedContent.length, size: pageSize, totalElements: totalElements, totalPages: totalPages, }, deviceStats: deviceStats, upgradingDeviceNum: filteredDevices.filter(d => d.upgradeInfo?.upgrading).length, needUpdateDeviceStatus: false, // todo: 这可能是一个额外的业务逻辑 }; console.log(5) console.log(77777777777777, response) return response; };
09-24
#pragma once #include "Sphere.h" class Background : public Sphere // 改为继承 Sphere { public: Background(); void initData(DataParam* param = nullptr) override; void render(glm::mat4& view, glm::mat4& projection) override; // 现在可以 override void update(float dt) override; }; #pragma once #include <glm/glm.hpp> class Camera { public: glm::vec3 Position; glm::vec3 Front = glm::vec3(0.0f, 0.0f, -1.0f); glm::vec3 Up = glm::vec3(0.0f, 1.0f, 0.0f); glm::vec3 Right; glm::vec3 WorldUp = glm::vec3(0.0f, 1.0f, 0.0f); float Yaw = -90.0f; float Pitch = 0.0f; float MovementSpeed = 2.5f; float MouseSensitivity = 0.1f; Camera(glm::vec3 position = glm::vec3(0.0f, 50.0f, 100.0f)); glm::mat4 GetViewMatrix(); void ProcessKeyboard(int direction, float dt); void ProcessMouseMovement(float xoffset, float yoffset); private: void updateCameraVectors(); }; #pragma once #include "Sphere.h" class Moon : public Sphere { public: Moon(); void update(float dt, const glm::mat4& earthModel); // 特殊更新函数 private: float orbitRadius = 15.0f; float orbitAngle = 0.0f; float rotationAngle = 0.0f; float orbitSpeed = 0.5f; float rotationSpeed = 0.1f; }; #pragma once #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <string> #include "Shader.h" typedef struct { glm::vec3 coordinate; glm::vec3 color; glm::vec2 texture; glm::vec3 normal; } TextureColorVertex; typedef struct { GLuint latSegments; GLuint longSegments; GLfloat radius; GLfloat height; } DataParam; class Object { public: Object(std::string vs, std::string fs, std::string texName = ""); virtual ~Object(); Shader* shader = nullptr; glm::mat4 model; void createShader(const char* vs, const char* fs); void setTexture(std::string texName); virtual void render(glm::mat4& view, glm::mat4& projection); virtual void initData(DataParam* param = nullptr) = 0; virtual void update(float dt) {} virtual void renderObject() = 0; virtual void updateDataBuffer(); protected: TextureColorVertex* vertices = nullptr; GLushort* indices = nullptr; GLuint indexCount = 0; GLint verticesSize = 0; GLuint indexSize = 0; GLuint texture = 0; GLuint VBO = 0, VAO = 0, EBO = 0; float rotationSpeed = 0.0f; float revolutionSpeed = 0.0f; float rotationAngle = 0.0f; float revolutionAngle = 0.0f; glm::vec3 translation = glm::vec3(0.0f); GLsizei stride = sizeof(TextureColorVertex); void createBuffer(bool createEBO = true, GLenum usage = GL_STATIC_DRAW); }; #pragma once #include "Sphere.h" class Planet : public Sphere { public: Planet(std::string texName, glm::vec3 orbitPos, float revSpeed, float rotSpeed); void update(float dt) override; // 声明 override → 必须实现 }; #pragma once #include <string> #include <glad/glad.h> class Shader { public: unsigned int ID; Shader(const char* vertexPath, const char* fragmentPath); void use(); void setInt(const std::string& name, int value); void setMat4(const std::string& name, const float* mat); void setVec3(const std::string& name, float x, float y, float z); private: void checkCompileErrors(unsigned int shader, std::string type); }; #pragma once #include "Object.h" class Sphere : public Object { public: Sphere(std::string vs, std::string fs, std::string texName = ""); ~Sphere(); void initData(DataParam* param) override; void renderObject() override; void update(float dt) override; }; #pragma once #include "Sphere.h" class Sun : public Sphere { public: Sun(); void renderObject() override; void update(float dt) override; }; #pragma once #include <glad/glad.h> #include <GLFW/glfw3.h> #include <map> #include <string> using namespace std; typedef map<string, GLuint> Textures; class TexturePool { public: virtual ~TexturePool(); private: TexturePool(); Textures textures; public: void addTexture(string name, string path); static TexturePool* getInstance(); GLuint getTexture(string name); }; // Background.cpp #include "Background.h" #include <glm/gtx/transform.hpp> Background::Background() : Sphere("shaders/background.vs", "shaders/background.fs", "background") { // 构造器初始化着色器和纹理 } void Background::initData(DataParam* param) { DataParam p = { 60, 60, 500.0f, 0 }; Sphere::initData(&p); // 调用父类生成球面数据 } void Background::render(glm::mat4& view, glm::mat4& projection) { // 移除摄像机位移,保持背景不动 glm::mat4 viewNoTrans = glm::mat4(glm::mat3(view)); Object::render(viewNoTrans, projection); // 调用 Object::render(this, ...) } void Background::update(float dt) { // 背景无需更新 } #include "Camera.h" #include <glad/glad.h> // 必须第一行 #include <GLFW/glfw3.h> // 第二行 #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #define GLM_ENABLE_EXPERIMENTAL #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> // 这个提供 glm::lookAt #include <glm/gtc/type_ptr.hpp> Camera::Camera(glm::vec3 position) : Position(position) { updateCameraVectors(); } glm::mat4 Camera::GetViewMatrix() { return glm::lookAt(Position, Position + Front, Up); } void Camera::ProcessKeyboard(int direction, float dt) { float velocity = MovementSpeed * dt; if (direction == 'W') Position += Front * velocity; if (direction == 'S') Position -= Front * velocity; if (direction == 'A') Position -= Right * velocity; if (direction == 'D') Position += Right * velocity; } void Camera::ProcessMouseMovement(float xoffset, float yoffset) { xoffset *= MouseSensitivity; yoffset *= MouseSensitivity; Yaw += xoffset; Pitch += yoffset; if (Pitch > 89.0f) Pitch = 89.0f; if (Pitch < -89.0f) Pitch = -89.0f; updateCameraVectors(); } void Camera::updateCameraVectors() { glm::vec3 front; front.x = cos(glm::radians(Pitch)) * cos(glm::radians(Yaw)); front.y = sin(glm::radians(Pitch)); front.z = cos(glm::radians(Pitch)) * sin(glm::radians(Yaw)); Front = glm::normalize(front); Right = glm::normalize(glm::cross(Front, WorldUp)); Up = glm::normalize(glm::cross(Right, Front)); } #include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> // ✅ 新增:标准库支持 #include <vector> #include <memory> // 用于 unique_ptr #include "TexturePool.h" // 必须放在 glfw/glad 之后! #include "Object.h" #include "Sphere.h" #include "Planet.h" #include "Sun.h" #include "Background.h" #include "Camera.h" #include "moon.h" #define DEBUG_SUN_POS using namespace std; const unsigned int SCR_WIDTH = 1200; const unsigned int SCR_HEIGHT = 800; Camera camera(glm::vec3(0, 50, 120)); // 从上方偏远处观察太阳系 float lastX = SCR_WIDTH / 2.0f; float lastY = SCR_HEIGHT / 2.0f; bool firstMouse = true; float deltaTime = 0.1f; float lastFrame = 0.0f; void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; return; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; lastX = xpos; lastY = ypos; camera.ProcessMouseMovement(xoffset, yoffset); } void processInput(GLFWwindow* window) { float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera.ProcessKeyboard('W', deltaTime); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera.ProcessKeyboard('S', deltaTime); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera.ProcessKeyboard('A', deltaTime); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.ProcessKeyboard('D', deltaTime); } int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Solar System", NULL, NULL); if (!window) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); glEnable(GL_DEPTH_TEST); Moon moon; Planet* earth = nullptr; // 初始化纹理池 TexturePool* tp = TexturePool::getInstance(); tp->addTexture("sun", "textures/sun.jpg"); tp->addTexture("earth", "textures/earth.jpg"); tp->addTexture("mars", "textures/mars.jpg"); tp->addTexture("jupiter", "textures/jupiter.jpg"); tp->addTexture("mercury", "textures/mercury.jpg"); tp->addTexture("moon", "textures/moon.jpg"); tp->addTexture("neptune", "textures/neptune.jpg"); tp->addTexture("saturn", "textures/saturn.jpg"); tp->addTexture("uranus", "textures/uranus.jpg"); tp->addTexture("venus", "textures/venus.jpg"); tp->addTexture("background", "textures/background.jpg"); // 初始化对象 Sun sun; DataParam param{ 60, 60, 20.0f, 0 }; sun.initData(&param); Background bg; bg.initData(); std::vector<std::unique_ptr<Planet>> planets; planets.push_back(std::make_unique<Planet>("mercury", glm::vec3(0, 0, 60), 0.08f, 1.0f)); planets.push_back(std::make_unique<Planet>("venus", glm::vec3(0, 0, 70), 0.06f, 0.8f)); planets.push_back(std::make_unique<Planet>("earth", glm::vec3(0, 0, 80), 0.04f, 1.2f)); planets.push_back(std::make_unique<Planet>("mars", glm::vec3(0, 0, 90), 0.03f, 1.0f)); planets.push_back(std::make_unique<Planet>("jupiter", glm::vec3(0, 0, 100), 0.02f, 0.6f)); planets.push_back(std::make_unique<Planet>("saturn", glm::vec3(0, 0, 120), 0.015f, 0.5f)); planets.push_back(std::make_unique<Planet>("uranus", glm::vec3(0, 0, 140), 0.01f, 0.4f)); planets.push_back(std::make_unique<Planet>("neptune", glm::vec3(0, 0, 160), 0.008f, 0.3f)); for (auto& p : planets) { p->initData(&param); } earth = planets[2].get(); glfwSetCursorPosCallback(window, mouse_callback); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); while (!glfwWindowShouldClose(window)) { processInput(window); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 view = camera.GetViewMatrix(); glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / SCR_HEIGHT, 0.1f, 1000.0f); sun.render(view, proj); bg.render(view, proj); for (auto& p : planets) { p->shader->use(); glm::vec3 sunPos(sun.model[3][0], sun.model[3][1], sun.model[3][2]); p->shader->setVec3("lightPos", sunPos.x, sunPos.y, sunPos.z); // 设置摄像机位置(用于高光) p->shader->setVec3("viewPos", camera.Position.x, camera.Position.y, camera.Position.z); p->render(view, proj); } sun.update(deltaTime * 100); bg.update(deltaTime); for (auto& p : planets) p->update(deltaTime * 100); moon.update(deltaTime * 100, earth->model); moon.render(view, proj); #ifdef DEBUG_SUN_POS std::cout << "Sun pos: (" << sun.model[3][0] << ", " << sun.model[3][1] << ", " << sun.model[3][2] << ")\n"; #endif glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); return 0; } #include "Moon.h" Moon::Moon() : Sphere("shaders/planet.vs", "shaders/planet.fs", "moon") { } void Moon::update(float dt, const glm::mat4& earthModel) { orbitAngle += orbitSpeed * dt; rotationAngle += rotationSpeed * dt; model = glm::mat4(1.0f); // 获取地球的位置矩阵 model = earthModel; // 绕地球公转(绕Y轴) model = glm::rotate(model, glm::radians(orbitAngle), glm::vec3(0, 1, 0)); model = glm::translate(model, glm::vec3(0, 0, -orbitRadius)); // 向前飞一段 // 自转 model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0, 1, 0)); // 缩小尺寸 model = glm::scale(model, glm::vec3(0.5f)); } #include "Object.h" #include <glad/glad.h> // 必须第一行 #include <GLFW/glfw3.h> // 第二行 #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include "TexturePool.h" Object::Object(std::string vs, std::string fs, std::string texName) { createShader(vs.c_str(), fs.c_str()); if (!texName.empty()) { texture = TexturePool::getInstance()->getTexture(texName); if (shader) { shader->use(); shader->setInt("tex", 0); } } } Object::~Object() { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); delete shader; } void Object::createShader(const char* vs, const char* fs) { if (shader) delete shader; shader = new Shader(vs, fs); } void Object::setTexture(std::string texName) { texture = TexturePool::getInstance()->getTexture(texName); } void Object::createBuffer(bool createEBO, GLenum usage) { glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); if (createEBO) glGenBuffers(1, &EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, verticesSize, vertices, usage); if (createEBO && indices) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, usage); } glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)offsetof(TextureColorVertex, color)); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)offsetof(TextureColorVertex, texture)); glEnableVertexAttribArray(2); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, stride, (void*)offsetof(TextureColorVertex, normal)); glEnableVertexAttribArray(3); glBindVertexArray(0); } void Object::render(glm::mat4& view, glm::mat4& projection) { if (!shader || !texture) return; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(VAO); shader->use(); shader->setMat4("model", glm::value_ptr(model)); shader->setMat4("view", glm::value_ptr(view)); shader->setMat4("projection", glm::value_ptr(projection)); renderObject(); } void Object::updateDataBuffer() { glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferSubData(GL_ARRAY_BUFFER, 0, verticesSize, vertices); glBindBuffer(GL_ARRAY_BUFFER, 0); } #include "Planet.h" // 构造函数保持不变 Planet::Planet(std::string texName, glm::vec3 orbitPos, float revSpeed, float rotSpeed) : Sphere("shaders/planet.vs", "shaders/planet.fs", texName) { translation = orbitPos; revolutionSpeed = revSpeed; rotationSpeed = rotSpeed; } void Planet::update(float dt) { revolutionAngle += revolutionSpeed * dt; rotationAngle += rotationSpeed * dt; model = glm::mat4(1.0f); // Step 1: 绕 Y 轴旋转(实现“绕太阳公转”的角度变化) model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0, 1, 0)); // Step 2: 向外平移(例如 z = -80),表示轨道半径 float orbitRadius = translation.z; // 构造时传入的距离 model = glm::translate(model, glm::vec3(0, 0, -orbitRadius)); // 注意是负值! // Step 3: 绕自身轴自转 model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0, 1, 0)); // Step 4: 缩放 model = glm::scale(model, glm::vec3(1.0f)); } #include "Shader.h" #include <fstream> #include <sstream> #include <iostream> Shader::Shader(const char* vertexPath, const char* fragmentPath) { std::string vCode, fCode; std::ifstream vFile, fFile; vFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { vFile.open(vertexPath); fFile.open(fragmentPath); std::stringstream vStream, fStream; vStream << vFile.rdbuf(); fStream << fFile.rdbuf(); vFile.close(); fFile.close(); vCode = vStream.str(); fCode = fStream.str(); } catch (...) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl; } const char* vShaderCode = vCode.c_str(); const char* fShaderCode = fCode.c_str(); unsigned int vShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vShader, 1, &vShaderCode, NULL); glCompileShader(vShader); checkCompileErrors(vShader, "VERTEX"); unsigned int fShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fShader, 1, &fShaderCode, NULL); glCompileShader(fShader); checkCompileErrors(fShader, "FRAGMENT"); ID = glCreateProgram(); glAttachShader(ID, vShader); glAttachShader(ID, fShader); glLinkProgram(ID); checkCompileErrors(ID, "PROGRAM"); glDeleteShader(vShader); glDeleteShader(fShader); } void Shader::use() { glUseProgram(ID); } void Shader::setInt(const std::string& name, int value) { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } void Shader::setMat4(const std::string& name, const float* mat) { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, mat); } void Shader::setVec3(const std::string& name, float x, float y, float z) { glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); } void Shader::checkCompileErrors(unsigned int shader, std::string type) { int success; char infoLog[1024]; if (type != "PROGRAM") { glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << std::endl; } } else { glGetProgramiv(shader, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::PROGRAM_LINKING_ERROR\n" << infoLog << std::endl; } } } #include "Sphere.h" #include <cmath> #include <glad/glad.h> // 必须第一行 #include <GLFW/glfw3.h> // 第二行 #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> Sphere::Sphere(std::string vs, std::string fs, std::string texName) : Object(vs, fs, texName) { } Sphere::~Sphere() = default; void Sphere::initData(DataParam* param) { GLuint longSeg = param->longSegments; GLuint latSeg = param->latSegments; GLfloat r = param->radius; verticesSize = (longSeg + 1) * (latSeg + 1) * sizeof(TextureColorVertex); vertices = new TextureColorVertex[(longSeg + 1) * (latSeg + 1)]; float dPhi = glm::pi<float>() / latSeg; float dTheta = 2.0f * glm::pi<float>() / longSeg; TextureColorVertex* p = vertices; for (GLuint i = 0; i <= latSeg; ++i) { float phi = i * dPhi - glm::pi<float>() / 2.0f; for (GLuint j = 0; j <= longSeg; ++j) { float theta = j * dTheta; p->coordinate.x = r * cosf(phi) * cosf(theta); p->coordinate.y = r * sinf(phi); p->coordinate.z = r * cosf(phi) * sinf(theta); p->color = glm::vec3(1.0f); p->texture = glm::vec2((float)j / longSeg, (float)i / latSeg); p->normal = glm::normalize(p->coordinate); ++p; } } indexCount = (longSeg + 1) * 2 * (latSeg + 1); indices = new GLushort[indexCount]; GLushort* idx = indices; for (GLuint i = 0; i < latSeg; ++i) { for (GLuint j = 0; j <= longSeg; ++j) { idx[0] = i * (longSeg + 1) + j; idx[1] = (i + 1) * (longSeg + 1) + j; idx += 2; } } indexSize = indexCount * sizeof(GLushort); createBuffer(true, GL_STATIC_DRAW); delete[] vertices; vertices = nullptr; delete[] indices; indices = nullptr; rotationSpeed = 0.5f; revolutionSpeed = 0.01f; } void Sphere::renderObject() { glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_SHORT, 0); } void Sphere::update(float dt) { revolutionAngle += revolutionSpeed * dt; rotationAngle += rotationSpeed * dt; model = glm::mat4(1.0f); model = glm::translate(model, translation); model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0, 1, 0)); model = glm::translate(model, glm::vec3(0, 0, 5)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0, 1, 0)); model = glm::scale(model, glm::vec3(1.0f)); } #include "Sun.h" Sun::Sun() : Sphere("shaders/sun.vs", "shaders/sun.fs", "sun") { rotationSpeed = 0.2f; } void Sun::update(float dt) { rotationAngle += rotationSpeed * dt; model = glm::mat4(1.0f); // 单位矩阵 到 原点 model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0, 1, 0)); // 绕 Y 轴自转 model = glm::scale(model, glm::vec3(2.0f)); // 可以稍大一点,比如 2倍 } void Sun::renderObject() { glDepthMask(GL_FALSE); // 不写入深度缓冲,避免挡住后面行星 glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_SHORT, 0); glDepthMask(GL_TRUE); } #include "TexturePool.h" #include <SOIL2/SOIL2.h> #include <iostream> TexturePool::TexturePool() {} TexturePool::~TexturePool() { for (auto it = textures.begin(); it != textures.end(); ++it) glDeleteTextures(1, &it->second); } void TexturePool::addTexture(string name, string path) { GLuint texID = SOIL_load_OGL_texture(path.c_str(), SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y); if (texID == 0) { cout << "Failed to load texture: " << path << endl; return; } textures[name] = texID; glBindTexture(GL_TEXTURE_2D, texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } TexturePool* TexturePool::getInstance() { static TexturePool instance; return &instance; } GLuint TexturePool::getTexture(string name) { auto it = textures.find(name); return it != textures.end() ? it->second : 0; } 你看完我就说我的问题
最新发布
11-30
根据指导书用opengl写一整个项目,但是我不要飞船模型,不用绑定飞船模型,直接通过摄像机游览就行,然后我有一个texture文件装着贴图照片里面有background,earth,jupiter,mars,mercury,moon,neptune,saturn,sun,uranus,venus,全部都是.jpg,然后以太阳作为点光源,照射别的星球的表面就行了,然后不要全部写在一起,要有各部分的模块化,各自的.h.cpp,然后参考以下代码,不是一定要完全一样,可小幅度调整,Object类、Sphere类、TexturePool类,重要的是参考格式,#pragma once #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <string> #include "Shader.h" typedef struct { glm::vec3 coordinate; glm::vec3 color; glm::vec2 texture; glm::vec3 normal; // 法向量 - 新增 } TextureColorVertex; typedef struct { GLuint latSegments; GLuint longSegments; GLfloat radius; GLfloat height; }DataParam; class Object { public: Object(std::string vs, std::string fs, std::string texName = ""); Shader* shader; glm::mat4 model; virtual ~Object(); protected: TextureColorVertex* vertices; GLushort * indices; GLuint indexCount; GLint verticesSize; GLuint indexSize; GLuint texture; GLuint VBO, VAO, EBO; protected: float rotationSpeed; float revolutionSpeed; float rotationAngle; float revolutionAngle; glm::vec3 translation; GLsizei stride; void createBuffer(GLsizei stride,bool createEBO = false, GLenum ussage = GL_STATIC_DRAW); public: void createShader(const char* vs, const char* fs); virtual void initData(DataParam *param = nullptr) = 0; void setTexture(std::string texName); void render(glm::mat4& view, glm::mat4& projection); virtual void update(float dt) {} virtual void renderObject() = 0; virtual void updateDataBuffer(); }; #include <glad/glad.h> #include "TexturePool.h" #include "Object.h" Object::Object(std::string vs, std::string fs, std::string texName) { createShader(vs.c_str(), fs.c_str()); if (texName != "") { texture = TexturePool::getInstance()->getTexture(texName); // activate shader shader->use(); shader->setInt("tex", 0); shader->setVec4("testColor", glm::vec4(255, 0, 0, 255)); } vertices = nullptr; indices = nullptr; stride = 0; } Object::~Object() { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); if (shader) { delete shader; } /*if (vertices) { delete[]vertices; }*/ } void Object::createShader(const char* vs, const char* fs) { if (shader) { delete shader; } shader = new Shader(vs, fs); } void Object::setTexture(std::string texName) { texture = TexturePool::getInstance()->getTexture(texName); } void Object::createBuffer(GLsizei stride, bool createEBO , GLenum ussage) { glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); if (createEBO) { glGenBuffers(1, &EBO); } glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, verticesSize, vertices, ussage); if (createEBO) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, ussage); } // 位置属性 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(0); // 颜色属性 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)offsetof(TextureColorVertex, color)); glEnableVertexAttribArray(1); // 纹理坐标属性 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)offsetof(TextureColorVertex, texture)); glEnableVertexAttribArray(2); // 法向量属性 - 新增 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, stride, (void*)offsetof(TextureColorVertex, normal)); glEnableVertexAttribArray(3); if (createEBO && indices) { glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, ussage); } glBindVertexArray(0); this -> stride = stride; updateDataBuffer(); } void Object::render(glm::mat4& view, glm::mat4& projection) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(VAO); shader->use(); shader->setMat4("model", model); shader->setMat4("view", view); shader->setMat4("projection", projection); renderObject(); } void Object::updateDataBuffer() { //position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(1 * sizeof(glm::vec3))); glEnableVertexAttribArray(1); // texture coord attribute glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(2 * sizeof(glm::vec3))); glEnableVertexAttribArray(2); }#pragma once #include "Object.h" class Sphere : public Object { public: Sphere(std::string vs, std::string fs, std::string texName = ""); ~Sphere(); void initData(DataParam *param = nullptr); void renderObject(); void update(float dt); }; #include "Sphere.h" Sphere::Sphere(std::string vs, std::string fs, std::string texName) :Object(vs,fs,texName ) { } Sphere::~Sphere() { } void Sphere::initData(DataParam *param) { GLfloat radius = param->radius; GLuint longSegments = param->longSegments; GLuint latSegments = param->latSegments; float fPhi = glm::pi<float>() / latSegments; //纬度上角度差:Phi float fTheta = (glm::pi<float>() * 2.0f) / longSegments; //经度上角度差:Theta //生成顶点数据,请补充代码 verticesSize = ((longSegments + 1) * (latSegments + 1)) * sizeof(TextureColorVertex); vertices = new TextureColorVertex[(longSegments + 1) * (latSegments + 1)]; //创建顶点数组 TextureColorVertex * p = vertices; for (GLuint i = 0; i < latSegments + 1; i++) { float latitude = i * fPhi - glm::pi<float>() / 2.0f;; //fPhi = π / latSegments → 每一“段”的纬度跨度。i * fPhi:当前在总半圆中的位置(从 0 到 π)。减去 π/2 是为了让角度中心对齐赤道!所以最终 latitude ∈ [-π/2, +π/2] for (GLuint j = 0; j < longSegments + 1; j++) { float longitude = j * fTheta; //经度longitude ∈ [0, 2π) p->coordinate.x = radius * cosf(latitude) * cosf(longitude); p->coordinate.y = radius * sinf(latitude); p->coordinate.z = radius * cosf(latitude) * sinf(longitude); p->color.r =1.0f; p->color.g =1.0f; p->color.b =1.0f; p->texture.s = longitude / (glm::pi<float>() * 2.0f); p->texture.t = (latitude + glm::pi<float>() / 2.0f) / glm::pi<float>();//(s,t) ∈ [0,1]×[0,1] p++; } } //生成索引数据 indexCount = (1 + longSegments) * 2 * (1 + latSegments); //计算索引数量 indices = new GLushort[indexCount]; indexSize = indexCount * sizeof(GLushort); GLushort * pIdx = indices; for (GLuint i = 0; i < latSegments + 1; i++) { for (GLuint j = 0; j < longSegments + 1; j++) { *pIdx = i * (longSegments + 1) + j; pIdx++; *pIdx = (i + 1) * (longSegments + 1) + j; pIdx++; } } createBuffer(sizeof(TextureColorVertex),true); delete[]vertices; delete[]indices; revolutionAngle = 0.0f; //公转角度 rotationAngle = 0.0f; //自转角度 revolutionSpeed = 0.01f; //公转速度 rotationSpeed = 0.5f; //自转速度 p->normal = glm::normalize(p->coordinate); // 球面法向量就是顶点坐标归一化 } void Sphere::renderObject() { glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_SHORT, 0); } void Sphere::update(float dt) { revolutionAngle += revolutionSpeed; rotationAngle += rotationSpeed; model = glm::mat4(1.0f); model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::translate(model, glm::vec3(5.0f,0.0f,0.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); } #pragma once #include <glad/glad.h> #include <GLFW/glfw3.h> #include <map> #include <string> using namespace std; typedef map<string, GLuint> Textures; class TexturePool { public: virtual ~TexturePool(); private: TexturePool(); Textures textures; public: void addTexture(string name, string path); static TexturePool *getInstance(); GLuint getTexture(string name); }; #include "TexturePool.h" #include <SOIL2/SOIL2.h> #include <iostream> TexturePool::TexturePool() { } TexturePool::~TexturePool() { for (Textures::iterator ite = textures.begin(); ite != textures.end(); ++ite) { glDeleteTextures(1, &ite->second); } } void TexturePool::addTexture(string name, string path) { GLuint texID; if (name.empty()) { return; } texID = SOIL_load_OGL_texture(path.c_str(), 0, 0, SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y); if (texID != 0) { textures[name] = texID; } else { std::cout << "Failed to load texture" << path <<" " <<std::endl; } glBindTexture(GL_TEXTURE_2D, texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } TexturePool* TexturePool::getInstance() { static TexturePool instance; return &instance; } GLuint TexturePool::getTexture(string name) { if (textures.find(name) != textures.end()) { return textures[name]; } return 0; } 除了我提到的点,剩下按指导书完成
11-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值