Related
I already tried to clamp it with mathf or hardocding it, but it didnt help either, it just slips trough, every time I rotate the camera on the edge of the map (min/max hsp - min/max vsp) the given edges of the terrain.
I'm out of ideas and searched days for a similar problem in hope to see my mistake and now I'm here. Hopefully someone can help me and show me the mistake I made. I want to learn so badly. you can see the code I used here:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraMovementScript : MonoBehaviour
{
float speed = 1f;
float zoomSpeed = 10f;
float rotateSpeed = 50f;
float maxHeight = 200f;
float minHeight = 20f;
float minHsp = 10f;
float maxHsp = 750f;
float minVsp = 10f;
float maxVsp = 750f;
Vector2 p1;
Vector2 p2;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.LeftShift))
{
speed = 1f;
zoomSpeed = 2000f;
}
else
{
speed = 0.5f;
zoomSpeed = 1550f;
}
float hsp = transform.position.y * speed * Input.GetAxis("Horizontal") * Time.deltaTime;
float vsp = transform.position.y * speed * Input.GetAxis("Vertical") * Time.deltaTime;
float scrollSP = Mathf.Log(transform.position.y) * -zoomSpeed * Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime;
if ((transform.position.y >= maxHeight) && (scrollSP > 0))
{
scrollSP = 0;
}
else if ((transform.position.y <= minHeight) && (scrollSP <0))
{
scrollSP = 0;
}
if((transform.position.y + scrollSP) > maxHeight)
{
scrollSP = maxHeight - transform.position.y;
}
else if((transform.position.y + scrollSP) < minHeight)
{
scrollSP = minHeight - transform.position.y;
}
if ((transform.position.x >= maxHsp) && (hsp > 0))
{
hsp = 0;
}
else if ((transform.position.x <= minHsp) && (hsp < 0))
{
hsp = 0;
}
if ((transform.position.x + hsp) > maxHsp)
{
hsp = maxHsp - transform.position.x;
}
else if ((transform.position.x + hsp) < minHsp)
{
hsp = minHsp - transform.position.x;
}
if ((transform.position.z >= maxVsp) && (vsp > 0))
{
vsp = 0;
}
else if ((transform.position.z <= minVsp) && (vsp < 0))
{
vsp = 0;
}
if ((transform.position.z + vsp) > maxVsp)
{
vsp = maxVsp - transform.position.z;
}
else if ((transform.position.z + vsp) < minVsp)
{
vsp = minVsp - transform.position.z;
}
Vector3 verticalMove = new Vector3(0,scrollSP,0);
Vector3 lateralMove = hsp * transform.right;
Vector3 forwardMove = transform.forward;
forwardMove.y = 0;
forwardMove.Normalize();
forwardMove *= vsp;
Vector3 move = verticalMove + lateralMove + forwardMove;
transform.position += move;
getCameraRotation();
}
void getCameraRotation()
{
if(Input.GetMouseButtonDown(2))
{
p1 = Input.mousePosition;
}
if(Input.GetMouseButton(2))
{
p2 = Input.mousePosition;
float dx = (p2 - p1).x * rotateSpeed * Time.deltaTime;
float dy = (p2 - p1).y * rotateSpeed * Time.deltaTime;
transform.rotation *= Quaternion.Euler(new Vector3(0,dx,0));
transform.GetChild(0).transform.rotation *= Quaternion.Euler(new Vector3(-dy,0,0));
p1 = p2;
}
}
}
I have one issue left with ASSIMP DIRECT X C++ ANIMATION WITH SKELETON.
for (UINT m = 0; m < currentMesh->mBones[k]->mNumWeights; m++) //verticer som påverkas
{
vertexVector[k].joints.x = currentMesh->mBones[k]->mWeights[m].mVertexId;
That code shows all vertices affected by a bone - k, inside an iteration.
All of these vertices must have the same vert ID since they are all affected by the same bone/joint.
The problem is, I need to make a list of every vertex and a list of every indice of a face, where I store position, UV, Normal etc.
The list that displays all of the vertices, is not in the same order obviously as the lists that displays all the vertices affected by each bone.
So how can I combine these lists?
"vertexVector"... etc is an example of a list with jointInfo that is corresponding to vertexID.
It has room for more places and another variable for the weight.
But that list doesn't work obviously.
What am I doing wrong with Assimp? Hope this was a clear post.
UPdate this is how i build the matrices: I don't know what is wrong.
void jointTransform(float
timeInSeconds, std::vector<DirectX::XMMATRIX>& transformM, aiAnimation*
ani, UINT nrOfJoints, std::vector<joints>& jointInfo, const aiScene*
scenePtr)
{
DirectX::XMMATRIX iD = DirectX::XMMatrixIdentity();
float ticksPerSecond = (float)ani->mTicksPerSecond;
if (ticksPerSecond == 0)
{
ticksPerSecond = 30;
}
float timeInTicks = timeInSeconds * ticksPerSecond;
float animationTime = fmod(timeInTicks, (float)ani->mDuration);
readNodeHeiarchy(animationTime, scenePtr->mRootNode, iD, jointInfo, ani,
scenePtr);
transformM.resize(nrOfJoints);
for (UINT i = 0; i < transformM.size(); i++)
{
transformM[i] = jointInfo[i].transformFinal;
}
}
void readNodeHeiarchy(float time, const aiNode* node, DirectX::XMMATRIX
parentMat, std::vector<joints>& jointInfo, aiAnimation* ani, const
aiScene* scenePtr)
{
std::string nodeNameString = node->mName.data;
//Skapa en parentTransform från noden. Som sedan skickas in som parent
matris, första gången är det identitetsmatrisen.
aiMatrix4x4 nodeTransform = node->mTransformation;
DirectX::XMMATRIX combined;
combined = DirectX::XMMatrixSet(nodeTransform.a1, nodeTransform.a2,
nodeTransform.a3, nodeTransform.a4,
nodeTransform.b1, nodeTransform.b2, nodeTransform.b3, nodeTransform.b4,
nodeTransform.c1, nodeTransform.c2, nodeTransform.c3, nodeTransform.c4,
nodeTransform.d1, nodeTransform.d2, nodeTransform.d3,
nodeTransform.d4);
const aiNodeAnim* joint = nullptr;
//Kolla om noden är ett ben.
for (UINT i = 0; i < ani->mNumChannels; i++)
{
if (nodeNameString == ani->mChannels[i]->mNodeName.data)
{
joint = ani->mChannels[i];
}
}
DirectX::XMMATRIX globalTransform = DirectX::XMMatrixIdentity();
//om den är ett ben så är joint inte längre nullptr, den blir det benet.
if (joint)
{
DirectX::XMMATRIX S;
DirectX::XMMATRIX R;
DirectX::XMMATRIX T;
//scale
aiVector3D scaleV;
calcLerpScale(scaleV, time, joint);
S = DirectX::XMMatrixScaling(scaleV.x, scaleV.y, scaleV.z);
//rotate
aiQuaternion rotationQ;
calcLerpRot(rotationQ, time, joint);
DirectX::XMVECTOR q;
q = DirectX::XMVectorSet(rotationQ.x, rotationQ.y, rotationQ.z,
rotationQ.w);
R = DirectX::XMMatrixRotationQuaternion(q);
//translate
aiVector3D transV;
calcLerpTrans(transV, time, joint);
T = DirectX::XMMatrixTranslation(transV.x, transV.y, transV.z);
combined = S * R * T;
globalTransform = combined * parentMat;
}
//DirectX::XMMATRIX globalTransform = combined * parentMat;
//if (jointInfo[jointInfo.size() - 1].name.C_Str() != nodeNameString)
//{
for (UINT i = 0; i < jointInfo.size(); i++)
{
if (jointInfo[i].name.C_Str() == nodeNameString)
{
OutputDebugStringA("\n");
OutputDebugStringA(jointInfo[i].name.C_Str());
OutputDebugStringA("\n");
aiMatrix4x4 off = jointInfo[i].offsetM;
DirectX::XMMATRIX offset;
offset = DirectX::XMMatrixSet(off.a1, off.a2, off.a3, off.a4,
off.b1, off.b2, off.b3, off.b4,
off.c1, off.c2, off.c3, off.c4,
off.d1, off.d2, off.d3, off.d4);
DirectX::XMMATRIX rootMInv;
aiMatrix4x4 rootInv = scenePtr->mRootNode-
>mTransformation.Inverse();
rootMInv = DirectX::XMMatrixSet(rootInv.a1, rootInv.a2,
rootInv.a3, rootInv.a4,
rootInv.b1, rootInv.b2, rootInv.b3, rootInv.b4,
rootInv.c1, rootInv.c2, rootInv.c3, rootInv.c4,
rootInv.d1, rootInv.d2, rootInv.d3, rootInv.d4);
jointInfo[i].transformFinal = offset * globalTransform *
rootMInv;
break;
}
}
//}
for (UINT i = 0; i < node->mNumChildren; i++)
{
readNodeHeiarchy(time, node->mChildren[i], globalTransform, jointInfo,
ani, scenePtr);
}
}
void calcLerpScale(aiVector3D& scale, float aniTime, const aiNodeAnim*
joint)
{
if (joint->mNumScalingKeys == 1)
{
scale = joint->mScalingKeys[0].mValue;
return;
}
UINT scaleInd = findIndexS(aniTime, joint);
UINT nextScale = scaleInd + 1;
assert(nextScale < joint->mNumScalingKeys);
float deltaTime = (float)joint->mScalingKeys[nextScale].mTime -
(float)joint->mScalingKeys[scaleInd].mTime;
float factor = (aniTime - (float)joint->mScalingKeys[scaleInd].mTime) /
deltaTime;
assert(factor >= 0.0f && factor <= 1.0f);
const aiVector3D& startScaleV = joint->mScalingKeys[scaleInd].mValue;
const aiVector3D& endScaleV = joint->mScalingKeys[nextScale].mValue;
//interpolate
aiVector3D Delta = endScaleV - startScaleV; // längden
scale = startScaleV + (factor * Delta); //gå ett antal steg beroende på
faktorn mellan start och slut.
scale.Normalize();
}
void calcLerpRot(aiQuaternion& rotation, float aniTime, const aiNodeAnim*
joint)
{
if (joint->mNumRotationKeys == 1)
{
rotation = joint->mRotationKeys[0].mValue;
return;
}
UINT rotIndex = findIndexRot(aniTime, joint);
UINT nextRot = (rotIndex + 1);
assert(nextRot < joint->mNumRotationKeys);
float deltaTime = (float)joint->mRotationKeys[nextRot].mTime -
(float)joint->mRotationKeys[rotIndex].mTime;
float factor = (aniTime - (float)joint->mRotationKeys[rotIndex].mTime) /
deltaTime;
assert(factor >= 0.0f && factor <= 1.0f);
const aiQuaternion& StartRotationQ = joint->mRotationKeys[rotIndex].mValue;
const aiQuaternion& EndRotationQ = joint->mRotationKeys[nextRot].mValue;
aiQuaternion::Interpolate(rotation, StartRotationQ, EndRotationQ, factor);
rotation.Normalize();
}
void calcLerpTrans(aiVector3D& translation, float aniTime, const
aiNodeAnim*
joint)
{
if (joint->mNumPositionKeys == 1)
{
translation = joint->mPositionKeys[0].mValue;
return;
}
UINT transIndex = findIndexT(aniTime, joint);
UINT nextTrans = (transIndex + 1);
assert(nextTrans < joint->mNumPositionKeys);
float deltaTime = (float)joint->mPositionKeys[nextTrans].mTime -
(float)joint->mPositionKeys[transIndex].mTime;
float factor = (aniTime - (float)joint->mPositionKeys[transIndex].mTime) /
deltaTime;
assert(factor >= 0.0f && factor <= 1.0f);
const aiVector3D& startTransV = joint->mPositionKeys[transIndex].mValue;
const aiVector3D& endTransV = joint->mPositionKeys[nextTrans].mValue;
//interpolate
aiVector3D Delta = endTransV - startTransV;
translation = startTransV + (factor * Delta);
translation.Normalize();
}
UINT findIndexRot(float aniTime, const aiNodeAnim* joint)
{
assert(joint->mNumRotationKeys > 0);
for (UINT i = 0; i < joint->mNumRotationKeys - 1; i++)
{
if (aniTime < (float)joint->mRotationKeys[i + 1].mTime)
{
return i;
}
}
assert(0);
}
}
Not sure what you mean by "All of these vertices must have the same vert ID" - the vertex id's of the k:th bone, according to mBones[k]->mWeights[..].mVertexId, are indices to vertices influenced by this bone, and they are going to be different (otherwise there would be either redundancy of conflict).
You probably want to have bone indices and bone weights as part of the vertex definition for easy handling in a shader. Something like
struct vertex (
vec3 pos;
vec3 normal;
float bone_weights[N]; // weights of bones influencing this vertex
unsigned bone_indices[N]; // indices of bones influencing this vertex
}
std::vector<vertex> mesh_vertices;
Where N is the maximum number of influence bones per vertex. A common value is four, but this depends on the mesh your are importing.
Based on your example, a rough draft could be something like this:
// k:th bone of bones in currentMesh
for (UINT m = 0; m < currentMesh->mBones[k]->mNumWeights; m++)
{
float bone_weight = currentMesh->mBones[k]->mWeights[m].mWeight;
unsigned vertex_index = currentMesh->mBones[k]->mWeights[m].mVertexId;
mesh_vertices[vertex_index].bone_weights[m] = bone_weight;
mesh_vertices[vertex_index].bone_indices[m] = k;
}
Here we've assumed that mNumWeights = N, but this needs to checked, as mentioned.
I am trying to make a basic first person camera scene using JOGL GL3 core and programmed vertex shader, but it doesn't look like the vertex array object is been correctly projected.
I believe the keyboard and mouse functions are working correctly and that the problem lies with shader program or vertex shader.
The AxisScene is where the bulk of the action happens, but the entire gradle project can be found here
I followed the projection theory from here
What code is wrong/missing to create true FPS behaviour?
package fpsscene.fpsscene;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GL3ES3;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLES3;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.math.Matrix4;
import fpsscene.adapters.ApplyXY;
import fpsscene.adapters.BasicMovement;
import fpsscene.gl.primitives.ColoredTriangle;
import fpsscene.gl.primitives.Point2f;
import fpsscene.gl.primitives.Point3f;
public class AxisScene extends Scene implements ApplyXY , BasicMovement{
private static String vertexShaderString = String.join("\n",
"#version 130\n",
"",
"in vec3 vertex_position;",
"in vec3 vertex_colour;",
"uniform mat4 view, proj;",
"out vec3 colour;",
"void main() {",
" colour = vertex_colour;",
" gl_Position = proj * view * vec4 (vertex_position, 1.0);",
"}"
);
private static String fragmentShaderString = String.join("\n",
"#version 130\n",
"in vec3 colour;",
"out vec4 frag_colour;",
"void main() {",
" frag_colour = vec4 (colour, 1.0);",
"}"
);
private int shaderProgram;
int vertShader;
int fragShader;
int view_mat_location;
int proj_mat_location;
Matrix4 proj_mat;
Matrix4 view_mat;
float sens_rot;
Point3f eye_default;
Point3f up_default;
Point2f rot_default;
Point2f fov_default;
Point3f eye;
Point3f up;
Point2f rot;
Point2f fov;
int axisVao[] = new int[1];
private int axisLen;
float near; // clipping plane
float far; // clipping plane
static final int COLOR_IDX = 0;
static final int VERTICES_IDX = 1;
private static final float DROT_FULL = 360.0f;
private static final float DROT_QUART = DROT_FULL/4.0f;
private int width=1920;
private int height=1080;
public AxisScene() {
this.eye_default = new Point3f(0.0f, 0.0f, 0.0f);
this.fov_default = new Point2f(120.0f, 90.0f);
this.rot_default = new Point2f(0.0f, 0.0f);
this.up_default = new Point3f(0.0f, 1.0f, 0.0f);
this.eye = eye_default;
this.fov = fov_default;
this.rot = rot_default;
this.up = up_default;
near = 0.01f;
far = 1000000.0f;
sens_rot = 0.03f;
rot.set(138.869919f, 4.44001198f);
eye.set(-4.66594696f,3.20000124f,-5.04626369f);
// rot.set(167.31528f,0.0f);
updateProjMat();
updateViewMatrix();
}
#Override
public void init(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
if(!gl.isGL3core()){
Logger.getAnonymousLogger().log(Level.SEVERE, "GL3core not enabled");
}
vertShader = createShaderFromString(gl, AxisScene.vertexShaderString,GL2ES2.GL_VERTEX_SHADER);
fragShader = createShaderFromString(gl, AxisScene.fragmentShaderString,GL2ES2.GL_FRAGMENT_SHADER);
shaderProgram = gl.glCreateProgram();
gl.glAttachShader(shaderProgram, vertShader);
gl.glAttachShader(shaderProgram, fragShader);
gl.glLinkProgram(shaderProgram);
this.view_mat_location = gl.glGetUniformLocation(shaderProgram, "view");
this.proj_mat_location = gl.glGetUniformLocation(shaderProgram, "proj");
gl.glDeleteShader(vertShader);
gl.glDeleteShader(fragShader);
List<ColoredTriangle> triangles = new AxisTrianges(100).createAxisTriangles();
float[] vertices = ColoredTriangle.verticesToArray(triangles);
float[] colors = ColoredTriangle.colorsToArray(triangles);
FloatBuffer fbVertices = Buffers.newDirectFloatBuffer(vertices);
FloatBuffer fbColors = Buffers.newDirectFloatBuffer(colors);
int[] points_vbo = new int[1];
gl.glGenBuffers(1, points_vbo,0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, points_vbo[0]);
gl.glBufferData(GL.GL_ARRAY_BUFFER, triangles.size() * 9 * Float.BYTES, fbVertices, GL.GL_STATIC_DRAW);
int[] colours_vbo = new int[1];
gl.glGenBuffers(1, colours_vbo,0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, colours_vbo[0]);
gl.glBufferData(GL.GL_ARRAY_BUFFER, triangles.size() * 9 * Float.BYTES, fbColors, GL.GL_STATIC_DRAW);
gl.glGenVertexArrays(1, axisVao,0);
gl.glBindVertexArray(axisVao[0]);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, points_vbo[0]);
gl.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, 0, 0L);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, colours_vbo[0]);
gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 0, 0L);
gl.glEnableVertexAttribArray(0);
gl.glEnableVertexAttribArray(1);
axisLen = triangles.size();
}
#Override
public void dispose(GLAutoDrawable drawable) {
System.out.println("cleanup, remember to release shaders");
GL3 gl = drawable.getGL().getGL3();
gl.glUseProgram(0);
gl.glDetachShader(shaderProgram, vertShader);
gl.glDeleteShader(vertShader);
gl.glDetachShader(shaderProgram, fragShader);
gl.glDeleteShader(fragShader);
gl.glDeleteProgram(shaderProgram);
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
this.width = width;
this.height = height;
this.updateProjMat();
GL3 gl = drawable.getGL().getGL3();
gl.glViewport((width-height)/2,0,height,height);
}
#Override
protected void glDisplay(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
gl.glClearColor(1, 1, 1, 1.0f);
gl.glClear(GL2ES2.GL_STENCIL_BUFFER_BIT | GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT );
gl.glUseProgram(shaderProgram);
gl.glUniformMatrix4fv(this.view_mat_location, 1, false, this.view_mat.getMatrix(), 0);
gl.glUniformMatrix4fv(this.proj_mat_location, 1, true, this.proj_mat.getMatrix(), 0);
gl.glBindVertexArray(axisVao[0]);
gl.glDrawArrays(GL2ES2.GL_TRIANGLES, 0, 3 * axisLen); //Draw the vertices as triangle
gl.glBindVertexArray(0);
gl.glCullFace(GL2ES2.GL_NONE);
gl.glDisable(GL2ES2.GL_CULL_FACE);
}
private void updateViewMatrix() {
Matrix4 T = new Matrix4();
T.translate(-eye.getX(), -eye.getY(), -eye.getZ());
Matrix4 yRot = new Matrix4();
yRot.rotate((float)Math.toRadians(rot.getX()), 0.0f, 1.0f, 0.0f);
Matrix4 xRot = new Matrix4();
xRot.rotate((float)Math.toRadians(Math.cos(-Math.toRadians(rot.getX())) * rot.getY()), 1.0f, 0.0f, 0.0f);
Matrix4 zRot = new Matrix4();
zRot.rotate((float)Math.toRadians(Math.sin(Math.toRadians(rot.getX())) * rot.getY()), 0.0f, 0.0f, 1.0f);
Matrix4 R = yRot;
R.multMatrix(xRot);
R.multMatrix(zRot);
view_mat = T;
view_mat.multMatrix(R);
}
#Override
protected boolean glRender(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
return false;
}
private void updateProjMat() {
float aspect = (float) width / (float) height; // aspect ratio
float range = (float) Math.tan(Math.toRadians(fov.getX() * 0.5f));
float proj_mat[] = new float[16];
proj_mat[0] = 1.0f / (range * aspect);
proj_mat[1] = 0.0f;
proj_mat[2] = 0.0f;
proj_mat[3] = 0.0f;
proj_mat[4] = 0.0f;
proj_mat[5] = 1.0f / range;
proj_mat[6] = 0.0f;
proj_mat[7] = 0.0f;
proj_mat[8] = 0.0f;
proj_mat[9] = 0.0f;
proj_mat[10] = -(far + near) / (far - near);
proj_mat[11] = -(2.0f * far * near) / (far - near);
proj_mat[12] = 0.0f;
proj_mat[13] = 0.0f;
proj_mat[14] =-1.0f;
proj_mat[15] = 0.0f;
this.proj_mat = new Matrix4();
this.proj_mat.multMatrix(proj_mat);
}
#Override
public void applyXY(float x, float y) {
rot.setX(fmod(rot.getX() + x * sens_rot, DROT_FULL));
rot.setY(Math.min(Math.max(rot.getY() + y * sens_rot, -DROT_QUART), DROT_QUART));
updateViewMatrix();
}
private float fmod(float f, float m) {
return ((f%m) + m) %m;
}
#Override
public void translate(float x, float y, float z) {
float deltax = z * (float)Math.sin(Math.toRadians(rot.getX())) + x * (float)Math.cos(Math.toRadians(rot.getX()));
float deltaz = z * (float)Math.cos(Math.toRadians(rot.getX())) - x * (float)Math.sin(Math.toRadians(rot.getX()));
eye.set( eye.getX()+deltax, eye.getY()+y, eye.getZ()+deltaz );
updateViewMatrix();
System.out.println(eye + rot.toString());
}
private int createShaderFromString(GL3 gl, String shaderCode,int type) {
int shader = gl.glCreateShader(type);;
String[] vlines = new String[] { shaderCode };
int[] vlengths = new int[] { vlines[0].length() };
gl.glShaderSource(shader, vlines.length, vlines, vlengths, 0);
gl.glCompileShader(shader);
int[] compiled = new int[1];
gl.glGetShaderiv(shader, GL2ES2.GL_COMPILE_STATUS, compiled,0);
if(compiled[0]!=0){
System.out.println("Horray! vertex shader compiled");
} else {
int[] logLength = new int[1];
gl.glGetShaderiv(shader, GL2ES2.GL_INFO_LOG_LENGTH, logLength, 0);
byte[] log = new byte[logLength[0]];
gl.glGetShaderInfoLog(shader, logLength[0], (int[])null, 0, log, 0);
System.err.println("Error compiling the vertex shader: " + new String(log));
System.exit(1);
}
return shader;
}
}
If you're looking for a way to make a camera have "true FPS behavior" then I suggest you to take a look at this tutorial: https://beta.wikiversity.org/wiki/Computer_graphics_--2008-2009--_info.uvt.ro/Laboratory_7
I personally went with solution nº 2. From what iv'e seen of the solution you went with, this one seems a lot more elegant. Of course I modified it to include the mouse. If you want to try to do it yourself just try to follow whatever solution better adjusts to your code. If you want I can instead show you my code with the modifications done but only if you ask for it, since I don't want to spoil you the solution.
Am trying to get the stroke data when the user scribbles on screen and redraw that same stroke on same location, in reduced size based on screen size of display. My issue is that this code works, it scales down striker but all scaled down strokes are connected which I don't want to be.
My ontouch code snippet:
#Override
public boolean onTouch(View arg0, final MotionEvent event) {
x = event.getX();
y =event.getY();
/* float x=(float) (xx*0.7);
float y=(float) (yy*0.7);*/
array_x.add(x);
array_y.add(y);
if(event.getPointerCount() == 2){
timevar2 = event.getEventTime();
float newx = event.getX(0);
float newy = event.getY(0);
float oldx = event.getX(1);
float oldy = event.getY(1);
mPath.reset();
float equa = (float) (Math.pow(newx - oldx, 2) + Math.pow(newy - oldy, 2));
float cscale = (float) Math.sqrt(equa)/100;
float scaled = (cscale - old_scale);
if(scaled < -0.1){
if(scale > 0.1){
scale -= 0.03;
}
}
if(scaled > 0.1){
scale += 0.03;
}
old_scale = cscale;
invalidate();
return true;
}
long dt = event.getEventTime() - timevar2;
if(dt < 100){
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
Log.v("TOUCH=======start","X=="+x + "Y=="+y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
Log.v("TOUCH=======move","X=="+x + "Y=="+y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up(x,y);
Log.v("TOUCH=======up","X=="+x + "Y=="+y);
//invalidate();
Handler mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
public void run() {
for(int i=0;i<array_x.size();i++)
{
x= array_x.get(i);
y= array_y.get(i);
if(i == 0){
x=(float) (x*0.7);
y=(float) (x*0.7);
Log.i("ARRAYYYYYY", "X=="+x+"Y=="+y);
touch_start(x, y);
invalidate();
}else if(i == array_x.size()-1){
x=(float) (x*0.7);
y=(float) (x*0.7);
touch_up(x, y);
invalidate();
mPath.reset();
}else{
x=(float) (x*0.7);
y=(float) (y*0.7);
touch_move(x, y);
invalidate();
}
}
}
}, 2000);
break;
}
return true;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
if (this.isErase) {
erasePath(mPath, x, y, mX, mY);
return;
}
PointF point = new PointF();
point.x = x;
point.y = y;
newPoint.points.add(point);
mCanvas.drawPath(mPath, mPaint);
}
private void touch_start(float x, float y) {
undonePaths.clear();
mPath = new Path();
newPoint = new Stroke();
PointF point = new PointF();
point.x = x;
point.y = y;
newPoint.points.add(point);
mCanvas.drawPath(mPath, mPaint);
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_up(float x, float y) {
if (this.isErase) {
return;
}
PointF point = new PointF();
point.x = x;
point.y = y;
newPoint.points.add(point);
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
Pair p = new Pair(mPath, newPoint);
this.Strokepaths.add(p);
}
Alas this is a university type question, but one im struggling with none the less.
I need to generate large test sets of rectangles, non-overlapping, that can then be used to test an algorithm that finds the adjacencies between them. The test sets will need to probably have upwards of 10000 - 100000 rectangles in them. Ive been searching the net for examples of how to generate test sets like this, but have come up with nothing. Im aware that I could use a purely brute force method, and every time a random rectangle is generated, check whether or not it overlaps with any of the other rectangles, but this seems like generating the test sets will end up taking days if not longer!
Any one know how to go about doing this, or at least where I should start looking?
I found your idea fun and challanging and therefore tried a solution by using a matrix.
Basicly, the idea is (when talking in pixels) to create a matrix of booleans of the same width and height as the square root of MaxWidthOfRectangle * (NumberOfRectangles) (just for simplicity the same width and height).
Next, for each entry in the matrix, generate a random rectangle between min and max bounds. and set all the bools in the matrix for the specific rectangle. Now when generating the next rectangle, you can simply check "around" the desired location to determine how much space you can occupy rather then having to estimate a size and compare with each other rectangle if it conflicts.
My code:
class RectangleGenerator
{
readonly bool[,] _matrix;
readonly int _size;
readonly int _minimalBoxSize;
readonly int _maximumBoxSize;
readonly Random _random = new Random(1);
readonly List<Point> _offsets;
public bool[,] Matrix { get { return _matrix; } }
public RectangleGenerator(int size, int minimalBoxSize, int maximumBoxSize)
{
_matrix = new bool[size, size];
_size = size;
_minimalBoxSize = minimalBoxSize;
_maximumBoxSize = maximumBoxSize;
_offsets = new List<Point>(size * size);
Reset();
}
public IEnumerable<Rectangle> Calculate()
{
while (_offsets.Count > 0)
{
Point currentPoint = _offsets[_offsets.Count - 1];
_offsets.RemoveAt(_offsets.Count - 1);
if (!_matrix[currentPoint.X, currentPoint.Y])
{
Rectangle rectangle;
if (TryCreateNextRectangle(currentPoint.X, currentPoint.Y, out rectangle))
{
// fill the matrix with the rectangle + padding
int startFillX = Math.Max(0, rectangle.Left);
int startFillY = Math.Max(0, rectangle.Top);
int endFillX = Math.Min(_size, rectangle.Right);
int endFillY = Math.Min(_size, rectangle.Bottom);
for (int fillX = startFillX; fillX < endFillX; fillX++)
for (int fillY = startFillY; fillY < endFillY; fillY++)
{
_matrix[fillX, fillY] = true;
}
yield return rectangle;
}
}
}
}
private bool TryCreateNextRectangle(int x, int y, out Rectangle rectangle)
{
int maxWidth = DetermineMaxWidth(x, y, _minimalBoxSize);
int maxHeight = DetermineMaxHeight(y, x, maxWidth);
if (maxWidth < _minimalBoxSize || maxHeight < _minimalBoxSize)
{
rectangle = Rectangle.Empty;
return false;
}
int width = _random.Next(_minimalBoxSize, maxWidth);
int height = _random.Next(_minimalBoxSize, maxHeight);
rectangle = new Rectangle(x, y, width, height);
return true;
}
private int DetermineMaxWidth(int x, int y, int height)
{
int result = Math.Min(_maximumBoxSize, _size - x);
for (int offsetX = 0; offsetX < result; offsetX++)
for (int offsetY = 0; offsetY < height; offsetY++)
{
if (_matrix[x + offsetX, y + offsetY])
{
result = offsetX;
break;
}
}
return result;
}
private int DetermineMaxHeight(int y, int x, int width)
{
int result = Math.Min(_maximumBoxSize, _size - y);
for (int offsetY = 0; offsetY < result; offsetY++)
for (int offsetX = 0; offsetX < width; offsetX++ )
{
if (_matrix[x + offsetX, y + offsetY])
{
result = offsetY;
break;
}
}
return result;
}
public void Reset()
{
// append for padding:
for (int x = 0; x < _size; x++)
for (int y = 0; y < _size; y++)
{
_matrix[x, y] = false;
if (_size - x >= _minimalBoxSize && _size - y >= _minimalBoxSize)
{
_offsets.Add(new Point(x, y));
}
}
_offsets.Sort((x, y) => x == y ? 0 : _random.Next(-1, 1));
}
}