diff --git a/SA2LevelEditor/SA2LevelEditor.vcxproj b/SA2LevelEditor/SA2LevelEditor.vcxproj
index 6eec386..480d07e 100644
--- a/SA2LevelEditor/SA2LevelEditor.vcxproj
+++ b/SA2LevelEditor/SA2LevelEditor.vcxproj
@@ -152,6 +152,7 @@
+
@@ -268,6 +269,7 @@
+
diff --git a/SA2LevelEditor/SA2LevelEditor.vcxproj.filters b/SA2LevelEditor/SA2LevelEditor.vcxproj.filters
index dccf2f9..41e1855 100644
--- a/SA2LevelEditor/SA2LevelEditor.vcxproj.filters
+++ b/SA2LevelEditor/SA2LevelEditor.vcxproj.filters
@@ -410,6 +410,9 @@
Source Files\entities\LevelSpecific\WeaponsBed
+
+ Source Files
+
@@ -752,6 +755,7 @@
Source Files\entities\LevelSpecific\WeaponsBed
+
diff --git a/SA2LevelEditor/res/Shaders/entity/fragmentShader.txt b/SA2LevelEditor/res/Shaders/entity/fragmentShader.txt
index c69157f..c007f3e 100644
--- a/SA2LevelEditor/res/Shaders/entity/fragmentShader.txt
+++ b/SA2LevelEditor/res/Shaders/entity/fragmentShader.txt
@@ -2,6 +2,7 @@
in vec2 pass_textureCoords;
in vec3 color;
+in vec3 vBary;
out vec4 out_Color;
@@ -10,20 +11,29 @@ uniform sampler2D textureSampler2;
uniform int hasTransparency;
uniform vec3 baseColour;
uniform float mixFactor;
+uniform int hasTexture;
void main(void)
{
- vec4 rawTextureColour = mix(texture(textureSampler, pass_textureCoords), texture(textureSampler2, pass_textureCoords), mixFactor);
- rawTextureColour.rgb *= baseColour*color;
+ if (hasTexture != 0) {
+ vec4 rawTextureColour = mix(texture(textureSampler, pass_textureCoords), texture(textureSampler2, pass_textureCoords), mixFactor);
+ rawTextureColour.rgb *= baseColour*color;
- if (hasTransparency == 0)
- {
- if (rawTextureColour.a < 0.9)
+ if (hasTransparency == 0)
{
- discard;
+ if (rawTextureColour.a < 0.9)
+ {
+ discard;
+ }
+ rawTextureColour.a = 1;
}
- rawTextureColour.a = 1;
- }
- out_Color = rawTextureColour;
+ out_Color = rawTextureColour;
+ } else {
+ float edge = min(vBary.x, min(vBary.y, vBary.z));
+ if (edge < 0.01)
+ out_Color = vec4(0.0, 0.0, 0.0, 1.0);
+ else
+ out_Color = vec4(baseColour*color,1.0);
+ }
}
diff --git a/SA2LevelEditor/res/Shaders/entity/vertexShader.txt b/SA2LevelEditor/res/Shaders/entity/vertexShader.txt
index b6eeae7..283a820 100644
--- a/SA2LevelEditor/res/Shaders/entity/vertexShader.txt
+++ b/SA2LevelEditor/res/Shaders/entity/vertexShader.txt
@@ -4,9 +4,11 @@ in vec3 position;
in vec2 textureCoords;
in vec3 normal;
in vec3 vertexColor;
+in vec3 bary;
out vec2 pass_textureCoords;
out vec3 color;
+out vec3 vBary;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
@@ -30,4 +32,5 @@ void main(void)
color = vertexColor;
color *= 0.75 + (normal.y/4);
+ vBary = bary;
}
diff --git a/SA2LevelEditor/src/collision/collisionmodel.h b/SA2LevelEditor/src/collision/collisionmodel.h
index 8be1ad0..a4b8afd 100644
--- a/SA2LevelEditor/src/collision/collisionmodel.h
+++ b/SA2LevelEditor/src/collision/collisionmodel.h
@@ -7,7 +7,39 @@ class SA2Object;
#include
#include
+#include "../toolbox/vector.h"
+
+struct PCMeshset {
+ uint16_t typeAndMaterialID;
+ uint16_t numMeshes;
+ int16_t* __ptr32 meshes;
+ uint32_t* __ptr32 attrA;
+ Vector3f* __ptr32 normals;
+ uint32_t* __ptr32 vertexColor;
+ uint32_t* __ptr32 vertexUV;
+};
+
+struct PCMeshModel {
+ Vector3f* __ptr32 points;
+ Vector3f* __ptr32 normals;
+ uint32_t numPoints;
+ struct PCMeshset* __ptr32 meshsets;
+ uint32_t materials;
+ uint16_t numMeshsets;
+ uint16_t numMaterials;
+ Vector3f center;
+ float radius;
+};
+struct PCMeshObject {
+ uint32_t evalFlags;
+ struct PCMeshModel* __ptr32 model;
+ Vector3f pos;
+ int32_t ang[3];
+ Vector3f scale;
+ struct PCMeshObject* __ptr32 child;
+ struct PCMeshObject* __ptr32 sibling;
+};
class CollisionModel
{
diff --git a/SA2LevelEditor/src/entities/LevelSpecific/PyramidCave/KEYDOOR.cpp b/SA2LevelEditor/src/entities/LevelSpecific/PyramidCave/KEYDOOR.cpp
new file mode 100644
index 0000000..0b331a1
--- /dev/null
+++ b/SA2LevelEditor/src/entities/LevelSpecific/PyramidCave/KEYDOOR.cpp
@@ -0,0 +1,427 @@
+#include "KEYDOOR.h"
+#include
+#include
+#include
+
+#include "../../entity.h"
+#include "../../dummy.h"
+#include "../../../toolbox/vector.h"
+#include "../../../models/texturedmodel.h"
+#include "../../../loading/objLoader.h"
+#include "../../../loading/levelloader.h"
+#include "../../../main/main.h"
+#include "../../../collision/collisionmodel.h"
+#include "../../../collision/collisionchecker.h"
+#include "../../../toolbox/maths.h"
+
+#include
+
+std::list KEYDOOR::models;
+CollisionModel* KEYDOOR::cmBase;
+
+KEYDOOR::KEYDOOR()
+{
+
+}
+
+void KEYDOOR::cleanUp()
+{
+ if (collideModelTransformed != nullptr)
+ {
+ CollisionChecker::deleteCollideModel(collideModelTransformed);
+ collideModelTransformed = nullptr;
+ }
+}
+
+KEYDOOR::KEYDOOR(char data[32], bool useDefaultValues)
+{
+ std::memcpy(rawData, data, 32);
+
+ ID = data[1];
+
+ signed short rX;
+ signed short rY;
+ signed short rZ;
+
+ char* ptr = (char*)(&rX);
+ memset(ptr, data[3], 1);
+ memset(ptr + 1, data[2], 1);
+
+ ptr = (char*)(&rY);
+ memset(ptr, data[5], 1);
+ memset(ptr + 1, data[4], 1);
+
+ ptr = (char*)(&rZ);
+ memset(ptr, data[7], 1);
+ memset(ptr + 1, data[6], 1);
+
+ rotationX = (int)rX;
+ rotationY = (int)rY;
+ rotationZ = (int)rZ;
+
+ char* x = (char*)&position.x;
+ x[3] = data[8];
+ x[2] = data[9];
+ x[1] = data[10];
+ x[0] = data[11];
+
+ char* y = (char*)&position.y;
+ y[3] = data[12];
+ y[2] = data[13];
+ y[1] = data[14];
+ y[0] = data[15];
+
+ char* z = (char*)&position.z;
+ z[3] = data[16];
+ z[2] = data[17];
+ z[1] = data[18];
+ z[0] = data[19];
+
+ char* v1 = (char*)&scaleX;
+ v1[3] = data[20];
+ v1[2] = data[21];
+ v1[1] = data[22];
+ v1[0] = data[23];
+
+ char* v2 = (char*)&scaleY;
+ v2[3] = data[24];
+ v2[2] = data[25];
+ v2[1] = data[26];
+ v2[0] = data[27];
+
+ char* v3 = (char*)&scaleZ;
+ v3[3] = data[28];
+ v3[2] = data[29];
+ v3[1] = data[30];
+ v3[0] = data[31];
+
+ scaleX = scaleX + 1.0f;
+ scaleY = scaleX;
+ scaleZ = scaleX;
+
+ if (useDefaultValues)
+ {
+ scaleX = 1.0f;
+ scaleY = 1.0f;
+ scaleZ = 1.0f;
+ }
+
+ rotationX = 0;
+ rotationZ = 0;
+
+ visible = true;
+ baseColour.set(1, 1, 1);
+ updateTransformationMatrixZXY();
+
+ collideModelOriginal = KEYDOOR::cmBase;
+ collideModelTransformed = KEYDOOR::cmBase->duplicateMe();
+ collideModelTransformed->parent = this;
+ CollisionChecker::addCollideModel(collideModelTransformed);
+
+ updateTransformationMatrixYXZ();
+ updateCollisionModelYXZ();
+}
+
+bool KEYDOOR::isSA2Object()
+{
+ return true;
+}
+
+void KEYDOOR::step()
+{
+ if (Global::selectedSA2Object == this)
+ {
+ baseColour.set(1.75f, 1.75f, 1.75f);
+ }
+ else
+ {
+ baseColour.set(1.0f, 1.0f, 1.0f);
+ }
+}
+
+std::list* KEYDOOR::getModels()
+{
+ return &KEYDOOR::models;
+}
+
+void KEYDOOR::loadStaticModels()
+{
+ if (KEYDOOR::models.size() > 0)
+ {
+ return;
+ }
+
+#ifdef DEV_MODE
+ std::fprintf(stdout, "Loading KEYDOOR static models...\n");
+#endif
+ loadObjModelFromPCGame(&KEYDOOR::models, (struct PCMeshObject *)0xabbbf0);
+ KEYDOOR::cmBase = loadCollisionModelFromPCGame((struct PCMeshObject *)0xabbbf0);
+}
+
+void KEYDOOR::deleteStaticModels()
+{
+#ifdef DEV_MODE
+ std::fprintf(stdout, "Deleting KEYDOOR static models...\n");
+#endif
+ Entity::deleteModels(&KEYDOOR::models);
+ Entity::deleteCollisionModel(&KEYDOOR::cmBase);
+}
+
+void KEYDOOR::updateValue(int btnIndex)
+{
+ char buf[128];
+ GetWindowTextA(Global::windowValues[btnIndex], buf, 128);
+ std::string text = buf;
+
+ switch (btnIndex)
+ {
+ case 0:
+ {
+ try
+ {
+ //we are going to change into a new object.
+ int newid = std::stoi(text);
+
+ if (newid != ID)
+ {
+ char data[32] = { 0 };
+ data[1] = (char)newid;
+
+ data[8] = *(((char*)&position.x) + 3);
+ data[9] = *(((char*)&position.x) + 2);
+ data[10] = *(((char*)&position.x) + 1);
+ data[11] = *(((char*)&position.x) + 0);
+ data[12] = *(((char*)&position.y) + 3);
+ data[13] = *(((char*)&position.y) + 2);
+ data[14] = *(((char*)&position.y) + 1);
+ data[15] = *(((char*)&position.y) + 0);
+ data[16] = *(((char*)&position.z) + 3);
+ data[17] = *(((char*)&position.z) + 2);
+ data[18] = *(((char*)&position.z) + 1);
+ data[19] = *(((char*)&position.z) + 0);
+
+ SA2Object* newObject = LevelLoader::newSA2Object(Global::levelID, newid, data, true);
+ if (newObject != nullptr)
+ {
+ newObject->lvlLineNum = lvlLineNum;
+ Global::addEntity(newObject);
+ Global::selectedSA2Object = newObject;
+ newObject->updateEditorWindows();
+ Global::redrawWindow = true;
+ cleanUp();
+ Global::deleteEntity(this);
+ }
+ }
+ }
+ catch (...) {}
+ break;
+ }
+
+ case 2:
+ {
+ try
+ {
+ float newX = std::stof(text);
+ position.x = newX;
+ SetWindowTextA(Global::windowValues[2], std::to_string(position.x).c_str());
+ break;
+ }
+ catch (...) { break; }
+ }
+
+ case 3:
+ {
+ try
+ {
+ float newY = std::stof(text);
+ position.y = newY;
+ SetWindowTextA(Global::windowValues[3], std::to_string(position.y).c_str());
+ break;
+ }
+ catch (...) { break; }
+ }
+
+ case 4:
+ {
+ try
+ {
+ float newZ = std::stof(text);
+ position.z = newZ;
+ SetWindowTextA(Global::windowValues[4], std::to_string(position.z).c_str());
+ break;
+ }
+ catch (...) { break; }
+ }
+
+ case 5:
+ {
+ try
+ {
+ int newRotX = std::stoi(text);
+ rotationX = newRotX;
+ SetWindowTextA(Global::windowValues[5], std::to_string(rotationX).c_str());
+ break;
+ }
+ catch (...) { break; }
+ }
+
+ case 6:
+ {
+ try
+ {
+ int newRotY = std::stoi(text);
+ rotationY = newRotY;
+ SetWindowTextA(Global::windowValues[6], std::to_string(rotationY).c_str());
+ break;
+ }
+ catch (...) { break; }
+ }
+
+ case 7:
+ {
+ try
+ {
+ int newRotZ = std::stoi(text);
+ rotationZ = newRotZ;
+ SetWindowTextA(Global::windowValues[7], std::to_string(rotationZ).c_str());
+ break;
+ }
+ catch (...) { break; }
+ }
+
+ case 8:
+ {
+ try
+ {
+ float newScale = std::stof(text);
+ scaleX = newScale;
+ scaleY = newScale;
+ scaleZ = newScale;
+ SetWindowTextA(Global::windowValues[8], std::to_string(newScale).c_str());
+ break;
+ }
+ catch (...) { break; }
+ }
+
+ //case 9:
+ //{
+ // try
+ // {
+ // float newScale = std::stof(text);
+ // scaleY = newScale;
+ // SetWindowTextA(Global::windowValues[9], std::to_string(newScale).c_str());
+ // break;
+ // }
+ // catch (...) { break; }
+ //}
+
+ default: break;
+ }
+
+ updateTransformationMatrixZXY();
+ updateCollisionModelZXY();
+ Global::redrawWindow = true;
+}
+
+void KEYDOOR::updateEditorWindows()
+{
+ SetWindowTextA(Global::windowLabels[0], "ID");
+ SetWindowTextA(Global::windowLabels[1], "Name");
+ SetWindowTextA(Global::windowLabels[2], "Position X");
+ SetWindowTextA(Global::windowLabels[3], "Position Y");
+ SetWindowTextA(Global::windowLabels[4], "Position Z");
+ SetWindowTextA(Global::windowLabels[5], "Rotation X");
+ SetWindowTextA(Global::windowLabels[6], "Rotation Y");
+ SetWindowTextA(Global::windowLabels[7], "Rotation Z");
+ SetWindowTextA(Global::windowLabels[8], "Scale?");
+ SetWindowTextA(Global::windowLabels[9], "Unknown");
+ SetWindowTextA(Global::windowLabels[10], "Side");
+
+ SetWindowTextA(Global::windowValues[0], std::to_string(ID).c_str());
+ SetWindowTextA(Global::windowValues[1], "KEYDOOR");
+ SetWindowTextA(Global::windowValues[2], std::to_string(position.x).c_str());
+ SetWindowTextA(Global::windowValues[3], std::to_string(position.y).c_str());
+ SetWindowTextA(Global::windowValues[4], std::to_string(position.z).c_str());
+ SetWindowTextA(Global::windowValues[5], std::to_string(rotationX).c_str());
+ SetWindowTextA(Global::windowValues[6], std::to_string(rotationY).c_str());
+ SetWindowTextA(Global::windowValues[7], std::to_string(rotationZ).c_str());
+ SetWindowTextA(Global::windowValues[8], std::to_string(scaleX).c_str());
+ SetWindowTextA(Global::windowValues[9], std::to_string(scaleY).c_str());
+
+ SendMessageA(Global::windowValues[0], EM_SETREADONLY, 0, 0);
+ SendMessageA(Global::windowValues[1], EM_SETREADONLY, 1, 0);
+ SendMessageA(Global::windowValues[2], EM_SETREADONLY, 0, 0);
+ SendMessageA(Global::windowValues[3], EM_SETREADONLY, 0, 0);
+ SendMessageA(Global::windowValues[4], EM_SETREADONLY, 0, 0);
+ SendMessageA(Global::windowValues[5], EM_SETREADONLY, 0, 0);
+ SendMessageA(Global::windowValues[6], EM_SETREADONLY, 0, 0);
+ SendMessageA(Global::windowValues[7], EM_SETREADONLY, 0, 0);
+ SendMessageA(Global::windowValues[8], EM_SETREADONLY, 0, 0);
+ SendMessageA(Global::windowValues[9], EM_SETREADONLY, 1, 0);
+ SendMessageA(Global::windowValues[10], EM_SETREADONLY, 1, 0);
+
+ SetWindowTextA(Global::windowDescriptions[0], "");
+ SetWindowTextA(Global::windowDescriptions[1], "");
+ SetWindowTextA(Global::windowDescriptions[2], "");
+ SetWindowTextA(Global::windowDescriptions[3], "");
+ SetWindowTextA(Global::windowDescriptions[4], "");
+ SetWindowTextA(Global::windowDescriptions[5], "");
+ SetWindowTextA(Global::windowDescriptions[6], "");
+ SetWindowTextA(Global::windowDescriptions[7], "");
+ SetWindowTextA(Global::windowDescriptions[8], "");
+ SetWindowTextA(Global::windowDescriptions[9], "Not sure");
+
+ updateTransformationMatrixZXY();
+ updateCollisionModelZXY();
+}
+
+void KEYDOOR::fillData(char data[32])
+{
+ data[1] = (char)ID;
+
+ data[2] = (char)((rotationX >> 8) & 0xFF);
+ data[3] = (char)((rotationX >> 0) & 0xFF);
+ data[4] = (char)((rotationY >> 8) & 0xFF);
+ data[5] = (char)((rotationY >> 0) & 0xFF);
+ data[6] = (char)((rotationZ >> 8) & 0xFF);
+ data[7] = (char)((rotationZ >> 0) & 0xFF);
+
+ char* ptr = (char*)(&position.x);
+ data[8] = (char)(*(ptr + 3));
+ data[9] = (char)(*(ptr + 2));
+ data[10] = (char)(*(ptr + 1));
+ data[11] = (char)(*(ptr + 0));
+
+ ptr = (char*)(&position.y);
+ data[12] = (char)(*(ptr + 3));
+ data[13] = (char)(*(ptr + 2));
+ data[14] = (char)(*(ptr + 1));
+ data[15] = (char)(*(ptr + 0));
+
+ ptr = (char*)(&position.z);
+ data[16] = (char)(*(ptr + 3));
+ data[17] = (char)(*(ptr + 2));
+ data[18] = (char)(*(ptr + 1));
+ data[19] = (char)(*(ptr + 0));
+
+ float var1 = scaleX - 1.0f;
+ ptr = (char*)(&var1);
+ data[20] = (char)(*(ptr + 3));
+ data[21] = (char)(*(ptr + 2));
+ data[22] = (char)(*(ptr + 1));
+ data[23] = (char)(*(ptr + 0));
+
+ float var2 = scaleY - 1.0f;
+ ptr = (char*)(&var2);
+ data[24] = (char)(*(ptr + 3));
+ data[25] = (char)(*(ptr + 2));
+ data[26] = (char)(*(ptr + 1));
+ data[27] = (char)(*(ptr + 0));
+
+ float var3 = 0.0f;
+ ptr = (char*)(&var3);
+ data[28] = (char)(*(ptr + 3));
+ data[29] = (char)(*(ptr + 2));
+ data[30] = (char)(*(ptr + 1));
+ data[31] = (char)(*(ptr + 0));
+}
diff --git a/SA2LevelEditor/src/entities/LevelSpecific/PyramidCave/KEYDOOR.h b/SA2LevelEditor/src/entities/LevelSpecific/PyramidCave/KEYDOOR.h
new file mode 100644
index 0000000..b246c95
--- /dev/null
+++ b/SA2LevelEditor/src/entities/LevelSpecific/PyramidCave/KEYDOOR.h
@@ -0,0 +1,37 @@
+#pragma once
+
+class CollisionModel;
+
+#include
+#include
+#include "../../entity.h"
+#include "../../sa2object.h"
+
+class KEYDOOR : public SA2Object
+{
+private:
+ static std::list models;
+ static CollisionModel* cmBase;
+public:
+ KEYDOOR();
+ KEYDOOR(char data[32], bool useDefaultValues);
+
+ void step();
+
+ void cleanUp();
+
+ void updateEditorWindows();
+
+ void updateValue(int btnIndex);
+
+ void fillData(char data[32]);
+
+ bool isSA2Object();
+
+ std::list* getModels();
+
+ static void loadStaticModels();
+
+ static void deleteStaticModels();
+};
+
diff --git a/SA2LevelEditor/src/loading/LevelLoader.cpp b/SA2LevelEditor/src/loading/LevelLoader.cpp
index 96d511e..9c849c4 100644
--- a/SA2LevelEditor/src/loading/LevelLoader.cpp
+++ b/SA2LevelEditor/src/loading/LevelLoader.cpp
@@ -81,6 +81,7 @@
#include "../entities/GlobalObjects/soapsw.h"
#include "../entities/GlobalObjects/tjumpdai.h"
#include "../entities/LevelSpecific/PyramidCave/torchcup.h"
+#include "../entities/LevelSpecific/PyramidCave/KEYDOOR.h"
#include "../entities/LevelSpecific/PyramidCave/snakestatue.h"
#include "../entities/LevelSpecific/PyramidCave/sneakrail.h"
#include "../entities/LevelSpecific/CosmicWall/cw_stage.h"
@@ -1025,6 +1026,7 @@ SA2Object* LevelLoader::newSA2Object(int levelID, int objectID, char data[32], b
else if (o == "EMERALD F") {return new EMERALD_F (data, useDefaultValues);}
else if (o == "SPIDERWEB") {return new SPIDERWEB (data, useDefaultValues);}
else if (o == "TORCHCUP") {return new TORCHCUP (data, useDefaultValues);}
+ else if (o == "KEYDOOR") {return new KEYDOOR (data, useDefaultValues);}
else if (o == "SNAKESTATUE") {return new SNAKESTATUE (data, useDefaultValues);}
else if (o == "SNEAKRAIL") {return new SNEAKRAIL (data, useDefaultValues);}
else if (o == "SCHBOX") {return new SCHBOX (data, useDefaultValues);}
diff --git a/SA2LevelEditor/src/loading/Loader.cpp b/SA2LevelEditor/src/loading/Loader.cpp
index 974fdd5..f8fc6c9 100644
--- a/SA2LevelEditor/src/loading/Loader.cpp
+++ b/SA2LevelEditor/src/loading/Loader.cpp
@@ -23,11 +23,12 @@ std::unordered_map Loader::texIdToFilename;
int Loader::vaoNumber = 0;
int Loader::vboNumber = 0;
-RawModel Loader::loadToVAO(std::vector* positions,
- std::vector* textureCoords,
- std::vector* normals,
- std::vector* vertexColors,
- std::vector* indicies)
+RawModel Loader::loadToVAO(std::vector* positions,
+ std::vector* textureCoords,
+ std::vector* normals,
+ std::vector* vertexColors,
+ std::vector* indicies,
+ std::vector* bary)
{
GLuint vaoID = createVAO();
std::list vboIDs;
@@ -37,12 +38,32 @@ RawModel Loader::loadToVAO(std::vector* positions,
vboIDs.push_back(storeDataInAttributeList(1, 2, textureCoords));
vboIDs.push_back(storeDataInAttributeList(2, 3, normals));
vboIDs.push_back(storeDataInAttributeList(3, 3, vertexColors));
+ if (bary != nullptr) {
+ vboIDs.push_back(storeDataInAttributeList(4, 3, bary));
+ }
+ else {
+ std::vector tmpBary(positions->size(), 0.0f);
+ vboIDs.push_back(storeDataInAttributeList(4, 3, &tmpBary));
+ }
unbindVAO();
return RawModel(vaoID, (int)indicies->size(), &vboIDs);
}
+RawModel Loader::loadToVAO(
+ std::vector* positions, std::vector* normals, std::vector* bary, std::vector* indices)
+{
+ GLuint vaoID = createVAO();
+ std::list vboIDs;
+
+ vboIDs.push_back(bindIndiciesBuffer(indices));
+ vboIDs.push_back(storeDataInAttributeList(0, 3, positions));
+ vboIDs.push_back(storeDataInAttributeList(2, 3, normals));
+ vboIDs.push_back(storeDataInAttributeList(4, 3, bary));
+ return RawModel(vaoID, (int)indices->size(), &vboIDs);
+}
+
//for gui
RawModel Loader::loadToVAO(std::vector* positions, int dimensions)
{
diff --git a/SA2LevelEditor/src/loading/loader.h b/SA2LevelEditor/src/loading/loader.h
index a307fac..c12dc61 100644
--- a/SA2LevelEditor/src/loading/loader.h
+++ b/SA2LevelEditor/src/loading/loader.h
@@ -43,7 +43,14 @@ class Loader
std::vector* textureCoords,
std::vector* normals,
std::vector* vertexColors,
- std::vector* indices);
+ std::vector* indices,
+ std::vector* bary=nullptr);
+
+ static RawModel loadToVAO(
+ std::vector* positions,
+ std::vector* normals,
+ std::vector* bary,
+ std::vector* indices);
//for gui
static RawModel loadToVAO(std::vector* positions, int dimensions);
diff --git a/SA2LevelEditor/src/loading/objLoader.cpp b/SA2LevelEditor/src/loading/objLoader.cpp
index 4ee1f52..7f0d236 100644
--- a/SA2LevelEditor/src/loading/objLoader.cpp
+++ b/SA2LevelEditor/src/loading/objLoader.cpp
@@ -28,19 +28,19 @@ void processVertexBinary(int, int, int,
std::vector* vertices,
std::vector* indices);
-void dealWithAlreadyProcessedVertex(Vertex*,
- int,
- int,
- std::vector*,
+void dealWithAlreadyProcessedVertex(Vertex*,
+ int,
+ int,
+ std::vector*,
std::vector*);
void removeUnusedVertices(std::vector* vertices);
void convertDataToArrays(
- std::vector* vertices,
+ std::vector* vertices,
std::vector* textures,
- std::vector* normals,
- std::vector* verticesArray,
+ std::vector* normals,
+ std::vector* verticesArray,
std::vector* texturesArray,
std::vector* normalsArray,
std::vector* colorsArray);
@@ -54,7 +54,7 @@ std::vector textureNamesList;
int loadModel(std::list* models, std::string filePath, std::string fileName)
{
int attemptBinaryOBJ = loadBinaryObjModel(models, filePath, fileName+".binobj");
-
+
if (attemptBinaryOBJ == -1)
{
int attemptBinaryVCL = loadBinaryVclModel(models, filePath, fileName+".binvcl");
@@ -65,8 +65,8 @@ int loadModel(std::list* models, std::string filePath, std::stri
if (attemptOBJ == -1)
{
- std::fprintf(stderr, "Error: Cannot load model from file\n'%s' or\n'%s' or\n'%s'\n",
- ((filePath + fileName) + ".binobj").c_str(),
+ std::fprintf(stderr, "Error: Cannot load model from file\n'%s' or\n'%s' or\n'%s'\n",
+ ((filePath + fileName) + ".binobj").c_str(),
((filePath + fileName) + ".binvcl").c_str(),
((filePath + fileName) + ".obj").c_str());
}
@@ -83,7 +83,7 @@ int loadModel(std::list* models, std::string filePath, std::stri
CollisionModel* loadCollisionModel(std::string filePath, std::string fileName)
{
CollisionModel* attemptBinaryCol = loadBinaryColCollisionModel(filePath, fileName+".bincol");
-
+
if (attemptBinaryCol == nullptr)
{
CollisionModel* attemptBinaryOBJ = loadBinaryObjCollisionModel(filePath, fileName+".binobj");
@@ -98,8 +98,8 @@ CollisionModel* loadCollisionModel(std::string filePath, std::string fileName)
if (attemptObj == nullptr)
{
- std::fprintf(stderr, "Error: Cannot load collision from file \n'%s' or\n'%s' or\n'%s' or \n'%s'\n",
- ((filePath + fileName) + ".bincol").c_str(),
+ std::fprintf(stderr, "Error: Cannot load collision from file \n'%s' or\n'%s' or\n'%s' or \n'%s'\n",
+ ((filePath + fileName) + ".bincol").c_str(),
((filePath + fileName) + ".binobj").c_str(),
((filePath + fileName) + ".binvcl").c_str(),
((filePath + fileName) + ".obj").c_str());
@@ -143,7 +143,7 @@ int loadBinaryObjModel(std::list* models, std::string filePath,
char fileType[4];
fread(fileType, sizeof(char), 4, file);
- if (fileType[0] != 'o' ||
+ if (fileType[0] != 'o' ||
fileType[1] != 'b' ||
fileType[2] != 'j' ||
fileType[3] != 0)
@@ -322,7 +322,7 @@ int loadBinaryVclModel(std::list* models, std::string filePath,
char fileType[4];
fread(fileType, sizeof(char), 4, file);
- if (fileType[0] != 'v' ||
+ if (fileType[0] != 'v' ||
fileType[1] != 'c' ||
fileType[2] != 'l' ||
fileType[3] != 0)
@@ -367,10 +367,10 @@ int loadBinaryVclModel(std::list* models, std::string filePath,
//new
float t[3];
fread(t, sizeof(float), 3, file);
-
+
Vector3f vertex(t[0], t[1], t[2]);
Vertex* newVertex = new Vertex((int)vertices.size(), &vertex); INCR_NEW("Vertex");
-
+
unsigned char c[3];
fread(c, sizeof(unsigned char), 3, file);
float red = ((float)c[0])/255.0f;
@@ -1041,7 +1041,7 @@ int loadBinaryObjModelWithMTL(std::list* models, std::string fil
char fileType[4];
fread(fileType, sizeof(char), 4, file);
- if (fileType[0] != 'o' ||
+ if (fileType[0] != 'o' ||
fileType[1] != 'b' ||
fileType[2] != 'j' ||
fileType[3] != 0)
@@ -1273,10 +1273,10 @@ void dealWithAlreadyProcessedVertex(
void convertDataToArrays(
- std::vector* vertices,
+ std::vector* vertices,
std::vector* textures,
- std::vector* normals,
- std::vector* verticesArray,
+ std::vector* normals,
+ std::vector* verticesArray,
std::vector* texturesArray,
std::vector* normalsArray,
std::vector* colorsArray)
@@ -1473,7 +1473,7 @@ CollisionModel* loadBinaryColCollisionModel(std::string filePath, std::string fi
char fileType[4];
fread(fileType, sizeof(char), 4, file);
- if (fileType[0] != 'c' ||
+ if (fileType[0] != 'c' ||
fileType[1] != 'o' ||
fileType[2] != 'l' ||
fileType[3] != 0)
@@ -1632,7 +1632,7 @@ CollisionModel* loadBinaryColCollisionModel(std::string filePath, std::string fi
CollisionModel* loadBinaryVclCollisionModel(std::string filePath, std::string fileName)
{
FILE* file = nullptr;
- int err = fopen_s(&file, (filePath+fileName).c_str(), "rb");
+ int err = fopen_s(&file, (filePath + fileName).c_str(), "rb");
if (file == nullptr || err != 0)
{
//std::fprintf(stderr, "Error: Cannot load file '%s'\n", (filePath + fileName).c_str());
@@ -1646,18 +1646,18 @@ CollisionModel* loadBinaryVclCollisionModel(std::string filePath, std::string fi
char fileType[4];
fread(fileType, sizeof(char), 4, file);
- if (fileType[0] != 'v' ||
+ if (fileType[0] != 'v' ||
fileType[1] != 'c' ||
fileType[2] != 'l' ||
fileType[3] != 0)
{
- std::fprintf(stdout, "Error: File '%s' is not a valid .binvcl file\n", (filePath+fileName).c_str());
+ std::fprintf(stdout, "Error: File '%s' is not a valid .binvcl file\n", (filePath + fileName).c_str());
return nullptr;
}
CollisionModel* model = new CollisionModel; INCR_NEW("CollisionModel")
- std::string line;
+ std::string line;
std::vector vertexList;
int mtllibLength;
@@ -1710,11 +1710,11 @@ CollisionModel* loadBinaryVclCollisionModel(std::string filePath, std::string fi
fread(&f[0], sizeof(int), 6, file);
- Vector3f v1 = vertexList[f[0]-1];
- Vector3f v2 = vertexList[f[2]-1];
- Vector3f v3 = vertexList[f[4]-1];
+ Vector3f v1 = vertexList[f[0] - 1];
+ Vector3f v2 = vertexList[f[2] - 1];
+ Vector3f v3 = vertexList[f[4] - 1];
- model->triangles.push_back(new Triangle3D(&v1, &v2, &v3)); INCR_NEW ("Triangle3D")
+ model->triangles.push_back(new Triangle3D(&v1, &v2, &v3)); INCR_NEW("Triangle3D")
}
}
@@ -1725,6 +1725,237 @@ CollisionModel* loadBinaryVclCollisionModel(std::string filePath, std::string fi
return model;
}
+int loadObjModelFromPCGame(std::list* models, struct PCMeshObject* objectPtr)
+{
+ if (models->size() > 0)
+ {
+ return 1;
+ }
+
+
+ HANDLE handle = Global::getSA2Handle();
+
+ std::vector vertices;
+ std::vector normals;
+ std::vector texCoords;
+ std::vector colors;
+ std::vector bary;
+ std::vector rawModels;
+ SIZE_T numberBytesRead;
+
+ struct PCMeshObject object;
+ if (!ReadProcessMemory(handle, objectPtr, &object, sizeof(struct PCMeshObject), &numberBytesRead) || \
+ numberBytesRead != sizeof(struct PCMeshObject)) {
+ return -1;
+ }
+
+ struct PCMeshModel model;
+ if (!ReadProcessMemory(handle, object.model, &model, sizeof(struct PCMeshModel), &numberBytesRead) || \
+ numberBytesRead != sizeof(struct PCMeshModel)) {
+ return -1;
+ }
+
+ vertices.resize(3 * model.numPoints);
+ if (!ReadProcessMemory(handle, model.points, vertices.data(), model.numPoints * 3 * sizeof(float), &numberBytesRead) || \
+ numberBytesRead != model.numPoints * 3 * sizeof(float)) {
+ return -1;
+ }
+ normals.resize(3 * model.numPoints);
+ if (!ReadProcessMemory(handle, model.normals, normals.data(), model.numPoints * 3 * sizeof(float), &numberBytesRead) || \
+ numberBytesRead != model.numPoints * 3 * sizeof(float)) {
+ return -1;
+ }
+
+ texCoords.resize(2 * model.numPoints);
+ colors.resize(3 * model.numPoints);
+ bary.resize(3 * model.numPoints);
+ for (uint32_t i = 0; i < model.numPoints; i++) {
+ texCoords[i*2]= 1.0f; // u
+ texCoords[i*2+1] = 1.0f; // v
+ colors[i * 3] = 0.8f;
+ colors[i * 3 + 1] = 0.8f;
+ colors[i * 3 + 2] = 0.8f;
+ bary[i * 3] = 0.0f;
+ bary[i * 3 + 1] = 0.0f;
+ bary[i * 3 + 2] = 0.0f;
+ }
+
+ std::vector meshsets;
+ meshsets.resize(model.numMeshsets);
+
+ if (!ReadProcessMemory(handle, model.meshsets, meshsets.data(), model.numMeshsets * sizeof(struct PCMeshset), &numberBytesRead) || \
+ numberBytesRead != model.numMeshsets * sizeof(struct PCMeshset)) {
+ return -1;
+ }
+
+ for (auto meshset : meshsets) {
+ std::vector indices;
+ std::vector meshVertexLists;
+ switch (meshset.typeAndMaterialID & 0xC000)
+ {
+ case 0xC000:
+ {
+ int16_t listSize = 0;
+ for (int i = 0; i < meshset.numMeshes; i++) {
+ int16_t tmpListSize = 0;
+ uint32_t offsetShorts = i + listSize;
+ if (!ReadProcessMemory(handle, meshset.meshes + offsetShorts, &tmpListSize, sizeof(int16_t), &numberBytesRead) || \
+ numberBytesRead != sizeof(int16_t)) {
+ return -1;
+ }
+ tmpListSize = tmpListSize & 0x7fff;
+ listSize += tmpListSize;
+ }
+ meshVertexLists.resize(listSize + meshset.numMeshes);
+ if (!ReadProcessMemory(handle, meshset.meshes, meshVertexLists.data(), (listSize + meshset.numMeshes) * sizeof(int16_t), &numberBytesRead) || \
+ numberBytesRead != (listSize + meshset.numMeshes) * sizeof(int16_t)) {
+ return -1;
+ }
+ uint32_t offsetCount = 0;
+ for (uint32_t i = 0; i < meshset.numMeshes; i++) {
+ // meshVertexLists[offsetCount] will always be at least 3
+ // as it's the number of vertices
+ uint32_t numVerts = meshVertexLists[offsetCount] & 0x7fff;
+ bool rightWinding = meshVertexLists[offsetCount] & 0x8000;
+ indices.clear();
+ indices.shrink_to_fit();
+ if (rightWinding) {
+ indices.emplace_back(meshVertexLists[offsetCount + 2]);
+ indices.emplace_back(meshVertexLists[offsetCount + 1]);
+ }
+ else {
+ indices.emplace_back(meshVertexLists[offsetCount + 1]);
+ indices.emplace_back(meshVertexLists[offsetCount + 2]);
+ }
+ for (uint32_t j = 3; j <= numVerts; j++) {
+ indices.emplace_back(meshVertexLists[offsetCount + j]);
+ }
+ offsetCount += (numVerts + 1);
+ std::unordered_set seen;
+ std::vector indicesSlice;
+ int startIdx = 0;
+ for (int j = 0; j < indices.size(); j++) {
+ int index = indices[j];
+ if (seen.find(index) != seen.end()) {
+ indicesSlice = std::vector(indices.begin() + startIdx, indices.begin() + j);
+ rawModels.push_back(Loader::loadToVAO(&vertices, &texCoords, &normals, &colors, &indicesSlice, &bary));
+
+ seen.clear();
+ seen.insert(indices[j - 1]);
+ seen.insert(indices[j - 2]);
+ startIdx = j - 2;
+ }
+ seen.insert(index);
+ bary[3 * index + 0] = 1.0f * ((j + 0) % 3 == 0);
+ bary[3 * index + 1] = 1.0f * ((j + 1) % 3 == 0);
+ bary[3 * index + 2] = 1.0f * ((j + 2) % 3 == 0);
+ }
+ indicesSlice = std::vector(indices.begin() + startIdx, indices.end());
+ rawModels.push_back(Loader::loadToVAO(&vertices, &texCoords, &normals, &colors, &indicesSlice, &bary));
+ }
+ }
+
+ default:
+ continue;
+ }
+ }
+ for (RawModel rawModel : rawModels) {
+ TexturedModel* tm = new TexturedModel(&rawModel, nullptr); INCR_NEW("TexturedModel")
+ models->push_back(tm);
+ }
+ return 1;
+}
+
+
+CollisionModel* loadCollisionModelFromPCGame(PCMeshObject* objectPtr)
+{
+ HANDLE handle = Global::getSA2Handle();
+ CollisionModel* collisionModel = new CollisionModel; INCR_NEW("CollisionModel")
+ std::vector vertices;
+ SIZE_T numberBytesRead;
+
+ struct PCMeshObject object;
+ if (!ReadProcessMemory(handle, objectPtr, &object, sizeof(struct PCMeshObject), &numberBytesRead) || \
+ numberBytesRead != sizeof(struct PCMeshObject)) {
+ return nullptr;
+ }
+
+ struct PCMeshModel model;
+ if (!ReadProcessMemory(handle, object.model, &model, sizeof(struct PCMeshModel), &numberBytesRead) || \
+ numberBytesRead != sizeof(struct PCMeshModel)) {
+ return nullptr;
+ }
+
+ vertices.resize(model.numPoints);
+ if (!ReadProcessMemory(handle, model.points, vertices.data(), model.numPoints * sizeof(Vector3f), &numberBytesRead) || \
+ numberBytesRead != model.numPoints * sizeof(Vector3f)) {
+ return nullptr;
+ }
+
+ std::vector meshsets;
+ meshsets.resize(model.numMeshsets);
+
+ if (!ReadProcessMemory(handle, model.meshsets, meshsets.data(), model.numMeshsets * sizeof(struct PCMeshset), &numberBytesRead) || \
+ numberBytesRead != model.numMeshsets * sizeof(struct PCMeshset)) {
+ return nullptr;
+ }
+
+ for (auto meshset : meshsets) {
+ std::vector meshVertexLists;
+ switch (meshset.typeAndMaterialID & 0xC000)
+ {
+ case 0xC000:
+ {
+ int32_t listSize = 0;
+ for (int i = 0; i < meshset.numMeshes; i++) {
+ int16_t tmpListSize = 0;
+ uint32_t offsetShorts = i + listSize;
+ if (!ReadProcessMemory(handle, meshset.meshes + offsetShorts, &tmpListSize, sizeof(int16_t), &numberBytesRead) || \
+ numberBytesRead != sizeof(int16_t)) {
+ return nullptr;
+ }
+ // MSB is used to indicate winding of triangles in strip
+ tmpListSize = tmpListSize & 0x7fff;
+ listSize += tmpListSize;
+ }
+ meshVertexLists.resize(listSize + meshset.numMeshes);
+ if (!ReadProcessMemory(handle, meshset.meshes, meshVertexLists.data(), (listSize + meshset.numMeshes) * sizeof(int16_t), &numberBytesRead) || \
+ numberBytesRead != (listSize + meshset.numMeshes) * sizeof(int16_t)) {
+ return nullptr;
+ }
+ uint32_t offsetCount = 0;
+ for (uint32_t i = 0; i < meshset.numMeshes; i++) {
+ // meshVertexLists[offsetCount] will always be at least 3
+ // as it's the number of vertices
+ uint32_t numVerts = meshVertexLists[offsetCount] & 0x7fff;
+ bool rightWinding = meshVertexLists[offsetCount] & 0x8000;
+ for (uint32_t j = 3; j <= numVerts; j++) {
+ Vector3f v1, v2, v3;
+ if (rightWinding) {
+ v2 = vertices[meshVertexLists[offsetCount + j - 1]];
+ v1 = vertices[meshVertexLists[offsetCount + j - 2]];
+ v3 = vertices[meshVertexLists[offsetCount + j]];
+ }
+ else {
+ v1 = vertices[meshVertexLists[offsetCount + j - 2]];
+ v2 = vertices[meshVertexLists[offsetCount + j - 1]];
+ v3 = vertices[meshVertexLists[offsetCount + j]];
+ }
+ collisionModel->triangles.push_back(new Triangle3D(&v1, &v2, &v3)); INCR_NEW("Triangle3D")
+ rightWinding = !rightWinding;
+ }
+ offsetCount += (numVerts + 1);
+ }
+ break;
+ }
+ default:
+ return nullptr;
+ }
+ }
+ collisionModel->generateMinMaxValues();
+ return collisionModel;
+}
+
CollisionModel* loadBinaryObjCollisionModel(std::string filePath, std::string fileName)
{
FILE* file = nullptr;
@@ -1742,7 +1973,7 @@ CollisionModel* loadBinaryObjCollisionModel(std::string filePath, std::string fi
char fileType[4];
fread(fileType, sizeof(char), 4, file);
- if (fileType[0] != 'o' ||
+ if (fileType[0] != 'o' ||
fileType[1] != 'b' ||
fileType[2] != 'j' ||
fileType[3] != 0)
diff --git a/SA2LevelEditor/src/loading/objLoader.h b/SA2LevelEditor/src/loading/objLoader.h
index e1d27bc..5a037f5 100644
--- a/SA2LevelEditor/src/loading/objLoader.h
+++ b/SA2LevelEditor/src/loading/objLoader.h
@@ -6,6 +6,7 @@ class CollisionModel;
#include
#include
+#include "../collision/collisionmodel.h"
//Attempts to load a model as either an OBJ or binary format.
//Checks for binary file first, then tries OBJ.
@@ -47,4 +48,7 @@ CollisionModel* loadBinaryObjCollisionModel(std::string filePath, std::string fi
//The CollisionModel returned must be deleted later.
CollisionModel* loadBinaryVclCollisionModel(std::string filePath, std::string fileName);
+
+int loadObjModelFromPCGame(std::list* models, struct PCMeshObject* objectPtr);
+CollisionModel* loadCollisionModelFromPCGame(struct PCMeshObject* objectPtr);
#endif
diff --git a/SA2LevelEditor/src/main/Main.cpp b/SA2LevelEditor/src/main/Main.cpp
index 71b3860..f9e406c 100644
--- a/SA2LevelEditor/src/main/Main.cpp
+++ b/SA2LevelEditor/src/main/Main.cpp
@@ -97,6 +97,7 @@
#include "../entities/GlobalObjects/soapsw.h"
#include "../entities/GlobalObjects/tjumpdai.h"
#include "../entities/LevelSpecific/PyramidCave/torchcup.h"
+#include "../entities/LevelSpecific/PyramidCave/KEYDOOR.h"
#include "../entities/LevelSpecific/PyramidCave/snakestatue.h"
#include "../entities/LevelSpecific/PyramidCave/sneakrail.h"
#include "../entities/LevelSpecific/CosmicWall/cw_stage.h"
@@ -1195,6 +1196,11 @@ DWORD sa2PID = NULL;
HANDLE sa2Handle = NULL;
float timeUntilNextProcessAttach = ATTACH_DELAY;
+HANDLE Global::getSA2Handle()
+{
+ return sa2Handle;
+}
+
DWORD getPIDByName(const char* processName)
{
PROCESSENTRY32 pe32 = {0};
@@ -1302,6 +1308,10 @@ void Global::attemptAttachToSA2()
DolphinBase::m_ARAMAccessible = false;
}
}
+ else if (sa2Handle != NULL && Global::sa2Type == Global::SA2Type::Steam) {
+ KEYDOOR::loadStaticModels();
+ }
+
}
}
else
@@ -2077,4 +2087,4 @@ void Global::deleteGhost(short slot)
}
Global::userGhosts[slot] = nullptr;
-}
+}
\ No newline at end of file
diff --git a/SA2LevelEditor/src/main/main.h b/SA2LevelEditor/src/main/main.h
index 5c8ee47..1db19ba 100644
--- a/SA2LevelEditor/src/main/main.h
+++ b/SA2LevelEditor/src/main/main.h
@@ -250,5 +250,7 @@ class Global
static void addTransparentEntity(Entity* entityToAdd);
static void deleteTransparentEntity(Entity* entityToDelete);
static void deleteAllTransparentEntites();
+
+ static HANDLE getSA2Handle();
};
#endif
diff --git a/SA2LevelEditor/src/models/TexturedModel.cpp b/SA2LevelEditor/src/models/TexturedModel.cpp
index 799a64e..39cfe26 100644
--- a/SA2LevelEditor/src/models/TexturedModel.cpp
+++ b/SA2LevelEditor/src/models/TexturedModel.cpp
@@ -26,8 +26,13 @@ TexturedModel::TexturedModel(RawModel* model, ModelTexture* texture)
}
//Copy over the ModelTexture data
- this->texture = ModelTexture(texture);
- this->texture.addMeToAnimationsSetIfNeeded();
+ if (texture) {
+ this->texture = ModelTexture(texture);
+ this->texture.addMeToAnimationsSetIfNeeded();
+ }
+ else {
+ this->texture = ModelTexture();
+ }
}
RawModel* TexturedModel::getRawModel()
diff --git a/SA2LevelEditor/src/rendering/Renderer.cpp b/SA2LevelEditor/src/rendering/Renderer.cpp
index 55fb194..6cd8d44 100644
--- a/SA2LevelEditor/src/rendering/Renderer.cpp
+++ b/SA2LevelEditor/src/rendering/Renderer.cpp
@@ -29,11 +29,16 @@ void EntityRenderer::renderNEW(std::unordered_map* entityList = &entry.second;
-
+ int noTexture = entry.first->getTexture()->getIDs()->size() == 0;
for (Entity* entity : (*entityList))
{
prepareInstance(entity);
- glDrawElements(GL_TRIANGLES, (entry.first)->getRawModel()->getVertexCount(), GL_UNSIGNED_INT, 0);
+ if (noTexture) {
+ glDrawElements(GL_TRIANGLE_STRIP, (entry.first)->getRawModel()->getVertexCount(), GL_UNSIGNED_INT, 0);
+ }
+ else {
+ glDrawElements(GL_TRIANGLES, (entry.first)->getRawModel()->getVertexCount(), GL_UNSIGNED_INT, 0);
+ }
}
unbindTexturedModel();
}
@@ -47,8 +52,11 @@ void EntityRenderer::prepareTexturedModel(TexturedModel* model)
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
+ glEnableVertexAttribArray(4);
ModelTexture* texture = model->getTexture();
+ int noTexture = texture->getIDs()->size() == 0;
+
//if (texture->getHasTransparency() != 0)
{
//Master_disableCulling();
@@ -60,10 +68,17 @@ void EntityRenderer::prepareTexturedModel(TexturedModel* model)
shader->loadTransparency(texture->hasTransparency);
shader->loadTextureOffsets(clockTime * (texture->scrollX), clockTime * (texture->scrollY));
shader->loadMixFactor(texture->mixFactor());
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture->getID());
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, texture->getID2());
+ if (texture->getIDs()->size() > 0) {
+ shader->loadHasTexture(1);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texture->getID());
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture->getID2());
+
+ }
+ else {
+ shader->loadHasTexture(0);
+ }
}
void EntityRenderer::unbindTexturedModel()
@@ -72,6 +87,7 @@ void EntityRenderer::unbindTexturedModel()
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
+ glDisableVertexAttribArray(4);
glBindVertexArray(0);
}
diff --git a/SA2LevelEditor/src/shaders/ShaderProgram.cpp b/SA2LevelEditor/src/shaders/ShaderProgram.cpp
index f9a6f99..b51582c 100644
--- a/SA2LevelEditor/src/shaders/ShaderProgram.cpp
+++ b/SA2LevelEditor/src/shaders/ShaderProgram.cpp
@@ -70,6 +70,11 @@ void ShaderProgram::loadTransparency(int transparency)
loadInt(location_hasTransparency, transparency);
}
+void ShaderProgram::loadHasTexture(int hasTexture)
+{
+ loadInt(location_hasTexture, hasTexture);
+}
+
void ShaderProgram::loadBaseColour(Vector3f* baseColour)
{
loadVector(location_baseColour, baseColour);
@@ -87,6 +92,7 @@ void ShaderProgram::bindAttributes()
bindAttribute(1, "textureCoords");
bindAttribute(2, "normal");
bindAttribute(3, "vertexColor");
+ bindAttribute(4, "bary");
}
void ShaderProgram::bindAttribute(int attribute, const char* variableName)
@@ -111,6 +117,7 @@ void ShaderProgram::getAllUniformLocations()
location_clipPlaneBehind = getUniformLocation("clipPlaneBehind");
location_mixFactor = getUniformLocation("mixFactor");
location_textureSampler2 = getUniformLocation("textureSampler2");
+ location_hasTexture = getUniformLocation("hasTexture");
}
int ShaderProgram::getUniformLocation(const char* uniformName)
diff --git a/SA2LevelEditor/src/shaders/shaderprogram.h b/SA2LevelEditor/src/shaders/shaderprogram.h
index 368f0ff..2a17482 100644
--- a/SA2LevelEditor/src/shaders/shaderprogram.h
+++ b/SA2LevelEditor/src/shaders/shaderprogram.h
@@ -26,6 +26,7 @@ class ShaderProgram
int location_clipPlaneBehind;
int location_mixFactor;
int location_textureSampler2;
+ int location_hasTexture;
public:
ShaderProgram(const char* vertexFilename, const char* fragmentFilename);
@@ -52,8 +53,12 @@ class ShaderProgram
void loadMixFactor(float factor);
+ void loadHasTexture(int hasTexture);
+
void connectTextureUnits();
+
+
protected:
void bindAttributes();