• Hi Guest!

    We are extremely excited to announce the release of our first Beta1.1 and the first release of our Public AddonKit!
    To participate in the Beta, a subscription to the Entertainer or Creator Tier is required. For access to the Public AddonKit you must be a Creator tier member. Once subscribed, download instructions can be found here.

    Click here for information and guides regarding the VaM2 beta. Join our Discord server for more announcements and community discussion about VaM2.
  • Hi Guest!

    VaM2 Resource Categories have now been added to the Hub! For information on posting VaM2 resources and details about VaM2 related changes to our Community Forums, please see our official announcement here.

VaM 1.x NPC CUA creation

Threads regarding the original VaM 1.x

ivam

Well-known member
Featured Contributor
Joined
Jun 30, 2022
Messages
95
Reactions
624
Hey guys,

something that always bothered me is the lack of NPCs on the hub/in general. If you want to create a crowded scene, you have a very hard time, finding some fitting characters to fill the scene. there are some CUA NPCs but they are all limited to their built-in poses. You can also use XPS models and pose them with plugins, but this is always very janky, the workflow is slow and they look terrible inside vam.

https://hub.virtamate.com/resources/texture-painting-tattoos-over-seams-using-blender.52855
A while ago this guide tought me that you can export your current character model from vam as an .obj file. It creates 2 .obj files - one in a t-pose and another in the specific pose, your character in vam has right now, including it's physical appearance. So I imported the textures, exported it to unity and then imported it to vam. So what should I say - it works flawlessly. You can add huge amounts of your previously created characters to vam without significant fps drops, plus they have the appearance you previously gave them to fit your scene.

The only problem is the fact that this process is insanely tedious and time consuming and your characters have no hair or clothes. I wanted to ask if someone has an idea to speed up the exporting process (export, and add textures) with a plugin, so you won't have to do all these steps from the guide by hand every time. I think it would be a great thing for vam to have an easy NPC-creation tool.

https://hub.virtamate.com/resources/hairexporter.26293
I also found this plugin to export hair, but it doesn't seem to work anymore (at least I couldn't get it to work) Does anyone have experience with hair export or can tell me how to do it right?

Is there also a way to "capture" the state, the clothing has and export them as well, so you can merge them to the NPC later?

Sorry, so many questions but I think if there is a way to make this more user friendly, we could have way cooler scenesthat won't feel so empty anymore. I am glad for everyone who might help here.
Have a nice day everyone.
 
Clothing for me is what kills that option, which would have been amazing to have more secondary persons at low cost. AFAIK there's no way to get the clothes out of VAM.
A workaround for situations where the POV has a very limited range is to use images or videos with transparency. Get the right ligting and POV and they look like they have depth.
 
yeah that's a fair point. But starting with nude NPCs is a beginning at least.

I spent the day creating an addon for blender (okay chatgpt did it) that automates the process of that guide, adds normal-maps and other missing textures and makes the model ready for export to unity. In Blender everything looks perfect, but when it comes to unity, I have problems regarding the eyelashes and eyes. The transparency of the glossy part around the eyeball doesn't work and for god's sake I can't get the eyelashes to look good. But at least I have kind of an "easy" workflow to create posed NPCs. With the help of CUA Hair and Unity asset vamifier they look really good in vam.

I will post the process later, maybe some people are interested. Would be cool if we could get more good looking NPCs in VAM.
 
I'd love to see this happen,especially with everyday poses like sitting, standing casually etc.! Worst case scenario maybe you could create skins that look like really tight clothing?
 
I also thought about this, for tight lingerie, leggings or jeans, corsets it might look promising. things like robber masks could also be okay if you don't look too close. Mostly static clothes (like shoes, some accessories, belts, bdsm stuff, ...) can be merged with the model directly in blender or unity.
 
Okay I refined the plugin a bit and simply want to show what I got for now.
Just copy and paste it into a text-file and change the ending to .py
Now you can install it in Blender.

bl_info = {
"name": "Auto Material Merge with Gender Auto",
"author": "Ivam & ChatGPT",
"version": (1, 11),
"blender": (4, 4, 0),
"description": "Automatically merge character materials and apply textures, auto-detect male/female",
"category": "Object",
}

import bpy
import os

# --------------------------
# Material Mappings
# --------------------------

MATERIAL_GROUPS_FEMALE = {
"Limb Materials": ["Legs-1","Toenails-1","Fingernails-1","Hands-1","Shoulders-1","Forearms-1","Feet-1"],
"Torso Materials": ["Head-1","Neck-1","Hips-1","Torso-1","Nipples-1","Ears-1"],
"Face Materials": ["Nostrils-1","Lips-1","Face-1"],
"Gens Materials": ["defaultMat-1"],
"Eye Materials": ["Lacrimals-1","Pupils-1","Irises-1","Sclera-1"],
"Mouth Materials": ["Gums-1","Teeth-1","Tongue-1","InnerMouth-1"],
}

MATERIAL_GROUPS_MALE = {
"Limb Materials": ["Legs-1","Toenails-1","Fingernails-1","Hands-1","Shoulders-1","Forearms-1","Feet-1"],
"Torso Materials": ["Head-1","Neck-1","Hips-2","Torso-1","Nipples-1","Ears-1"],
"Face Materials": ["Nostrils-1","Lips-1","Face-1"],
"Gens Materials": ["Genitalia-1"],
"Anus Materials": ["Anus-1"],
"Eye Materials": ["Lacrimals-1","Pupils-1","Irises-1","Sclera-1"],
"Mouth Materials": ["Gums-1","Teeth-1","Tongue-1","InnerMouth-1"],
}

TEXTURE_MAP = {
"Limb Materials": "LimbsD",
"Torso Materials": "TorsoD",
"Face Materials": "FaceD",
"Gens Materials": "GenitalsD",
"Anus Materials": "AnusD",
"Eye Materials": "EyesD",
"Mouth Materials": "MouthD",
"Eyelashes-1": "EyelashesA",
}

IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg"]

# --------------------------
# Material Merge Funktion
# --------------------------

def merge_and_apply(obj, mat_groups, obj_path):
tex_dir = os.path.join(os.path.dirname(obj_path), "textures")

# Merge normale Materialien
for target_name, sources in mat_groups.items():
target_mat = bpy.data.materials.get(target_name)
if not target_mat:
target_mat = bpy.data.materials.new(name=target_name)
target_mat.use_nodes = True

for slot in obj.material_slots:
if slot.material and slot.material.name in sources:
slot.material = target_mat

# Texturen anwenden
tex_base = TEXTURE_MAP.get(target_name)
if tex_base:
diffuse_img = None
normal_img = None
for ext in IMAGE_EXTENSIONS:
path = os.path.join(tex_dir, tex_base + ext)
if os.path.exists(path):
diffuse_img = bpy.data.images.load(path)
break
normal_base = tex_base.replace("D","N")
for ext in IMAGE_EXTENSIONS:
npath = os.path.join(tex_dir, normal_base + ext)
if os.path.exists(npath):
normal_img = bpy.data.images.load(npath)
break

nodes = target_mat.node_tree.nodes
links = target_mat.node_tree.links
principled = next((n for n in nodes if n.type=="BSDF_PRINCIPLED"), None)
if not principled:
principled = nodes.new("ShaderNodeBsdfPrincipled")
out = next((n for n in nodes if n.type=="OUTPUT_MATERIAL"), None)
if out:
links.new(principled.outputs["BSDF"], out.inputs["Surface"])

if diffuse_img:
tex_node = nodes.get("AutoTex_" + target_name)
if not tex_node:
tex_node = nodes.new("ShaderNodeTexImage")
tex_node.name = "AutoTex_" + target_name
links.new(tex_node.outputs["Color"], principled.inputs["Base Color"])
tex_node.image = diffuse_img

if normal_img:
normal_tex = nodes.new("ShaderNodeTexImage")
normal_tex.image = normal_img
normal_tex.image.colorspace_settings.name = "Non-Color"
normal_node = nodes.new("ShaderNodeNormalMap")
normal_node.inputs["Strength"].default_value = 0.4
links.new(normal_tex.outputs["Color"], normal_node.inputs["Color"])
links.new(normal_node.outputs["Normal"], principled.inputs["Normal"])

# --------------------------
# Cornea transparent machen
# --------------------------
cornea = bpy.data.materials.get("Cornea-1")
if cornea:
cornea.use_nodes = True
nodes = cornea.node_tree.nodes
links = cornea.node_tree.links
principled = next((n for n in nodes if n.type=="BSDF_PRINCIPLED"), None)
if principled:
principled.inputs["Alpha"].default_value = 0.0
out = next((n for n in nodes if n.type=="OUTPUT_MATERIAL"), None)
if out:
cornea.blend_method = 'BLEND'
links.new(principled.outputs["BSDF"], out.inputs["Surface"])

# --------------------------
# EyeReflection und Tear transparent
# --------------------------
for mat_name in ["EyeReflection-1", "Tear-1"]:
mat = bpy.data.materials.get(mat_name)
if mat:
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
principled = next((n for n in nodes if n.type=="BSDF_PRINCIPLED"), None)
if principled:
principled.inputs["Alpha"].default_value = 0.0
out = next((n for n in nodes if n.type=="OUTPUT_MATERIAL"), None)
if out:
mat.blend_method = 'BLEND'
links.new(principled.outputs["BSDF"], out.inputs["Surface"])

# --------------------------
# Eyelashes als Cutout, Base Color schwarz
# --------------------------
for mat in obj.data.materials:
if mat.name in ["Eyelashes-1", "Eyelashes Materials"]:
mat.name = "Eyelashes Materials"
if not mat.node_tree:
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links

principled = next((n for n in nodes if n.type=='BSDF_PRINCIPLED'), None)
if not principled:
principled = nodes.new('ShaderNodeBsdfPrincipled')
output = next((n for n in nodes if n.type=='OUTPUT_MATERIAL'), None)
if output:
links.new(principled.outputs['BSDF'], output.inputs['Surface'])

principled.inputs['Base Color'].default_value = (0,0,0,1) # Schwarz

tex_node = nodes.get('EyelashesTex')
if not tex_node:
tex_node = nodes.new('ShaderNodeTexImage')
tex_node.name = 'EyelashesTex'
tex_node.label = 'EyelashesTex'

for ext in IMAGE_EXTENSIONS:
tex_path = os.path.join(tex_dir, "EyelashesA" + ext)
if os.path.exists(tex_path):
tex_node.image = bpy.data.images.load(tex_path)
tex_node.image.colorspace_settings.name = 'Non-Color'
break

links.new(tex_node.outputs['Color'], principled.inputs['Alpha'])
mat.blend_method = 'CLIP'
mat.alpha_threshold = 0.5
continue

# --------------------------
# Operator
# --------------------------

class OBJECT_OT_merge_materials(bpy.types.Operator):
bl_idname = "object.merge_materials"
bl_label = "Merge Materials"
filepath: bpy.props.StringProperty(subtype="FILE_PATH")

def execute(self, context):
obj = context.object
if not obj:
self.report({'ERROR'}, "No active object")
return {'CANCELLED'}

# Automatische Geschlechtsbestimmung
if bpy.data.materials.get("Anus-1"):
mat_groups = MATERIAL_GROUPS_MALE
char_type = "MALE"
else:
mat_groups = MATERIAL_GROUPS_FEMALE
char_type = "FEMALE"

merge_and_apply(obj, mat_groups, self.filepath)
self.report({'INFO'}, f"Materials merged for {char_type}")
return {'FINISHED'}

def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}

# --------------------------
# UI Panel
# --------------------------

class MATERIAL_PT_merge_panel(bpy.types.Panel):
bl_label = "Add Textures" # Panel-Titel innerhalb des Reiters
bl_idname = "MATERIAL_PT_merge_panel"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "VAM NPC Creator" # Name des Reiters im N-Panel

def draw(self, context):
layout = self.layout
layout.operator("object.merge_materials", text="Select .obj") # Button-Text

# --------------------------
# Register
# --------------------------

classes = [
MATERIAL_PT_merge_panel,
OBJECT_OT_merge_materials,
]

def register():
for cls in classes:
bpy.utils.register_class(cls)

def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)

if __name__ == "__main__":
register()

1. Pose your character inside vam and most importantly change the Skin in Skin select to Female Custom or Male custom (the materials names are a bit different on some skins, these two will work definitely)
step 1.JPG


2. Export your posed character and make sure to copy the skinned.obj file into a new folder. in this folder you need another folder called "textures" With the following textures named exactly like in the picture.
step 2.JPG

step 3.JPG

step 4.JPG

step 5a.JPG


3. I am using Blender 4.4.3. My plugin was created for that version and I don't know if it will work with other versions. Install the plugin and import the obj file with the usual blender importer.
step 6.JPG


4. Now press N and open the VAM NPC creator plugin, click on select .obj and open the same file again.
step 7.JPG
step 8.JPG

5. In Viewport shading your character now should have textures and should be ready to export as .fbx for unity.
step 9.JPG
 
Last edited:
Back
Top Bottom