I have a model in .glb format with nothing edit(but a mesh) in the scene. How do I apply a material of a glb/gltf mesh using Python? I am using Pygltflib and Trimesh although I can use other libraries.
I can only give a genereal answer, because you did not provide any code, but you would do it like this in principal:
material = Material() # Create a material
pbr = PbrMetallicRoughness() # Use PbrMetallicRoughness
pbr.baseColorFactor = [1.0, 0.0, 0.0, 1.0] # solid red
material.pbrMetallicRoughness = pbr
after that supply the material to your primitive like that
primitive.material = 0
and do not forget to add it to the gltf. As always if you use more materials, the order will be important of course:
gltf.materials.append(material)
For completeness here is how to add a double sided red metallicRoughnessMaterial with "MASK" alphaMode to the triangle example and save it as .glb:
from pygltflib import *
# create gltf objects for a scene with a primitive triangle with indexed geometry
gltf = GLTF2()
scene = Scene()
mesh = Mesh()
material = Material()
primitive = Primitive()
node = Node()
buffer = Buffer()
bufferView1 = BufferView()
bufferView2 = BufferView()
accessor1 = Accessor()
accessor2 = Accessor()
# add data
buffer.uri = "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA="
buffer.byteLength = 44
bufferView1.buffer = 0
bufferView1.byteOffset = 0
bufferView1.byteLength = 6
bufferView1.target = ELEMENT_ARRAY_BUFFER
bufferView2.buffer = 0
bufferView2.byteOffset = 8
bufferView2.byteLength = 36
bufferView2.target = ARRAY_BUFFER
accessor1.bufferView = 0
accessor1.byteOffset = 0
accessor1.componentType = UNSIGNED_SHORT
accessor1.count = 3
accessor1.type = SCALAR
accessor1.max = [2]
accessor1.min = [0]
accessor2.bufferView = 1
accessor2.byteOffset = 0
accessor2.componentType = FLOAT
accessor2.count = 3
accessor2.type = VEC3
accessor2.max = [1.0, 1.0, 0.0]
accessor2.min = [0.0, 0.0, 0.0]
pbr = PbrMetallicRoughness() # Use PbrMetallicRoughness
pbr.baseColorFactor = [1.0, 0.0, 0.0, 1.0] # solid red
material.pbrMetallicRoughness = pbr
material.doubleSided = True # make material double sided
material.alphaMode = MASK # to get around 'MATERIAL_ALPHA_CUTOFF_INVALID_MODE' warning
primitive.attributes.POSITION = 1
primitive.material = 0
node.mesh = 0
scene.nodes = [0]
# assemble into a gltf structure
gltf.scenes.append(scene)
gltf.meshes.append(mesh)
gltf.materials.append(material)
gltf.meshes[0].primitives.append(primitive)
gltf.nodes.append(node)
gltf.buffers.append(buffer)
gltf.bufferViews.append(bufferView1)
gltf.bufferViews.append(bufferView2)
gltf.accessors.append(accessor1)
gltf.accessors.append(accessor2)
gltf.convert_buffers(BufferFormat.BINARYBLOB) # Convert buffers to allow saving as .glb
# save to a .glb file
gltf.save("triangle.glb")
I have written this GPU code in C using GLES and EGL, and it ran fine. I am now trying to port this GPU code to python using ModernGL, except right after I call the render function, ctx returns a GL_INVALID_ENUM error. I am using a NanoPi M1 Plus with Mali400 GPU which supports only OpenGL version 120.
GPU CODE:
import moderngl
import numpy as np
ctx = moderngl.create_context(standalone=True,
backend='egl'
)
prog = ctx.program(
vertex_shader='''
#version 120
attribute vec4 vPosition;
void main() {
gl_Position = vPosition;
}
''',
fragment_shader='''
#version 120
uniform float Aarr[1000];
void main() {
int my_index = int(gl_FragCoord[0]);
float ex = exp(-Aarr[my_index]);
float result = 1 / (1.0 + ex);
gl_FragColor = vec4(result, 0.0, 0.0, 1.0);
}
''',
)
vertices = np.array([
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0
],
dtype='f4',
)
vbo = ctx.buffer(vertices)
vao = ctx.simple_vertex_array(prog, vbo, 'vPosition')
A_vec = prog['Aarr']
A_vec.write(np.random.uniform(-256,256,[1000]).astype('f4'))
fbo = ctx.simple_framebuffer((1000, 2), components=4)
fbo.use()
fbo.clear(0.0, 0.0, 0.0, 1.0)
vao.render()
print("Error after render: ",ctx.error)
Output:
libGL error: MESA-LOADER: malformed or no PCI ID
libGL error: unable to load driver: mali_drm_dri.so
libGL error: driver pointer missing
libGL error: failed to load driver: mali_drm
Error after render: GL_INVALID_ENUM
Any help would be greatly appreciated as this is required for my final year project.
Mali400 GPU which supports only OpenGL version 120
It doesn't support OpenGL at all; it supports OpenGL ES 1.1 and 2.0.
I wrote a python script that automatically add a texture to the DAE model.
Usage: blender --background --python Script.py
This script gives an incorrect display of the texture:
import bpy
from math import pi
from mathutils import Quaternion
myscale = 0.1;
daepath = "input.dae"
bpy.ops.wm.read_factory_settings(use_empty=True)
# Import Dae
bpy.ops.wm.collada_import(filepath=daepath)
# Rotate
bpy.ops.transform.rotate(value=-pi/2, constraint_axis=(False, True, True))
bpy.ops.transform.resize(value=(myscale, myscale, myscale))
# Change to orthographic view and switch to topview
bpy.context.screen.areas[2].type = 'VIEW_3D'
rv3d = bpy.context.screen.areas[2].spaces[0].region_3d
rv3d.view_rotation = Quaternion((1.0, 0.0, 0.0, 0.0))
rv3d.view_perspective = "ORTHO"
rv3d.view_distance += 1000.0
# Unwrap
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_all(action = 'SELECT')
for oWindow in bpy.context.window_manager.windows:
oScreen = oWindow.screen
for oArea in oScreen.areas:
if oArea.type == 'VIEW_3D':
for oRegion in oArea.regions:
if oRegion.type == 'WINDOW':
override = {'window': oWindow, 'screen': oScreen, 'area': oArea, 'region': oRegion, 'scene': bpy.context.scene, 'edit_object': bpy.context.edit_object, 'active_object': bpy.context.active_object, 'selected_objects': bpy.context.selected_objects}
bpy.ops.uv.project_from_view(override , camera_bounds=False, correct_aspect=True, scale_to_bounds=True)
bpy.ops.object.mode_set(mode = 'OBJECT')
# Add Texture
imgpath = "input.jpg"
img = bpy.data.images.load(filepath=imgpath)
mat = bpy.data.materials['m0DefaultMaterial']
mat.diffuse_intensity = 1.0
mat.specular_intensity = 0.0
tex = bpy.data.textures.new("SomeName", 'IMAGE')
tex.image = img
slot = mat.texture_slots.add()
slot.texture = tex
# Save Dae
bpy.ops.wm.collada_export(filepath="output.dae")
If I divide the script into 2 parts (1 part before section # Unwrap) and run their in Blender
open app
choose scripting mode
open .py files in run
I get right result.
I was looking for all the similar problems, but I could not find the reason for this script behavior.
Tell me, please, where is the error?
I am receiving the following error when importing pandas in a Python program
monas-mbp:book mona$ sudo pip install python-dateutil
Requirement already satisfied (use --upgrade to upgrade): python-dateutil in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python
Cleaning up...
monas-mbp:book mona$ python t1.py
No module named dateutil.parser
Traceback (most recent call last):
File "t1.py", line 4, in <module>
import pandas as pd
File "/Library/Python/2.7/site-packages/pandas/__init__.py", line 6, in <module>
from . import hashtable, tslib, lib
File "tslib.pyx", line 31, in init pandas.tslib (pandas/tslib.c:48782)
ImportError: No module named dateutil.parser
Also here's the program:
import codecs
from math import sqrt
import numpy as np
import pandas as pd
users = {"Angelica": {"Blues Traveler": 3.5, "Broken Bells": 2.0,
"Norah Jones": 4.5, "Phoenix": 5.0,
"Slightly Stoopid": 1.5,
"The Strokes": 2.5, "Vampire Weekend": 2.0},
"Bill":{"Blues Traveler": 2.0, "Broken Bells": 3.5,
"Deadmau5": 4.0, "Phoenix": 2.0,
"Slightly Stoopid": 3.5, "Vampire Weekend": 3.0},
"Chan": {"Blues Traveler": 5.0, "Broken Bells": 1.0,
"Deadmau5": 1.0, "Norah Jones": 3.0, "Phoenix": 5,
"Slightly Stoopid": 1.0},
"Dan": {"Blues Traveler": 3.0, "Broken Bells": 4.0,
"Deadmau5": 4.5, "Phoenix": 3.0,
"Slightly Stoopid": 4.5, "The Strokes": 4.0,
"Vampire Weekend": 2.0},
"Hailey": {"Broken Bells": 4.0, "Deadmau5": 1.0,
"Norah Jones": 4.0, "The Strokes": 4.0,
"Vampire Weekend": 1.0},
"Jordyn": {"Broken Bells": 4.5, "Deadmau5": 4.0,
"Norah Jones": 5.0, "Phoenix": 5.0,
"Slightly Stoopid": 4.5, "The Strokes": 4.0,
"Vampire Weekend": 4.0},
"Sam": {"Blues Traveler": 5.0, "Broken Bells": 2.0,
"Norah Jones": 3.0, "Phoenix": 5.0,
"Slightly Stoopid": 4.0, "The Strokes": 5.0},
"Veronica": {"Blues Traveler": 3.0, "Norah Jones": 5.0,
"Phoenix": 4.0, "Slightly Stoopid": 2.5,
"The Strokes": 3.0}
}
class recommender:
def __init__(self, data, k=1, metric='pearson', n=5):
""" initialize recommender
currently, if data is dictionary the recommender is initialized
to it.
For all other data types of data, no initialization occurs
k is the k value for k nearest neighbor
metric is which distance formula to use
n is the maximum number of recommendations to make"""
self.k = k
self.n = n
self.username2id = {}
self.userid2name = {}
self.productid2name = {}
# for some reason I want to save the name of the metric
self.metric = metric
if self.metric == 'pearson':
self.fn = self.pearson
#
# if data is dictionary set recommender data to it
#
if type(data).__name__ == 'dict':
self.data = data
def convertProductID2name(self, id):
"""Given product id number return product name"""
if id in self.productid2name:
return self.productid2name[id]
else:
return id
def userRatings(self, id, n):
"""Return n top ratings for user with id"""
print ("Ratings for " + self.userid2name[id])
ratings = self.data[id]
print(len(ratings))
ratings = list(ratings.items())
ratings = [(self.convertProductID2name(k), v)
for (k, v) in ratings]
# finally sort and return
ratings.sort(key=lambda artistTuple: artistTuple[1],
reverse = True)
ratings = ratings[:n]
for rating in ratings:
print("%s\t%i" % (rating[0], rating[1]))
def loadBookDB(self, path=''):
"""loads the BX book dataset. Path is where the BX files are
located"""
self.data = {}
i = 0
#
# First load book ratings into self.data
#
f = codecs.open(path + "BX-Book-Ratings.csv", 'r', 'utf8')
for line in f:
i += 1
#separate line into fields
fields = line.split(';')
user = fields[0].strip('"')
book = fields[1].strip('"')
rating = int(fields[2].strip().strip('"'))
if user in self.data:
currentRatings = self.data[user]
else:
currentRatings = {}
currentRatings[book] = rating
self.data[user] = currentRatings
f.close()
#
# Now load books into self.productid2name
# Books contains isbn, title, and author among other fields
#
f = codecs.open(path + "BX-Books.csv", 'r', 'utf8')
for line in f:
i += 1
#separate line into fields
fields = line.split(';')
isbn = fields[0].strip('"')
title = fields[1].strip('"')
author = fields[2].strip().strip('"')
title = title + ' by ' + author
self.productid2name[isbn] = title
f.close()
#
# Now load user info into both self.userid2name and
# self.username2id
#
f = codecs.open(path + "BX-Users.csv", 'r', 'utf8')
for line in f:
i += 1
#print(line)
#separate line into fields
fields = line.split(';')
userid = fields[0].strip('"')
location = fields[1].strip('"')
if len(fields) > 3:
age = fields[2].strip().strip('"')
else:
age = 'NULL'
if age != 'NULL':
value = location + ' (age: ' + age + ')'
else:
value = location
self.userid2name[userid] = value
self.username2id[location] = userid
f.close()
print(i)
def pearson(self, rating1, rating2):
sum_xy = 0
sum_x = 0
sum_y = 0
sum_x2 = 0
sum_y2 = 0
n = 0
for key in rating1:
if key in rating2:
n += 1
x = rating1[key]
y = rating2[key]
sum_xy += x * y
sum_x += x
sum_y += y
sum_x2 += pow(x, 2)
sum_y2 += pow(y, 2)
if n == 0:
return 0
# now compute denominator
denominator = (sqrt(sum_x2 - pow(sum_x, 2) / n)
* sqrt(sum_y2 - pow(sum_y, 2) / n))
if denominator == 0:
return 0
else:
return (sum_xy - (sum_x * sum_y) / n) / denominator
def computeNearestNeighbor(self, username):
"""creates a sorted list of users based on their distance to
username"""
distances = []
for instance in self.data:
if instance != username:
distance = self.fn(self.data[username],
self.data[instance])
distances.append((instance, distance))
# sort based on distance -- closest first
distances.sort(key=lambda artistTuple: artistTuple[1],
reverse=True)
return distances
def recommend(self, user):
"""Give list of recommendations"""
recommendations = {}
# first get list of users ordered by nearness
nearest = self.computeNearestNeighbor(user)
#
# now get the ratings for the user
#
userRatings = self.data[user]
#
# determine the total distance
totalDistance = 0.0
for i in range(self.k):
totalDistance += nearest[i][1]
# now iterate through the k nearest neighbors
# accumulating their ratings
for i in range(self.k):
# compute slice of pie
weight = nearest[i][1] / totalDistance
# get the name of the person
name = nearest[i][0]
# get the ratings for this person
neighborRatings = self.data[name]
# get the name of the person
# now find bands neighbor rated that user didn't
for artist in neighborRatings:
if not artist in userRatings:
if artist not in recommendations:
recommendations[artist] = (neighborRatings[artist]
* weight)
else:
recommendations[artist] = (recommendations[artist]
+ neighborRatings[artist]
* weight)
# now make list from dictionary
recommendations = list(recommendations.items())
recommendations = [(self.convertProductID2name(k), v)
for (k, v) in recommendations]
# finally sort and return
recommendations.sort(key=lambda artistTuple: artistTuple[1],
reverse = True)
# Return the first n items
return recommendations[:self.n]
r = recommender(users)
# The author implementation
r.loadBookDB('/Users/mona/Downloads/BX-Dump/')
ratings = pd.read_csv('/Users/danialt/BX-CSV-Dump/BX-Book-Ratings.csv', sep=";", quotechar="\"", escapechar="\\")
books = pd.read_csv('/Users/danialt/BX-CSV-Dump/BX-Books.csv', sep=";", quotechar="\"", escapechar="\\")
users = pd.read_csv('/Users/danialt/BX-CSV-Dump/BX-Users.csv', sep=";", quotechar="\"", escapechar="\\")
pivot_rating = ratings.pivot(index='User-ID', columns='ISBN', values='Book-Rating')
On Ubuntu you may need to install the package manager pip first:
sudo apt-get install python-pip
Then install the python-dateutil package with:
sudo pip install python-dateutil
For Python 3:
pip3 install python-dateutil
You can find the dateutil package at https://pypi.python.org/pypi/python-dateutil. Extract it to somewhere and run the command:
python setup.py install
It worked for me!
I have same issues on my MacOS and it's work for me to try
pip3 install python-dateutil
on Ubuntu
sudo apt-get install python-dateutil
For Python 3 above, use:
sudo apt-get install python3-dateutil
If you're using a virtualenv, make sure that you are running pip from within the virtualenv.
$ which pip
/Library/Frameworks/Python.framework/Versions/Current/bin/pip
$ find . -name pip -print
./flask/bin/pip
./flask/lib/python2.7/site-packages/pip
$ ./flask/bin/pip install python-dateutil
None of the solutions worked for me. If you are using PIP do:
pip install pycrypto==2.6.1
In Ubuntu 18.04 for Python2:
sudo apt-get install python-dateutil
I had the similar problem. This is the stack trace:
Traceback (most recent call last):
File "/usr/local/bin/aws", line 19, in <module> import awscli.clidriver
File "/usr/local/lib/python2.7/dist-packages/awscli/clidriver.py", line 17, in <module> import botocore.session
File "/usr/local/lib/python2.7/dist-packages/botocore/session.py", line 30, in <module> import botocore.credentials
File "/usr/local/lib/python2.7/dist-packages/botocore/credentials.py", line 27, in <module> from dateutil.parser import parse
ImportError: No module named dateutil.parser
I tried to (re-)install dateutil.parser through all possible ways. It was unsuccessful.
I solved it with
pip3 uninstall awscli
pip3 install awscli
sudo python3 -m pip install PyPDF2 passlib babel werkzeug lxml decorator polib pillow psycopg2 idna python-dateutil psutil requests jinja2
If you are using Pipenv, you may need to add this to your Pipfile:
[packages]
python-dateutil = "*"
I want to draw a Rectangle in pyOpenGL using VBOs with indices. I am using the glDrawRangeElements() function for that but I always get the same mistake in the line glDrawRangeElements:
WindowsError: exception: access violation reading 0x00000000
I tried a lot of things and was looking on the internet for the solution and was studying code examples all day so now I really do not know how to go on. It would be nice if someone here could help me.
This is should be the part of the code in which the error is created:
vertexPositions = [[-0.75, -0.75, 0.0],
[0.75, -0.75, 0.0],
[0.75, 0.75, 0.0],
[-0.75, 0.75, 0.0] ]
vertexIndices = [0, 1, 2,
1, 2, 3]
vertexComponents = 3
positionBufferObject = None
indexBufferObject = None
x = 0
def glGenVertexArray():
vao_id = GL.GLuint(0)
vertex_array_object.glGenVertexArrays(1, vao_id)
return vao_id.value
def initialize_vertex_buffer():
global positionBufferObject, indexBufferObject
indexBufferObject = GL.glGenBuffers(1)
GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBufferObject)
array_type = (GL.GLushort * len(vertexIndices))
GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, len(vertexIndices) * 2,
array_type(*vertexIndices), GL.GL_STATIC_DRAW)
GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0)
positionBufferObject = GL.glGenBuffers(1)
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, positionBufferObject)
array_type = (GL.GLfloat * len(vertexPositions))
GL.glBufferData(GL.GL_ARRAY_BUFFER,
len(vertexPositions[0])*len(vertexPositions)*sizeOfFloat,
array_type(*vertexPositions), GL.GL_STATIC_DRAW
)
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0)
glBindVertexArray( glGenVertexArray() )
def init():
initialize_vertex_buffer()
def display():
global x
GL.glClearColor(0.0, 0.0, 0.0, 0.0)
GL.glClear(GL.GL_COLOR_BUFFER_BIT)
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
GL.glEnableClientState(GL.GL_INDEX_ARRAY)
GL.glLoadIdentity()
GL.glTranslate(0, 0, -5)
GL.glRotate(x, 0, 1, 0)
GL.glBindVertexArray(glGenVertexArray())
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, positionBufferObject)
GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBufferObject)
GL.glEnableVertexAttribArray(0)
GL.glDrawRangeElements(GL.GL_TRIANGLES,0, 4, 6, GL.GL_UNSIGNED_SHORT, c_void_p(0))
#GL.glVertexAttribPointer(0, vertexComponents, GL.GL_FLOAT, False, 0, null)
#GL.glDrawArrays(GL.GL_QUADS, 0, len(vertexPositions) / vertexComponents)
GL.glDisableVertexAttribArray(0)
GL.glDisableClientState(GL.GL_VERTEX_ARRAY)
GL.glDisableClientState(GL.GL_INDEX_ARRAY)
pygame.display.flip()
I have to admit that do not really have a clue of all these things yet, just trying to understand it because I need it for a project, so if there are any additional mistakes I have overlooked so far please tell my ;)
Thanks in advance
Shouldn't your call:
GL.glBindVertexArray (glGenVertexArray())
be
GL.glBindVertexArray (GL.glGenVertexArray())
Also, you probably want to keep track of that vertex array so you can delete it later and free up the resources it uses.