From 0455dc6a8acd41b4b825ea4f5857aaddd9c7d5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E8=B1=AA?= <11985835+Meill2486@user.noreply.gitee.com> Date: Tue, 13 Jan 2026 17:34:08 +0800 Subject: [PATCH] =?UTF-8?q?```=20chore(git):=20=E6=9B=B4=E6=96=B0.gitignor?= =?UTF-8?q?e=E6=96=87=E4=BB=B6=E4=BB=A5=E5=8C=85=E5=90=AB=E6=9B=B4?= =?UTF-8?q?=E5=A4=9APython=E5=92=8C=E9=A1=B9=E7=9B=AE=E7=89=B9=E5=AE=9A?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加Python相关忽略规则(__pycache__、.pyc等) - 添加虚拟环境相关忽略(venv、env等) - 添加IDE相关忽略(.vscode、.idea等) - 添加C++/CMake相关忽略(CMakeFiles、Makefile等) - 添加Panda3D/RenderPipeline特定忽略(.bam、.egg等) - 添加样本和测试模型相关忽略 - 添加操作系统特定文件忽略 - 移除旧的忽略规则并重新组织结构 ``` --- .gitignore | 192 ++++++++++++++++++++---------------- samples/.gitignore | 8 ++ samples/README.md | 14 +++ samples/download_samples.py | 44 +++++++++ samples/orbit_alt_drag.py | 158 +++++++++++++++++++++++++++++ 5 files changed, 333 insertions(+), 83 deletions(-) create mode 100644 samples/.gitignore create mode 100644 samples/README.md create mode 100644 samples/download_samples.py create mode 100644 samples/orbit_alt_drag.py diff --git a/.gitignore b/.gitignore index 5c6c6ce..b41b382 100644 --- a/.gitignore +++ b/.gitignore @@ -1,89 +1,115 @@ -# --- Ignored extensions --- -# *.pyd -*.pyc -*.ignore -*.old +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +*.pyd +.Python +*.egg-info/ +dist/ +build/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ *.egg -*.psd -*.blend1 -*.blend2 -*.pdb -*.stackdump -*.exr -*.trace -*.autogen* -*.mip -mitsuba.*.log -*.exr -# *.txo.pz +MANIFEST + +# Virtual Environment +venv/ +env/ +ENV/ +.venv/ +*.venv + +# IDEs +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store +*.sublime-* +*.sublime-workspace +.spyderproject +.spyproject + +# Project specific +data/install.flag +rpcore/native/use_cxx.flag +imgui.ini *.log + +# C++ / CMake +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +Makefile +*.cmake +!CMakeLists.txt +compile_commands.json +.clang_complete +compile_flags.txt + +# Panda3D / RenderPipeline specific +# *.txo +*.bam +*.egg.pz +# *.txo.gz +*.egg +*.glb.cache + +# Generated shader files +rpplugins/env_probes/shader/mips/ + +# Skin assets (PSD files) +*.psd + +# Samples (optional - large files) +samples/00-Loading the pipeline/* +samples/01-Material-Demo/* +samples/02-Roaming-Ralph/* +samples/03-Lights/* +samples/04-Material-Blending/* +samples/05-Quboid/* +samples/06-Car/* +samples/07-Shading-Models/* +samples/08-Terrain/* +samples/09-Benchmark/* +samples/10-Plugin-Showcase-AO/* +samples/11-Instancing/* +!samples/.gitignore +!samples/download_samples.py +!samples/README.md + +# Test models +test_models/*.glb +!test_models/.gitignore + +# Temporary files *.tmp *.bak -.DS_Store +*.backup +*.old +*~ + +# OS specific Thumbs.db +ehthumbs.db +Desktop.ini +$RECYCLE.BIN/ +*.cab +*.msi +*.msix +*.msm +*.msp +*.lnk - -# --- Ignored folders and patterns --- -temp/ -models/ -data/film_grain/*.png -data/default_cubemap/filtered/ -_DEV -toolkit/pathtracing_reference/mitsuba/ -toolkit/pathtracing_reference/scene*.png -toolkit/pathtracing_reference/Scene*.blend -toolkit/pathtracing_reference/envmap.png -rpplugins/clouds/resources/slices/* - -toolkit/rp_distributor/built/ -__pycache__/ -.pytest_cache/ -.mypy_cache/ -.cache/ -build/ -dist/ -*.egg-info/ -htmlcov/ - -# Common IDE / venvs -.idea/ -.vscode -.venv -.env -.python-version - -# Big Models -assets/big_models/ - -# Samples folder -samples/ -test_models/ - -# Generated pipeline assets -# data/**/*.txo -toolkit/**/__pycache__/ - -# --- Ignored files --- -TODO.txt -*.flag -desktop.ini -scattering_lut.png -old/ -data/gui/loading_screen -data/environment_brdf/scene.png -data/environment_brdf/res/scene.png -toolkit/pathtracing_reference/batch_compare/ -toolkit/pathtracing_reference/difference.png -toolkit/pathtracing_reference/res/Scene.blend -toolkit/pathtracing_reference/res/scene.png -toolkit/pathtracing_reference/scene*.png -toolkit/pathtracing_reference/res/tex/envmap.png -_tmp_material.py - -*/poisson_disk_generator/source/config_module* - -_bake_params* -raw-bake.png -toolkit/bake_gi/resources/*.bam -toolkit/bake_gi/resources/*.blend -toolkit/bake_gi/scene +# Package managers +pip-log.txt +pip-delete-this-directory.txt +requirements-dev.txt \ No newline at end of file diff --git a/samples/.gitignore b/samples/.gitignore new file mode 100644 index 0000000..ba1fdf8 --- /dev/null +++ b/samples/.gitignore @@ -0,0 +1,8 @@ +*.pyc +*.pyd + +*.blend1 +03-Forest +06-Map +*.blend1 +*.blend2 diff --git a/samples/README.md b/samples/README.md new file mode 100644 index 0000000..968adcd --- /dev/null +++ b/samples/README.md @@ -0,0 +1,14 @@ +## Render Pipeline Samples + +The samples are not included in this repository to keep the size small. + +#### Automatic Download (recommended) +You can run `python download_samples.py` to automatically download the samples. + +#### Manual Download +If you want to manually download the samples (for whatever reason), you can +find them here: +https://github.com/tobspr/RenderPipeline-Samples + +After downloading, place the downloaded contents in this folder to run the samples. diff --git a/samples/download_samples.py b/samples/download_samples.py new file mode 100644 index 0000000..d747311 --- /dev/null +++ b/samples/download_samples.py @@ -0,0 +1,44 @@ +""" + +RenderPipeline + +Copyright (c) 2014-2016 tobspr + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +# Script to download the Render Pipeline samples + +import os +import sys + +sys.path.insert(0, "../") +sys.path.insert(0, "../rpcore/util") + +from submodule_downloader import download_submodule # noqa + +if __name__ == "__main__": + + # Make sure we are in the right directory + main_dir = os.path.dirname(os.path.realpath(__file__)) + os.chdir(main_dir) + + # Now extract the samples + download_submodule("tobspr", "RenderPipeline-Samples", ".", ["README.md", "LICENSE"]) diff --git a/samples/orbit_alt_drag.py b/samples/orbit_alt_drag.py new file mode 100644 index 0000000..b2dc627 --- /dev/null +++ b/samples/orbit_alt_drag.py @@ -0,0 +1,158 @@ +import math + +from direct.showbase.ShowBase import ShowBase +from panda3d.core import KeyboardButton, MouseButton, Point2, Vec3, loadPrcFileData + + +# Basic window settings for clarity. +loadPrcFileData("", "window-title Alt+LMB Orbit Demo") +loadPrcFileData("", "show-frame-rate-meter #t") + + +class OrbitDemo(ShowBase): + def __init__(self): + super().__init__() + self.disableMouse() # We manage the camera manually. + + self.focus_distance = 8.0 + self.orbit_active = False + self.pan_active = False + self.radius = self.focus_distance + self.azimuth = 0.0 + self.elevation = 0.0 + self.last_mouse = None + self.last_mouse_pan = None + self.pivot = Vec3(0, 0, 0) + + self._setup_scene() + self._refresh_camera_from_angles() + + self.accept("mouse1", self._on_mouse1_down) + self.accept("alt-mouse1", self._on_mouse1_down) + self.accept("mouse1-up", self._on_mouse1_up) + self.accept("mouse2", self._on_mouse2_down) + self.accept("mouse2-up", self._on_mouse2_up) + self.accept("wheel_up", lambda: self._on_wheel(1)) + self.accept("wheel_down", lambda: self._on_wheel(-1)) + + bt = self.buttonThrowers[0].node() + bt.setButtonDownEvent("btn-down") + bt.setButtonUpEvent("btn-up") + bt.setKeystrokeEvent("keystroke") + self.accept("btn-down", lambda name: print("btn-down:", name)) + self.accept("btn-up", lambda name: print("btn-up:", name)) + self.accept("keystroke", lambda key: print("key:", key)) + self.taskMgr.add(self._update_orbit, "update_orbit") + + def _setup_scene(self): + env = self.loader.loadModel("models/environment") + env.reparentTo(self.render) + env.setScale(0.1) + env.setPos(-8, 42, 0) + + # Small marker that shows the current orbit center. + self.focus_marker = self.loader.loadModel("models/smiley") + self.focus_marker.reparentTo(self.render) + self.focus_marker.setScale(0.15) + self.focus_marker.setColor(1, 0.9, 0.2, 1) + self.focus_marker.hide() # Shown only while orbiting. + + def _point_in_front(self): + forward = self.camera.getQuat(self.render).getForward() + return self.camera.getPos(self.render) + forward.normalized() * self.focus_distance + + def _sync_angles_from_camera(self): + offset = self.camera.getPos(self.render) - self.pivot + self.radius = offset.length() + if self.radius < 1e-5: + self.radius = self.focus_distance + offset = Vec3(0, -self.radius, 0) + self.azimuth = math.atan2(offset.x, offset.y) + self.elevation = math.asin(max(-1.0, min(1.0, offset.z / self.radius))) + + def _refresh_camera_from_angles(self): + # print("Orbiting around:", self.pivot) + cos_el = math.cos(self.elevation) + x = math.sin(self.azimuth) * cos_el + y = math.cos(self.azimuth) * cos_el + z = math.sin(self.elevation) + + self.camera.setPos(self.pivot + Vec3(x, y, z) * self.radius) + self.camera.lookAt(self.pivot) + + def _on_mouse1_down(self): + self.orbit_active = True + print(self.orbit_active) + self.pivot = self._point_in_front() + self.focus_marker.setPos(self.pivot) + self.focus_marker.show() + self._sync_angles_from_camera() + self.last_mouse = Point2(self.mouseWatcherNode.getMouse()) + + def _on_mouse1_up(self): + self.orbit_active = False + self.last_mouse = None + self.focus_marker.hide() + print(self.orbit_active) + + def _on_mouse2_down(self): + if not self.mouseWatcherNode.hasMouse(): + return + self.pan_active = True + self.last_mouse_pan = Point2(self.mouseWatcherNode.getMouse()) + + def _on_mouse2_up(self): + self.pan_active = False + self.last_mouse_pan = None + + def _on_wheel(self, direction): + # direction: +1 for wheel_up (zoom in), -1 for wheel_down (zoom out) + zoom_factor = 0.9 if direction > 0 else 1.1 + self.radius = max(0.5, min(200.0, self.radius * zoom_factor)) + self._refresh_camera_from_angles() + + def _update_orbit(self, task): + # Middle mouse pan (translates camera and pivot together). + if self.pan_active and self.mouseWatcherNode.hasMouse(): + current = Point2(self.mouseWatcherNode.getMouse()) + if self.last_mouse_pan is not None: + delta = current - self.last_mouse_pan + right = self.camera.getQuat(self.render).getRight() + up = self.camera.getQuat(self.render).getUp() + pan_scale = self.radius * 0.8 + offset = (right * delta.x + up * delta.y) * pan_scale + self.camera.setPos(self.camera.getPos(self.render) + offset) + self.pivot += offset + self._sync_angles_from_camera() + self.last_mouse_pan = current + elif self.pan_active and not self.mouseWatcherNode.isButtonDown(MouseButton.two()): + self._on_mouse2_up() + + if not self.orbit_active: + return task.cont + + if not self.mouseWatcherNode.isButtonDown(MouseButton.one()) or not self.mouseWatcherNode.isButtonDown(KeyboardButton.alt()): + # print("Press Alt+LMB to activate orbit mode.") + return task.cont + + if not self.mouseWatcherNode.hasMouse() or self.last_mouse is None: + print("Mouse not available.") + return task.cont + + current = Point2(self.mouseWatcherNode.getMouse()) + delta = current - self.last_mouse + self.last_mouse = current + + # Screen space is [-1, 1], so multiply by a comfortable radians-per-unit factor. + rot_speed = math.pi # 180° per full screen swipe. + self.azimuth += delta.x * rot_speed + self.elevation -= delta.y * rot_speed + self.elevation = max(math.radians(-85.0), min(math.radians(85.0), self.elevation)) + + self._refresh_camera_from_angles() + return task.cont + + +if __name__ == "__main__": + app = OrbitDemo() + app.run()