Skip to content
This repository was archived by the owner on Dec 24, 2023. It is now read-only.

Commit 93af8b2

Browse files
committed
HLViewer: Add sprite 3D view
1 parent 97d01ac commit 93af8b2

File tree

14 files changed

+236
-22
lines changed

14 files changed

+236
-22
lines changed
12.4 KB
Binary file not shown.
8.77 KB
Binary file not shown.

_workdir/hlviewer/mapsrc/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/build
2+
*.map
3+
*.jmx
4+
*.max
5+
*.temp
Binary file not shown.

src/hlviewer/src/sprite_viewer.cpp

Lines changed: 131 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#include <bsp/sprite.h>
2+
#include <bsp/entity_key_values.h>
23
#include <imgui_impl_shaders.h>
34
#include <hlviewer/assets/asset_manager.h>
5+
#include <hlviewer/assets/asset_loader.h>
6+
#include <hlviewer/scene_view.h>
47
#include "sprite_viewer.h"
58

69
namespace {
@@ -21,6 +24,8 @@ const char *s_SyncTypes[] = {
2124
"ST_RAND",
2225
};
2326

27+
const char *s_AvailSkies[] = {"desert", "2desert", "dusk", "night", "alien1", "xen8"};
28+
2429
template <typename E, int N>
2530
void showEnumValue(const char *name, E value, const char *(&values)[N]) {
2631
int v = (int)value;
@@ -57,6 +62,112 @@ SpriteBlitShader s_2DShader;
5762

5863
}
5964

65+
class SpriteViewer::View3D {
66+
public:
67+
View3D(SpriteViewer &viewer)
68+
: m_Viewer(viewer) {
69+
try {
70+
AssetLoader loader;
71+
m_Level = loader.loadLevel("assets:maps/dev/sprite_preview.bsp");
72+
loader.processQueue(true);
73+
74+
m_pView = std::make_unique<View>(*this, m_Level);
75+
updateSky(0);
76+
} catch (const std::exception &e) {
77+
m_bLoadError = true;
78+
m_LoadErrorText = e.what();
79+
}
80+
}
81+
82+
void show() {
83+
if (m_bLoadError) {
84+
ImGui::TextUnformatted("3D view failed to load:");
85+
ImGui::TextUnformatted(m_LoadErrorText.c_str());
86+
} else {
87+
if (ImGui::Combo("Skybox", &m_iCurSky, s_AvailSkies, (int)std::size(s_AvailSkies))) {
88+
updateSky(m_iCurSky);
89+
}
90+
91+
m_pView->showImage();
92+
}
93+
}
94+
95+
void preRender() {
96+
if (m_pView) {
97+
m_pView->setFov(90);
98+
m_pView->renderBackBuffer();
99+
}
100+
}
101+
102+
private:
103+
class View : public SceneView {
104+
public:
105+
View3D &m_View;
106+
ClientEntity m_Sprite;
107+
108+
View(View3D &view, LevelAsset &level)
109+
: SceneView(level)
110+
, m_View(view) {
111+
// Set initial camera position
112+
bsp::EntityKeyValuesDict ents(level.getLevel().getEntitiesLump());
113+
int ent = ents.findEntityByName("camera_pos");
114+
115+
if (ent != -1) {
116+
setCameraPos(ents[ent].get("origin").asFloat3());
117+
setCameraRot(ents[ent].get("angles").asFloat3());
118+
} else {
119+
printw("Sprite preview map is missing camera_pos entity");
120+
}
121+
}
122+
123+
void addVisibleEnts() override {
124+
switch (m_View.m_Viewer.m_pSprite->getModel().spriteInfo.texFormat) {
125+
case bsp::SPR_NORMAL: {
126+
m_Sprite.iRenderMode = kRenderNormal;
127+
break;
128+
}
129+
case bsp::SPR_ADDITIVE: {
130+
m_Sprite.iRenderMode = kRenderTransAdd;
131+
break;
132+
}
133+
case bsp::SPR_INDEXALPHA:
134+
case bsp::SPR_ALPHATEST: {
135+
m_Sprite.iRenderMode = kRenderTransTexture;
136+
break;
137+
}
138+
}
139+
140+
m_Sprite.vOrigin = {0, 0, 0};
141+
m_Sprite.vAngles = {0, 0, 0};
142+
m_Sprite.iRenderFx = kRenderFxNone;
143+
m_Sprite.iFxAmount = 255;
144+
m_Sprite.vFxColor = glm::ivec3(m_View.m_Viewer.m_FgColor * 255.0f);
145+
m_Sprite.pModel = &m_View.m_Viewer.m_pSprite->getModel();
146+
m_Sprite.flFrame = m_View.m_Viewer.m_flCurrentFrame;
147+
m_Sprite.flScale = 1.0f;
148+
149+
if (m_Sprite.vFxColor == glm::ivec3(0, 0, 0)) {
150+
m_Sprite.vFxColor = glm::ivec3(255, 255, 255);
151+
}
152+
153+
addEntity(&m_Sprite);
154+
}
155+
};
156+
157+
SpriteViewer &m_Viewer;
158+
bool m_bLoadError = false;
159+
std::string m_LoadErrorText;
160+
161+
LevelAsset m_Level;
162+
std::unique_ptr<View> m_pView;
163+
int m_iCurSky = 0;
164+
165+
void updateSky(int idx) {
166+
m_iCurSky = idx;
167+
m_pView->setSkyTexture(s_AvailSkies[idx]);
168+
}
169+
};
170+
60171
SpriteViewer::SpriteViewer(std::string_view path) {
61172
// Remove tag from path and set title
62173
size_t tagEnd = path.find(':');
@@ -87,6 +198,14 @@ SpriteViewer::SpriteViewer(std::string_view path) {
87198
}
88199
}
89200

201+
void SpriteViewer::preRender() {
202+
DialogBase::preRender();
203+
204+
if (m_p3DView) {
205+
m_p3DView->preRender();
206+
}
207+
}
208+
90209
void SpriteViewer::showContents() {
91210
const bsp::SpriteInfo &info = m_pSprite->getModel().spriteInfo;
92211

@@ -115,6 +234,9 @@ void SpriteViewer::showContents() {
115234
ImGui::Text("%d/%d", frame + 1, info.numFrames);
116235
}
117236

237+
ImGui::ColorEdit3("BG", &m_BgColor.r);
238+
ImGui::ColorEdit3("FG", &m_FgColor.r);
239+
118240
if (ImGui::BeginTabBar("TabBar")) {
119241
if (ImGui::BeginTabItem("2D view")) {
120242
show2D();
@@ -159,15 +281,18 @@ void SpriteViewer::show2D() {
159281
ImGui::SameLine();
160282
ImGui::Checkbox("Filter", &m_b2DFilter);
161283

162-
ImGui::ColorEdit3("BG", &m_2DBgColor.r);
163-
ImGui::ColorEdit3("FG", &m_2DFgColor.r);
164-
165284
glm::vec2 size(info.width, info.height);
166285
size *= m_fl2DScale;
167286
ImGui::Image(m_p2DMaterial.get(), ImVec2(size.x, size.y));
168287
}
169288

170-
void SpriteViewer::show3D() {}
289+
void SpriteViewer::show3D() {
290+
if (!m_p3DView) {
291+
m_p3DView = std::make_unique<View3D>(*this);
292+
}
293+
294+
m_p3DView->show();
295+
}
171296

172297
void SpriteViewer::showInfo() {
173298
const bsp::SpriteInfo &info = m_pSprite->getModel().spriteInfo;
@@ -188,7 +313,7 @@ void SpriteViewer::update2DContents() {
188313
// Set up the framebuffer
189314
glViewport(0, 0, info.width, info.height);
190315
m_2DFramebuffer.bind(GL_FRAMEBUFFER);
191-
glClearColor(m_2DBgColor.r, m_2DBgColor.g, m_2DBgColor.b, 1.0f);
316+
glClearColor(m_BgColor.r, m_BgColor.g, m_BgColor.b, 1.0f);
192317
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
193318

194319
// Blending
@@ -208,7 +333,7 @@ void SpriteViewer::update2DContents() {
208333
ShaderInstance *shaderInstance = s_2DShader.getShaderInstance(SHADER_TYPE_BLIT_IDX);
209334
shaderInstance->enable(0);
210335
shaderInstance->getShader<SpriteBlitShader>().m_Frame.set(std::floor(m_flCurrentFrame));
211-
shaderInstance->getShader<SpriteBlitShader>().m_Color.set(m_2DFgColor);
336+
shaderInstance->getShader<SpriteBlitShader>().m_Color.set(m_FgColor);
212337

213338
glActiveTexture(GL_TEXTURE0);
214339
m_pSprite->getModel().spriteMat->getTexture(0)->bind();

src/hlviewer/src/sprite_viewer.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,30 @@ class SpriteViewer : public DialogBase {
1111
public:
1212
SpriteViewer(std::string_view path);
1313

14+
void preRender() override;
15+
1416
protected:
1517
void showContents() override;
1618

1719
private:
20+
class View3D;
21+
1822
SpriteAssetRef m_pSprite;
1923
bool m_bPlayAnim = true;
2024
float m_flFramerate = 10.0f;
2125
float m_flCurrentFrame = 0.0f;
26+
glm::vec3 m_BgColor = glm::vec3(0, 0, 0);
27+
glm::vec3 m_FgColor = glm::vec3(1, 1, 1);
2228

2329
// 2D
2430
MaterialPtr m_p2DMaterial;
2531
Framebuffer m_2DFramebuffer;
26-
glm::vec3 m_2DBgColor = glm::vec3(0, 0, 0);
27-
glm::vec3 m_2DFgColor = glm::vec3(1, 1, 1);
2832
float m_fl2DScale = 1;
2933
bool m_b2DFilter = false;
3034

35+
// 3D
36+
std::unique_ptr<View3D> m_p3DView;
37+
3138
void showMenuBar();
3239
void show2D();
3340
void show3D();

src/hlviewer_shared/include/hlviewer/entities/base_entity.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ class BaseEntity : appfw::NoMove {
105105
inline const glm::vec4 &getAABBTintColor() { return m_AABBTintColor; }
106106

107107
inline Model *getModel() { return m_pModel; }
108+
inline float getFrame() { return m_flFrame; }
109+
inline float getFramerate() { return m_flFramerate; }
110+
inline float getScale() { return m_flScale; }
108111

109112
inline RenderMode getRenderMode() { return m_nRenderMode; }
110113
inline RenderFx getRenderFx() { return m_nRenderFx; }
@@ -140,6 +143,9 @@ class BaseEntity : appfw::NoMove {
140143

141144
// Model
142145
Model *m_pModel = nullptr;
146+
float m_flFrame = 0;
147+
float m_flFramerate = 0;
148+
float m_flScale = 1;
143149

144150
// Rendering effects
145151
RenderMode m_nRenderMode = kRenderNormal;

src/hlviewer_shared/include/hlviewer/scene_view.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ class SceneView : public IRendererEngine, public ILevelViewRenderer, appfw::NoMo
6969
//! Adds entities to the scene renderer.
7070
virtual void addVisibleEnts();
7171

72+
//! Adds an entity to the scene renderer.
73+
//! Must only be called from addVisibleEnts.
74+
void addEntity(ClientEntity *pClent);
75+
7276
//! Adds an entity box.
7377
//! @param origin Box center
7478
//! @param size Box size

src/hlviewer_shared/include/hlviewer/world_state_base.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <bsp/level.h>
77
#include <renderer/const.h>
88
#include <hlviewer/assets/level_asset.h>
9+
#include <hlviewer/assets/sprite_asset.h>
910
#include <hlviewer/entities/base_entity.h>
1011
#include <hlviewer/brush_model.h>
1112
#include <hlviewer/vis.h>
@@ -27,6 +28,10 @@ class WorldStateBase : appfw::NoMove {
2728
//! @returns the sky name
2829
std::string getSkyName();
2930

31+
//! Loads a model with specified name.
32+
//! @returns model or nullpltr
33+
Model *loadModel(std::string_view modelName);
34+
3035
//! Returns the brush model or nullptr if doesn't exist.
3136
BrushModel *getBrushModel(size_t idx);
3237

@@ -88,6 +93,9 @@ class WorldStateBase : appfw::NoMove {
8893
// Lighting
8994
LightStyle m_LightStyles[MAX_LIGHTSTYLES];
9095

96+
// Asset refs
97+
std::map<std::string, SpriteAssetRef> m_Sprites;
98+
9199
// Level loading
92100
void loadBrushModels();
93101
void loadEntities();

src/hlviewer_shared/src/assets/asset_manager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ SpriteAssetRef AssetManager::loadSprite(std::string_view path) {
103103
return ref;
104104
}
105105

106+
printi("AssetManager: Loading sprite {}", path);
106107
SpriteAsset asset;
107108
asset.loadFromFile(*this, path);
108109

0 commit comments

Comments
 (0)