diff --git a/Client/App/App.vcproj b/Client/App/App.vcproj
index d37b5c48..9130c10e 100644
--- a/Client/App/App.vcproj
+++ b/Client/App/App.vcproj
@@ -797,6 +797,10 @@
RelativePath=".\include\v8datamodel\Camera.h"
>
+
+
@@ -1302,6 +1306,10 @@
RelativePath=".\v8datamodel\Camera.cpp"
>
+
+
@@ -1388,7 +1396,6 @@
diff --git a/Client/App/include/v8datamodel/CustomMesh.h b/Client/App/include/v8datamodel/CustomMesh.h
new file mode 100644
index 00000000..b5be1147
--- /dev/null
+++ b/Client/App/include/v8datamodel/CustomMesh.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include
+#include "reflection/reflection.h"
+#include "util/MeshId.h"
+#include "util/TextureId.h"
+#include "v8tree/Instance.h"
+
+namespace RBX {
+ extern const char* sSpecialMesh;
+
+ class SpecialShape : public RBX::DescribedCreatable
+ {
+ public:
+ enum MeshType
+ {
+ HEAD_MESH,
+ TORSO_MESH,
+ WEDGE_MESH,
+ SPHERE_MESH,
+ CYLINDER_MESH,
+ FILE_MESH,
+ BRICK_MESH
+ };
+
+ private:
+ MeshType meshType;
+ G3D::Vector3 scale;
+ TextureId textureId;
+ MeshId meshId;
+ G3D::Vector3 vertColor;
+ public:
+ SpecialShape();
+ const MeshType getMeshType() const
+ {
+ return meshType;
+ }
+ void setMeshType(MeshType value);
+ const G3D::Vector3& getScale() const
+ {
+ return scale;
+ }
+ void setScale(const G3D::Vector3& value);
+ const G3D::Vector3& getVertColor() const
+ {
+ return vertColor;
+ }
+ void setVertColor(const G3D::Vector3& value);
+ const float getAlpha() const;
+
+ const MeshId getMeshId() const
+ {
+ return meshId;
+ }
+
+ void setMeshId(const MeshId& value);
+ const TextureId getTextureId() const
+ {
+ return textureId;
+ }
+ void setTextureId(const TextureId& value);
+ protected:
+ virtual bool askSetParent(const Instance*) const;
+ };
+
+};
\ No newline at end of file
diff --git a/Client/App/include/v8datamodel/Decal.h b/Client/App/include/v8datamodel/Decal.h
index b3c7a80a..d23010ff 100644
--- a/Client/App/include/v8datamodel/Decal.h
+++ b/Client/App/include/v8datamodel/Decal.h
@@ -3,10 +3,12 @@
#include "reflection/reflection.h"
#include "v8datamodel/FaceInstance.h"
#include "util/TextureId.h"
+#include
namespace RBX
{
extern const char* sDecal;
+ extern const char* sTexture;
class Decal : public DescribedCreatable
{
@@ -20,11 +22,50 @@ namespace RBX
static const Reflection::PropDescriptor prop_Shiny;
Decal();
- TextureId getTexture() const;
+ TextureId getTexture() const
+ {
+ return texture;
+ }
+
void setTexture(TextureId);
- float getSpecular() const;
+
+ float getSpecular() const
+ {
+ return specular;
+ }
+
void setSpecular(float);
- float getShiny() const;
+
+ float getShiny() const
+ {
+ return shiny;
+ }
void setShiny(float);
};
+
+ class Texture : public DescribedCreatable
+ {
+ private:
+ G3D::Vector2 studsPerTile;
+ public:
+ static const Reflection::PropDescriptor prop_StudsPerTileU;
+ static const Reflection::PropDescriptor prop_StudsPerTileV;
+
+ Texture();
+ const G3D::Vector2& getStudsPerTile()
+ {
+ return studsPerTile;
+ }
+
+ float getStudsPerTileU() const
+ {
+ return studsPerTile.x;
+ }
+ void setStudsPerTileU(float value);
+ float getStudsPerTileV() const
+ {
+ return studsPerTile.y;
+ }
+ void setStudsPerTileV(float value);
+ };
};
\ No newline at end of file
diff --git a/Client/App/include/v8datamodel/FaceInstance.h b/Client/App/include/v8datamodel/FaceInstance.h
index 79161332..09f82ff3 100644
--- a/Client/App/include/v8datamodel/FaceInstance.h
+++ b/Client/App/include/v8datamodel/FaceInstance.h
@@ -15,7 +15,10 @@ namespace RBX
public:
static const Reflection::EnumPropDescriptor prop_Face;
FaceInstance();
- NormalId getFace() const;
+ NormalId getFace() const
+ {
+ return face;
+ }
void setFace(NormalId);
protected:
virtual bool askSetParent(const Instance*) const;
diff --git a/Client/App/v8datamodel/CustomMesh.cpp b/Client/App/v8datamodel/CustomMesh.cpp
new file mode 100644
index 00000000..4eadce7d
--- /dev/null
+++ b/Client/App/v8datamodel/CustomMesh.cpp
@@ -0,0 +1,95 @@
+#include "v8datamodel/CustomMesh.h"
+#include "v8datamodel/PartInstance.h"
+namespace RBX
+{
+ const char* sSpecialMesh = "SpecialMesh";
+ static const Reflection::EnumPropDescriptor desc_meshType("MeshType", "Data", &SpecialShape::getMeshType, &SpecialShape::setMeshType, Reflection::EnumPropertyDescriptor::STANDARD);
+ static const Reflection::PropDescriptor desc_scale("Scale", "Data", &SpecialShape::getScale, &SpecialShape::setScale, Reflection::PropertyDescriptor::STANDARD);
+ static const Reflection::PropDescriptor desc_meshId("MeshId", "Data", &SpecialShape::getMeshId, &SpecialShape::setMeshId, Reflection::PropertyDescriptor::STANDARD);
+ static const Reflection::PropDescriptor desc_textureId("TextureId", "Data", &SpecialShape::getTextureId, &SpecialShape::setTextureId, Reflection::PropertyDescriptor::STANDARD);
+ static const Reflection::PropDescriptor desc_vertColor("VertexColor", "Data", &SpecialShape::getVertColor, &SpecialShape::setVertColor, Reflection::PropertyDescriptor::STANDARD);
+
+ const float SpecialShape::getAlpha() const
+ {
+ if (getParent())
+ {
+ PartInstance* part = fastDynamicCast(getParent());
+
+ if (part)
+ {
+ return part->getTransparencyUi();
+ }
+ }
+ return 0.0f;
+ }
+
+ SpecialShape::SpecialShape()
+ : meshType(HEAD_MESH),
+ scale(1.0f, 1.0f, 1.0f),
+ textureId(),
+ meshId(),
+ vertColor(1.0f, 1.0f, 1.0f)
+ {
+ setName("Mesh");
+ }
+
+ void SpecialShape::setMeshType(MeshType value)
+ {
+ if (meshType != value)
+ {
+ meshType = value;
+ raisePropertyChanged(desc_meshType);
+ }
+ }
+
+ void SpecialShape::setScale(const G3D::Vector3& value)
+ {
+ if (scale != value)
+ {
+ scale = value;
+ raisePropertyChanged(desc_scale);
+ }
+ }
+
+ void SpecialShape::setVertColor(const G3D::Vector3& value)
+ {
+ if (vertColor != value)
+ {
+ vertColor = value;
+ raisePropertyChanged(desc_vertColor);
+ }
+ }
+
+ void SpecialShape::setMeshId(const MeshId& value)
+ {
+ if (meshId != value)
+ {
+ meshId = value;
+ raisePropertyChanged(desc_meshId);
+ if (meshType != FILE_MESH)
+ {
+ meshType = FILE_MESH;
+ raisePropertyChanged(desc_meshType);
+ }
+ }
+ }
+
+ void SpecialShape::setTextureId(const TextureId& value)
+ {
+ if (textureId != value)
+ {
+ textureId = value;
+ raisePropertyChanged(desc_textureId);
+ if (meshType != FILE_MESH)
+ {
+ meshType = FILE_MESH;
+ raisePropertyChanged(desc_meshType);
+ }
+ }
+ }
+
+ bool SpecialShape::askSetParent(const Instance* instance) const
+ {
+ return fastDynamicCast(instance) != NULL;
+ }
+};
\ No newline at end of file
diff --git a/Client/App/v8datamodel/Decal.cpp b/Client/App/v8datamodel/Decal.cpp
index 3cf561b8..158628d0 100644
--- a/Client/App/v8datamodel/Decal.cpp
+++ b/Client/App/v8datamodel/Decal.cpp
@@ -6,9 +6,12 @@
namespace RBX
{
const char* sDecal = "Decal";
+ const char* sTexture = "Texture";
const Reflection::PropDescriptor Decal::prop_Texture("Texture", "Appearance", &Decal::getTexture, &Decal::setTexture, Reflection::PropertyDescriptor::STANDARD);
const Reflection::PropDescriptor Decal::prop_Specular("Specular", "Appearance", &Decal::getSpecular, &Decal::setSpecular, Reflection::PropertyDescriptor::STANDARD);
const Reflection::PropDescriptor Decal::prop_Shiny("Shiny", "Appearance", &Decal::getShiny, &Decal::setShiny, Reflection::PropertyDescriptor::STANDARD);
+ const Reflection::PropDescriptor Texture::prop_StudsPerTileU("StudsPerTileU", "Appearance", &Texture::getStudsPerTileU, &Texture::setStudsPerTileU, Reflection::PropertyDescriptor::STANDARD);
+ const Reflection::PropDescriptor Texture::prop_StudsPerTileV("StudsPerTileV", "Appearance", &Texture::getStudsPerTileV, &Texture::setStudsPerTileV, Reflection::PropertyDescriptor::STANDARD);
Decal::Decal()
:texture(),
@@ -17,21 +20,6 @@ namespace RBX
{
setName("Decal");
}
-
- float Decal::getShiny() const
- {
- return shiny;
- }
-
- float Decal::getSpecular() const
- {
- return specular;
- };
-
- TextureId Decal::getTexture() const
- {
- return texture;
- }
void Decal::setTexture(TextureId value)
{
@@ -59,4 +47,28 @@ namespace RBX
raisePropertyChanged(prop_Shiny);
}
}
+
+ void Texture::setStudsPerTileU(float value)
+ {
+ if (studsPerTile.x != value && value > 0.0f)
+ {
+ studsPerTile.x = value;
+ raisePropertyChanged(prop_StudsPerTileU);
+ }
+ }
+
+ void Texture::setStudsPerTileV(float value)
+ {
+ if (studsPerTile.y != value && value > 0.0f)
+ {
+ studsPerTile.y = value;
+ raisePropertyChanged(prop_StudsPerTileV);
+ }
+ }
+
+ Texture::Texture()
+ : studsPerTile(2.0f, 2.0f)
+ {
+ setName("Texture");
+ }
};
\ No newline at end of file
diff --git a/Client/App/v8datamodel/FaceInstance.cpp b/Client/App/v8datamodel/FaceInstance.cpp
index 225c61cb..14f7a8b3 100644
--- a/Client/App/v8datamodel/FaceInstance.cpp
+++ b/Client/App/v8datamodel/FaceInstance.cpp
@@ -22,12 +22,6 @@ namespace RBX
}
}
-
- NormalId FaceInstance::getFace() const
- {
- return face;
- }
-
bool FaceInstance::askSetParent(const Instance* instance) const
{
return fastDynamicCast(instance) != NULL;
diff --git a/Client/RbxView/FileMesh.cpp b/Client/RbxView/FileMesh.cpp
index 1c1324ea..db8a3694 100644
--- a/Client/RbxView/FileMesh.cpp
+++ b/Client/RbxView/FileMesh.cpp
@@ -1,10 +1,61 @@
#include "FileMesh.h"
#include
+#include "util/ContentProvider.h"
+#include
namespace RBX
{
namespace View
{
+ //44.36% matching
+ //a *start*
+ bool FileMesh::loadFromMeshFile(const G3D::Vector3 &scale, const RBX::MeshId meshFile)
+ {
+ std::string fileName;
+ int num_faces;
+ if (!RBX::ContentProvider::singleton().requestContentFile(meshFile, fileName))
+ {
+ return false;
+ }
+ Render::Mesh::Level* level = new Render::Mesh::Level(G3D::RenderDevice::TRIANGLES);
+ levels.append(level);
+
+ FILE* fp = fopen(fileName.c_str(), "r");
+ fscanf(fp, "version 1.00\n");
+ fscanf(fp, "%d\n", num_faces);
+
+ std::vector verts;
+ for (int i = 0; i < num_faces; i++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ float vtxX, vtxY, vtxZ, normX, normY, normZ, texU, texV, texW;
+ fscanf(fp, "[%f,%f,%f][%f,%f,%f][%f,%f,%f]", &vtxX, &vtxY, &vtxZ, &normX, &normY, &normZ, &texU, &texV, &texW);
+ G3D::Vector3 vert(vtxX * 0.5f, vtxY * 0.5f, vtxY * 0.5f);
+ G3D::Vector2 tex(texU, 1.0f - texV);
+ G3D::Vector3 norm(normX, normY, normZ);
+ vert *= scale;
+ unsigned int vtx1 = allocVertex(vert, norm, tex, true);
+ verts.push_back(vtx1);
+ unsigned int vtx2 = allocVertex(i, 1);
+ verts.push_back(vtx2);
+ unsigned int vtx3 = allocVertex(i, 1);
+ verts.push_back(vtx3);
+ unsigned int vtx4 = allocVertex(i, 1);
+ verts.push_back(vtx4);
+ level->indexArray.append(vtx1, vtx2, vtx3, vtx4);
+
+ for (int k = 0; k < 3; k++)
+ {
+ freeVertex(verts[k]);
+ }
+
+ verts.clear();
+ }
+ }
+ return true;
+ }
+
G3D::ReferenceCountedPointer FileMesh::create(const G3D::Vector3& scale, const MeshId meshFile)
{
FileMesh* newMesh = new FileMesh;
diff --git a/Client/RbxView/HeadMesh.cpp b/Client/RbxView/HeadMesh.cpp
index be956568..5dd2c929 100644
--- a/Client/RbxView/HeadMesh.cpp
+++ b/Client/RbxView/HeadMesh.cpp
@@ -5,7 +5,11 @@ class CylinderTransform
const float bevel;
const int halfVertexCount;
public:
- CylinderTransform(float, int);
+ CylinderTransform(float bevel, int halfVertexCount)
+ : bevel(bevel),
+ halfVertexCount(halfVertexCount)
+ {
+ }
void operator()(G3D::Vector3&, G3D::Vector3&, G3D::Vector2&, const G3D::Vector3&, const G3D::Vector2int16&);
};
@@ -19,3 +23,98 @@ class EndcapTransform
}
void operator()(G3D::Vector3&, G3D::Vector3&, G3D::Vector2&, const G3D::Vector3&, const G3D::Vector2int16&);
};
+
+//72.86% matching
+//Weird stuff with the size setting
+inline G3D::Vector3 getSizeMax(const G3D::Vector3& v) {
+ float maxSizeX = G3D::min(v.x, v.z);
+ float maxSizeZ = G3D::min(v.x, v.z);
+
+ G3D::Vector3 newVec;
+ newVec.x = maxSizeX;
+ newVec.y = v.y;
+ newVec.z = maxSizeZ;
+
+ return newVec;
+}
+
+HeadBuilder::HeadBuilder(G3D::ReferenceCountedPointer level, G3D::Vector3 size, RBX::View::RenderSurfaceTypes surfaceTypes, size_t elements, float bevel)
+: LevelBuilder(level, getSizeMax(size), surfaceTypes),
+ elements(elements),
+ bevel(bevel)
+{
+}
+
+void HeadBuilder::buildTop(RBX::View::LevelBuilder::Purpose purpose) {
+ int e = elements;
+ buildFace(EndcapTransform(bevel), G3D::Vector2int16(e, e), purpose);
+}
+
+void HeadBuilder::buildBottom(RBX::View::LevelBuilder::Purpose purpose) {
+ int e = elements;
+ buildFace(EndcapTransform(bevel), G3D::Vector2int16(e, e), purpose);
+}
+
+//77.81% matching
+void HeadBuilder::buildLeft(RBX::View::LevelBuilder::Purpose purpose) {
+ int e = elements;
+ buildFace(CylinderTransform(bevel, e / 2), G3D::Vector2int16(e, e), purpose);
+}
+
+//77.81% matching
+void HeadBuilder::buildRight(RBX::View::LevelBuilder::Purpose purpose) {
+ int e = elements;
+ buildFace(CylinderTransform(bevel, e / 2), G3D::Vector2int16(e, e), purpose);
+}
+
+//77.81% matching
+void HeadBuilder::buildFront(RBX::View::LevelBuilder::Purpose purpose) {
+ int e = elements;
+ buildFace(CylinderTransform(bevel, e / 2), G3D::Vector2int16(e, e), purpose);
+};
+
+//77.81% matching
+void HeadBuilder::buildBack(RBX::View::LevelBuilder::Purpose purpose) {
+ int e = elements;
+ buildFace(CylinderTransform(bevel, e / 2), G3D::Vector2int16(e, e), purpose);
+}
+
+namespace RBX {
+ namespace View {
+
+ HeadMesh::HeadMesh(const G3D::Vector3& size, NormalId decalFace)
+ {
+ float bevel = G3D::min(size.x, size.z);
+ bevel *= 0.25f;
+ Render::Mesh::Level* level = new Render::Mesh::Level(G3D::RenderDevice::QUADS);
+ levels.push_back(level);
+
+ HeadBuilder builder(level, size, RenderSurfaceTypes(), 9, bevel);
+ builder.buildFace(decalFace, LevelBuilder::Decal);
+ }
+
+ HeadMesh::HeadMesh(const G3D::Vector3& size, NormalId textureFace, const G3D::Vector2& studsPerTile)
+ {
+ float bevel = G3D::min(size.x, size.z);
+ bevel *= 0.25f;
+ Render::Mesh::Level* level = new Render::Mesh::Level(G3D::RenderDevice::QUADS);
+ levels.push_back(level);
+
+ HeadBuilder builder(level, size, RenderSurfaceTypes(), 9, bevel);
+ builder.textureScale = mapToUvw_Legacy(size, textureFace).xy() * 2.0f / studsPerTile;
+
+ builder.buildFace(textureFace, LevelBuilder::Decal);
+ }
+
+ HeadMesh::HeadMesh(const G3D::Vector3& partSize, RenderSurfaceTypes surfaceTypes)
+ {
+ float bevel = G3D::min(partSize.x, partSize.z);
+ bevel *= 0.25f;
+ levels.push_back(new Render::Mesh::Level(G3D::RenderDevice::QUADS));
+
+ G3D::ReferenceCountedPointer level = levels.last();
+ HeadBuilder builder(level, partSize, surfaceTypes, 9, bevel);
+ builder.build(LevelBuilder::Surface);
+ }
+ };
+};
\ No newline at end of file
diff --git a/Client/RbxView/MaterialFactory.h b/Client/RbxView/MaterialFactory.h
index 0149eaea..f78ed5c4 100644
--- a/Client/RbxView/MaterialFactory.h
+++ b/Client/RbxView/MaterialFactory.h
@@ -9,6 +9,7 @@ namespace RBX
{
class MaterialFactory
{
+ public:
struct Attributes
{
const BrickColor color;
diff --git a/Client/RbxView/Part.cpp b/Client/RbxView/Part.cpp
index fd4f341c..d8ae825e 100644
--- a/Client/RbxView/Part.cpp
+++ b/Client/RbxView/Part.cpp
@@ -1 +1,652 @@
-#include "stdafx.h"
+#include "Part.h"
+#include "v8tree/Instance.h"
+#include "reflection/property.h"
+#include "v8datamodel/Surfaces.h"
+#include "v8datamodel/CustomMesh.h"
+#include "v8datamodel/Workspace.h"
+#include "v8datamodel/FaceInstance.h"
+#include "v8datamodel/Decal.h"
+#include
+#include
+#include
+#include "RbxView/View.h"
+#include "RenderLib/RenderScene.h"
+#include "QuadVolume.h"
+#include "BrickMesh.h"
+#include "HeadMesh.h"
+#include "CylinderMesh.h"
+#include "FileMesh.h"
+#include "SphereMesh.h"
+#include "PBBMesh.h"
+#include "WedgeMesh.h"
+#include "TorsoMesh.h"
+#include "MeshFactory.h"
+#include "MaterialFactory.h"
+
+namespace RBX {
+ namespace View {
+ const G3D::CoordinateFrame& PartChunk::cframe()
+ {
+ coordinateFrame = partInstance->getCoordinateFrame();
+ return coordinateFrame;
+ }
+
+ void PartChunk::onSpecialShapeChanged()
+ {
+ invalidateMesh();
+ invalidateMaterial();
+ }
+
+ G3D::ReferenceCountedPointer PartChunk::getMesh()
+ {
+ if (mesh.isNull())
+ updateMesh();
+
+ return mesh;
+ }
+
+ void PartChunk::onChildRemoved(boost::shared_ptr child)
+ {
+ if (child.px == (Instance*)specialShape)
+ {
+ shapePropertyChangedConnection.disconnect();
+ specialShape = NULL;
+ invalidateMesh();
+ }
+ }
+
+ void PartChunk::onPropertyChanged(const RBX::Reflection::PropertyDescriptor* descriptor)
+ {
+ if (descriptor == &RBX::PartInstance::prop_Size)
+ {
+ invalidateMesh();
+ invalidateMaterial();
+ return;
+ }
+
+ //this could be an inline
+ if (descriptor == &RBX::PartInstance::prop_shapeXml) {
+ invalidateMesh();
+ return;
+ } else if (RBX::Surfaces::isSurfaceDescriptor(*descriptor)) {
+ invalidateMesh();
+ }
+ }
+
+ //97.33% matching
+ void PartChunk::onChildAdded(boost::shared_ptr child)
+ {
+ RBX::SpecialShape* shape = RBX::Instance::fastDynamicCast(child.get());
+ if (shape) {
+ specialShape = shape;
+ //This line is the cause
+ //If I move the boost::slot, that causes even more mismatches
+ shapePropertyChangedConnection = RBX::Instance::event_propertyChanged.connect(specialShape, boost::slot>(boost::bind(&PartChunk::onSpecialShapeChanged, this)));
+ invalidateMesh();
+ }
+ }
+
+ //99.81% matching
+ void PartChunk::onAncestorChanged(boost::shared_ptr ancestor)
+ {
+ RBX::Workspace* workspace = RBX::Workspace::findWorkspace(partInstance.px);
+ RBX::Instance* parent;
+
+ //the issue seems to be lie with the parent = partInstance.get()->getParent(), however the parent check needs to be after the workspace check
+ if (!workspace || (parent = partInstance.get()->getParent(), workspace == parent) || !parent || !parent->isDescendentOf(workspace))
+ {
+ view->sceneManager->removeModel(this);
+ }
+ }
+
+ PartChunk::~PartChunk() {}
+
+ void PartChunk::invalidateMesh()
+ {
+ mesh = NULL;
+ view->sceneManager->invalidateModel(this, partInstance.get()->getCanAggregate());
+ }
+
+ void PartChunk::invalidateMaterial()
+ {
+ material = NULL;
+ materialInvalid = true;
+ view->sceneManager->invalidateModel(this, partInstance.get()->getCanAggregate());
+ }
+
+ PartChunk::PartChunk(float polygonOffset, const boost::shared_ptr &partInstance, RBX::View::View *view)
+ : Chunk(polygonOffset),
+ coordinateFrame(),
+ childAddedConnection(),
+ childRemovedConnection(),
+ ancestorChangedConnection(),
+ propertyChangedConnection(),
+ shapePropertyChangedConnection(),
+ partInstance(partInstance),
+ material(),
+ materialInvalid(true),
+ mesh(),
+ view(view),
+ specialShape()
+ {
+ view->sceneManager->addModel(this);
+ childAddedConnection = RBX::Instance::event_childAdded.connect(specialShape, boost::slot)>>(boost::bind(&PartChunk::onChildAdded, this, _1)));
+ childRemovedConnection = RBX::Instance::event_childRemoved.connect(specialShape, boost::slot)>>(boost::bind(&PartChunk::onChildRemoved, this, _1)));
+ ancestorChangedConnection = RBX::Instance::event_ancestryChanged.connect(specialShape, boost::slot)>>(boost::bind(&PartChunk::onAncestorChanged, this, _1)));
+ propertyChangedConnection = RBX::Instance::event_propertyChanged.connect(specialShape, boost::slot>(boost::bind(&PartChunk::onPropertyChanged, this, _1)));
+ //RBX::Instance::visitChildren call
+ }
+
+ bool Part::usesMegaTexture() const
+ {
+ if (!specialShape)
+ {
+ RBX::PartInstance* px = partInstance.get();
+
+ if (px->getPartType() != RBX::Part::BLOCK_PART)
+ return false;
+
+ G3D::Vector3 size = px->getPartSizeXml();
+ return primaryComponent(size) < 30.0f;
+ }
+
+ return false;
+ }
+
+ void Part::onPropertyChanged(const RBX::Reflection::PropertyDescriptor *descriptor)
+ {
+ if (descriptor == &RBX::PartInstance::prop_Size)
+ {
+ invalidateMesh();
+ invalidateMaterial();
+ } else if (descriptor == &RBX::PartInstance::prop_shapeXml)
+ {
+ invalidateMesh();
+ } else if (RBX::Surfaces::isSurfaceDescriptor(*descriptor))
+ {
+ invalidateMesh();
+ }
+
+ if (descriptor == &RBX::PartInstance::prop_Color)
+ {
+ if (usesMegaTexture())
+ {
+ invalidateMesh();
+ invalidateMaterial();
+ return;
+ }
+ } else if (descriptor != &RBX::PartInstance::prop_Transparency && descriptor != &RBX::PartInstance::prop_Reflectance)
+ return;
+
+ invalidateMaterial();
+ }
+
+ void Part::onEvent(const RBX::PartInstance *source, RBX::CanAggregateChanged event)
+ {
+ //having to do with RBX::Notifier in specialShape
+ }
+
+ //73.90% matching
+ //pretty messy
+ //setSurfaceType for RenderSurfaceTypes will need to be defined for 100%
+ //also the switch case could be apart of an inline? not too sure
+ void Part::updateMesh()
+ {
+ RenderSurfaceType curSurface;
+
+ RenderSurfaceTypes surfaceTypes;
+
+ switch(partInstance.get()->getSurfaces()[NORM_X].getSurfaceType())
+ {
+ case STUDS:
+ curSurface = STUDS;
+ break;
+ case INLET:
+ curSurface = INLET;
+ break;
+ case WELD:
+ curSurface = WELD;
+ break;
+ case GLUE:
+ curSurface = GLUE;
+ break;
+ default:
+ curSurface = FLAT;
+ break;
+ }
+ surfaceTypes.setSurfaceType(NORM_X, curSurface);
+ switch(partInstance.get()->getSurfaces()[NORM_Y].getSurfaceType())
+ {
+ case STUDS:
+ curSurface = STUDS;
+ break;
+ case INLET:
+ curSurface = INLET;
+ break;
+ case WELD:
+ curSurface = WELD;
+ break;
+ case GLUE:
+ curSurface = GLUE;
+ break;
+ default:
+ curSurface = FLAT;
+ break;
+ }
+ surfaceTypes.setSurfaceType(NORM_Y, curSurface);
+ switch(partInstance.get()->getSurfaces()[NORM_Z].getSurfaceType())
+ {
+ case STUDS:
+ curSurface = STUDS;
+ break;
+ case INLET:
+ curSurface = INLET;
+ break;
+ case WELD:
+ curSurface = WELD;
+ break;
+ case GLUE:
+ curSurface = GLUE;
+ break;
+ default:
+ curSurface = FLAT;
+ break;
+ }
+ surfaceTypes.setSurfaceType(NORM_Z, curSurface);
+ switch(partInstance.get()->getSurfaces()[NORM_X_NEG].getSurfaceType())
+ {
+ case STUDS:
+ curSurface = STUDS;
+ break;
+ case INLET:
+ curSurface = INLET;
+ break;
+ case WELD:
+ curSurface = WELD;
+ break;
+ case GLUE:
+ curSurface = GLUE;
+ break;
+ default:
+ curSurface = FLAT;
+ break;
+ }
+ surfaceTypes.setSurfaceType(NORM_X_NEG, curSurface);
+ switch(partInstance.get()->getSurfaces()[NORM_Y_NEG].getSurfaceType())
+ {
+ case STUDS:
+ curSurface = STUDS;
+ break;
+ case INLET:
+ curSurface = INLET;
+ break;
+ case WELD:
+ curSurface = WELD;
+ break;
+ case GLUE:
+ curSurface = GLUE;
+ break;
+ default:
+ curSurface = FLAT;
+ break;
+ }
+ surfaceTypes.setSurfaceType(NORM_Y_NEG, curSurface);
+ switch(partInstance.get()->getSurfaces()[NORM_Z_NEG].getSurfaceType())
+ {
+ case STUDS:
+ curSurface = STUDS;
+ break;
+ case INLET:
+ curSurface = INLET;
+ break;
+ case WELD:
+ curSurface = WELD;
+ break;
+ case GLUE:
+ curSurface = GLUE;
+ break;
+ default:
+ curSurface = FLAT;
+ break;
+ }
+ surfaceTypes.setSurfaceType(NORM_Z_NEG, curSurface);
+
+ G3D::Vector3 size = partInstance.get()->getPartSizeXml();
+
+ if (usesMegaTexture())
+ {
+ mesh = RBX::View::BrickMesh::create(size, surfaceTypes, partInstance.get()->getColor());
+ } else if (partInstance.get()->getPartType())
+ {
+ switch (partInstance.get()->getPartType())
+ {
+ case RBX::Part::CYLINDER_PART:
+ mesh = RBX::View::MeshFactory::create(size, surfaceTypes);
+ break;
+ case RBX::Part::BLOCK_PART:
+ mesh = RBX::View::MeshFactory::create(size, surfaceTypes);
+ break;
+ case RBX::Part::BALL_PART:
+ mesh = RBX::View::MeshFactory::create(size, surfaceTypes);
+ break;
+ }
+ }
+
+ if (specialShape)
+ {
+ size *= specialShape->getScale();
+ switch(specialShape->getMeshType())
+ {
+ case SpecialShape::WEDGE_MESH:
+ mesh = RBX::View::MeshFactory::create(size, surfaceTypes);
+ break;
+ case SpecialShape::HEAD_MESH:
+ mesh = RBX::View::MeshFactory::create(size, surfaceTypes);
+ break;
+ case SpecialShape::TORSO_MESH:
+ mesh = RBX::View::MeshFactory::create(size, surfaceTypes);
+ break;
+ case SpecialShape::SPHERE_MESH:
+ mesh = RBX::View::MeshFactory::create(size, surfaceTypes);
+ break;
+ case SpecialShape::CYLINDER_MESH:
+ mesh = RBX::View::MeshFactory::create(size, surfaceTypes);
+ break;
+ case SpecialShape::BRICK_MESH:
+ mesh = RBX::View::MeshFactory::create(size, surfaceTypes);
+ break;
+ case SpecialShape::FILE_MESH:
+ mesh = RBX::View::FileMesh::create(size, specialShape->getMeshId());
+ break;
+ }
+ }
+
+ radius = sqrt(2.0f) * 0.5 * primaryComponent(size);
+ }
+
+ //34.14% matching
+ //also messy
+ G3D::ReferenceCountedPointer Part::getMaterial()
+ {
+ if (materialInvalid)
+ {
+ RBX::PartInstance* partInstancePX = partInstance.get();
+ RBX::View::MaterialFactory::Attributes attributes = {partInstancePX->getColor(), partInstancePX->getTransparencyUi(), partInstancePX->getReflectance()};
+ if (usesMegaTexture())
+ {
+ material = view->materialFactory->getMegaMaterial(attributes);
+ } else if (!specialShape || specialShape->getMeshType() != SpecialShape::FILE_MESH)
+ {
+ material = view->materialFactory->getMaterial(attributes);
+ return material;
+ }
+
+ std::string texFile;
+ if (RBX::ContentProvider::singleton().requestContentFile(specialShape->getTextureId(), texFile))
+ {
+ G3D::Color3 vertColor = specialShape->getVertColor();
+ float alpha = specialShape->getAlpha();
+
+ material = new RBX::Render::Material();
+ RBX::Render::TextureProxy* texProxy = new RBX::Render::TextureProxy(*view->textureManager.get(), texFile, false);
+ material.getPointer()->appendLevel(texProxy, vertColor, 0.0f, 0.1f, 0.0f, partInstance.get()->getTransparencyUi());
+ } else
+ {
+ material = view->materialFactory->getMaterial(attributes);
+ }
+ materialInvalid = false;
+ return material;
+ }
+ return material;
+ }
+
+ //78.70% matching
+ Part::~Part() {
+ //has Notifier remove listener
+ }
+
+ void Decal::onDecalPropertyChanged(const RBX::Reflection::PropertyDescriptor* descriptor)
+ {
+ if (descriptor == &FaceInstance::prop_Face)
+ {
+ invalidateMesh();
+ } else if (descriptor == &RBX::Decal::prop_Texture || descriptor == &RBX::Decal::prop_Specular || descriptor == &RBX::Decal::prop_Shiny)
+ {
+ invalidateMaterial();
+ }
+ }
+
+
+ //99.88% matching
+ void Decal::onDecalAncestorChanged(boost::shared_ptr ancestor)
+ {
+ RBX::Workspace* workspace = RBX::Workspace::findWorkspace(decal.get());
+ RBX::Instance* parent;
+
+ //same error as the PartChunk variant
+ if (!workspace || (parent = decal.get()->getParent(), workspace == parent) || !parent || !parent->isDescendentOf(workspace))
+ {
+ view->sceneManager->removeModel(this);
+ }
+ }
+
+ //38.85% matching
+ //would probably be way higher if it weren't for the fact that the part type switch case is above where it should be
+ //i legit don't know why it isn't in its proper position
+ void Decal::updateMesh()
+ {
+ if (partInstance.get())
+ {
+ G3D::Vector3 size = partInstance->getPartSizeXml();
+ if (specialShape)
+ {
+ size *= specialShape->getScale();
+ }
+
+ if (partInstance->getPartType())
+ {
+ switch (partInstance->getPartType())
+ {
+ case RBX::Part::CYLINDER_PART:
+ mesh = RBX::View::MeshFactory::createDecal(size, decal->getFace());
+ break;
+ case RBX::Part::BLOCK_PART:
+ mesh = RBX::View::MeshFactory::createDecal(size, decal->getFace());
+ break;
+ case RBX::Part::BALL_PART:
+ mesh = RBX::View::MeshFactory::createDecal(size, decal->getFace());
+ break;
+ }
+ }
+
+ if (specialShape)
+ {
+ switch(specialShape->getMeshType())
+ {
+ case SpecialShape::WEDGE_MESH:
+ mesh = RBX::View::MeshFactory::createDecal(size, decal->getFace());
+ break;
+ case SpecialShape::HEAD_MESH:
+ mesh = RBX::View::MeshFactory::createDecal(size, decal->getFace());
+ break;
+ case SpecialShape::TORSO_MESH:
+ mesh = RBX::View::MeshFactory::createDecal(size, decal->getFace());
+ break;
+ case SpecialShape::SPHERE_MESH:
+ mesh = RBX::View::MeshFactory::createDecal(size, decal->getFace());
+ break;
+ case SpecialShape::CYLINDER_MESH:
+ mesh = RBX::View::MeshFactory::createDecal(size, decal->getFace());
+ break;
+ case SpecialShape::BRICK_MESH:
+ mesh = RBX::View::MeshFactory::createDecal(size, decal->getFace());
+ break;
+ default:
+ break;
+ }
+ }
+ radius = sqrt(2.0f) * 0.5 * primaryComponent(size);
+ }
+ }
+
+ //75.61% matching
+ G3D::ReferenceCountedPointer Decal::getMaterial()
+ {
+ if (materialInvalid)
+ {
+ std::string textureFile;
+ if (RBX::ContentProvider::singleton().requestContentFile(decal->getTexture(), textureFile))
+ {
+ RBX::Render::Material* newMat = new RBX::Render::Material();
+ material = newMat;
+ RBX::Render::TextureProxy* texProxy = new RBX::Render::TextureProxy(*view->textureManager.get(), textureFile, false);
+ material->appendLevel(texProxy, G3D::Color3::WHITE, decal->getSpecular(), decal->getShiny(), 0.0f, 0.0f);
+ materialInvalid = false;
+ }
+ }
+
+ return material;
+ }
+
+ Decal::~Decal() {}
+
+ //75.92% matching
+ //more boost connection problems
+ Decal::Decal(RBX::Decal &decal, RBX::PartInstance &partInstance, RBX::View::View *view)
+ : PartChunk(RBX::Render::Chunk::DECAL_OFFSET, RBX::shared_from(&partInstance), view),
+ decal(RBX::shared_from(&decal)),
+ decalAncestorChangedConnection(),
+ decalPropertyChangedConnection()
+ {
+ decalAncestorChangedConnection = RBX::Instance::event_ancestryChanged.connect(&decal, boost::slot)>>(boost::bind(&Decal::onDecalAncestorChanged, this, _1)));
+ decalPropertyChangedConnection = RBX::Instance::event_propertyChanged.connect(&decal, boost::slot>(boost::bind(&Decal::onDecalPropertyChanged, this, _1)));
+ }
+
+ //99.88% matching
+ void Texture::onTextureAncestorChanged(boost::shared_ptr ancestor)
+ {
+ RBX::Workspace* workspace = RBX::Workspace::findWorkspace(texture.get());
+ RBX::Instance* parent;
+
+ //same error as the PartChunk variant
+ if (!workspace || (parent = texture.get()->getParent(), workspace == parent) || !parent || !parent->isDescendentOf(workspace))
+ {
+ view->sceneManager->removeModel(this);
+ }
+ }
+
+ //99.71% matching
+ //Branching :pray:
+ void Texture::onTexturePropertyChanged(const RBX::Reflection::PropertyDescriptor *descriptor)
+ {
+ if (descriptor != &FaceInstance::prop_Face)
+ {
+ if (descriptor == &RBX::Decal::prop_Texture || descriptor == &RBX::Decal::prop_Specular || descriptor == &RBX::Decal::prop_Shiny)
+ {
+ invalidateMaterial();
+ return;
+ }
+ }
+ if (descriptor != &RBX::Texture::prop_StudsPerTileU && descriptor != &RBX::Texture::prop_StudsPerTileV)
+ {
+ return;
+ }
+ invalidateMesh();
+ }
+
+ //75.62% matching
+ G3D::ReferenceCountedPointer Texture::getMaterial()
+ {
+ if (materialInvalid)
+ {
+ std::string textureFile;
+ if (RBX::ContentProvider::singleton().requestContentFile(texture->getTexture(), textureFile))
+ {
+ RBX::Render::Material* newMat = new RBX::Render::Material();
+ material = newMat;
+ RBX::Render::TextureProxy* texProxy = new RBX::Render::TextureProxy(*view->textureManager.get(), textureFile, true);
+ material->appendLevel(texProxy, G3D::Color3::WHITE, texture->getSpecular(), texture->getShiny(), 0.0f, 0.0f);
+ materialInvalid = false;
+ }
+ }
+
+ return material;
+ }
+
+ Texture::~Texture()
+ {
+ }
+
+ //38.85% matching
+ //just like decals
+ void Texture::updateMesh()
+ {
+ if (partInstance.get())
+ {
+ G3D::Vector3 size = partInstance->getPartSizeXml();
+ if (specialShape)
+ {
+ size *= specialShape->getScale();
+ }
+
+ if (partInstance->getPartType())
+ {
+ switch (partInstance->getPartType())
+ {
+ case RBX::Part::CYLINDER_PART:
+ mesh = RBX::View::MeshFactory::createTexture(size, texture->getFace(), texture->getStudsPerTile());
+ break;
+ case RBX::Part::BLOCK_PART:
+ mesh = RBX::View::MeshFactory::createTexture(size, texture->getFace(), texture->getStudsPerTile());
+ break;
+ case RBX::Part::BALL_PART:
+ mesh = RBX::View::MeshFactory::createTexture(size, texture->getFace(), texture->getStudsPerTile());
+ break;
+ }
+ }
+
+ if (specialShape)
+ {
+ switch(specialShape->getMeshType())
+ {
+ case SpecialShape::WEDGE_MESH:
+ mesh = RBX::View::MeshFactory::createTexture(size, texture->getFace(), texture->getStudsPerTile());
+ break;
+ case SpecialShape::HEAD_MESH:
+ mesh = RBX::View::MeshFactory::createTexture(size, texture->getFace(), texture->getStudsPerTile());
+ break;
+ case SpecialShape::TORSO_MESH:
+ mesh = RBX::View::MeshFactory::createTexture(size, texture->getFace(), texture->getStudsPerTile());
+ break;
+ case SpecialShape::SPHERE_MESH:
+ mesh = RBX::View::MeshFactory::createTexture(size, texture->getFace(), texture->getStudsPerTile());
+ break;
+ case SpecialShape::CYLINDER_MESH:
+ mesh = RBX::View::MeshFactory::createTexture(size, texture->getFace(), texture->getStudsPerTile());
+ break;
+ case SpecialShape::BRICK_MESH:
+ mesh = RBX::View::MeshFactory::createTexture(size, texture->getFace(), texture->getStudsPerTile());
+ break;
+ default:
+ break;
+ }
+ }
+ radius = sqrt(2.0f) * 0.5 * primaryComponent(size);
+ }
+ }
+
+
+ //75.92%
+ //similar to decal's
+ Texture::Texture(RBX::Texture &texture, RBX::PartInstance &parentPart, RBX::View::View *view)
+ : PartChunk(RBX::Render::Chunk::TEXTURE_OFFSET, RBX::shared_from(&parentPart), view),
+ texture(RBX::shared_from(&texture)),
+ textureAncestorChangedConnection(),
+ texturePropertyChangedConnection()
+ {
+ textureAncestorChangedConnection = RBX::Instance::event_ancestryChanged.connect(&texture, boost::slot)>>(boost::bind(&Texture::onTextureAncestorChanged, this, _1)));
+ texturePropertyChangedConnection = RBX::Instance::event_propertyChanged.connect(&texture, boost::slot>(boost::bind(&Texture::onTexturePropertyChanged, this, _1)));
+ }
+
+ };
+};
\ No newline at end of file
diff --git a/Client/RbxView/Part.h b/Client/RbxView/Part.h
index e69de29b..3198a182 100644
--- a/Client/RbxView/Part.h
+++ b/Client/RbxView/Part.h
@@ -0,0 +1,113 @@
+#pragma once
+
+#include "RenderLib/Chunk.h"
+#include "v8datamodel/PartInstance.h"
+#include "reflection/reflection.h"
+#include
+#include
+#include
+
+namespace RBX
+{
+ class SpecialShape;
+ class Instance;
+ class Decal;
+ class Texture;
+
+ namespace View
+ {
+ class View;
+
+ class __declspec(novtable) PartChunk : public RBX::Render::Chunk
+ {
+ private:
+ G3D::CoordinateFrame coordinateFrame;
+ boost::signals::scoped_connection childAddedConnection;
+ boost::signals::scoped_connection childRemovedConnection;
+ boost::signals::scoped_connection ancestorChangedConnection;
+ boost::signals::scoped_connection propertyChangedConnection;
+ boost::signals::scoped_connection shapePropertyChangedConnection;
+ protected:
+ boost::shared_ptr partInstance;
+ G3D::ReferenceCountedPointer material;
+ bool materialInvalid;
+ G3D::ReferenceCountedPointer mesh;
+ View* view;
+ RBX::SpecialShape* specialShape;
+ private:
+ virtual void updateMesh() = 0;
+ public:
+ virtual ~PartChunk(); //May not actually exist
+ virtual bool castShadows() const
+ {
+ return true;
+ }
+ virtual bool cullable() const
+ {
+ return true;
+ }
+ protected:
+ PartChunk(float polygonOffset, const boost::shared_ptr& partInstance, View* view);
+ void invalidateMaterial();
+ void invalidateMesh();
+ virtual void onPropertyChanged(const RBX::Reflection::PropertyDescriptor* descriptor);
+ virtual G3D::ReferenceCountedPointer getMesh();
+ virtual const G3D::CoordinateFrame& cframe();
+ private:
+ void onAncestorChanged(boost::shared_ptr);
+ void onChildAdded(boost::shared_ptr);
+ void onChildRemoved(boost::shared_ptr);
+ void onSpecialShapeChanged();
+ };
+
+ class Part : public PartChunk, public RBX::Listener
+ {
+ public:
+ Part(const boost::shared_ptr& partInstance, RBX::View::View* view);
+ virtual ~Part();
+ virtual G3D::ReferenceCountedPointer getMaterial();
+ protected:
+ virtual void onPropertyChanged(const RBX::Reflection::PropertyDescriptor* descriptor);
+ virtual void onEvent(const RBX::PartInstance* source, RBX::CanAggregateChanged event);
+ private:
+ bool usesMegaTexture() const;
+ virtual void updateMesh();
+ };
+
+ class Decal : public PartChunk
+ {
+ private:
+ boost::shared_ptr decal;
+ boost::signals::scoped_connection decalAncestorChangedConnection;
+ boost::signals::scoped_connection decalPropertyChangedConnection;
+ public:
+ Decal(RBX::Decal& decal, RBX::PartInstance& partInstance, RBX::View::View* view);
+ virtual ~Decal();
+ virtual G3D::ReferenceCountedPointer getMaterial();
+ protected:
+ void onDecalPropertyChanged(const RBX::Reflection::PropertyDescriptor* descriptor);
+ void onDecalAncestorChanged(boost::shared_ptr ancestor);
+ private:
+ virtual void updateMesh();
+ };
+
+ class Texture : public PartChunk
+ {
+ private:
+ boost::shared_ptr texture;
+ boost::signals::scoped_connection textureAncestorChangedConnection;
+ boost::signals::scoped_connection texturePropertyChangedConnection;
+ public:
+ Texture(RBX::Texture& decal, RBX::PartInstance& parentPart, RBX::View::View* view);
+ virtual ~Texture();
+ virtual G3D::ReferenceCountedPointer getMaterial();
+ protected:
+ void onTexturePropertyChanged(const RBX::Reflection::PropertyDescriptor* descriptor);
+ void onTextureAncestorChanged(boost::shared_ptr ancestor);
+ private:
+ virtual void updateMesh();
+ };
+
+ float primaryComponent(const G3D::Vector3& v);
+ };
+};
\ No newline at end of file
diff --git a/Client/RbxView/QuadVolume.h b/Client/RbxView/QuadVolume.h
index eedeb3d2..c7f65337 100644
--- a/Client/RbxView/QuadVolume.h
+++ b/Client/RbxView/QuadVolume.h
@@ -24,7 +24,7 @@ namespace RBX
: data(0)
{
}
- void setSurfaceType(NormalId, RenderSurfaceType);
+ void setSurfaceType(NormalId normal, RenderSurfaceType type);
RenderSurfaceType getSurfaceType(NormalId) const;
unsigned int hashCode() const;
diff --git a/Client/RbxView/RbxView.vcproj b/Client/RbxView/RbxView.vcproj
index a44bfa6b..e17091f6 100644
--- a/Client/RbxView/RbxView.vcproj
+++ b/Client/RbxView/RbxView.vcproj
@@ -261,6 +261,10 @@
RelativePath=".\TorsoMesh.h"
>
+
+
diff --git a/Client/RbxView/include/RbxView/View.h b/Client/RbxView/include/RbxView/View.h
new file mode 100644
index 00000000..05ecdb0e
--- /dev/null
+++ b/Client/RbxView/include/RbxView/View.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include "ViewBase.h"
+#include
+#include
+#include
+#include
+#include