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()