2013-04-08 24 views
6

Tôi đang tạo một công cụ đồ họa 3D và một trong những yêu cầu là dây thừng hoạt động giống như trong công cụ nguồn của Valve. Vì vậy, trong công cụ nguồn, một phần của dây là một quad quay theo trục hướng của nó để đối mặt với máy ảnh, vì vậy nếu phần của dây là theo hướng + Z, nó sẽ xoay dọc theo trục Z để nó khuôn mặt đang đối diện với vị trí trung tâm của máy ảnh.Nguồn động cơ được tạo kiểu theo kiểu dây thừng

Hiện tại, tôi có phần dây thừng được xác định, vì vậy tôi có thể có một sợi dây cong đẹp, nhưng bây giờ tôi đang cố gắng xây dựng ma trận sẽ xoay nó dọc theo vector hướng của nó.

Tôi đã có một ma trận cho rendering sprites billboard dựa trên kỹ thuật billboarding này: Constructing a Billboard Matrix Và tại thời điểm này tôi đã cố gắng để trang bị lại nó để Phải, Lên, Forward vector phù hợp với véc tơ hướng phân khúc dây thừng của.

Dây của tôi được tạo thành từ nhiều phần, mỗi phần là một hình chữ nhật được tạo thành từ hai hình tam giác, như tôi đã nói ở trên, tôi có thể nhận được vị trí và các phần hoàn hảo, đó là quay để đối mặt với máy ảnh gây ra cho tôi rất nhiều vấn đề.

Đây là trong OpenGL ES2 và viết bằng C.

tôi đã nghiên cứu đang chùm vẽ Doom 3 trong Model_beam.cpp, phương pháp này sử dụng có để tính toán bù đắp dựa trên normals thay vì sử dụng ma trận, vì vậy tôi đã tạo ra một kỹ thuật tương tự trong mã C của tôi và nó sắp xếp công việc, ít nhất nó, hoạt động nhiều như tôi cần nó ngay bây giờ. Vì vậy, đối với những người cũng đang cố gắng tìm ra sản phẩm này, hãy sử dụng sản phẩm chéo giữa điểm giữa của sợi dây với vị trí của máy ảnh, bình thường hóa và sau đó nhân nó với chiều rộng bạn muốn sợi dây , sau đó khi xây dựng các đỉnh, bù trừ mỗi đỉnh theo hướng + hoặc - của vectơ kết quả.

Trợ giúp thêm sẽ rất tuyệt vời vì điều này không hoàn hảo!

Cảm ơn bạn

+2

Để xoay thứ gì đó theo một góc nhất định về một trục cụ thể, hãy sử dụng [quaternion] (https://en.wikipedia.org/wiki/Quaternion). –

+0

Tôi hiện đang sử dụng quaternions, nhưng tôi không chắc chắn làm thế nào để xoay nó về phía vị trí của máy ảnh –

+4

Để bình thường của hình chữ nhật/phần là 'N', và vectơ dọc theo trục của hình chữ nhật là' V'. Sau đó, 'VxN' sẽ cung cấp cho bạn vectơ thứ ba' U', với 'U' và' N' tạo thành một "mặt phẳng nằm ngang" so với phần dây của bạn. Bây giờ tính toán 'EyePos - C' (trong đó' C' là trung tâm của hình chữ nhật của bạn) và bình thường hóa nó để có được 'E', hướng camera. Dự án 'E' lên mặt phẳng' UN' để lấy 'E''. Cuối cùng, vòng xoay bạn muốn (về trục 'V') là' arccos (N. E ') '. –

Trả lời

1

Check-out this related stackoverflow post on billboards in OpenGL Nó trích dẫn một hướng dẫn lighthouse3d đó là một đọc khá tốt. Dưới đây là các điểm nổi bật của kỹ thuật:

void billboardCylindricalBegin(
       float camX, float camY, float camZ, 
       float objPosX, float objPosY, float objPosZ) { 

     float lookAt[3],objToCamProj[3],upAux[3]; 
     float modelview[16],angleCosine; 

     glPushMatrix(); 

    // objToCamProj is the vector in world coordinates from the 
    // local origin to the camera projected in the XZ plane 
     objToCamProj[0] = camX - objPosX ; 
     objToCamProj[1] = 0; 
     objToCamProj[2] = camZ - objPosZ ; 

    // This is the original lookAt vector for the object 
    // in world coordinates 
     lookAt[0] = 0; 
     lookAt[1] = 0; 
     lookAt[2] = 1; 


    // normalize both vectors to get the cosine directly afterwards 
     mathsNormalize(objToCamProj); 

    // easy fix to determine wether the angle is negative or positive 
    // for positive angles upAux will be a vector pointing in the 
    // positive y direction, otherwise upAux will point downwards 
    // effectively reversing the rotation. 

     mathsCrossProduct(upAux,lookAt,objToCamProj); 

    // compute the angle 
     angleCosine = mathsInnerProduct(lookAt,objToCamProj); 

    // perform the rotation. The if statement is used for stability reasons 
    // if the lookAt and objToCamProj vectors are too close together then 
    // |angleCosine| could be bigger than 1 due to lack of precision 
     if ((angleCosine < 0.99990) && (angleCosine > -0.9999)) 
      glRotatef(acos(angleCosine)*180/3.14,upAux[0], upAux[1], upAux[2]); 
    } 
+0

Trong khi liên kết này có thể trả lời câu hỏi, tốt hơn nên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở thành không hợp lệ nếu trang được liên kết thay đổi. – Brian

+0

Điểm tốt Brian. Tôi đã thêm điểm mấu chốt của kỹ thuật .. – henderso