replace materials by name, hide material mode for now

This commit is contained in:
SamGondelman 2018-02-13 13:24:08 -08:00
parent ad40961864
commit 38290064c1
9 changed files with 126 additions and 30 deletions

View file

@ -346,8 +346,12 @@ void MaterialEntityItem::applyMaterial() {
}
void MaterialEntityItem::postAdd() {
removeMaterial();
applyMaterial();
// postAdd is called every time we are added to a new octree cell, but we only need to update the material the first time
if (!_hasBeenAddedToOctree) {
removeMaterial();
applyMaterial();
_hasBeenAddedToOctree = true;
}
}
void MaterialEntityItem::preDelete() {

View file

@ -19,7 +19,7 @@ class MaterialEntityItem : public EntityItem {
using Pointer = std::shared_ptr<MaterialEntityItem>;
public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
MaterialEntityItem(const EntityItemID& entityItemID);
ALLOW_INSTANTIATION // This class can be instantiated
@ -44,9 +44,9 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) override;
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) override;
void debugDump() const override;
@ -89,20 +89,39 @@ public:
void postParentFixup() override;
private:
// URL for this material. Currently, only JSON format is supported. Set to "userData" to use the user data to live edit a material.
// The following fields are supported in the JSON:
// strings:
// name (NOT YET USED)
// floats:
// opacity, roughness, metallic, scattering
// colors (arrays of 3 floats 0-1. Optional fourth value in array can be a boolean isSRGB):
// emissive, albedo, fresnel
// urls to textures:
// emissiveMap, albedoMap, metallicMap, roughnessMap, normalMap, occlusionMap, lightmapMap, scatteringMap
QString _materialURL;
// Type of material. "uv" or "projected". NOT YET IMPLEMENTED, only UV is used
MaterialMode _materialMode { UV };
// Priority for this material when applying it to its parent. Only the highest priority material will be used. Materials with the same priority are (essentially) randomly sorted.
// Base materials that come with models always have priority 0.
quint16 _priority { 0 };
// An identifier for choosing a submesh or submeshes within a parent. If in the format "mat::<string>", all submeshes with material name "<string>" will be replaced. Otherwise,
// parentMaterialID will be parsed as an unsigned int (strings not starting with "mat::" will parse to 0), representing the mesh index to modify.
QString _parentMaterialID { "0" };
// Offset position in UV-space of top left of material, (0, 0) to (1, 1)
glm::vec2 _materialPos { 0, 0 };
// How much to scale this material within its parent's UV-space
glm::vec2 _materialScale { 1, 1 };
// How much to rotate this material within its parent's UV-space (degrees)
float _materialRot { 0 };
NetworkMaterialResourcePointer _networkMaterial;
QHash<QString, std::shared_ptr<NetworkMaterial>> _materials;
std::vector<QString> _materialNames;
QString _currentMaterialName;
bool _retryApply { false };
bool _hasBeenAddedToOctree { false };
};

View file

@ -34,6 +34,7 @@ Material::Material() :
}
Material::Material(const Material& material) :
_name(material._name),
_key(material._key),
_textureMaps(material._textureMaps)
{
@ -50,6 +51,8 @@ Material::Material(const Material& material) :
Material& Material::operator= (const Material& material) {
QMutexLocker locker(&_textureMapsMutex);
_name = material._name;
_key = (material._key);
_textureMaps = (material._textureMaps);
_hasCalculatedTextureInfo = false;

View file

@ -359,6 +359,11 @@ public:
void setTextureTransforms(const Transform& transform);
const QString& getName() { return _name; }
protected:
QString _name { "" };
private:
mutable MaterialKey _key;
mutable UniformBufferView _schemaBuffer;

View file

@ -619,6 +619,7 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur
graphics::Material(*material._material),
_textures(MapChannel::NUM_MAP_CHANNELS)
{
_name = material.name;
if (!material.albedoTexture.filename.isEmpty()) {
auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP);
_albedoTransform = material.albedoTexture.transform;

View file

@ -828,6 +828,7 @@ void Model::removeFromScene(const render::ScenePointer& scene, render::Transacti
_modelMeshRenderItemIDs.clear();
_modelMeshRenderItemsMap.clear();
_modelMeshRenderItems.clear();
_modelMeshMaterialNames.clear();
_modelMeshRenderItemShapes.clear();
foreach(auto item, _collisionRenderItemsMap.keys()) {
@ -1456,6 +1457,7 @@ void Model::createVisibleRenderItemSet() {
Q_ASSERT(_modelMeshRenderItems.isEmpty());
_modelMeshRenderItems.clear();
_modelMeshMaterialNames.clear();
_modelMeshRenderItemShapes.clear();
Transform transform;
@ -1479,6 +1481,7 @@ void Model::createVisibleRenderItemSet() {
int numParts = (int)mesh->getNumParts();
for (int partIndex = 0; partIndex < numParts; partIndex++) {
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
_modelMeshMaterialNames.push_back(getGeometry()->getShapeMaterial(shapeID)->getName());
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i });
shapeID++;
}
@ -1524,11 +1527,24 @@ bool Model::isRenderable() const {
return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty());
}
std::vector<unsigned int> Model::getMeshIDsFromMaterialID(const QString& parentMaterialID) {
std::vector<unsigned int> toReturn;
// TODO: first, try to find all meshes with materials that match parentMaterialID as a string
std::vector<unsigned int> Model::getMeshIDsFromMaterialID(QString parentMaterialID) {
// try to find all meshes with materials that match parentMaterialID as a string
// if none, return parentMaterialID as a uint
toReturn.push_back(parentMaterialID.toUInt());
std::vector<unsigned int> toReturn;
const QString MATERIAL_NAME_PREFIX = "mat::";
if (parentMaterialID.startsWith(MATERIAL_NAME_PREFIX)) {
parentMaterialID.replace(0, MATERIAL_NAME_PREFIX.size(), QString(""));
for (int i = 0; i < _modelMeshMaterialNames.size(); i++) {
if (_modelMeshMaterialNames[i] == parentMaterialID) {
toReturn.push_back(i);
}
}
}
if (toReturn.empty()) {
toReturn.push_back(parentMaterialID.toUInt());
}
return toReturn;
}

View file

@ -438,6 +438,7 @@ protected:
render::ItemIDs _modelMeshRenderItemIDs;
using ShapeInfo = struct { int meshIndex; };
std::vector<ShapeInfo> _modelMeshRenderItemShapes;
std::vector<QString> _modelMeshMaterialNames;
bool _addedToScene { false }; // has been added to scene
bool _needsFixupInScene { true }; // needs to be removed/re-added to scene
@ -472,7 +473,7 @@ private:
void calculateTextureInfo();
std::vector<unsigned int> getMeshIDsFromMaterialID(const QString& parentMaterialID);
std::vector<unsigned int> getMeshIDsFromMaterialID(QString parentMaterialID);
};
Q_DECLARE_METATYPE(ModelPointer)

View file

@ -772,12 +772,19 @@
</div>
</fieldset>
<fieldset class="minor">
<div class="material-group material-section property dropdown">
<label>Material mode </label>
<select name="SelectMaterialMode" id="property-material-mode">
<option value="uv">UV space material</option>
<option value="projected">3D projected material</option>
</select>
<div class="material-group material-section property text" id="property-parent-material-id-string-container">
<label for="property-parent-material-id-string">Material Name to Replace </label>
<input type="text" id="property-parent-material-id-string">
</div>
<div class="material-group material-section property number" id="property-parent-material-id-number-container">
<label for="property-parent-material-id-number">Submesh to Replace </label>
<input type="number" min="0" step="1" value="0" id="property-parent-material-id-number">
</div>
<div class="material-group material-section property checkbox">
<input type="checkbox" id="property-parent-material-id-checkbox">
<label for="property-parent-material-id-checkbox">Select Submesh</label>
</div>
<div class="material-group material-section property number">
@ -785,12 +792,17 @@
<input type="number" id="property-priority" min="0">
</div>
<div class="material-group material-section property text">
<label>Parent Material ID </label>
<input type="text" id="property-parent-material-id">
</div>
<fieldset>
<!-- TODO: support 3D projected materials
<div class="material-group material-section property dropdown">
<label>Material mode </label>
<select name="SelectMaterialMode" id="property-material-mode">
<option value="uv">UV space material</option>
<option value="projected">3D projected material</option>
</select>
</div>
-->
<div class="material-group material-section property xy fstuple">
<label>Material Position </label>
<div class="tuple">

View file

@ -33,6 +33,8 @@ var KEY_P = 80; // Key code for letter p used for Parenting hotkey.
var colorPickers = [];
var lastEntityID = null;
var MATERIAL_PREFIX_STRING = "mat::";
function debugPrint(message) {
EventBridge.emitWebEvent(
JSON.stringify({
@ -509,6 +511,18 @@ function clearSelection() {
}
}
function showParentMaterialIDBox(number, elNumber, elString) {
if (number) {
$('#property-parent-material-id-number-container').show();
$('#property-parent-material-id-string-container').hide();
elString.value = "";
} else {
$('#property-parent-material-id-string-container').show();
$('#property-parent-material-id-number-container').hide();
elNumber.value = 0;
}
}
function loaded() {
openEventBridge(function() {
@ -632,9 +646,11 @@ function loaded() {
var elModelOriginalTextures = document.getElementById("property-model-original-textures");
var elMaterialURL = document.getElementById("property-material-url");
var elMaterialMode = document.getElementById("property-material-mode");
//var elMaterialMode = document.getElementById("property-material-mode");
var elPriority = document.getElementById("property-priority");
var elParentMaterialID = document.getElementById("property-parent-material-id");
var elParentMaterialIDString = document.getElementById("property-parent-material-id-string");
var elParentMaterialIDNumber = document.getElementById("property-parent-material-id-number");
var elParentMaterialIDCheckbox = document.getElementById("property-parent-material-id-checkbox");
var elMaterialPosX = document.getElementById("property-material-pos-x");
var elMaterialPosY = document.getElementById("property-material-pos-y");
var elMaterialScaleX = document.getElementById("property-material-scale-x");
@ -1127,10 +1143,18 @@ function loaded() {
elZTextureURL.value = properties.zTextureURL;
} else if (properties.type === "Material") {
elMaterialURL.value = properties.materialURL;
elMaterialMode.value = properties.materialMode;
setDropdownText(elMaterialMode);
//elMaterialMode.value = properties.materialMode;
//setDropdownText(elMaterialMode);
elPriority.value = properties.priority;
elParentMaterialID.value = properties.parentMaterialID;
if (properties.parentMaterialID.startsWith(MATERIAL_PREFIX_STRING)) {
elParentMaterialIDString.value = properties.parentMaterialID.replace(MATERIAL_PREFIX_STRING, "");
showParentMaterialIDBox(false, elParentMaterialIDNumber, elParentMaterialIDString);
elParentMaterialIDCheckbox.checked = false;
} else {
elParentMaterialIDNumber.value = parseInt(properties.parentMaterialID);
showParentMaterialIDBox(true, elParentMaterialIDNumber, elParentMaterialIDString);
elParentMaterialIDCheckbox.checked = true;
}
elMaterialPosX.value = properties.materialPos.x.toFixed(4);
elMaterialPosY.value = properties.materialPos.y.toFixed(4);
elMaterialScaleX.value = properties.materialScale.x.toFixed(4);
@ -1407,9 +1431,20 @@ function loaded() {
elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));
elMaterialURL.addEventListener('change', createEmitTextPropertyUpdateFunction('materialURL'));
elMaterialMode.addEventListener('change', createEmitTextPropertyUpdateFunction('materialMode'));
//elMaterialMode.addEventListener('change', createEmitTextPropertyUpdateFunction('materialMode'));
elPriority.addEventListener('change', createEmitNumberPropertyUpdateFunction('priority', 0));
elParentMaterialID.addEventListener('change', createEmitTextPropertyUpdateFunction('parentMaterialID'));
elParentMaterialIDString.addEventListener('change', function () { updateProperty("parentMaterialID", MATERIAL_PREFIX_STRING + this.value); });
elParentMaterialIDNumber.addEventListener('change', function () { updateProperty("parentMaterialID", this.value); });
elParentMaterialIDCheckbox.addEventListener('change', function () {
if (this.checked) {
updateProperty("parentMaterialID", elParentMaterialIDNumber.value);
showParentMaterialIDBox(true, elParentMaterialIDNumber, elParentMaterialIDString);
} else {
updateProperty("parentMaterialID", MATERIAL_PREFIX_STRING + elParentMaterialIDString.value);
showParentMaterialIDBox(false, elParentMaterialIDNumber, elParentMaterialIDString);
}
});
var materialPosChangeFunction = createEmitVec2PropertyUpdateFunction('materialPos', elMaterialPosX, elMaterialPosY);
elMaterialPosX.addEventListener('change', materialPosChangeFunction);